Created
March 28, 2023 23:09
-
-
Save samneggs/6f846d459769977c74b3ff25107d6bff to your computer and use it in GitHub Desktop.
Artillery Game on Pi Pico in MicroPython
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
#Artillery | |
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 music import music, tones, bogey, o1812 | |
MAXSCREEN_X = const(160) | |
MAXSCREEN_Y = const(128) | |
SCALE = const(13) | |
BROWN = const(0x2159) | |
BLAST_NUM = const(50) | |
SMOKE_NUM = const(50) | |
SKYBLUE = const(0b11111111_00111011) | |
DRKGREEN = const(0b11100000_00000001) | |
# gun parameters | |
MOUNT_X = const(0) | |
MOUNT_Y = const(1) | |
ANGLE = const(2) | |
POWDER = const(3) | |
SHELL_X = const(4) | |
SHELL_Y = const(5) | |
SHELL_XV = const(6) | |
SHELL_YV = const(7) | |
SHELL_XA = const(8) | |
SHELL_YA = const(9) | |
BARREL_X = const(10) | |
BARREL_Y = const(11) | |
SHOW_T = const(12) | |
FPS = const(13) | |
FIRED = const(14) | |
EXPLODE = const(15) | |
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) | |
fire_rgb = array.array('H',(8192 ,8216 ,24616 ,24640 ,41040 ,57440 ,57456 ,8329 ,24729 ,57513 ,8378 ,8386 ,24794 , | |
41178 ,41178 ,57554 ,57554 ,8659 ,25035 ,41419 ,57803 ,8908 ,8900 ,25284 ,41924 ,58300 , | |
58300 ,9405 ,9405 ,26045 ,26037 ,42421 ,42677 ,28110 ,62430 ,30959 ,65535)) | |
@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_gun(): | |
global GUN, BLAST, SMOKE | |
SMOKE = array.array('i',(0 for _ in range(10*100))) | |
BLAST = array.array('i',(0 for _ in range(1000))) | |
GUN = array.array('i',()) | |
GUN.append(10) # MOUNT_X | |
GUN.append(HILL[10]) # MOUNT_Y | |
GUN.append(315<<SCALE) # ANGLE | |
GUN.append(1<<SCALE) # POWDER | |
GUN.append(0) # SHELL_X | |
GUN.append(0) # SHELL_Y | |
GUN.append(0) # SHELL_XV | |
GUN.append(0) # SHELL_YV | |
GUN.append(0) # SHELL_XA | |
GUN.append(0) # SHELL_YA | |
GUN.append(0) # BARREL_X | |
GUN.append(0) # BARREL_Y | |
GUN.append(0) # SHOW_T | |
GUN.append(111) # FPS | |
GUN.append(0) # FIRED | |
GUN.append(0) # EXPLODE | |
def init_enemy(): | |
global ENEMY, SMOKE | |
ENEMY = array.array('i',()) | |
for i in range(len(SMOKE)): | |
SMOKE[i] = 0 | |
x = randint(80,150) | |
ENEMY.append(x) # MOUNT_X | |
ENEMY.append(HILL[x]) # MOUNT_Y | |
ENEMY.append(240<<SCALE) # ANGLE | |
ENEMY.append(1<<SCALE) # POWDER | |
ENEMY.append(0) # SHELL_X | |
ENEMY.append(0) # SHELL_Y | |
ENEMY.append(0) # SHELL_XV | |
ENEMY.append(0) # SHELL_YV | |
ENEMY.append(0) # SHELL_XA | |
ENEMY.append(0) # SHELL_YA | |
ENEMY.append(0) # BARREL_X | |
ENEMY.append(0) # BARREL_Y | |
ENEMY.append(0) # SHOW_T | |
ENEMY.append(111) # FPS | |
ENEMY.append(0) # FIRED | |
ENEMY.append(0) # EXPLODE | |
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(): | |
gun = ptr32(GUN) | |
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 | |
angle = gun[ANGLE] - x_inc*500 | |
powder = gun[POWDER] - y_inc*10 | |
if angle == gun[ANGLE] and powder == gun[POWDER]: | |
gun[SHOW_T] = 0 | |
else: | |
gun[SHOW_T] = 1 | |
if angle>0 and angle<360<<SCALE: | |
gun[ANGLE] = angle | |
if powder>0 and powder<=2<<SCALE: | |
gun[POWDER] = powder | |
if not FIRE_BUTTON.value(): | |
init_shell() | |
@micropython.viper | |
def init_explode(): | |
hill = ptr8(HILL) | |
hill_exp = ptr8(HILL_EXP) | |
gun = ptr32(GUN) | |
sine = ptr32(isin) | |
cx = gun[SHELL_X]>>SCALE | |
cy = gun[SHELL_Y]>>SCALE | |
r = 10 | |
for x in range(cx-r,cx+r): # crater | |
y = int(isqrt(r*r - ((x - cx)*(x - cx)))) #y = sqrt(r^2 - (x - cx)^2) | |
if hill[x] < cy + y: | |
hill_exp[x] = cy + y | |
gun[EXPLODE] = 20 | |
def isqrt(n): | |
return int(sqrt(n)) | |
@micropython.viper | |
def explode(): | |
global EXIT | |
hill = ptr8(HILL) | |
hill_exp = ptr8(HILL_EXP) | |
gun = ptr32(GUN) | |
enemy = ptr32(ENEMY) | |
for x in range(MAXSCREEN_X): | |
if hill[x] < hill_exp[x]: | |
hill[x] += 1 | |
hill_exp[x] -= 1 | |
if gun[EXPLODE] > 0: | |
gun[EXPLODE] -= 1 | |
if gun[EXPLODE] == 1 and int(distance_asm(gun[SHELL_X]>>SCALE,gun[SHELL_Y]>>SCALE,enemy[MOUNT_X],enemy[MOUNT_Y])) < 10: | |
init_land() | |
init_enemy() | |
@micropython.asm_thumb | |
def distance_asm(r0,r1,r2,r3): # x1,y1,x2,y2 | |
sub(r4,r2,r0) # x2-x1 | |
sub(r5,r3,r1) # y2-y1 | |
mul(r4,r4) # (x2-x1)^2 | |
mul(r5,r5) # (y2-y1)^2 | |
add(r0,r4,r5) # (x2-x1)^2 + (y2-y1)^2 | |
mov(r2,0) # r2 = res | |
cmp(r0,0) # r0 = num | |
bpl(MAIN) | |
mov(r0,0) | |
b(EXIT) | |
label(MAIN) | |
mov(r1,1) # r1 = bit | |
lsl(r1,r1,30) | |
label(FOUR_POWER) | |
cmp(r1,r0) # bit <= num | |
ble(LOOP) | |
asr(r1,r1,2) # bit = bit >> 2 | |
b(FOUR_POWER) | |
label(LOOP) | |
cmp(r1,0) | |
beq(EXIT) # bit == 0 | |
add(r3,r1,r2) # res + bit | |
cmp(r0,r3) # if num >= res + bit | |
blt(ELSE) | |
sub(r0,r0,r3) # num = num - (res + bit) | |
asr(r4,r2,1) # res >> 1 | |
add(r2,r4,r1) # res = (res >> 1) + bit | |
b(IF_DONE) | |
label(ELSE) | |
asr(r2,r2,1) # res = res>>1 | |
label(IF_DONE) | |
asr(r1,r1,2) # bit = bit >> 2 | |
b(LOOP) | |
label(EXIT) | |
cmp(r0,r2) # if num <= res: | |
ble(NO_ROUND) | |
add(r2,r2,1) # res += 1 | |
label(NO_ROUND) | |
mov(r0,r2) | |
@micropython.viper | |
def fill_circle(x0:int, y0:int, radius:int, color:int): | |
screen_ptr = ptr16(LCD.buffer) | |
max_addr = MAXSCREEN_X * MAXSCREEN_Y | |
# From Adafruit GFX Arduino library | |
y_start = y0 - radius | |
for y2 in range(y_start, y_start+2*radius + 1): | |
addr = y2 * MAXSCREEN_X + x0 | |
if addr > 0 and addr < max_addr: | |
screen_ptr[addr] = color | |
f = 1 - radius | |
ddF_x = 1 | |
ddF_y = -2 * radius | |
x = 0 | |
y = radius | |
while x < y: | |
if f >= 0: | |
y -= 1 | |
ddF_y += 2 | |
f += ddF_y | |
x += 1 | |
ddF_x += 2 | |
f += ddF_x | |
x2 = x0 + x | |
y_start = y0 - y | |
for y2 in range(y_start, y_start+2*y + 1): | |
addr = y2 * MAXSCREEN_X + x2 | |
if addr > 0 and addr < max_addr: | |
screen_ptr[addr] = color | |
x2 = x0 + y | |
y_start = y0 - x | |
for y2 in range(y_start,y_start+ 2*x + 1): | |
addr = y2 * MAXSCREEN_X + x2 | |
if addr > 0 and addr < max_addr: | |
screen_ptr[addr] = color | |
x2 = x0 - x | |
y_start = y0 - y | |
for y2 in range(y_start, y_start+2*y + 1): | |
addr = y2 * MAXSCREEN_X + x2 | |
if addr > 0 and addr < max_addr: | |
screen_ptr[addr] = color | |
x2 = x0 - y | |
y_start = y0 - x | |
for y2 in range(y_start, y_start+2*x + 1): | |
addr = y2 * MAXSCREEN_X + x2 | |
if addr > 0 and addr < max_addr: | |
screen_ptr[addr] = color | |
@micropython.viper | |
def draw(): | |
hill = ptr8(HILL) | |
gun = ptr32(GUN) | |
enemy = ptr32(ENEMY) | |
fire = ptr16(fire_rgb) | |
blast = ptr32(BLAST) | |
for h_x in range(MAXSCREEN_X): | |
h_y = hill[h_x] | |
LCD.line(h_x,MAXSCREEN_Y,h_x,h_y,BROWN) # hill | |
LCD.text('FPS:',0,0,0xff) | |
show_num_viper(gun[FPS],40,0,0xff) | |
LCD.text('ANGLE:',0,10,0xff) | |
show_num_viper(360-(gun[ANGLE]>>SCALE),70,10,0xff) | |
LCD.text('POWDER:',0,20,0xff) | |
show_num_viper(gun[POWDER]>>7,70,20,0xff) | |
e_x = enemy[MOUNT_X] | |
e_y = enemy[MOUNT_Y] | |
LCD.rect(e_x-5,e_y,13,MAXSCREEN_Y-e_y,BROWN,1) # enemy turret base | |
# for h_x in range(MAXSCREEN_X): | |
# h_y = hill[h_x] | |
# LCD.line(h_x,MAXSCREEN_Y,h_x,h_y,BROWN) # hill | |
draw_smoke() | |
x = gun[MOUNT_X] | |
y = gun[MOUNT_Y] | |
b_x = gun[BARREL_X] | |
b_y = gun[BARREL_Y] | |
LCD.ellipse(x,y,5,5,LCD.BLACK,True,0b0011) # turret | |
LCD.line(x,y,b_x,b_y,LCD.BLACK) # barrel | |
x = enemy[MOUNT_X] | |
y = enemy[MOUNT_Y] | |
b_x = enemy[BARREL_X] | |
b_y = enemy[BARREL_Y] | |
LCD.ellipse(x,y,5,5,LCD.BLACK,True,0b0011) # enemy turret | |
LCD.line(x,y,b_x,b_y,LCD.BLACK) # enemy barrel | |
#LCD.pixel(gun[SHELL_X]>>SCALE,gun[SHELL_Y]>>SCALE,0xffff) # shell | |
if gun[EXPLODE] > 10: | |
radius = 21 - gun[EXPLODE] | |
else: | |
radius = gun[EXPLODE] | |
if gun[FIRED] == 1: | |
LCD.ellipse(gun[SHELL_X]>>SCALE,gun[SHELL_Y]>>SCALE,1,1,0xffff,True) # shell | |
for index in range(BLAST_NUM): | |
b = index * 5 | |
if blast[b+4] == 0:continue | |
LCD.pixel(blast[b+0]>>SCALE,blast[b+1]>>SCALE, fire[blast[b+4]+20]) # turret blast | |
if gun[EXPLODE] > 0: | |
fill_circle(gun[SHELL_X]>>SCALE,gun[SHELL_Y]>>SCALE,radius,fire[gun[EXPLODE]]) # circle explosion | |
LCD.show() | |
LCD.rect(0,0,MAXSCREEN_X,80,SKYBLUE,1) | |
LCD.rect(0,80,MAXSCREEN_X,MAXSCREEN_Y-80,DRKGREEN,1) | |
@micropython.viper | |
def calc(): | |
hill = ptr8(HILL) | |
screen = ptr16(LCD.buffer) | |
gun = ptr32(GUN) | |
enemy = ptr32(ENEMY) | |
sine = ptr32(isin) | |
cosine = ptr32(icos) | |
colors = ptr16(fire_rgb) | |
deg = enemy[ANGLE]>>SCALE | |
length = 10 | |
b_x = (cosine[deg]*length)>>SCALE | |
b_y = (sine[deg]*length)>>SCALE | |
enemy[BARREL_X] = enemy[MOUNT_X] + b_x | |
enemy[BARREL_Y] = enemy[MOUNT_Y] + b_y | |
deg = gun[ANGLE]>>SCALE | |
length = 10 | |
b_x = (cosine[deg]*length)>>SCALE | |
b_y = (sine[deg]*length)>>SCALE | |
gun[BARREL_X] = gun[MOUNT_X] + b_x | |
gun[BARREL_Y] = gun[MOUNT_Y] + b_y | |
s_x = gun[BARREL_X]<<SCALE | |
s_y = gun[BARREL_Y]<<SCALE | |
max_y = MAXSCREEN_Y<<SCALE | |
v_x = (cosine[deg]*gun[POWDER])>>SCALE | |
v_y = (sine[deg]*gun[POWDER])>>SCALE | |
a_y = 0 | |
enemy[FPS] = 0 - int(ticks_ms()) | |
while s_y < max_y and gun[SHOW_T] == 1 and s_y>>SCALE < hill[s_x>>SCALE]: # draw tragectory | |
s_x += v_x | |
s_y += v_y - a_y | |
#LCD.pixel(s_x>>SCALE,s_y>>SCALE,colors[((enemy[FPS]>>3) % 37)]) | |
LCD.pixel(s_x>>SCALE,s_y>>SCALE,0xff) | |
a_y -= 100 | |
enemy[FPS] += 1 | |
@micropython.viper | |
def init_shell(): | |
gun = ptr32(GUN) | |
sine = ptr32(isin) | |
cosine = ptr32(icos) | |
deg = gun[ANGLE]>>SCALE | |
if gun[FIRED] == 1 : return | |
gun[FIRED] = 1 | |
gun[SHELL_XV] = (cosine[deg]*gun[POWDER])>>SCALE | |
gun[SHELL_YV] = (sine[deg]*gun[POWDER])>>SCALE | |
gun[SHELL_X] = gun[BARREL_X]<<SCALE | |
gun[SHELL_Y] = gun[BARREL_Y]<<SCALE | |
gun[SHELL_XA] = 0 | |
gun[SHELL_YA] = 0 | |
init_blast() | |
@micropython.viper | |
def move_shell(): | |
hill = ptr8(HILL) | |
screen = ptr16(LCD.buffer) | |
gun = ptr32(GUN) | |
enemy = ptr32(ENEMY) | |
sine = ptr32(isin) | |
cosine = ptr32(icos) | |
if gun[FIRED] == 1: # draw shell | |
gun[SHELL_X] += gun[SHELL_XV] | |
gun[SHELL_Y] += gun[SHELL_YV] - gun[SHELL_YA] | |
gun[SHELL_YA] -= 100 | |
if gun[SHELL_Y]>>SCALE > hill[gun[SHELL_X]>>SCALE]: | |
gun[FIRED] = 0 | |
init_explode() | |
init_smoke() | |
if gun[SHELL_Y]>>SCALE > MAXSCREEN_Y or gun[SHELL_Y]>>SCALE > hill[gun[SHELL_X]>>SCALE] or gun[SHELL_X]>>SCALE > 159 : | |
gun[FIRED] = 0 | |
if int(distance_asm(gun[SHELL_X]>>SCALE,gun[SHELL_Y]>>SCALE,enemy[MOUNT_X],enemy[MOUNT_Y])) < 10: | |
gun[FIRED] = 0 | |
init_explode() | |
init_smoke() | |
def init_land(): | |
global HILL, HILL_EXP | |
HILL = bytearray(MAXSCREEN_X) | |
HILL_EXP = bytearray(MAXSCREEN_X) | |
h=0 | |
s=0 | |
d=1 | |
max_height = randint(1,60) | |
start = max_height | |
LCD.rect(0,0,MAXSCREEN_X,80,SKYBLUE,1) # sky blue | |
LCD.rect(0,80,MAXSCREEN_X,MAXSCREEN_Y-80,DRKGREEN,1) # green ground | |
for x in range(MAXSCREEN_X): | |
sleep(0.01) | |
LCD.show() | |
if x> 60-start: | |
s+=1 * d | |
h+=s | |
h2 = h//10 | |
if h2>max_height: | |
d=-1 | |
y = MAXSCREEN_Y-h2 | |
LCD.line(x,MAXSCREEN_Y,x,y,BROWN) | |
else: | |
y=127 | |
if y > 127: y = 127 | |
HILL[x] = y | |
HILL_EXP[x] = y | |
def main(): | |
init_imath() | |
init_pot() | |
init_land() | |
init_gun() | |
init_enemy() | |
gc.collect() | |
print(gc.mem_free()) | |
debug_ticks = 0 | |
pot_ticks = 0 | |
shell_ticks = 0 | |
explode_ticks = 0 | |
blast_ticks = 0 | |
smoke_ticks = 0 | |
while not EXIT: | |
gticks = ticks_ms() | |
if gticks-pot_ticks>30: | |
pot_ticks = gticks | |
read_pot() | |
if gticks-shell_ticks>20: | |
shell_ticks = gticks | |
move_shell() | |
if gticks-explode_ticks>20: | |
explode_ticks = gticks | |
explode() | |
if gticks-debug_ticks>500: | |
debug_ticks = gticks | |
if gticks-blast_ticks>20: | |
blast_ticks = gticks | |
calc_blast() | |
if gticks-smoke_ticks>20: | |
smoke_ticks = gticks | |
move_smoke() | |
calc() | |
draw() | |
GUN[FPS] = 1_000//ticks_diff(ticks_ms()+1,gticks) | |
def core1(): | |
global EXIT | |
Pin(16,Pin.OUT).high() | |
x = True | |
mySong = music(bogey, pins=[Pin(17),Pin(3),Pin(4),Pin(5)], tempo=3, looping = False,duty = 2000) # | |
while EXIT == False and x == True: | |
x = mySong.tick() | |
sleep(0.04) | |
x = True | |
mySong = music(o1812, pins=[Pin(17),Pin(3),Pin(4),Pin(5)], tempo=2, looping = False,duty = 2000) | |
while EXIT == False and x == True: | |
x = mySong.tick() | |
sleep(0.04) | |
Pin(16,Pin.OUT).low() | |
print('Core1 Stop') | |
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() | |
@micropython.viper | |
def init_blast(): | |
gun = ptr32(GUN) | |
blast = ptr32(BLAST) | |
for index in range(BLAST_NUM): | |
i = index * 5 | |
blast[i+0] = gun[SHELL_X] | |
blast[i+1] = gun[SHELL_Y] | |
blast[i+2] = gun[SHELL_XV] + int(randint(-4000,4000)) | |
blast[i+3] = gun[SHELL_YV] + int(randint(-4000,4000)) | |
blast[i+4] = int(randint(10,15)) | |
@micropython.viper | |
def calc_blast(): | |
gun = ptr32(GUN) | |
blast = ptr32(BLAST) | |
for index in range(BLAST_NUM): | |
i = index * 5 | |
if blast[i+4] < 1 : continue | |
blast[i+0] += blast[i+2] | |
blast[i+1] += blast[i+3] | |
blast[i+4] -= 1 | |
def fade(input_color1, input_color2): | |
color1=input_color1<<8 | input_color1>>8 # byte swap to normal RBG565 | |
red1 =color1>>11& 0b11111 # extract red #13 | |
green1=color1>>6 & 0b11111 # extract green | |
blue1 =color1 & 0b11111 # extract blue | |
color2=input_color2<<8 | input_color2>>8 # byte swap | |
red2 =color2>>11& 0b11111 # extract red | |
green2=color2>>6 & 0b11111 # extract green | |
blue2 =color2 & 0b11111 # extract blue | |
inc_red =(red2- red1)/31 # find increment step | |
inc_green=(green2-green1)/31 | |
inc_blue =(blue2- blue1)/31 | |
for i in range(0,32): | |
red3 =red1 +int(i*inc_red) # build colors by steps | |
green3=green1+int(i*inc_green) | |
blue3 =blue1 +int(i*inc_blue) | |
color3=red3<<11 | green3<<6 | blue3 # combine RGB | |
COLORS.append((color3 & 0x00FF)<<8 | (color3>>8)) # byte swap to LCD RGB565 | |
SMOKE_PARAMS = const(9) | |
SMOKE_X1 = const(0) # start x | |
SMOKE_Y1 = const(1) # start y | |
SMOKE_X2 = const(2) # moving x | |
SMOKE_Y2 = const(3) # moving y | |
SMOKE_R = const(4) | |
SMOKE_VX = const(5) | |
SMOKE_VY = const(6) | |
SMOKE_C = const(7) | |
SMOKE_ON = const(8) | |
@micropython.viper | |
def init_smoke(): | |
gun = ptr32(GUN) | |
smoke = ptr32(SMOKE) | |
for i in range(SMOKE_NUM): | |
index = i * SMOKE_PARAMS | |
smoke[index+SMOKE_X1] = gun[SHELL_X] | |
smoke[index+SMOKE_Y1] = gun[SHELL_Y] + 40000 | |
smoke[index+SMOKE_X2] = gun[SHELL_X] | |
smoke[index+SMOKE_Y2] = gun[SHELL_Y] + 40000 | |
smoke[index+SMOKE_VX] = int(randint(-700,700)) | |
smoke[index+SMOKE_VY] = int(randint(-5000,-2000)) | |
smoke[index+SMOKE_R] = 1<<SCALE | |
smoke[index+SMOKE_C] = 0 | |
@micropython.viper | |
def move_smoke(): | |
smoke = ptr32(SMOKE) | |
total = 0 | |
for i in range(SMOKE_NUM): | |
index = i * SMOKE_PARAMS | |
y = smoke[index+SMOKE_Y2] | |
if y < (10<<SCALE) : | |
smoke[index+SMOKE_X2] = smoke[index+SMOKE_X1] | |
#smoke[index+SMOKE_Y2] = smoke[index+SMOKE_Y1] | |
smoke[index+SMOKE_R] = 1<<SCALE | |
smoke[index+SMOKE_X2] += smoke[index+SMOKE_VX] | |
smoke[index+SMOKE_Y2] += smoke[index+SMOKE_VY] | |
smoke[index+SMOKE_R] += 1 | |
smoke[index+SMOKE_C] = 0 | |
total += 1 | |
@micropython.viper | |
def draw_smoke(): | |
smoke = ptr32(SMOKE) | |
color = ptr16(COLORS) | |
for i in range(SMOKE_NUM): | |
index = i * SMOKE_PARAMS | |
y = smoke[index+SMOKE_Y2]>>SCALE | |
if y < 10 : continue | |
x = smoke[index+SMOKE_X2]>>SCALE | |
r = smoke[index+SMOKE_R]>>SCALE | |
c = smoke[index+SMOKE_C] | |
r = (smoke[index+SMOKE_Y1] - smoke[index+SMOKE_Y2])>>(SCALE+3) | |
if r < 2: r = 2 | |
c = color[r*3] | |
if r*3<35: | |
LCD.ellipse(x,y,r,r,c,True) | |
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() | |
COLORS = array.array('H', []) | |
fade(0xffff,SKYBLUE) | |
fade(SKYBLUE,SKYBLUE) | |
EXIT = 0 | |
_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