Created
March 5, 2022 05:04
-
-
Save samneggs/5c808a5d1529c17a272fc230220f1648 to your computer and use it in GitHub Desktop.
Asteroids game using PI Pico and WaveShare LCD 1.14 v2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from LCD_1inch14 import LCD_1inch14 | |
| #from LCD7789 import LCD_st7789 | |
| from machine import Timer, reset, WDT,PWM,Pin | |
| from math import sin,cos,radians | |
| from random import randint | |
| from sys import exit | |
| import _thread, array | |
| import gc | |
| from micropython import const | |
| from time import sleep_ms, sleep_us, ticks_diff, ticks_us, sleep | |
| class Point(): | |
| def __init__(self): | |
| self.x = 0 | |
| self.y = 0 | |
| self.ax = 0 | |
| self.ay = 0 | |
| self.c = 0 | |
| self.exp = 0 | |
| self.deg = 0 | |
| self.active = 0 | |
| class Obj_point(): | |
| def __init__(self): | |
| self.x = 0 | |
| self.y = 0 | |
| class Ship(): | |
| def __init__(self,ptdeg,ptrad,pts,tumble,x,y,size): | |
| self.x = x # 230000 | |
| self.y = y # 125000 | |
| self.ax = 0 #randint(-40,40)*10 #10 # accel x | |
| self.ay = 0 #randint(-40,40)*10 # accel y | |
| self.deg = 0 # degrees obj is pointing | |
| self.size = size # size of obj | |
| self.coll = self.size*5 # collision h and w | |
| self.exp = 0 # explode progression | |
| self.damage = True # ship can take damage | |
| self.pt = [] # active points | |
| self.ptrad = ptrad # radius - points | |
| self.ptdeg = ptdeg # degrees - points | |
| self.pts = pts # number of points | |
| self.tumble = tumble # degress added for tumbling | |
| self.active = True # show on screen, move... | |
| self.back_color = LCD.black | |
| self.color = LCD.white #0x008A | |
| class Score(): | |
| def __init__(self): | |
| self.value = 0 | |
| self.digits = ['0','1','2','3','4','5','6','7','8','9'] | |
| self.places = 0 | |
| self.lives = 3 | |
| self.show = False | |
| MAXSCREEN_X = const(240) | |
| MAXSCREEN_Y = const(135) | |
| SCALE = const(1000) | |
| BL = const(13) | |
| LCD = LCD_1inch14() | |
| #LCD = LCD_st7789() | |
| score = Score() | |
| r= [-3,-2,-1,1,2,3] # tumble, removed zero | |
| m = [] # missile point list | |
| p = [] # point list | |
| a = [] # asteroid point list | |
| e = [] # explode point list | |
| h = [] | |
| asteroid = [] # big asteroids | |
| t=[] # title letters | |
| let_rad= [] # intro letters radii | |
| let_deg= [] # intro letters degrees | |
| score_list = [] # score numbers | |
| score_rad= [] # score numbers radii | |
| score_deg= [] # score numbers degrees | |
| over_list = [] # game over | |
| let_deg.append([54,270,126,90,54]) # A | |
| let_rad.append([17,18,17,4,17]) | |
| let_deg.append([306,270,234,54,90,126]) # S | |
| let_rad.append([17,18,17,17,18,17]) | |
| let_deg.append( [234, 306, 270, 90] ) # T | |
| let_rad.append( [17, 17, 12, 14] ) | |
| let_deg.append( [306, 234, 0, 126, 54] ) # E | |
| let_rad.append( [17, 17, 0, 17, 17] ) | |
| let_deg.append( [0, 306, 270, 234, 126, 191, 0, 60] ) # R | |
| let_rad.append( [0, 17, 16, 17, 17, 10, 0, 16] ) | |
| let_deg.append( [306, 270, 234, 126, 90, 54, 306] ) # O | |
| let_rad.append( [17, 16, 17, 17, 16, 17, 17] ) | |
| let_deg.append( [306, 270, 234, 270, 90, 54, 90, 126] ) # I | |
| let_rad.append( [17, 16, 17, 14, 14, 17, 16, 17] ) | |
| let_deg.append( [234, 270, 0, 90, 126, 234] ) # D | |
| let_rad.append( [17, 14, 10, 14, 17, 17] ) | |
| let_deg.append([306,270,234,54,90,126]) # S | |
| let_rad.append([17,18,17,17,18,17]) | |
| let_deg.append( [126, 234, 0, 306, 54] ) # M | |
| let_rad.append( [17, 17, 0, 17, 17] ) | |
| let_deg.append( [234, 90, 306] ) # V | |
| let_rad.append( [17, 18, 17] ) | |
| score_deg.append( [306, 270, 234, 126, 90, 54, 306] ) # 0 | |
| score_rad.append( [17, 18, 17, 17, 18, 17, 17] ) | |
| score_deg.append( [90, 270, 234] ) # 1 | |
| score_rad.append( [18, 18, 17] ) | |
| score_deg.append( [234, 270, 306, 126, 90, 54] ) # 2 | |
| score_rad.append( [17, 18, 17, 17, 18, 17] ) | |
| score_deg.append( [234, 270, 306, 0, 54, 90, 126] ) # 3 | |
| score_rad.append( [17, 18, 17, 0, 17, 18, 17] ) | |
| score_deg.append( [90, 270, 180, 0] ) # 4 | |
| score_rad.append( [18, 18, 18, 0] ) | |
| score_deg.append( [306, 270, 234, 180, 0, 54, 90, 126] ) # 5 | |
| score_rad.append( [17, 18, 17, 10, 10, 17, 18, 17] ) | |
| score_deg.append( [306, 270, 234, 126, 90, 54, 0, 180] ) #6 | |
| score_rad.append( [17, 18, 17, 17, 18, 17, 0, 10] ) | |
| score_deg.append( [234, 270, 306, 90] ) #7 | |
| score_rad.append( [17, 18, 17, 18] ) | |
| score_deg.append( [270, 306, 126, 90, 54, 234, 270] ) #8 | |
| score_rad.append( [18, 17, 17, 18, 17, 17, 18] ) | |
| score_deg.append( [306, 0, 234, 270, 306, 90] ) #9 | |
| score_rad.append( [17, 0, 17, 18, 17, 18] ) | |
| scoring = [0,100,50,20,200,1000] # points | |
| token = 1 # 1 is show | |
| gticks = 0 | |
| rfire = 0 | |
| threaded = False | |
| demo = 0 # 1 = demo mode | |
| num_asteroids=1 # number of asteroids to start | |
| active_asteroids = num_asteroids | |
| asteroid_count = num_asteroids | |
| explode_clean_token = False | |
| isin=array.array('i',range(0,361)) | |
| icos=array.array('i',range(0,361)) | |
| white_shades=array.array('i',range(0,32)) | |
| red_shades=array.array('i',range(0,32)) | |
| green_shades=array.array('i',range(0,32)) | |
| yellow_shades=array.array('i',range(0,32)) | |
| 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 screen_fps(n:int,p:int): | |
| dest=ptr16(LCD.buffer) | |
| c_map=ptr8(char_map) | |
| huns = n//100 | |
| tens = n%100//10 #int((0xcc_cccd*n)>>27) # n//10 | |
| ones = n%10 #n-(tens*10) # n%10 | |
| row = 8 | |
| offset=p*8+50 | |
| while(row): | |
| row-=1 | |
| col=8 | |
| while(col): | |
| col-=1 | |
| r=(row*MAXSCREEN_X+col)+offset | |
| if huns>0 and c_map[(huns<<3)+row] & 1<<col: | |
| dest[r] = 0xffff | |
| if c_map[(tens<<3)+row] & 1<<col: | |
| dest[r+8] = 0xffff | |
| if c_map[(ones<<3)+row] & 1<<col: | |
| dest[r+16] = 0xffff | |
| def init_shades(): | |
| for i in range(0,32): | |
| c=i<<11|i<<6|i # red shifted 11 bits, green shifted 6, blue | |
| white_shades[i]=c>>8|c<<8 # swap low and high bytes | |
| c=i<<11 # red shifted 11 bits, green shifted 6, blue | |
| red_shades[i]=c>>8|c<<8 # swap low and high bytes | |
| c=i<<6 # red shifted 11 bits, green shifted 6, blue | |
| green_shades[i]=c>>8|c<<8 # swap low and high bytes | |
| c=(i)<<11 |(i)<<6 # red all on, green on, blue ramped | |
| yellow_shades[i]=c>>8|c<<8 # swap low and high bytes | |
| # LCD.fill_rect(i*7,0,7,100,red_shades[i]) | |
| # LCD.show() | |
| def perimeter(obj,xmax,ymax): #return x,y on the perimeter of x,y | |
| x=randint(0,xmax) | |
| y=randint(0,ymax) | |
| p=randint(0,xmax*2+ymax*2) | |
| if p<ymax: | |
| x=0 | |
| elif p>xmax*2+ymax: | |
| x=xmax | |
| elif p<xmax+ymax: | |
| y=0 | |
| else: | |
| y=ymax | |
| obj.x = x | |
| obj.y = y | |
| def timed_function(f, *args, **kwargs): # for timing defs | |
| myname = str(f).split(' ')[1] | |
| def new_func(*args, **kwargs): | |
| t = utime.ticks_us() | |
| result = f(*args, **kwargs) | |
| delta = utime.ticks_diff(utime.ticks_us(), t) | |
| print('Function {} Time = {:6.3f}ms'.format(myname, delta/1000)) | |
| return result | |
| return new_func | |
| def init_isin(): # integer sin lookup table | |
| for i in range(0,361): | |
| isin[i]=int(sin(radians(i))*10000) | |
| def init_icos(): # integer cos lookup table | |
| for i in range(0,361): | |
| icos[i]=int(cos(radians(i))*10000) | |
| def init_title(): | |
| for i in range(0,9): | |
| t.append(init_obj(let_deg[i],let_rad[i],len(let_deg[i]*2),0,0,0,1000)) | |
| t[i].ax=0 | |
| t[i].ay=0 | |
| t[i].size = 0 | |
| t[i].back_color = LCD.red | |
| def init_game_over(): | |
| over_list.append(init_obj(score_deg[6],score_rad[6],len(score_deg[6]*2),0,0,0,0)) # G | |
| over_list.append(init_obj(let_deg[0],let_rad[0],len(let_deg[0]*2),0,0,0,0)) # A | |
| over_list.append(init_obj(let_deg[9],let_rad[9],len(let_deg[9]*2),0,0,0,0)) # M | |
| over_list.append(init_obj(let_deg[3],let_rad[3],len(let_deg[3]*2),0,0,0,0)) # E | |
| over_list.append(init_obj(let_deg[5],let_rad[5],len(let_deg[5]*2),0,0,0,0)) # O | |
| over_list.append(init_obj(let_deg[10],let_rad[10],len(let_deg[10]*2),0,0,0,0)) # V | |
| over_list.append(init_obj(let_deg[3],let_rad[3],len(let_deg[3]*2),0,0,0,0)) # E | |
| over_list.append(init_obj(let_deg[4],let_rad[4],len(let_deg[4]*2),0,0,0,0)) # R | |
| def show_title(objs): | |
| start=100000 | |
| y=10000 | |
| c=0 | |
| while (keyA.value() != 0): | |
| star_field(y) | |
| explode() | |
| start-=1000 | |
| if c<31: | |
| c+=1 | |
| j=0 | |
| for i in objs: | |
| if j == 9: | |
| break | |
| if i.size<800: | |
| y+=70 | |
| i.size+=10 | |
| i.x=start+(j*i.size*32) | |
| i.y=10000+i.size*60 | |
| i.back_color=red_shades[i.size//26] | |
| else: | |
| i.tumble = 0 | |
| #LCD.fill(LCD.black) | |
| #return # **remove** | |
| draw_object2(i,False) | |
| j+=1 | |
| LCD.show() | |
| for i in objs: | |
| init_explode(i,50,1) | |
| while i.exp<10: | |
| explode() | |
| LCD.show() | |
| i.exp+=1 | |
| explode_cleanup() | |
| i.size=0 | |
| draw_object2(i,False) | |
| LCD.fill(LCD.black) | |
| def init_big_score(): | |
| for i in range(0,10): | |
| score_list.append(init_obj(score_deg[i],score_rad[i],len(score_deg[i]*2),0,0,8000,1000)) | |
| score_list[i].y=70000 | |
| score_list[i].ax=0 | |
| score_list[i].ay=0 | |
| score_list[i].back_color = LCD.white | |
| score_list[i].color = LCD.white | |
| def show_small_score(): # small fast score using text | |
| LCD.fill_rect(110-score.places,0,score.places,14,LCD.black) | |
| xpos= 100 | |
| num = score.value | |
| score.places = 0 | |
| while num>0: | |
| LCD.text(score.digits[num % 10], xpos, 5, LCD.green) | |
| num //= 10 | |
| xpos -= 9 | |
| score.places += 10 | |
| def show_big_score(): # large custom score | |
| # a_lock.acquire() | |
| LCD.fill(LCD.black) | |
| LCD.show() | |
| score.show = True | |
| num = score.value | |
| places = 0 | |
| while num>0: | |
| digit = num % 10 | |
| score_list[digit].x = 200_000 - places | |
| draw_object2(score_list[digit],False) | |
| num //= 10 | |
| places += 30000 | |
| LCD.show() | |
| if score.lives == 0: | |
| game_over() | |
| score.show = False | |
| return | |
| over_list[1].size = 1000 | |
| over_list[1].y = 30000 | |
| over_list[1].back_color = LCD.black | |
| over_list[1].x = 120000 - score.lives*20000//2 | |
| for i in range(0,score.lives): | |
| over_list[1].x += 20000 | |
| draw_object2(over_list[1],False) | |
| over_list[1].back_color = LCD.white | |
| LCD.show() | |
| for j in range(0,100000): | |
| pass | |
| for i in range(0,200_000): | |
| pass | |
| LCD.fill(LCD.black) | |
| score.show = False | |
| # a_lock.release() | |
| def game_over(): | |
| global num_asteroids,active_asteroids,asteroid_count | |
| for i in over_list: | |
| i.size = 0 | |
| show_title(over_list) | |
| more_asteroids() | |
| score.value = 0 | |
| score.lives = 3 | |
| num_asteroids=1 # number of asteroids to start | |
| active_asteroids = num_asteroids | |
| asteroid_count = num_asteroids | |
| for i in asteroid: | |
| i.active = False | |
| def init_obj(ptdeg,ptrad,pts,tumble,x,y,size): # create 2 for every point | |
| obj = Ship(ptdeg,ptrad,pts,tumble,x,y,size) | |
| for i in range(0,obj.pts): | |
| obj.pt.append(Obj_point()) #Point()) | |
| return obj | |
| def init_asteroids(): # create asteroids list one time | |
| global num_asteroids | |
| for j in range(0,30): #num_asteroids): 40 | |
| asteroid.append(init_obj([0,60,120,180,240,300,0],[7]+[randint(6,9) for _ in range(5)]+[7],14,r[randint(0,5)],0,0,3001)) | |
| perimeter(asteroid[j],MAXSCREEN_X*SCALE,MAXSCREEN_Y*SCALE) | |
| asteroid[j].ax = randint(-40,40)*10 | |
| asteroid[j].ay = randint(-40,40)*10 | |
| if j>=num_asteroids: | |
| asteroid[j].active = False | |
| def more_asteroids(): # reactivate asteroids | |
| global num_asteroids, asteroid_count | |
| for i in range(0,num_asteroids): #num_asteroids): | |
| asteroid[i].active = True | |
| perimeter(asteroid[i],MAXSCREEN_X*SCALE,MAXSCREEN_Y*SCALE) | |
| asteroid[i].size = 3001 | |
| asteroid[i].coll = asteroid[i].size*5 | |
| asteroid[i].tumble = r[randint(0,5)] | |
| asteroid[i].exp = 0 | |
| asteroid[i].ax = randint(-40,40)*20 | |
| asteroid[i].ay = randint(-40,40)*20 | |
| asteroid_count=num_asteroids | |
| def new_ship(): | |
| ship.exp = 0 | |
| ship.x = 120000 # randint(10000,230000) | |
| ship.y = 65000 # randint(10000,125000) | |
| ship.ax = 0 | |
| ship.ay = 0 | |
| ship.size = 3000 | |
| ship.damage=False | |
| tim.init(mode=Timer.ONE_SHOT, period=2000, callback=no_damage) | |
| def init_missiles(): | |
| for i in range(0,10): | |
| m.append(Point()) | |
| def init_explosion(): # create list one time | |
| for i in range(0,90): | |
| e.append(Point()) | |
| for i in range(0,50): | |
| h.append(Point()) | |
| def line(x1,y1,x2,y2,color): | |
| LCD.line(x1//1000,y1//1000,x2//1000,y2//1000,color) | |
| def pixel(x,y,color): | |
| LCD.pixel(int(x//1000),int(y//1000),color) | |
| def draw_object2(obj,explode): | |
| # global token | |
| # token = 0 | |
| for i in range(0,obj.pts-2,2): | |
| line(obj.pt[i].x,obj.pt[i].y,obj.pt[i+1].x,obj.pt[i+1].y,obj.back_color) # erase old obj | |
| if (obj.exp > -1 and obj.tumble==0) or (obj.size>0 and obj.tumble!=0) or score.show: # ship not exploding or asteroid alive | |
| move_object2(obj,explode) | |
| c = obj.color | |
| if ship.damage==False and obj.color==LCD.green: | |
| c=LCD.red | |
| if obj.exp>30: | |
| c=white_shades[60-obj.exp] | |
| for i in range(0,obj.pts-2,2): | |
| line(obj.pt[i].x,obj.pt[i].y,obj.pt[i+1].x,obj.pt[i+1].y,c) # draw new obj | |
| #@timed_function | |
| def slow_ship(): | |
| if ship.ax > 0: # slow ship down automatically | |
| ship.ax=ship.ax - 5 | |
| if ship.ay > 0: | |
| ship.ay=ship.ay - 5 | |
| if ship.ax < 0: | |
| ship.ax=ship.ax + 5 | |
| if ship.ay < 0: | |
| ship.ay=ship.ay + 5 | |
| if ship.ax < 5 and ship.ax > -5: # if very slow then stop | |
| ship.ax = 0 | |
| if ship.ay < 5 and ship.ay > -5: | |
| ship.ay = 0 | |
| #@timed_function | |
| def move_object2(obj,explode): | |
| global asteroid_count | |
| if not obj.active: | |
| return | |
| if obj.tumble!=0: | |
| obj.x+=obj.ax*asteroid_count//2 # add accel to x,y + compensation for asteroids | |
| obj.y+=obj.ay*asteroid_count//2 | |
| else: | |
| obj.x+=obj.ax # add accel to x,y | |
| obj.y+=obj.ay | |
| if obj.x > MAXSCREEN_X*SCALE: # wrap around if out of bounds | |
| obj.x = 0 | |
| if obj.x < 0: | |
| obj.x = MAXSCREEN_X*SCALE | |
| if obj.y > MAXSCREEN_Y*SCALE: | |
| obj.y = 0 | |
| if obj.y < 0: | |
| obj.y = MAXSCREEN_Y*SCALE | |
| obj.deg+=obj.tumble # add tumble to deg | |
| if obj.deg>359: | |
| obj.deg-=360 | |
| if obj.deg<0: | |
| obj.deg+=360 | |
| for i in range(0,obj.pts-2,2): # go through all points of obj | |
| deg1=int(obj.deg+obj.ptdeg[i//2])+(obj.size//150) * explode | |
| if deg1>359: | |
| deg1-=360 | |
| deg2=int(obj.deg+obj.ptdeg[1+i//2])-(obj.size//150) * explode | |
| if deg2>359: | |
| deg2-=360 | |
| if not explode: | |
| obj.pt[i].x=int(obj.ptrad[i//2]*obj.size*icos[deg1]//10000+obj.x) # calc x,y from deg,radius | |
| obj.pt[i].y=int(obj.ptrad[i//2]*obj.size*isin[deg1]//10000+obj.y) | |
| obj.pt[i+1].x=int(obj.ptrad[1+i//2]*obj.size*icos[deg2]//10000+obj.x) # calc x,y from deg,radius | |
| obj.pt[i+1].y=int(obj.ptrad[1+i//2]*obj.size*isin[deg2]//10000+obj.y) | |
| else: | |
| obj.size+=10 | |
| obj.pt[i].x=int(obj.ptrad[i//2]*obj.size*icos[deg1]//10000+obj.x) # calc x,y from deg,radius | |
| obj.pt[i].y=int(obj.ptrad[i//2]*obj.size*isin[deg1]//10000+obj.y) | |
| obj.pt[i+1].x=int(obj.ptrad[1+i//2]*obj.size*icos[deg2]//10000+obj.x) # calc x,y from deg,radius | |
| obj.pt[i+1].y=int(obj.ptrad[1+i//2]*obj.size*isin[deg2]//10000+obj.y) | |
| #@timed_function | |
| def thrust(): | |
| ship.ax=ship.ax+icos[ship.deg]//150 # add accel in direction ship is pointed | |
| ship.ay=ship.ay+isin[ship.deg]//150 | |
| init_exhaust() | |
| def init_exhaust(): | |
| i = 0 | |
| for j in range(0,len(h),2): | |
| if i==len(h)-2: # end of the list? | |
| i = 0 # start over | |
| else: | |
| i +=2 # next index | |
| if h[i].active == False: | |
| h[i].active = True | |
| h[i+1].active = True | |
| h[i].x = ship.pt[2].x # .x+randint(-2000,2000) | |
| h[i].y = ship.pt[2].y #h[last].y+randint(-2000,2000) | |
| h[i+1].x = ship.pt[3].x # .x+randint(-2000,2000) | |
| h[i+1].y = ship.pt[3].y #h[last].y+randint(-2000,2000) | |
| if ship.deg > 179: | |
| deg = ship.deg - 180 | |
| else: | |
| deg = ship.deg + 180 | |
| h[i].ax=ship.ax+icos[deg]//10*1 +randint(-10,10)*10 # missile accel of ship + 3x | |
| h[i].ay=ship.ay+isin[deg]//10*1 +randint(-10,10)*10 | |
| h[i+1].ax=ship.ax+icos[deg]//10*1 +randint(-10,10)*10 # missile accel of ship + 3x | |
| h[i+1].ay=ship.ay+isin[deg]//10*1 +randint(-10,10)*10 | |
| return | |
| def show_exhaust(): | |
| for i in h: | |
| if i.active == True: | |
| i.exp += 1 | |
| LCD.pixel(int(i.x//1000),int(i.y//1000),LCD.black) # erase old | |
| if i.exp >31: | |
| i.active = False | |
| i.exp = 0 | |
| else: | |
| i.x += i.ax | |
| i.y += i.ay | |
| # c=LCD.black | |
| # if i.exp<31: | |
| # if randint(0,1): | |
| # c=red_shades[31-i.exp] | |
| # else: | |
| # c=yellow_shades[31-i.exp] | |
| if randint(0,1): | |
| c=red_shades[31] | |
| else: | |
| c=yellow_shades[31] | |
| LCD.pixel(int(i.x//1000),int(i.y//1000),c) #c | |
| #@timed_function | |
| def buttons(fps): | |
| global rfire,threaded,asteroid_count, demo | |
| if(key6.value() == 0): # rotate ship CW | |
| ship.deg+=6-(2*threaded)+(50-fps)//5 | |
| if ship.deg>359: | |
| ship.deg=0 | |
| if(key4.value() == 0): # rotate ship CCW | |
| ship.deg-=6-(2*threaded)+(50-fps)//5 | |
| if ship.deg<0: | |
| ship.deg=359 | |
| if(key2.value() == 0): | |
| thrust() | |
| rfire+=1 | |
| if(keyB.value() == 0) and ship.damage or demo: # fire | |
| if rfire> 8+(4*threaded)-(50-fps)//7: | |
| rfire=0 | |
| fire() | |
| if demo: | |
| ship.deg+=1 | |
| if ship.deg>359: | |
| ship.deg=0 | |
| if(keyA.value() == 0) and (keyB.value() == 0): # reboot if frozen | |
| reset() | |
| #@timed_function | |
| def fire(): | |
| # print(gc.mem_free()) | |
| for i in m: | |
| if i.active == False: | |
| i.active = True | |
| i.x=ship.pt[0].x # start missile at tip of ship | |
| i.y=ship.pt[0].y | |
| i.ax=ship.ax+icos[ship.deg]//10*3 # missile accel of ship + 3x | |
| i.ay=ship.ay+isin[ship.deg]//10*3 | |
| return | |
| def spawn_asteroid(objs,last): # find next free object in list | |
| i = last | |
| for j in range(len(objs)): | |
| if i==len(objs)-1: # end of the list? | |
| i = 0 # start over | |
| else: | |
| i +=1 # next index | |
| if objs[i].active == False: | |
| objs[i].active = True | |
| objs[i].x = objs[last].x+randint(-2000,2000)*5 | |
| objs[i].y = objs[last].y+randint(-2000,2000)*5 | |
| objs[i].ax = randint(-40,40)*20 | |
| objs[i].ay = randint(-40,40)*20 | |
| if objs[i].ax <1000: | |
| objs[i].ax +=200 | |
| if objs[i].ay <1000: | |
| objs[i].ay +=200 | |
| objs[i].size = objs[last].size | |
| objs[i].coll = objs[i].size*5 | |
| objs[i].exp = 0 | |
| return | |
| #@timed_function | |
| def move_miss_new(): | |
| global asteroid_count | |
| for i in range(0,10): | |
| if m[i].active and m[i].x >-1000 and m[i].x<241000 and m[i].y>-1000 and m[i].y<136000: # check miss inbounds | |
| # LCD.pixel(int(m[i].x//1000),int(m[i].y//1000),LCD.black) # erase old miss | |
| pixel(m[i].x,m[i].y,LCD.black) # erase old miss | |
| m[i].x=m[i].x+m[i].ax # calc new miss | |
| m[i].y=m[i].y+m[i].ay | |
| if randint(0,1): | |
| c=red_shades[31] | |
| else: | |
| c=LCD.white | |
| # LCD.pixel(int(m[i].x//1000),int(m[i].y//1000),c) # draw new miss | |
| pixel(m[i].x,m[i].y,c) | |
| for j in range(0,len(asteroid)): # loop thought asteroid list | |
| if asteroid[j].active and m[i].x < asteroid[j].x+asteroid[j].coll and m[i].x > asteroid[j].x-asteroid[j].coll and m[i].y < asteroid[j].y+asteroid[j].coll and m[i].y > asteroid[j].y-asteroid[j].coll and asteroid[j].size>0 and asteroid[j].exp==0 and ship.damage: # check collision | |
| LCD.pixel(int(m[i].x//1000),int(m[i].y//1000),LCD.black) | |
| score.value += scoring[asteroid[j].size//1000] | |
| asteroid[j].size-=1000 | |
| asteroid[j].coll-=3 | |
| if asteroid[j].size >100: | |
| spawn_asteroid(asteroid,j) | |
| spawn_asteroid(asteroid,j) | |
| explode_clean_token = True | |
| # init_explode(asteroid[j],20,3) | |
| asteroid[j].exp=1 | |
| asteroid[j].tumble = 0 | |
| asteroid[j].ax = 0 | |
| asteroid[j].ay = 0 | |
| m[i].active = False | |
| else: | |
| m[i].active = False | |
| #@timed_function | |
| def move_asteroid(): | |
| global asteroid_count | |
| asteroid_count = 0 | |
| for i in range(0,len(asteroid)): # go through list of asteroids | |
| asteroid_count+=(asteroid[i].active==True) | |
| if asteroid[i].active: | |
| if asteroid[i].exp>0: | |
| asteroid[i].exp+=1 | |
| draw_object2(asteroid[i],(asteroid[i].exp>0)) # draw/move | |
| if ship.damage and ship.exp == 0 and ship.x < asteroid[i].x+asteroid[i].coll and ship.x > asteroid[i].x-asteroid[i].coll and ship.y < asteroid[i].y+asteroid[i].coll and ship.y > asteroid[i].y-asteroid[i].coll and asteroid[i].exp == 0: | |
| ship.exp = 1 # asteroid collide with ship | |
| score.lives -= 1 | |
| if asteroid[i].size>5500 or asteroid[i].size<1 or asteroid[i].exp > 59: # and len(e) == 0: | |
| draw_object2(asteroid[i],True) | |
| asteroid[i].active = False | |
| asteroid[i].exp= 0 | |
| def star_field(y): | |
| for i in e: | |
| if i.active == False: | |
| i.active = True | |
| i.x=120000 | |
| i.y=y | |
| i.ax = randint(-1000,1000)*10//1 | |
| i.ay = randint(-1000,1000)*10//1 | |
| return | |
| def stars(): | |
| j = 0 | |
| k = 0 | |
| for i in range(0,10): # len(e)): | |
| if e[i].active: | |
| if e[i].x >=0 and e[i].x<=MAXSCREEN_X*SCALE and e[i].y>=0 and e[i].y<=MAXSCREEN_Y*SCALE: | |
| LCD.pixel(int(e[i].x//1000),int(e[i].y//1000),LCD.black) | |
| if ship.deg > 179: | |
| deg = ship.deg - 180 | |
| else: | |
| deg = ship.deg + 180 | |
| e[i].x=int(e[i].x-ship.ax+icos[deg]//10) | |
| e[i].y=int(e[i].y-ship.ay+isin[deg]//10) | |
| color=LCD.white | |
| LCD.pixel(int(e[i].x//1000),int(e[i].y//1000),color) | |
| j+=1 | |
| else: | |
| # LCD.pixel(int(e[i].x//1000),int(e[i].y//1000),LCD.black) | |
| e[i].active = False | |
| else: | |
| k = i | |
| if j<9: | |
| if e[k].x<0: | |
| e[k].x = MAXSCREEN_X*SCALE | |
| e[k].y = randint(0,MAXSCREEN_Y*SCALE) | |
| elif e[k].x>MAXSCREEN_X*SCALE: | |
| e[k].x = 0 | |
| e[k].y = randint(0,MAXSCREEN_Y*SCALE) | |
| elif e[k].y<0: | |
| e[k].y = MAXSCREEN_Y*SCALE | |
| e[k].x = randint(0,MAXSCREEN_X*SCALE) | |
| elif e[k].y>MAXSCREEN_Y*SCALE: | |
| e[k].y = 0 | |
| e[k].x = randint(0,MAXSCREEN_X*SCALE) | |
| else: | |
| e[k].x = randint(0,MAXSCREEN_X*SCALE) | |
| e[k].y = randint(0,MAXSCREEN_Y*SCALE) | |
| e[k].active = True | |
| #@timed_function | |
| def init_explode(objhit,n,s): # obj, number, speed | |
| for i in range(0,n): | |
| LCD.pixel(int(e[i].x//1000),int(e[i].y//1000),LCD.black) | |
| e[i].active = True | |
| e[i].x=objhit.x | |
| e[i].y=objhit.y | |
| e[i].ax = objhit.ax+randint(-1000,1000)*10//s | |
| e[i].ay = objhit.ay+randint(-1000,1000)*10//s | |
| #@timed_function | |
| def explode(): | |
| for i in range(0,len(e)): | |
| if e[i].active: | |
| if e[i].x >-1000 and e[i].x<241000 and e[i].y>-1000 and e[i].y<136000 and e[i].exp<51: | |
| LCD.pixel(int(e[i].x//1000),int(e[i].y//1000),LCD.black) | |
| e[i].x=int(e[i].x+e[i].ax) | |
| e[i].y=int(e[i].y+e[i].ay) | |
| color=LCD.white | |
| if e[i].exp>20: | |
| color=white_shades[51-e[i].exp] | |
| LCD.pixel(int(e[i].x//1000),int(e[i].y//1000),color) | |
| e[i].exp+=1 | |
| else: | |
| LCD.pixel(int(e[i].x//1000),int(e[i].y//1000),LCD.black) | |
| e[i].active = False | |
| e[i].exp=0 | |
| def explode_cleanup(): | |
| for i in range(0,len(e)): | |
| if e[i].active or 0: | |
| LCD.pixel(int(e[i].x//1000),int(e[i].y//1000),LCD.black) | |
| e[i].active = False | |
| e[i].exp=0 | |
| def ship_condition(): | |
| if ship.exp >60 or score.show == True : # explosion done | |
| # explode_clean_token = True | |
| # explode_cleanup() | |
| show_big_score() | |
| new_ship() | |
| if ship.exp == 1: # 1=init | |
| ship.ax = 0 | |
| ship.ay = 0 | |
| # explode_clean_token = True | |
| # explode_cleanup() | |
| # init_explode(ship,90,5) | |
| ship.exp = 2 | |
| if ship.exp > 1: # 2+=exploding | |
| #explode() | |
| ship.exp+=1 | |
| def watchdog(timer): | |
| if(keyA.value() == 0) and (keyB.value() == 0): # reboot if frozen | |
| reset() | |
| def no_damage(timer): | |
| ship.damage = True | |
| def show_display(): # core 1 | |
| # micropython.alloc_emergency_exception_buf(100) | |
| global token,explode_clean_token,asteroid_count,num_asteroids, gticks | |
| while True: | |
| ship_condition() | |
| draw_object2(ship,ship.exp>0) | |
| slow_ship() | |
| move_miss_new() | |
| show_exhaust() | |
| stars() | |
| LCD.show() | |
| fps=1_000_000//ticks_diff(ticks_us(), gticks) | |
| buttons(fps) | |
| gticks = ticks_us() | |
| LCD.fill_rect(0,0,20,10,LCD.black) | |
| screen_fps(fps,23) | |
| if __name__=='__main__': | |
| # micropython.alloc_emergency_exception_buf(100) | |
| pwm = PWM(Pin(BL)) | |
| pwm.freq(1000) | |
| pwm.duty_u16(32768)#max 65535 | |
| LCD.fill(LCD.black) | |
| keyA = Pin(15,Pin.IN,Pin.PULL_UP) | |
| keyB = Pin(17,Pin.IN,Pin.PULL_UP) | |
| key2 = Pin(2 ,Pin.IN,Pin.PULL_UP) # up | |
| key3 = Pin(3 ,Pin.IN,Pin.PULL_UP)#中 | |
| key4 = Pin(16 ,Pin.IN,Pin.PULL_UP)#左 | |
| key5 = Pin(18 ,Pin.IN,Pin.PULL_UP)#下 | |
| key6 = Pin(20 ,Pin.IN,Pin.PULL_UP)#右 | |
| init_isin() | |
| init_icos() | |
| init_shades() | |
| init_explosion() | |
| init_big_score() | |
| init_game_over() | |
| ship=init_obj([0,140,220,0],[3,3,3,3],8,0,120000,65000,3000) | |
| ship.color = LCD.green | |
| init_title() | |
| show_title(t) | |
| gc.collect() | |
| print(gc.mem_free()) | |
| del t | |
| gc.collect() | |
| print(gc.mem_free()) | |
| init_asteroids() | |
| init_missiles() | |
| gc.collect() | |
| print(gc.mem_free()) | |
| tim = Timer() #set the no damage timer | |
| tim2 = Timer() #soft watchdog | |
| gc.collect() | |
| for i in range(0,10000): | |
| pass | |
| if threaded: | |
| print('core 1') | |
| a_lock = _thread.allocate_lock() | |
| wdt=machine.WDT(id=0, timeout=8000) | |
| # tim2.init(mode=Timer.PERIODIC, freq=1, callback=watchdog) | |
| _thread.start_new_thread(show_display, ()) | |
| try: # core 0 | |
| while(1): | |
| while token == 0 or 1: | |
| # kbhit() | |
| if asteroid_count==0: | |
| score.show = True | |
| more_asteroids() | |
| num_asteroids+=1 | |
| ship.damage=False | |
| tim.init(mode=Timer.ONE_SHOT, period=2000, callback=no_damage) | |
| if not score.show: | |
| move_asteroid() | |
| if not threaded: | |
| ship_condition() | |
| draw_object2(ship,ship.exp>0) | |
| move_miss_new() | |
| show_exhaust() | |
| stars() | |
| LCD.show() | |
| fps=1_000_000//ticks_diff(ticks_us(), gticks) | |
| buttons(fps) | |
| gticks = ticks_us() | |
| LCD.fill_rect(0,0,20,10,LCD.black) | |
| screen_fps(fps,23) | |
| else: | |
| wdt.feed() | |
| show_small_score() | |
| #print(gc.mem_free()) | |
| except KeyboardInterrupt: | |
| print('asteroids: ',len(asteroid),asteroid[0].x,asteroid[0].y, asteroid[0].pt[0].x,asteroid[0].pt[0].y,asteroid[0].ptdeg,asteroid[0].ptrad,asteroid[0].size) | |
| print('asteroid coll,exp: ',asteroid[0].coll,asteroid[0].exp) | |
| print('asteroid coll,exp: ',asteroid[0].ax,asteroid[0].ay) | |
| print('ship size,active: ',ship.size,ship.active) | |
| print('explosion: ',len(e)) | |
| print('ship damage,exp: ',ship.damage,ship.exp) | |
| print('mem free: ',gc.mem_free()) | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from machine import Pin,SPI,PWM | |
| import framebuf | |
| import time | |
| BL = 13 | |
| DC = 8 | |
| RST = 12 | |
| MOSI = 11 | |
| SCK = 10 | |
| CS = 9 | |
| # LCD 1.14 Version 2 | |
| class LCD_1inch14(framebuf.FrameBuffer): | |
| def __init__(self): | |
| self.temp = bytearray(1) | |
| self.width = 240 | |
| self.height = 135 | |
| self.cs = Pin(CS,Pin.OUT) | |
| self.rst = Pin(RST,Pin.OUT) | |
| self.cs(1) | |
| self.spi = SPI(1) | |
| self.spi = SPI(1,1000_000) | |
| self.spi = SPI(1,65_000_000,polarity=0, phase=0,sck=Pin(SCK),mosi=Pin(MOSI),miso=None) | |
| self.dc = Pin(DC,Pin.OUT) | |
| self.dc(1) | |
| self.buffer = bytearray(self.height * self.width * 2) | |
| super().__init__(self.buffer, self.width, self.height, framebuf.RGB565) | |
| self.init_display() | |
| self.red = 0x07E0 | |
| self.green = 0x001f | |
| self.blue = 0xf800 | |
| self.white = 0xffff | |
| self.yellow= 0xFFE0 | |
| self.orange= 0xE0FC | |
| self.black = 0x0 | |
| def write_cmd(self, cmd): | |
| self.temp[0] = cmd | |
| self.cs(1) | |
| self.dc(0) | |
| self.cs(0) | |
| self.spi.write(self.temp) | |
| self.cs(1) | |
| def write_data(self, buf): | |
| self.temp[0] = buf | |
| self.cs(1) | |
| self.dc(1) | |
| self.cs(0) | |
| self.spi.write(self.temp) | |
| self.cs(1) | |
| def init_display(self): | |
| #Initialize dispaly | |
| self.rst(1) | |
| self.rst(0) | |
| self.rst(1) | |
| self.write_cmd(0x36) | |
| self.write_data(0x70) | |
| self.write_cmd(0x3A) | |
| self.write_data(0x05) | |
| self.write_cmd(0xB2) | |
| self.write_data(0x0C) | |
| self.write_data(0x0C) | |
| self.write_data(0x00) | |
| self.write_data(0x33) | |
| self.write_data(0x33) | |
| self.write_cmd(0xB7) | |
| self.write_data(0x35) | |
| self.write_cmd(0xBB) | |
| self.write_data(0x19) | |
| self.write_cmd(0xC0) | |
| self.write_data(0x2C) | |
| self.write_cmd(0xC2) | |
| self.write_data(0x01) | |
| self.write_cmd(0xC3) | |
| self.write_data(0x12) | |
| self.write_cmd(0xC4) | |
| self.write_data(0x20) | |
| self.write_cmd(0xC6) | |
| self.write_data(0x0F) | |
| self.write_cmd(0xD0) | |
| self.write_data(0xA4) | |
| self.write_data(0xA1) | |
| self.write_cmd(0xE0) | |
| self.write_data(0xD0) | |
| self.write_data(0x04) | |
| self.write_data(0x0D) | |
| self.write_data(0x11) | |
| self.write_data(0x13) | |
| self.write_data(0x2B) | |
| self.write_data(0x3F) | |
| self.write_data(0x54) | |
| self.write_data(0x4C) | |
| self.write_data(0x18) | |
| self.write_data(0x0D) | |
| self.write_data(0x0B) | |
| self.write_data(0x1F) | |
| self.write_data(0x23) | |
| self.write_cmd(0xE1) | |
| self.write_data(0xD0) | |
| self.write_data(0x04) | |
| self.write_data(0x0C) | |
| self.write_data(0x11) | |
| self.write_data(0x13) | |
| self.write_data(0x2C) | |
| self.write_data(0x3F) | |
| self.write_data(0x44) | |
| self.write_data(0x51) | |
| self.write_data(0x2F) | |
| self.write_data(0x1F) | |
| self.write_data(0x1F) | |
| self.write_data(0x20) | |
| self.write_data(0x23) | |
| self.write_cmd(0x21) | |
| self.write_cmd(0x11) | |
| self.write_cmd(0x29) | |
| def show(self): | |
| self.write_cmd(0x2A) | |
| self.write_data(0x00) | |
| self.write_data(0x28) | |
| self.write_data(0x01) | |
| self.write_data(0x17) | |
| self.write_cmd(0x2B) | |
| self.write_data(0x00) | |
| self.write_data(0x35) | |
| self.write_data(0x00) | |
| self.write_data(0xBB) | |
| self.write_cmd(0x2C) | |
| self.cs(1) | |
| self.dc(1) | |
| self.cs(0) | |
| self.spi.write(self.buffer) | |
| self.cs(1) | |
| if __name__=='__main__': | |
| pwm = PWM(Pin(BL)) | |
| pwm.freq(1000) | |
| pwm.duty_u16(32768)#max 65535 | |
| LCD = LCD_1inch14() | |
| print(LCD.spi) | |
| #color BRG | |
| LCD.fill(LCD.white) | |
| LCD.show() | |
| LCD.text("Raspberry Pi Pico",90,40,LCD.red) | |
| LCD.text("PicoGo",90,60,LCD.green) | |
| LCD.text("Pico-LCD-1.14",90,80,LCD.blue) | |
| LCD.hline(10,10,220,LCD.blue) | |
| LCD.hline(10,125,220,LCD.blue) | |
| LCD.vline(10,10,115,LCD.blue) | |
| LCD.vline(230,10,115,LCD.blue) | |
| LCD.show() | |
| keyA = Pin(15,Pin.IN,Pin.PULL_UP) | |
| keyB = Pin(17,Pin.IN,Pin.PULL_UP) | |
| key2 = Pin(2 ,Pin.IN,Pin.PULL_UP) #上 | |
| key3 = Pin(3 ,Pin.IN,Pin.PULL_UP)#中 | |
| key4 = Pin(16 ,Pin.IN,Pin.PULL_UP)#左 | |
| key5 = Pin(18 ,Pin.IN,Pin.PULL_UP)#下 | |
| key6 = Pin(20 ,Pin.IN,Pin.PULL_UP)#右 | |
| while(1): | |
| if(keyA.value() == 0): | |
| LCD.fill_rect(208,12,20,20,LCD.red) | |
| else : | |
| LCD.fill_rect(208,12,20,20,LCD.white) | |
| LCD.rect(208,12,20,20,LCD.red) | |
| if(keyB.value() == 0): | |
| LCD.fill_rect(208,103,20,20,LCD.red) | |
| else : | |
| LCD.fill_rect(208,103,20,20,LCD.white) | |
| LCD.rect(208,103,20,20,LCD.red) | |
| if(key2.value() == 0):#上 | |
| LCD.fill_rect(37,35,20,20,LCD.red) | |
| else : | |
| LCD.fill_rect(37,35,20,20,LCD.white) | |
| LCD.rect(37,35,20,20,LCD.red) | |
| if(key3.value() == 0):#中 | |
| LCD.fill_rect(37,60,20,20,LCD.red) | |
| else : | |
| LCD.fill_rect(37,60,20,20,LCD.white) | |
| LCD.rect(37,60,20,20,LCD.red) | |
| if(key4.value() == 0):#左 | |
| LCD.fill_rect(12,60,20,20,LCD.red) | |
| else : | |
| LCD.fill_rect(12,60,20,20,LCD.white) | |
| LCD.rect(12,60,20,20,LCD.red) | |
| if(key5.value() == 0):#下 | |
| LCD.fill_rect(37,85,20,20,LCD.red) | |
| else : | |
| LCD.fill_rect(37,85,20,20,LCD.white) | |
| LCD.rect(37,85,20,20,LCD.red) | |
| if(key6.value() == 0):#右 | |
| LCD.fill_rect(62,60,20,20,LCD.red) | |
| else : | |
| LCD.fill_rect(62,60,20,20,LCD.white) | |
| LCD.rect(62,60,20,20,LCD.red) | |
| LCD.show() | |
| time.sleep(1) | |
| LCD.fill(0xFFFF) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment