Skip to content

Instantly share code, notes, and snippets.

@samneggs
Created April 16, 2023 02:30
Show Gist options
  • Select an option

  • Save samneggs/b712092662938ccf55e3ef2966b0a27e to your computer and use it in GitHub Desktop.

Select an option

Save samneggs/b712092662938ccf55e3ef2966b0a27e to your computer and use it in GitHub Desktop.
StarCastle game on Pi Pico in MicroPython
# Star Castle
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,atan2
MAXSCREEN_X = const(160)
MAXSCREEN_Y = const(128)
SCALE = const(13)
NUM_STARS = const(100)
NUM_MISSILES= const(20)
SKYBLUE = const(0b11111111_00111011)
YELLOW = const(255)
ORANGE = const(0xe0fb)
RED = const(248)
PLAYER_PARAMS = const(10)
X = const(0)
Y = const(1)
DEG = const(2)
VX = const(3)
VY = const(4)
AX = const(5)
AY = const(6)
M = const(7)
GAME_PARAMS = const(10)
FPS = const(0)
LIVES = const(1)
HIT_CANNON = const(2)
DEG_CANNON = const(3)
FIRE_CANNON = const(4)
SCORE = const(5)
SHIELD_PARAMS = const(10)
SHIELD_LIFE = const(3)
SHIELD_DIR = const(4)
SHIELD_RAD = const(5)
MISSILE_PARAMS = const(10)
MISS_LIFE = const(2)
STARS_PARAMS = const(10)
STAR_COLOR = const(2)
STAR_DIR = const(3)
EXPLODE_PARAMS = const(10)
EXP_LIFE = const(2)
EXP_COLOR = const(5)
MINE_SHIELD = const(5)
SHIP_POINTS = const(16)
SHIP_DEG = array.array('H',(0, 306, 180, 54, 0, 333, 349, 333, 189, 333, 0, 27, 11, 27, 171, 27) )
SHIP_RADIUS = array.array('H',(0, 17, 8, 17, 0, 4, 10, 9, 12, 4, 0, 4, 10, 9, 12, 4) )
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
def init_imath(): #integer math
global ISIN,ICOS
ISIN = array.array('i',())
ICOS = array.array('i',())
for i in range(0,360):
ISIN.append(int(sin(radians(i))*(1<<SCALE)))
ICOS.append(int(cos(radians(i))*(1<<SCALE)))
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
isin = ptr32(ISIN)
icos = ptr32(ICOS)
player = ptr32(PLAYER)
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 or y_inc > 0 :
y_inc=0
if not FIRE_BUTTON.value(): EXIT = True
player[DEG] -= x_inc
if player[DEG] >= 360: player[DEG] -= 360
if player[DEG] < 0 : player[DEG] += 360
deg = int(player[DEG])
x = (100*y_inc * int(icos[deg]))>>SCALE
y = (100*y_inc * int(isin[deg]))>>SCALE
player[VX] += x
player[VY] += y
def init_player():
global PLAYER , SHIP_COORDS, MISSILES, CANNON_COORDS
PLAYER = array.array('i',0 for _ in range(PLAYER_PARAMS))
SHIP_COORDS = array.array('i',0 for _ in range(50*2))
CANNON_COORDS = array.array('i',0 for _ in range(50*2))
MISSILES = array.array('i',0 for _ in range(MISSILE_PARAMS*NUM_MISSILES))
PLAYER[X] = 10<<SCALE
PLAYER[Y] = 10<<SCALE
PLAYER[DEG]= 220
PLAYER[VX] = 0<<SCALE
PLAYER[VY] = 0<<SCALE
PLAYER[AX] = 0
PLAYER[AY] = 0
PLAYER[M] = 0
@micropython.viper
def player_reset():
miss = ptr32(MISSILES)
player = ptr32(PLAYER)
player[X] = 10<<SCALE
player[Y] = 10<<SCALE
player[DEG]= 220
for index in range(NUM_MISSILES):
i = index * MISSILE_PARAMS
miss[i + MISS_LIFE] = 0
def init_game():
global GAME, SHIELD, STARS, COLORS, EXPLODE, FPS_ARRY, CANNON_MISL, MINES
GAME = array.array('i',0 for _ in range(GAME_PARAMS))
SHIELD = array.array('i',0 for _ in range(SHIELD_PARAMS*12*3))
STARS = array.array('i',0 for _ in range(STARS_PARAMS*NUM_STARS))
COLORS = array.array('H',(YELLOW,ORANGE,RED))
EXPLODE = array.array('i',0 for _ in range(EXPLODE_PARAMS*20))
CANNON_MISL = array.array('i',0 for _ in range(MISSILE_PARAMS))
MINES = array.array('i',0 for _ in range(MISSILE_PARAMS*3))
FPS_ARRY = bytearray(100)
GAME[FPS] = 0
GAME[LIVES] = 3
for index in range(NUM_STARS):
i = index * STARS_PARAMS
STARS[i + X] = randint(0,159)
STARS[i + Y] = randint(0,127)
STARS[i + STAR_COLOR] = randint(0,15)
if STARS[i + STAR_COLOR] > 7:
STARS[i + STAR_DIR] = -1
else:
STARS[i + STAR_DIR] = 1
def init_shields():
global SHIELD
for index in range(12*3):
i = index * SHIELD_PARAMS
deg = (index % 12) * 30
radius = 10 + (5 * (index//12))
SHIELD[i + X] = int(cos(radians(deg))*radius + MAXSCREEN_X//2)
SHIELD[i + Y] = int(sin(radians(deg))*radius + MAXSCREEN_Y//2)
SHIELD[i + DEG] = deg
SHIELD[i + SHIELD_LIFE] = 2
SHIELD[i + SHIELD_DIR] = 5
if index>11 and index<24:
SHIELD[i + SHIELD_DIR] = -5
SHIELD[i + SHIELD_RAD] = radius
@micropython.viper
def init_missile():
miss = ptr32(MISSILES)
player = ptr32(PLAYER)
isin = ptr32(ISIN)
icos = ptr32(ICOS)
game = ptr32(GAME)
if game[LIVES] < 1: return
x = player[X]
y = player[Y]
vx = player[VX]
vy = player[VY]
deg = player[DEG] + 180
if deg >= 360: deg -= 360
for index in range(NUM_MISSILES):
i = index * MISSILE_PARAMS
if miss[i + MISS_LIFE] == 0:
miss[i + MISS_LIFE] = 200
miss[i + X] = icos[deg]*10 + x
miss[i + Y] = isin[deg]*10 + y
abs_vx = (vx + icos[deg])>>1
abs_vy = (vy + isin[deg])>>1
abs_vx = abs_vx if abs_vx > 0 else abs_vx*-1
abs_vy = abs_vy if abs_vy > 0 else abs_vy*-1
if abs_vx < 5000 and abs_vy < 5000:
miss[i + VX] = (icos[deg])>>1
miss[i + VY] = (isin[deg])>>1
else:
miss[i + VX] = (vx + icos[deg])>>1
miss[i + VY] = (vy + isin[deg])>>1
return
@micropython.viper
def init_cannon():
miss = ptr32(CANNON_MISL)
game = ptr32(GAME)
isin = ptr32(ISIN)
icos = ptr32(ICOS)
if game[LIVES] == 0: return
x = 80 << SCALE
y = 64 << SCALE
deg = game[DEG_CANNON] + 180
if deg >= 360: deg -= 360
if miss[MISS_LIFE] == 0:
miss[MISS_LIFE] = 200
miss[X] = icos[deg]*10 + x
miss[Y] = isin[deg]*10 + y
miss[VX] = (icos[deg])>>1
miss[VY] = (isin[deg])>>1
@micropython.viper
def init_mine():
mine = ptr32(MINES)
mine[(0*MISSILE_PARAMS) + MINE_SHIELD] = 1
mine[(1*MISSILE_PARAMS) + MINE_SHIELD] = 4
mine[(2*MISSILE_PARAMS) + MINE_SHIELD] = 8
@micropython.viper
def move_mine():
shield = ptr32(SHIELD)
mine = ptr32(MINES)
isin = ptr32(ISIN)
icos = ptr32(ICOS)
player = ptr32(PLAYER)
game = ptr32(GAME)
for index in range(3):
i = index * MISSILE_PARAMS
shield_pos = mine[i + MINE_SHIELD]
shield_index = shield_pos * SHIELD_PARAMS
if shield_pos < 24 and shield[shield_index + DEG] == shield[(12*SHIELD_PARAMS+shield_index) + DEG] and int(randint(1,3))==3:
shield_pos += 12
mine[i + MINE_SHIELD] = shield_pos
if shield[(12*SHIELD_PARAMS+shield_index) + SHIELD_LIFE] == 0:
mine[i + MINE_SHIELD] == 36
if shield_pos < 36:
shield_index = shield_pos * MISSILE_PARAMS
mine[i + X] = shield[shield_index + X] << SCALE
mine[i + Y] = shield[shield_index + Y] << SCALE
if shield_pos > 23 and shield_pos < 36 and int(randint(1,20))==20:
mine[i + MINE_SHIELD] = 36
deg = shield[shield_index + DEG]
mine[i + VX] = (icos[deg])>>1
mine[i + VY] = (isin[deg])>>1
mine[i + MISS_LIFE] = 20000
if mine[i + MINE_SHIELD] == 36 and mine[i + MISS_LIFE] > 0 :
mine[i + MISS_LIFE] -= 1
mine[i + X] += mine[i + VX]
mine[i + Y] += mine[i + VY]
if mine[i + X] < player[X] : mine[i + VX] += 200
if mine[i + X] > player[X] : mine[i + VX] -= 200
if mine[i + Y] < player[Y] : mine[i + VY] += 200
if mine[i + Y] > player[Y] : mine[i + VY] -= 200
if mine[i + X] < 0 or mine[i + X] > MAXSCREEN_X<<SCALE or mine[i + Y] < 0 or mine[i + Y] > MAXSCREEN_Y<<SCALE:
mine[i + MINE_SHIELD] = 1
if mine[i + X] > player[X] - 20000 and mine[i + X] < player[X] + 20000 and mine[i + Y] > player[Y]-20000 and mine[i + Y] < player[Y]+20000:
init_explode(player[X],player[Y],30,10000)
game[LIVES] -= 1
player_reset()
init_mine()
@micropython.viper
def move_missile():
miss = ptr32(MISSILES)
isin = ptr32(ISIN)
icos = ptr32(ICOS)
shield = ptr32(SHIELD)
game = ptr32(GAME)
mine = ptr32(MINES)
for index in range(NUM_MISSILES): # calc missile positions
i = index * MISSILE_PARAMS
if miss[i + MISS_LIFE] > 0:
miss[i + MISS_LIFE] -= 1
x = miss[i + X]
y = miss[i + Y]
x += miss[i + VX]
y += miss[i + VY]
if x < 0 or y < 0 or x > MAXSCREEN_X<<SCALE or y > MAXSCREEN_Y<<SCALE:
miss[i + MISS_LIFE] = 0
continue
miss[i + X] = x
miss[i + Y] = y
x >>= SCALE
y >>= SCALE
if x > 77 and x < 83 and y > 62 and y < 68: # hit cannon
miss[i + MISS_LIFE] = 0
init_explode(miss[i + X],miss[i + Y],100,10000)
game[HIT_CANNON] = 80
player_reset()
game[SCORE] += 1440
game[LIVES] += 1
break
for index2 in range(12*3): # missile to shield collision
i2 = index2 * SHIELD_PARAMS
if shield[i2 + SHIELD_LIFE] > 0:
s_x1 = shield[i2 + X]
s_y1 = shield[i2 + Y]
if index2 == 11 or index2 == 23 or index2 == 35:
s_x2 = shield[(index2-11) * SHIELD_PARAMS + X ]
s_y2 = shield[(index2-11) * SHIELD_PARAMS + Y ]
else:
s_x2 = shield[i2 + X + SHIELD_PARAMS]
s_y2 = shield[i2 + Y + SHIELD_PARAMS]
if s_x1 > s_x2: s_x1,s_x2 = s_x2,s_x1
if s_y1 > s_y2: s_y1,s_y2 = s_y2,s_y1
if x > s_x1-1 and x < s_x2+1 and y > s_y1-1 and y < s_y2+1: # hit shield
shield[i2 + SHIELD_LIFE] -= 1
miss[i + MISS_LIFE] = 0
if shield[i2 + SHIELD_LIFE] == 0:
init_explode(miss[i + X],miss[i + Y],20,5000) # 10, 10000
score(index2)
break
for index3 in range(3):
i = index3 * MISSILE_PARAMS
mine_x = mine[i + X] >> SCALE
mine_y = mine[i + Y] >> SCALE
if x > mine_x-3 and x < mine_x+3 and y > mine_y-3 and y < mine_y+3: # hit mine
mine[i + MINE_SHIELD] = 1
init_explode(mine[i + X],mine[i + Y],20,5000)
@micropython.viper
def score(shield:int):
game = ptr32(GAME)
if shield > 23:
game[SCORE] += 10
elif shield < 12:
game[SCORE] += 30
else:
game[SCORE] += 20
@micropython.viper
def move_cannon_misl():
miss = ptr32(CANNON_MISL)
game = ptr32(GAME)
player = ptr32(PLAYER)
player_x = player[X]>>SCALE
player_y = player[Y]>>SCALE
if miss[MISS_LIFE] > 0:
miss[MISS_LIFE] -= 1
x = miss[X]
y = miss[Y]
x += miss[VX]
y += miss[VY]
if x < 0 or y < 0 or x > MAXSCREEN_X<<SCALE or y > MAXSCREEN_Y<<SCALE:
miss[MISS_LIFE] = 0
return
miss[X] = x
miss[Y] = y
x >>= SCALE
y >>= SCALE
if x > player_x-4 and x < player_x+4 and y > player_y-4 and y < player_y+4: # hit player
miss[MISS_LIFE] = 0
init_explode(miss[X],miss[Y],30,10000)
game[LIVES] -= 1
player_reset()
@micropython.viper
def move_cannon():
game = ptr32(GAME)
player = ptr32(PLAYER)
x = (player[X]>>SCALE) - 80
y = (player[Y]>>SCALE) - 64
start = int(my_atan2(x,y))
end = game[DEG_CANNON]
raw_diff = int(abs(start - end))
mod_diff = raw_diff % 360
if mod_diff > 180:
dist = 360 - mod_diff
if start < end:
dist = dist * -1
else:
dist = mod_diff
if start > end:
dist = dist * -1
if dist>0:
game[DEG_CANNON] -= 1
else:
game[DEG_CANNON] += 1
if game[DEG_CANNON] > 359: game[DEG_CANNON] -= 360
if game[DEG_CANNON] < 0 : game[DEG_CANNON] += 360
def my_atan2(x,y):
return int(atan2(y,x) * 180 / 3.1415926) + 180
@micropython.viper
def move():
player = ptr32(PLAYER)
deg = ptr16(SHIP_DEG)
radius = ptr16(SHIP_RADIUS)
coords = ptr32(SHIP_COORDS)
cannon = ptr32(CANNON_COORDS)
isin = ptr32(ISIN)
icos = ptr32(ICOS)
shield = ptr32(SHIELD)
stars = ptr32(STARS)
game = ptr32(GAME)
size = 1
player[X] += player[VX]
player[Y] += player[VY]
player[VX] -= player[VX]>>5 # auto slow to stop
player[VY] -= player[VY]>>5
if player[X] < 0: player[X] = MAXSCREEN_X<<SCALE
if player[Y] < 0: player[Y] = MAXSCREEN_Y<<SCALE
if player[X] > MAXSCREEN_X<<SCALE : player[X] = 0
if player[Y] > MAXSCREEN_Y<<SCALE : player[Y] = 0
x = player[X]
y = player[Y]
for index in range(SHIP_POINTS): # calc ship points
i = index * 2
pt_deg = deg[index] + player[DEG]
if pt_deg >= 360: pt_deg -= 360
if pt_deg < 0 : pt_deg += 360
coords[i] = ((radius[index] * size * icos[pt_deg])>>14)
coords[i+1] = ((radius[index] * size * isin[pt_deg])>>14)
for index in range(SHIP_POINTS): # calc cannon points
i = index * 2
pt_deg = deg[index] + game[DEG_CANNON]
if pt_deg >= 360: pt_deg -= 360
if pt_deg < 0 : pt_deg += 360
cannon[i] = ((radius[index] * size * icos[pt_deg])>>14)
cannon[i+1] = ((radius[index] * size * isin[pt_deg])>>14)
for index in range(12*3): # calc shield points
i = index * SHIELD_PARAMS
shield_rad = shield[i + SHIELD_RAD]
shield_deg = shield[i + DEG] + shield[i + SHIELD_DIR]
if shield_deg < 0: shield_deg += 360
if shield_deg >= 360: shield_deg -= 360
shield[i + DEG] = shield_deg
shield[i + X] = ((icos[shield_deg]*shield_rad)>>SCALE) + MAXSCREEN_X//2
shield[i + Y] = ((isin[shield_deg]*shield_rad)>>SCALE) + MAXSCREEN_Y//2
x >>= SCALE
y >>= SCALE
for index in range(12*3): # ship/shield collision
i = index * SHIELD_PARAMS
if shield[i + SHIELD_LIFE] > 0:
s_x1 = shield[i + X]
s_y1 = shield[i + Y]
if index == 11 or index == 23 or index == 35:
s_x2 = shield[(index-11) * SHIELD_PARAMS + X ]
s_y2 = shield[(index-11) * SHIELD_PARAMS + Y ]
else:
s_x2 = shield[i + X + SHIELD_PARAMS]
s_y2 = shield[i + Y + SHIELD_PARAMS]
if s_x1 > s_x2: s_x1,s_x2 = s_x2,s_x1
if s_y1 > s_y2: s_y1,s_y2 = s_y2,s_y1
if x > s_x1 and x < s_x2 and y > s_y1 and y < s_y2: # hit
player_deg = player[DEG] + 180
if player_deg >= 360: player_deg -= 360
if player_deg < 0 : player_deg += 360
player[DEG] = player_deg
player[VX] *= -1
player[VY] *= -1
player[X] += player[VX]<<3
player[Y] += player[VY]<<3
@micropython.viper
def check_cannon():
shield = ptr32(SHIELD)
game = ptr32(GAME)
cannon_deg = game[DEG_CANNON]
first = 0
second = 0
third = 0
for index in range(0,36): # 0-12, 13-24, 25-36
i = index * SHIELD_PARAMS
deg = (index % 12) * 30
shield_deg = shield[i + DEG] + 180
if shield_deg > 359: shield_deg -= 360
shield_life = shield[i + SHIELD_LIFE]
if shield_life > 0 or shield_deg > cannon_deg + 15 or shield_deg < cannon_deg - 15: continue
if index < 12:
first = 1
elif index > 24:
third = 1
else:
second = 1
if first+second+third == 3:
game[FIRE_CANNON] = 1
init_cannon()
@micropython.viper
def twinkle_stars():
stars = ptr32(STARS)
for index in range(NUM_STARS):
i = index * STARS_PARAMS
dim = int(stars[i + STAR_COLOR])
dim += stars[i + STAR_DIR]
if dim > 14 or dim < 1:
stars[i + STAR_DIR] *= -1
else:
stars[i + STAR_COLOR] = dim
@micropython.viper
def init_explode(x:int,y:int,life:int,speed:int):
exp = ptr32(EXPLODE)
exp[X] = x
exp[Y] = y
for index in range(1,20):
i = index * EXPLODE_PARAMS
exp[i + X] = x
exp[i + Y] = y
exp[i + VX] = int(randint(-1*speed,speed))
exp[i + VY] = int(randint(-1*speed,speed))
exp[i + EXP_LIFE] = life
exp[i + EXP_COLOR] = 0
@micropython.viper
def explode():
exp = ptr32(EXPLODE)
game = ptr32(GAME)
if game[HIT_CANNON] > 0:
game[HIT_CANNON] -= 1
if game[HIT_CANNON] == 0:
init_shields()
init_mine()
for index in range(1,20):
i = index * EXPLODE_PARAMS
if exp[i + EXP_LIFE] > 0:
exp[i + X] += exp[i + VX]
exp[i + Y] += exp[i + VY]
exp[i + EXP_LIFE] -= 1
@micropython.viper
def draw():
game = ptr32(GAME)
player = ptr32(PLAYER)
coords = ptr32(SHIP_COORDS)
can_miss = ptr32(CANNON_MISL)
stars = ptr32(STARS)
shield = ptr32(SHIELD)
colors = ptr16(COLORS)
miss = ptr32(MISSILES)
exp = ptr32(EXPLODE)
mine = ptr32(MINES)
for index in range(NUM_STARS): # draw stars
i = index * STARS_PARAMS
LCD.pixel(stars[i+X],stars[i+Y],stars[i + STAR_COLOR]<<8)
if game[HIT_CANNON] == 0:
for index in range(12*3): # draw shield
i = index * SHIELD_PARAMS
if shield[i + SHIELD_LIFE] > 0:
x1 = shield[i + X]
y1 = shield[i + Y]
if index == 11 or index == 23 or index == 35:
x2 = shield[(index-11) * SHIELD_PARAMS + X ]
y2 = shield[(index-11) * SHIELD_PARAMS + Y ]
else:
x2 = shield[i + X + SHIELD_PARAMS]
y2 = shield[i + Y + SHIELD_PARAMS]
LCD.line(x1,y1,x2,y2,colors[index//12])
for index in range(NUM_MISSILES): # draw missiles
i = index * MISSILE_PARAMS
if miss[i + MISS_LIFE] > 0:
LCD.pixel(miss[i + X]>>SCALE, miss[i + Y]>>SCALE, 0xffff)
if can_miss[MISS_LIFE] > 0:
cannon_misl_x = can_miss[X]>>SCALE
cannon_misl_y = can_miss[Y]>>SCALE
LCD.pixel(cannon_misl_x,cannon_misl_y, 0xffff) # draw cannon missile
color = colors[int(randint(0,2))]
for i in range(10):
x = int(randint(-8,8))
y = int(randint(-8,8))
LCD.line(cannon_misl_x,cannon_misl_y, cannon_misl_x+x,cannon_misl_y+y,color)
e_x = exp[X]
e_y = exp[Y]
for index in range(1,20): # draw explosion
i = index * EXPLODE_PARAMS
if exp[i + EXP_LIFE] > 0:
LCD.line(e_x>>SCALE,e_y>>SCALE,exp[i + X]>>SCALE,exp[i + Y]>>SCALE,colors[(exp[i + EXP_LIFE]//12) % 3])
for index in range(3):
i = index * MISSILE_PARAMS # draw mines
mine_x = mine[i + X] >> SCALE
mine_y = mine[i + Y] >> SCALE
for i in range(10):
x = int(randint(-3,3))
y = int(randint(-3,3))
LCD.line(mine_x,mine_y, mine_x+x,mine_y+y,0xffff)
LCD.text('FPS',0,0,0xff)
show_num_viper(game[FPS],10,10,0xff)
LCD.text('SCORE',60,0,0xff)
show_num_viper(game[SCORE],90,10,0xff)
LCD.text('LIVES',115,0,0xff)
show_num_viper(game[LIVES],125,10,0xff)
if game[FIRE_CANNON] == 1 and 0:
LCD.text('OPEN',60,10,0xff)
if game[LIVES] == 0:
LCD.text('GAME OVER',42,30,0xff)
x = player[X] >> SCALE
y = player[Y] >> SCALE
if game[LIVES] > 0:
LCD.poly(x,y,SHIP_COORDS,SKYBLUE) # draw ship
if game[HIT_CANNON] == 0:
LCD.poly(80,64,CANNON_COORDS,0xffff) # draw cannon
LCD.show()
LCD.rect(0,0,MAXSCREEN_X,MAXSCREEN_Y,0,1) # clear screen
@micropython.viper
def main():
init_imath()
init_pot()
init_game()
init_shields()
init_player()
init_mine()
game = ptr32(GAME)
gticks = int(ticks_ms())
pot_ticks = gticks
move_ticks = gticks
init_miss_ticks = gticks
move_miss_ticks = gticks
twinkle_ticks = gticks
explode_ticks = gticks
while not EXIT:
gticks = int(ticks_ms())
if gticks-pot_ticks>30:
pot_ticks = int(ticks_ms())
read_pot()
if gticks-move_ticks>40:
move_ticks = int(ticks_ms())
move()
move_mine()
check_cannon()
if gticks-init_miss_ticks>300:
init_miss_ticks = int(ticks_ms())
init_missile()
if gticks-twinkle_ticks>100:
twinkle_ticks = int(ticks_ms())
twinkle_stars()
if gticks-explode_ticks>10:
explode_ticks = int(ticks_ms())
explode()
move_cannon()
move_missile()
move_cannon_misl()
draw()
avg_fps(1_000//int(ticks_diff(ticks_ms(),gticks)))
@micropython.viper
def avg_fps(current_fps:int):
game = ptr32(GAME)
fps = ptr8(FPS_ARRY)
fps[0] += 1
fps[fps[0]] = current_fps
if fps[0] > 32:
fps[0] = 0
tot = 0
for i in range(2,34):
tot += fps[i]
game[FPS] = tot >> 5 # 16 samples
def shutdown():
global EXIT
EXIT = True
Pin(16,Pin.OUT).low() # buzzer off
pwm.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, ())
try:
main()
shutdown()
except KeyboardInterrupt :
shutdown()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment