Pixel Doom

On your display
Can it run DOOM? Well… your AWTRIX NG can now run a tiny 32×8 pixel shooter. 😈
- Works with
- AWTRIX NG
- Topic
- Gaming
- Includes
- Script
Choose your display in the next step.
Flow description
The ultimate question for any piece of hardware: Can it run DOOM?
Pixel Doom brings a tiny DOOM-inspired first-person shooter to the 32×8 pixel display of AWTRIX NG.
Fight your way through a dark pseudo-3D corridor while enemies emerge from the distance and get larger as they approach. Move between lanes, line up your weapon and fire before they reach you.
Despite having only 256 pixels, Pixel Doom is an actual playable game rather than a simple animation.
Features
🔫 Playable first-person pixel shooter
👹 Enemies approach from the distance
🏃 Move left and right to line up your shots
💥 Animated muzzle flashes
🔥 Enemy fireballs
❤️ Three-hit health system
☠️ Game-over screen
🏆 Kill counter
⚡ Difficulty increases as your kill count rises
🕹️ Runs entirely as an AWTRIX NG Berry script
📡 No server or external API required
Controls
LEFT — Move left
RIGHT — Move right
SELECT — Fire
After dying, press SELECT to start a new game.
Can it run DOOM?
Not actual DOOM. 😉
Pixel Doom uses procedural pixel graphics and a lightweight pseudo-3D perspective designed specifically around the extreme limitations of a 32×8 LED matrix.
But when someone sees a first-person demon shooter running on your pixel clock, there's really only one appropriate answer:
Yes. Yes, it can. 😈🔫
PPgJxV9vVReH.ax
# @name Pixel Doom
# @desc Tiny 32x8 pseudo-3D demon shooter
# @version 1.0
class PixelDoom
var px,hp,kills,enemy,ex,depth,shot,flash
var fire,last,spawn,seed,dead
def init()
self.seed=now_ms()+666
self.start()
end
def start()
self.px=1
self.hp=3
self.kills=0
self.enemy=false
self.depth=5
self.shot=0
self.flash=0
self.fire=0
self.last=now_ms()
self.spawn=now_ms()
self.dead=false
end
def rnd(n)
self.seed=(self.seed*1103515245+12345)%2147483647
if self.seed<0 self.seed=-self.seed end
return self.seed%n
end
# =====================================
# CONTROLS
# =====================================
def on_button(b)
if self.dead
if b=="select"
self.start()
end
return
end
if b=="left"
if self.px>0 self.px-=1 end
elif b=="right"
if self.px<2 self.px+=1 end
elif b=="select"
self.shot=3
if self.enemy && self.ex==self.px
self.enemy=false
self.kills+=1
self.flash=2
self.spawn=now_ms()
end
end
end
# =====================================
# GAME UPDATE
# =====================================
def update()
var n=now_ms()
if self.shot>0 self.shot-=1 end
if self.flash>0 self.flash-=1 end
if self.fire>0 self.fire-=1 end
if self.dead
return
end
# spawn enemy
if !self.enemy && n-self.spawn>900+self.rnd(1000)
self.enemy=true
self.ex=self.rnd(3)
self.depth=5
end
# game speed increases with kills
var speed=700-self.kills*18
if speed<260 speed=260 end
if n-self.last<speed
return
end
self.last=n
if self.enemy
self.depth-=1
# enemy attacks when close
if self.depth==2 && self.rnd(2)==0
self.fire=3
end
# enemy reaches player
if self.depth<=0
if self.ex==self.px
self.hp-=1
self.flash=4
if self.hp<=0
self.dead=true
return
end
end
self.enemy=false
self.spawn=n
end
end
end
# =====================================
# CORRIDOR
# =====================================
def room()
# damage flash
if self.flash>2
clear(0x350000)
else
clear(0x03050A)
end
# perspective walls
pixel(0,1,0x702020)
pixel(31,1,0x702020)
pixel(1,2,0x702020)
pixel(30,2,0x702020)
pixel(2,3,0x702020)
pixel(29,3,0x702020)
pixel(3,4,0x702020)
pixel(28,4,0x702020)
# ceiling perspective
line(0,0,31,0,0x301010)
line(7,1,24,1,0x201010)
# floor
line(0,5,31,5,0x301515)
pixel(4,4,0x502020)
pixel(27,4,0x502020)
pixel(8,4,0x301515)
pixel(23,4,0x301515)
# floor perspective markers
pixel(6,5,0x702020)
pixel(12,5,0x702020)
pixel(19,5,0x702020)
pixel(25,5,0x702020)
end
# =====================================
# ENEMY
# =====================================
def monster()
if !self.enemy
return
end
# three lanes
var x=8+self.ex*8
# far
if self.depth>=5
pixel(x,3,0xFF2020)
# distance 4
elif self.depth==4
pixel(x,3,0xFF2020)
pixel(x,4,0x8B0000)
# distance 3
elif self.depth==3
pixel(x-1,3,0xAA1010)
pixel(x,3,0xFF3030)
pixel(x+1,3,0xAA1010)
pixel(x,4,0x8B0000)
# distance 2
elif self.depth==2
rect_fill(x-1,2,3,3,0xA51010)
pixel(x-1,2,0xFF5500)
pixel(x+1,2,0xFF5500)
pixel(x,3,0xFFFF00)
# distance 1
else
rect_fill(x-2,1,5,4,0x8B1010)
# horns
pixel(x-2,0,0xFF5500)
pixel(x+2,0,0xFF5500)
# eyes
pixel(x-1,2,0xFFFF00)
pixel(x+1,2,0xFFFF00)
# mouth
pixel(x,3,0x000000)
end
end
# =====================================
# ENEMY FIREBALL
# =====================================
def fireball()
if self.fire==0
return
end
var x=8+self.ex*8
if self.fire==3
pixel(x,4,0xFF4000)
elif self.fire==2
pixel((x+16)/2,4,0xFF8000)
else
pixel(12+self.px*4,5,0xFFFF00)
end
end
# =====================================
# WEAPON
# =====================================
def gun()
var x=12+self.px*4
# hands
pixel(x-2,7,0xB06030)
pixel(x+3,7,0xB06030)
# gun
rect_fill(x,6,2,2,0x777777)
pixel(x,6,0xAAAAAA)
# muzzle flash
if self.shot>0
pixel(x,5,0xFFFFFF)
pixel(x-1,5,0xFFFF00)
pixel(x+1,5,0xFF8000)
if self.shot==3
pixel(x,4,0xFFFF00)
end
end
end
# =====================================
# HUD
# =====================================
def hud()
# health - top left
for i:0..self.hp-1
pixel(i*2,0,0xFF2020)
end
# kills - top right
var k=self.kills
if k>5 k=5 end
for i:0..k-1
pixel(31-i,0,0xFFAA00)
end
end
# =====================================
# GAME OVER
# =====================================
def gameover()
clear(0x100000)
text(0,6,"DEAD",0xFF2020)
# alternating score
if (now_ms()/1800)%2==1
clear(0x050000)
text(1,6,str(self.kills),0xFFFFFF)
end
end
# =====================================
# DRAW
# =====================================
def draw()
self.update()
if self.dead
self.gameover()
return
end
self.room()
self.monster()
self.fireball()
self.gun()
self.hud()
end
end
return PixelDoom()
Discussion 0
Ask a question, suggest a change or share how you use it.
No comments yet. Start the conversation.
More flows for AWTRIX NG Scripts or Gaming
Something wrong with this flow? Report it.
Have an idea?
Sign in to ask questions and join the conversation.