Skip to content

Instantly share code, notes, and snippets.

@samneggs
Created June 28, 2023 14:31
Show Gist options
  • Save samneggs/4232ebc172edcbbca7632d1830b70c1d to your computer and use it in GitHub Desktop.
Save samneggs/4232ebc172edcbbca7632d1830b70c1d to your computer and use it in GitHub Desktop.
Centipede game on PI Pico in MicroPython
# Centipede
import centi_splash
from lcd_1_8 import LCD_1inch8
import machine
from machine import Pin, PWM
from uctypes import addressof
from time import sleep, ticks_us, ticks_diff, ticks_ms
import gc, _thread, array
from sys import exit
from micropython import const
from random import randint
from math import sin,cos,tan,radians,sqrt
from rp2 import bootsel_button as RESET_PB
from centi_sound import Centi_Sound
MAXSCREEN_X = const(160)
MAXSCREEN_Y = const(128)
SCALE = const(13)
TEXTURE_WIDTH = const(16)
TEXTURE_HEIGHT = const(16)
NUM_TEXTURES = const(68)
FIELD_WIDTH = const(MAXSCREEN_X//8)
FIELD_HEIGHT = const(MAXSCREEN_Y//8)
RED = const(0b11111_000)
PLAYER_PARAMS = const(10)
X = const(0)
Y = const(1)
FIRED = const(2)
SPRITE_IND = const(3)
MISS_X = const(4)
MISS_Y = const(5)
PLAYER_DEAD = const(6)
GAME_PARAMS = const(10)
FPS = const(0)
LIVES = const(1)
SIZE = const(2)
NUM_MUSH = const(3)
C_SEGMENTS = const(4)
CENTI_DEAD = const(5)
EXPLODE_DONE= const(6)
SCORE = const(7)
CENTI_PARAMS = const(10)
#X,Y
DIRECTION = const(2)
#SPRITE_IND
SPRITE_START = const(4)
UP_DOWN = const(5)
REACH_BOT = const(6)
FLEA_PARAMS = const(10)
#X,Y
FLEA_SCORE = const(2)
FLEA_SCORE_Y = const(3)
SPID_PARAMS = const(10)
#X,Y
SPID_SCORE = const(2)
SPID_SCORE_X = const(3)
SPID_POINTS = const(4)
SPID_XDIR = const(5)
SPID_XINC = const(6)
SPID_YINC = const(7)
SPID_YDIST = const(8)
EXPLODE_PARAMS = const(10)
# X,Y
EXP_SPRITE = const(2)
EXP_COUNT = const(3)
# directions
#0=dead,1=right/down, 2=left/down, 3=down/right, 4 down/left,
# 5=right/up, 6=left/up, 7=up/right, 8=up/left
DEAD = const(0)
RIGHT_DOWN = const(1)
LEFT_DOWN = const(2)
DOWN_RIGHT = const(3)
DOWN_LEFT = const(4)
RIGHT_UP = const(5)
LEFT_UP = const(6)
UP_RIGHT = const(7)
UP_LEFT = const(8)
char_map=array.array('b',(
0x3E, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x3E, 0x00, # U+0030 (0)
0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00, # U+0031 (1)
0x1E, 0x33, 0x30, 0x1C, 0x06, 0x33, 0x3F, 0x00, # U+0032 (2)
0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00, # U+0033 (3)
0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x78, 0x00, # U+0034 (4)
0x3F, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00, # U+0035 (5)
0x1C, 0x06, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00, # U+0036 (6)
0x3F, 0x33, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x00, # U+0037 (7)
0x1E, 0x33, 0x33, 0x1E, 0x33, 0x33, 0x1E, 0x00, # U+0038 (8)
0x1E, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0E, 0x00)) # U+0039 (9)
@micropython.viper
def show_num_viper(num:int,x_offset:int,y_offset:int,color:int):
char_ptr = ptr8(char_map)
screen_ptr = ptr16(LCD.buffer)
size = 1 # 1,2,3
char = 0
offset = MAXSCREEN_X*y_offset+x_offset
while num > 0:
total = num//10
digit = num - (total * 10)
num = total
for y in range(8):
row_data = char_ptr[digit*8+y]
for x in range(8):
if row_data & (1<<x) > 0:
addr = size*y*MAXSCREEN_X+x-(char*8)+offset
screen_ptr[addr] = color
if size>1:
screen_ptr[MAXSCREEN_X+addr] = color
if size>2:
screen_ptr[2*MAXSCREEN_X+addr] = color
char += 1
# blit_image_file from Stewart Watkiss
# http://www.penguintutor.com/programming/picodisplayanimations
def blit_image_file(buf,filename,width,height,cw,ch): # file width, file height, char width, char height
with open (filename, "rb") as file:
file_position = 0
char_position = 0
ecount = 0
current_byte = file.read(4) # header
while file_position < (width * height * 2):
current_byte = file.read(1)
if len(current_byte) == 0:
break
buf[char_position] = ord(current_byte)
char_position += 1
file_position += 1
file.close()
def init_pot():
global POT_X,POT_Y,POT_X_ZERO,POT_Y_ZERO
POT_X = machine.ADC(27)
POT_Y = machine.ADC(26)
POT_X_ZERO = 0
POT_Y_ZERO = 0
for i in range(1000):
POT_X_ZERO += POT_X.read_u16()
POT_Y_ZERO += POT_Y.read_u16()
POT_X_ZERO = POT_X_ZERO//1000
POT_Y_ZERO = POT_Y_ZERO//1000
pot_scale = 12
@micropython.viper
def read_pot():
global EXIT
game = ptr32(GAME)
player = ptr32(PLAYER)
field = ptr8(FIELD)
pot_scale = 12
x_inc = int(POT_X.read_u16() - POT_X_ZERO)>>pot_scale
y_inc = int(POT_Y.read_u16() - POT_Y_ZERO)>>pot_scale
if int(abs(x_inc))<2:
x_inc=0
if int(abs(y_inc))<2:
y_inc=0
if not FIRE_BUTTON.value() and not player[FIRED]:
CENTI_SOUND.SOUND = int(CENTI_SOUND.SOUND) | 1<<1
player[FIRED] = 1
player[MISS_X] = (player[X]>>SCALE) + 8
player[MISS_Y] = (player[Y]>>SCALE) + 8
test_x = player[X] - (x_inc<<12) #12
test_y = player[Y] + (y_inc<<11)
if test_x < 0: test_x = 0
if test_y < 0: test_y = 0
if test_x > (MAXSCREEN_X-12)<<SCALE: test_x = (MAXSCREEN_X-12)<<SCALE
if test_y > (MAXSCREEN_Y-12)<<SCALE: test_y = (MAXSCREEN_Y-12)<<SCALE
x = ((8<<SCALE)+test_x)>>16
y = ((8<<SCALE)+test_y)>>16
sprite = field[y*20+x]
if sprite == 99:
player[X] = test_x
player[Y] = test_y
def init_player():
global PLAYER, CENTI, DIR_INC, START_IND
DIR_INC = array.array('i',(0,0,1,0,-1,0,0,1,0,1,1,0,-1,0,0,-1,0,-1))
START_IND = bytearray([0])
segments = GAME[C_SEGMENTS]
PLAYER = array.array('i',0 for _ in range(PLAYER_PARAMS))
CENTI = array.array('i',0 for _ in range(1+segments * CENTI_PARAMS))
PLAYER[X] = 80<<SCALE
PLAYER[Y] = 100<<SCALE
@micropython.viper
def init_centi():
field = ptr8(FIELD)
centi = ptr32(CENTI)
game = ptr32(GAME)
for i in range(20):
field[i] = 99
for index in range(game[C_SEGMENTS]):
i = index * CENTI_PARAMS
centi[i+X] = 100 - (8 * index)
centi[i+Y] = 0
centi[i+DIRECTION] = 1
centi[i+SPRITE_IND] = index % 4
centi[i+SPRITE_START] = 4
centi[i+REACH_BOT] = 0
centi[0+SPRITE_START] = 0 # head
def init_game():
global GAME, FPS_ARRY, TEXTURES, FIELD, FLEA, SPIDER, EXPLODE
GAME = array.array('i',0 for _ in range(GAME_PARAMS))
TEXTURES=bytearray(TEXTURE_WIDTH*TEXTURE_HEIGHT*2*NUM_TEXTURES)
FIELD = bytearray([99 for _ in range(FIELD_WIDTH*FIELD_HEIGHT*8)])
FPS_ARRY = bytearray(35)
FLEA = array.array('i',0 for _ in range(FLEA_PARAMS))
SPIDER = array.array('i',0 for _ in range(SPID_PARAMS))
EXPLODE = array.array('i',0 for _ in range(10 * EXPLODE_PARAMS))
SPIDER[SPID_XDIR] = 1
GAME[FPS] = 0
GAME[LIVES] = 3
GAME[SIZE] = 16
GAME[NUM_MUSH] = 20 # 20 mushrooms count
GAME[C_SEGMENTS] = 10
blit_image_file(TEXTURES,"Centipede_2.bin",16,16*NUM_TEXTURES,16,16)
@micropython.viper
def init_field():
field = ptr8(FIELD)
game = ptr32(GAME)
mush_count = 0
while mush_count < game[NUM_MUSH]:
pos = int(randint(FIELD_WIDTH,FIELD_WIDTH*(FIELD_HEIGHT-4))) # clear bottom 10 rows
if field[pos] == 99:
field[pos] = 49 # shroom sprite
mush_count += 1
@micropython.viper
def reset_field():
field = ptr8(FIELD)
game = ptr32(GAME)
if game[LIVES] == 0:
CENTI_SOUND.SOUND = 0
return
for x in range(20):
for y in range(16):
if 49 < field[y*20+x] < 53:
field[y*20+x] = 49
CENTI_SOUND.SOUND = int(CENTI_SOUND.SOUND) | 1<<1
draw_field()
LCD.show()
sleep(0.1)
CENTI_SOUND.SOUND = 0
sleep(0.1)
@micropython.viper
def init_explode(x:int,y:int,sprite:int):
explode = ptr32(EXPLODE)
game = ptr32(GAME)
for index in range(10):
i = index * EXPLODE_PARAMS
if explode[i + EXP_COUNT] == 0:
explode[i + X] = x
explode[i + Y] = y
explode[i + EXP_SPRITE] = sprite
explode[i + EXP_COUNT] = 100
game[EXPLODE_DONE] = 0
return
@micropython.viper
def move_miss():
player = ptr32(PLAYER)
field = ptr8(FIELD)
centi = ptr32(CENTI)
game = ptr32(GAME)
flea = ptr32(FLEA)
explode = ptr32(EXPLODE)
spider = ptr32(SPIDER)
if not player[FIRED]:
CENTI_SOUND.reset_fire()
CENTI_SOUND.SOUND = int(CENTI_SOUND.SOUND) & 0b1101
if player[FIRED]:
player[MISS_Y] -= 5
if player[MISS_Y] < 0:
player[FIRED] = 0
return
miss_x = (player[MISS_X]-1)>>3
miss_y = player[MISS_Y]>>3
sprite = field[miss_y*20+miss_x]
if sprite == 52: # last shroom bit
field[miss_y*20+miss_x] = 99
player[FIRED] = 0
game[SCORE] += 1
init_explode(miss_x*8+16,miss_y*8,49)
return
if 48 < sprite < 52: # hit shroom
field[miss_y*20+miss_x] = sprite + 1
player[FIRED] = 0
m_x = player[MISS_X]
m_y = player[MISS_Y]
f_x = flea[X]
f_y = flea[Y]
if flea[Y] > 0 and m_x < f_x+8 and m_x > f_x and m_y < f_y+8 and m_y > f_y: # hit flea
flea[FLEA_SCORE_Y] = flea[Y]
flea[FLEA_SCORE] = 50
game[SCORE] += 300
init_explode(flea[X],flea[Y],30)
flea[Y] = 0
s_x = spider[X]
s_y = spider[Y]
if 0 < s_y < 144 and m_x < s_x+16 and m_x > s_x and m_y < s_y+8 and m_y > s_y: # hit spider
spider[SPID_SCORE] = 30
game[SCORE] += 900
init_explode(s_x,s_y,24)
spider[SPID_SCORE_X] = spider[X]
spider[X] = 0
segments = game[C_SEGMENTS]
for index in range(segments):
i = index * CENTI_PARAMS
if centi[i + DIRECTION] == DEAD: continue
c_x = centi[i + X]
c_y = centi[i + Y]
if m_x < c_x+8 and m_x > c_x and m_y < c_y+8 and m_y > c_y: # hit centi
if centi[i+SPRITE_START] == 0 or centi[i+SPRITE_START] == 8:
game[SCORE] += 100
else:
game[SCORE] += 10
if index < segments-1 and centi[i + DIRECTION + CENTI_PARAMS] > 0: # make new head
centi[i+SPRITE_START+ CENTI_PARAMS] = 0
centi[i + DIRECTION] = DEAD
player[FIRED] = 0
field[miss_y*20+miss_x] = 49
init_explode(centi[i + X],centi[i + Y],centi[i + SPRITE_START])
return
@micropython.viper
def move_centi():
field = ptr8(FIELD)
centi = ptr32(CENTI)
game = ptr32(GAME)
textures = ptr16(TEXTURES)
dir_inc = ptr32(DIR_INC)
segments = game[C_SEGMENTS]
player = ptr32(PLAYER)
alive_segs = 0
for index in range(segments):
i = index * CENTI_PARAMS
if centi[i + DIRECTION] == DEAD: continue
alive_segs += 1
inc_x = dir_inc[centi[i + DIRECTION]*2]
inc_y = dir_inc[centi[i + DIRECTION]*2+1]
test_x = centi[i + X] + inc_x
test_y = centi[i + Y] + inc_y
f_x = test_x//8
f_y = test_y//8
direction = centi[i + DIRECTION]
if field[(f_y+1) * 20 + f_x] < 99: # erase trap
if centi[i + UP_DOWN] == 1:
field[(f_y+1) * 20 + f_x] = 99
if (direction == DOWN_LEFT or direction == UP_LEFT) and centi[i + UP_DOWN] > 7:
centi[i + UP_DOWN] = 0
if test_y > MAXSCREEN_Y-(8*1):
direction = LEFT_UP
centi[i + REACH_BOT] = 1
if test_y < MAXSCREEN_Y-(8*5) or centi[i + REACH_BOT] == 0:
direction = LEFT_DOWN
centi[i + REACH_BOT] = 0
elif (direction == DOWN_RIGHT or direction == UP_RIGHT) and centi[i + UP_DOWN] > 7:
centi[i + UP_DOWN] = 0
if test_y > MAXSCREEN_Y-(8*1):
direction = RIGHT_UP
centi[i + REACH_BOT] = 1
if test_y < MAXSCREEN_Y-(8*5) or centi[i + REACH_BOT] == 0:
direction = RIGHT_DOWN
centi[i + REACH_BOT] = 0
elif (field[f_y * 20 + f_x] < 99 or test_x > MAXSCREEN_X-8 or test_x < 0) and direction != DOWN_RIGHT and direction != DOWN_LEFT and direction != UP_RIGHT and direction != UP_LEFT:
if direction == RIGHT_DOWN:
direction = DOWN_LEFT
elif direction == LEFT_DOWN:
direction = DOWN_RIGHT
elif direction == RIGHT_UP:
direction = UP_LEFT
elif direction == LEFT_UP:
direction = UP_RIGHT
else:
centi[i + X] = test_x
centi[i + Y] = test_y
centi[i + SPRITE_IND] += 1
if centi[i + SPRITE_IND] == 4: centi[i + SPRITE_IND] = 0
if (2 < direction < 5) or (6 < direction):
centi[i + UP_DOWN] += 1
centi[i + SPRITE_START] ^= (((direction+1) % 2) ^ ((centi[i + SPRITE_START] >> 3) & 1)) << 3 # set sprite direction
m_x = (player[X]>>SCALE)+4
m_y = (player[Y]>>SCALE)+12
if m_x < test_x+8 and m_x > test_x and m_y < test_y+8 and m_y > test_y: # centi hit player
init_explode(m_x,m_y,67)
player_dies()
centi[i + DIRECTION] = direction
if alive_segs == 0:
init_centi()
@micropython.viper
def move_flea():
centi = ptr32(CENTI)
field = ptr8(FIELD)
flea = ptr32(FLEA)
game = ptr32(GAME)
player = ptr32(PLAYER)
if flea[FLEA_SCORE] > 0:
flea[FLEA_SCORE] -= 1
if not flea[FLEA_SCORE]:
init_explode(flea[X],flea[FLEA_SCORE_Y],36)
if flea[Y] == 0 and int(randint(0,300)) == 300 and flea[FLEA_SCORE] == 0: # new flea
CENTI_SOUND.SOUND = int(CENTI_SOUND.SOUND) | 1<<2
flea[X] = 8 * int(randint(0,20))
flea[Y] = 8
if flea[Y] == 0:
CENTI_SOUND.reset_flea()
CENTI_SOUND.SOUND = int(CENTI_SOUND.SOUND) & 0b1011
return
flea[Y] += 1
if flea[Y] > 120:
flea[Y] = 0
return
f_x = flea[X]//8
f_y = flea[Y]//8
if int(randint(0,30)) == 30: # chance of new shroom
for index in range(game[C_SEGMENTS]):
i = index * CENTI_PARAMS
if centi[i + DIRECTION] == DEAD: continue
c_x = centi[i + X]//8
c_y = centi[i + Y]//8
if f_x == c_x and f_y == c_y: return
field[(f_y) * 20 + f_x] = 49
m_x = (player[X]>>SCALE)+8
m_y = (player[Y]>>SCALE)+4
f_x = flea[X]
f_y = flea[Y]
if flea[Y] > 0 and m_x < f_x+8 and m_x > f_x and m_y < f_y+8 and m_y > f_y: # flea hit player
init_explode(m_x,m_y,67)
player_dies()
@micropython.viper
def move_spider():
global CENTI_SOUND
spider = ptr32(SPIDER)
field = ptr8(FIELD)
player = ptr32(PLAYER)
game = ptr32(GAME)
if spider[SPID_SCORE] > 0:
spider[SPID_SCORE] -= 1
if not spider[SPID_SCORE]:
init_explode(spider[SPID_SCORE_X],spider[Y],34)
if (spider[X] == 0 or spider[X] > 144) and int(randint(0,200)) == 200 and spider[SPID_SCORE] == 0: # new spider
CENTI_SOUND.SOUND = int(CENTI_SOUND.SOUND) | 1<<3
spider[X] = 144 if spider[SPID_XDIR] == -1 else 1
spider[Y] = int(randint(60,112))
spider[SPID_YDIST] = int(randint(10,40))
spider[SPID_XINC] = spider[SPID_XDIR] if randint(0,1) else 0
spider[SPID_YINC] = -1 if randint(0,1) else 1
if spider[X] < 1 or spider[X] > 144:
CENTI_SOUND.SOUND = int(CENTI_SOUND.SOUND) & 0b0111 # turn off spider sound
return
if spider[SPID_YDIST] > 0:
spider[SPID_YDIST] -= 1
spider[X] += spider[SPID_XINC]
spider[Y] += spider[SPID_YINC]
s_x = spider[X]//8
s_y = spider[Y]//8
field[(s_y) * 20 + s_x] = 99
field[(s_y) * 20 + s_x+1] = 99
if spider[Y] < 60 or spider[Y] > 112: spider[SPID_YINC] *= -1
if spider[X] == 0 or spider[X] > 144: spider[SPID_XDIR] *= -1
else:
spider[SPID_YDIST] = int(randint(10,40))
spider[SPID_XINC] = spider[SPID_XDIR] if randint(0,1) else 0
spider[SPID_YINC] = -1 if randint(0,1) else 1
m_x = (player[X]>>SCALE)+4
m_y = (player[Y]>>SCALE)+12
s_x = spider[X]
s_y = spider[Y]
if 0 < spider[X] < 144 and m_x < s_x+14 and m_x > s_x and m_y < s_y+14 and m_y > s_y: # spider hit player
init_explode(m_x,m_y,67)
player_dies()
@micropython.viper
def player_dies():
global CENTI_SOUND
game = ptr32(GAME)
player = ptr32(PLAYER)
spider = ptr32(SPIDER)
flea = ptr32(FLEA)
game[LIVES] -= 1
player[PLAYER_DEAD] = 100
player[X] = 80<<SCALE
player[Y] = 100<<SCALE
flea[Y] = 0
spider[X] = 0
CENTI_SOUND.SOUND = 1
@micropython.viper
def explode():
screen = ptr16(LCD.buffer)
textures = ptr16(TEXTURES)
explode = ptr32(EXPLODE)
game = ptr32(GAME)
count = 0
for index in range(10):
i = index * EXPLODE_PARAMS
if explode[i + EXP_COUNT] == 0: continue
count += 1
x1 = explode[i + X]
y1 = explode[i + Y]
sprite = explode[i + EXP_SPRITE]<<8
count = (explode[i + EXP_COUNT])//10
explode[i + EXP_COUNT] -= 1
for y in range(16):
for x in range(16):
x_off = ((x - 8)<<5)//(count)
y_off = ((y - 8)<<5)//(count)
addr = (y1 + y + y_off) * MAXSCREEN_X + x1 + x + x_off
if 0 < addr < 20480:
screen[addr] = textures[y * 16 + x + sprite]
if count == 0: game[EXPLODE_DONE] = 1
@micropython.viper
def all_sprites(): # utility only
g = ptr32(GAME)
screen=ptr16(LCD.buffer)
textures = ptr16(TEXTURES)
sprite = 0
for y1 in range(8): #16
for x1 in range(10): #8
sprite += 1
offset = (y1*16) * MAXSCREEN_X + (x1*16)
for y in range(16):
for x in range(16):
if sprite<79:
screen[y*MAXSCREEN_X + x+ offset] = textures[y*16 + x + (sprite<<8)]
@micropython.viper
def zoom(width:int): # utility only
game = ptr32(GAME)
screen=ptr16(LCD.buffer)
textures = ptr16(TEXTURES)
player = ptr32(PLAYER)
sprite = player[SPRITE_IND]
offset = 0
height = width
for y1 in range(height):
for x1 in range(width):
x = x1*16//width
y = y1*16//height
screen[y1*MAXSCREEN_X + x1+ offset] = textures[y*16 + x + (sprite<<8)]
@micropython.viper
def draw_field():
game = ptr32(GAME)
player = ptr32(PLAYER)
textures = ptr16(TEXTURES)
screen=ptr16(LCD.buffer)
field = ptr8(FIELD)
for f_y in range(FIELD_HEIGHT):
for f_x in range(FIELD_WIDTH):
sprite = field[f_y*FIELD_WIDTH+f_x]
if sprite < 99:
field_pos = f_y*(8*MAXSCREEN_X)+(f_x*8)
sprite_offset = (sprite<<8)+ (16*4)
for t_y in range(TEXTURE_HEIGHT//2):
for t_x in range(TEXTURE_WIDTH//2):
screen[t_y * MAXSCREEN_X + t_x + field_pos] = textures[t_y*16 + t_x + sprite_offset]
@micropython.viper
def draw_score(x:int,y:int,sprite:int,offset:int):
textures = ptr16(TEXTURES)
screen = ptr16(LCD.buffer)
for t_y in range(TEXTURE_HEIGHT//2):
for t_x in range(TEXTURE_WIDTH):
screen[(y+t_y)*MAXSCREEN_X + x + t_x] = textures[(4+t_y)*16 + t_x + offset + (sprite<<8)] # draw score
@micropython.viper
def draw():
game = ptr32(GAME)
player = ptr32(PLAYER)
textures = ptr16(TEXTURES)
screen=ptr16(LCD.buffer)
centi = ptr32(CENTI)
flea = ptr32(FLEA)
spider = ptr32(SPIDER)
p_x = player[X]>>SCALE
p_y = player[Y]>>SCALE
draw_field()
if player[FIRED]:
LCD.line(player[MISS_X],player[MISS_Y],player[MISS_X],player[MISS_Y]+5,0xffff) # draw missile
if not player[PLAYER_DEAD]:
sprite = 67
for t_y in range(TEXTURE_HEIGHT):
for t_x in range(TEXTURE_WIDTH):
color = textures[t_y*16 + t_x + (sprite<<8)]
if color:
screen[(p_y+t_y)*MAXSCREEN_X + p_x+t_x] = color # draw player
segments = game[C_SEGMENTS]
for index in range(segments):
i = index * CENTI_PARAMS
if centi[i + DIRECTION] == DEAD: continue
c_x = centi[i + X]
c_y = centi[i + Y]
sprite = centi[i + SPRITE_IND] + centi[i + SPRITE_START]
for t_y in range(TEXTURE_HEIGHT//2):
for t_x in range(TEXTURE_WIDTH//2):
screen[(c_y+t_y)*MAXSCREEN_X + c_x+t_x] = textures[(4+t_y)*16 + t_x + 4 + (sprite<<8)] # draw centi
if flea[Y] > 0:
f_x = flea[X]
f_y = flea[Y]
sprite = 30 + (f_y % 4)
for t_y in range(TEXTURE_HEIGHT//2):
for t_x in range(TEXTURE_WIDTH//2):
screen[(f_y+t_y)*MAXSCREEN_X + f_x+t_x] = textures[(4+t_y)*16 + t_x + 4 + (sprite<<8)] # draw flea
if flea[FLEA_SCORE] > 0:
draw_score(flea[X],flea[FLEA_SCORE_Y],36,2)
if spider[SPID_SCORE] > 0:
draw_score(spider[SPID_SCORE_X],spider[Y],34,2)
if 0 < spider[X] < 145:
s_x = spider[X]
s_y = spider[Y]
sprite = 24 + (s_y % 6)
for t_y in range(TEXTURE_HEIGHT//2):
for t_x in range(TEXTURE_WIDTH):
color = textures[(4+t_y)*16 + t_x + 0 + (sprite<<8)]
if color:
screen[(s_y+t_y)*MAXSCREEN_X + s_x+t_x] = textures[(4+t_y)*16 + t_x + 0 + (sprite<<8)] # draw spider
LCD.text('FPS:',0,0,0xff)
show_num_viper(game[FPS],40,0,0xff)
#show_num_viper(gc.mem_free(),40,17,0xff)
show_num_viper(game[SCORE],150,0,0xff)
LCD.text('LIVES:',55,0,0xff)
show_num_viper(game[LIVES],105,0,0xff)
if game[LIVES] == 0:
LCD.rect(50,45,75,15,0,True)
LCD.text('GAME OVER',50,50,0xffff)
LCD.show()
LCD.rect(0,0,MAXSCREEN_X,MAXSCREEN_Y,0,1)
@micropython.asm_thumb
def avg_fps_asm(r0,r1): # r0 = fps[] , r1 = current_fps
ldrb(r2,[r0,0]) # r2 = fps[0]
add(r2,r2,1) # fps[0] += 1
cmp(r2,33)
blt(LT_32) # if fps[0] > 32:
mov(r2,1)
label(LT_32)
strb(r2,[r0,0]) # fps[0] = new index
add(r2,r2,r0)
strb(r1,[r2,0]) # fps[fps[0]] = current_fps
mov(r2,1) # r2 = i
mov(r3,0) # r3 = tot
label(LOOP)
add(r0,r0,1)
ldrb(r4,[r0,0]) # r4 = fps[i]
add(r3,r3,r4) # tot += fps[i]
add(r2,r2,1)
cmp(r2,33) #33
blt(LOOP)
asr(r0,r3,5)
def game_over():
CENTI_SOUND.SOUND = 0
CENTI_SOUND.OFF = 1
@micropython.viper
def main():
init_pot()
init_game()
init_player()
init_field()
init_centi()
game = ptr32(GAME)
move_centi_ticks = 0
read_pot_ticks = 0
move_flea_ticks = 0
move_spider_ticks = 0
CENTI_SOUND.SOUND = 1
player = ptr32(PLAYER)
while not EXIT:
sleep(0.001) # for thonny stop
gticks = int(ticks_ms())
if RESET_PB(): shutdown()
if not player[PLAYER_DEAD]:
if gticks - read_pot_ticks > 20:
read_pot_ticks = gticks
read_pot()
move_miss()
if gticks - move_centi_ticks > 10:
move_centi_ticks = gticks
move_centi()
if gticks - move_flea_ticks > 10:
move_flea_ticks = gticks
move_flea()
if gticks - move_spider_ticks > 20: # 20
move_spider_ticks = gticks
move_spider()
else:
player[PLAYER_DEAD] -= 1
if game[LIVES] == 0 :
player[PLAYER_DEAD] = 1
game_over()
if player[PLAYER_DEAD] == 0:
reset_field()
init_centi()
explode()
draw()
game[FPS] = int(avg_fps_asm(FPS_ARRY,1_000//int(ticks_diff(ticks_ms(),gticks))))
def core1():
global CENTI_SOUND
CENTI_SOUND = Centi_Sound()
CENTI_SOUND.OFF = 0
def shutdown():
global EXIT
EXIT = True
Pin(16,Pin.OUT).low() # buzzer off
CENTI_SOUND.deinit()
Pin(13,Pin.OUT).low() # screen off
gc.collect()
print(gc.mem_free())
print('Core0 Stop')
exit()
if __name__=='__main__':
FIRE_BUTTON = Pin(22, Pin.IN, Pin.PULL_UP)
machine.freq(200_000_000)
machine.mem32[0x40008048] = 1<<11 # enable peri_ctrl clock
pwm = PWM(Pin(13))
pwm.freq(1000)
pwm.duty_u16(0x8fff)#max 0xffff
LCD = LCD_1inch8()
# LCD.fill(0)
# LCD.show()
EXIT = False
_thread.start_new_thread(core1, ())
sleep(0.5)
try:
main()
shutdown()
except KeyboardInterrupt :
shutdown()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment