Toggle Navigation
Hatchery
Eggs
micromarble
__init__.py
Users
Badges
Login
Register
MCH2022 badge?
go to mch2022.badge.team
__init__.py
raw
Content
# # Micro Marble is published under ... # ---------------------------------------------------------------------------- # "THE TSCHUNK-WARE LICENSE" (Revision 23): # Niklas Roy wrote this file. As long as you retain this notice you # can do whatever you want with this stuff. If we meet some day, and you think # this stuff is worth it, you can buy me a tschunk in return # ---------------------------------------------------------------------------- # import buttons import display import ledfx import leds import math import bhi160 import utime import power import light_sensor import vibra import os disp = display.open() #orientation sensor variables sensor = 0 sensors = [{"sensor": bhi160.BHI160Orientation(sample_rate=30), "name": "Orientation"}] gx=0 #global tilt and turn values; reference is display x and y gy=0 gz=0 p_gx=0 p_gy=0 p_gz=0 WIDTH = 159 # screen size HEIGHT = 79 playfield = [] x_array_max = 0 y_array_max = 0 player_x = 0 # position of player on playfield in pixels player_y = 0 new_player_x= 0 new_player_y= 0 player_origin_x = 0 # starting position of player in playfield (px) player_origin_y = 0 playfield_color =(0,0,0) start_color =(0,0,0) playfield_bgnd = 0 max_time =0 level = 1 next_level = False score = 0 # total score bonus = 0 # score of this level light_level = -250 # dims light in background by substracting -n...0 falling = 0 # falling counter starts at 0, kinda drops 1, goes on with 2 calib_x = 360 calib_y = 360 calib_z = 0 timeout_timer = 0 pause_count = 0 lifes = 0 clamp_count = 10 # ball clamp counter extra_time_counter = 0 hiscore = 0 # highest score achieved in games (and saved in file) hilifes = 0 # balls needed for highest score totaltime=0 pf_col_lighted = (0,0,0) # playfield colors under light pf_start_lighted = (0,0,0) BLOCK_SIZE=16 TRACK = ord(':') START = ord('O') GOAL = ord('X') VOID = ord(' ') EOF = ord('E') BOOST_U = ord('<') BOOST_D = ord('>') BOOST_L = ord('^') BOOST_R = ord('v') EXTRA_T = ord('t') OSC_ST1 = ord('1') OSC_ST2 = ord('2') OSC_ST3 = ord('3') OSC_ST4 = ord('4') DROPPER = ord('d') ICE = ord('/') teleporters_visible = 0 # number of teleporters in viewport teleporters = [ [ 0 for i in range(2) ] for j in range(6) ] # screen coordinates of teleporters in viewport tele_block_x = [ 0 for i in range(6) ] # block coordinates of teleporters in playfield tele_block_y = [ 0 for i in range(6) ] teleporting = 0 p_teleporting = 0 start_screen_count = 0 start_screen_b_speed = -35 start_screen_b_pos = 45 start_screen_b_p_pos = 45 calib_count = 0 calib_return_count = 0 calib_return_ax = 0 calib_return_ay = 0 initial_gx = 0 initial_gy = 0 initial_gz = 0 p_initial_gx = 0 p_initial_gy = 0 p_initial_gz = 0 scroll_text = 0 scroll_y = 0 # buttons: p_pressed = 0 pressed = 0 button_top_right = 0 button_bottom_right = 0 button_bottom_left = 0 # game states: START_SCREEN = 0 RUNNING = 1 OVER = 2 WON = 3 TIMEOUT = 4 PAUSED = 5 CALIB = 6 game = START_SCREEN p_game = OVER calib_return = START_SCREEN title = ((1,1,1,1,1,0,2,0,3,3,3,3,0,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0), (1,0,1,0,1,0,0,0,3,0,0,0,0,4,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0), (1,0,1,0,1,0,2,0,3,0,0,0,0,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0), (1,0,0,0,1,0,2,0,3,0,0,0,0,4,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0), (1,0,0,0,1,0,2,0,3,3,3,3,0,4,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0), (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), (5,5,5,5,5,0,6,6,6,6,0,7,7,7,7,0,8,0,0,0,0,9,0,0,0,0,1,1,1,1), (5,0,5,0,5,0,6,0,0,6,0,7,0,0,7,0,8,0,0,0,0,9,0,0,0,0,1,0,0,1), (5,0,5,0,5,0,6,6,6,6,0,7,7,7,7,0,8,8,8,8,0,9,0,0,0,0,1,1,1,1), (5,0,0,0,5,0,6,0,0,6,0,7,0,7,0,0,8,0,0,8,0,9,0,0,0,0,1,0,0,0), (5,0,0,0,5,0,6,0,0,6,0,7,0,0,7,0,8,8,8,8,0,9,9,9,9,0,1,1,1,1)) title_colors=((50,110,200), (50,170,140), (140,170,50), (200,80,50), (140,50,140), (200,50,110), (110,50,170), (80,140,170), (200,200,50)) alphabet=( ((0,1,1,1,0), # 0 (1,0,0,0,1), (1,0,0,0,1), (1,0,0,0,1), (0,1,1,1,0)), ((0,0,1,0,0), # 1 (0,1,1,0,0), (1,0,1,0,0), (0,0,1,0,0), (1,1,1,1,1)), ((0,1,1,1,0), # 2 (0,0,0,0,1), (0,1,1,1,0), (1,0,0,0,0), (1,1,1,1,1)), ((0,1,1,1,0), # 3 (1,0,0,0,1), (0,0,1,1,0), (1,0,0,0,1), (0,1,1,1,0)), ((1,0,0,0,0), # 4 (1,0,1,0,0), (1,1,1,1,1), (0,0,1,0,0), (0,0,1,0,0)), ((1,1,1,1,1), # 5 (1,0,0,0,0), (1,1,1,1,0), (0,0,0,0,1), (0,1,1,1,0)), ((0,1,1,1,1), # 6 (1,0,0,0,0), (1,1,1,1,0), (1,0,0,0,1), (0,1,1,1,0)), ((1,1,1,1,1), # 7 (0,0,0,1,0), (0,0,1,0,0), (0,1,0,0,0), (1,0,0,0,0)), ((0,1,1,1,0), # 8 (1,0,0,0,1), (0,1,1,1,0), (1,0,0,0,1), (0,1,1,1,0)), ((0,1,1,1,0), # 9 (1,0,0,0,1), (0,1,1,1,1), (0,0,0,0,1), (0,1,1,1,0)), ((0,0,0,0,0), # + (0,0,1,0,0), (0,1,1,1,0), (0,0,1,0,0), (0,0,0,0,0)), ((0,0,1,0,0), # A (0,1,0,1,0), (1,1,1,1,1), (1,0,0,0,1), (1,0,0,0,1)), ((1,1,1,1,0), # B (1,0,0,0,1), (1,1,1,1,0), (1,0,0,0,1), (1,1,1,1,0)), ((0,1,1,1,0), # C (1,0,0,0,1), (1,0,0,0,0), (1,0,0,0,1), (0,1,1,1,0)), ((1,1,1,1,0), # D (1,0,0,0,1), (1,0,0,0,1), (1,0,0,0,1), (1,1,1,1,0)), ((1,1,1,1,1), # E (1,0,0,0,0), (1,1,1,1,0), (1,0,0,0,0), (1,1,1,1,1)), ((1,1,1,1,1), # F (1,0,0,0,0), (1,1,1,1,0), (1,0,0,0,0), (1,0,0,0,0)), ((0,1,1,1,0), # G (1,0,0,0,0), (1,0,1,1,1), (1,0,0,0,1), (0,1,1,1,0)), ((1,0,0,0,1), # H (1,0,0,0,1), (1,1,1,1,1), (1,0,0,0,1), (1,0,0,0,1)), ((1,1,1,1,1), # I (0,0,1,0,0), (0,0,1,0,0), (0,0,1,0,0), (1,1,1,1,1)), ((1,1,1,1,1), # J (0,0,0,0,1), (0,0,0,0,1), (1,0,0,0,1), (0,1,1,1,0)), ((1,0,0,0,1), # K (1,0,0,1,0), (1,1,1,1,1), (1,0,0,0,1), (1,0,0,0,1)), ((1,0,0,0,0), # L (1,0,0,0,0), (1,0,0,0,0), (1,0,0,0,0), (1,1,1,1,1)), ((1,0,0,0,1), # M (1,1,0,1,1), (1,0,1,0,1), (1,0,0,0,1), (1,0,0,0,1)), ((1,0,0,0,1), # N (1,1,0,0,1), (1,0,1,0,1), (1,0,0,1,1), (1,0,0,0,1)), ((0,1,1,1,0), # O (1,0,0,0,1), (1,0,0,0,1), (1,0,0,0,1), (0,1,1,1,0)), ((1,1,1,1,0), # P (1,0,0,0,1), (1,1,1,1,0), (1,0,0,0,0), (1,0,0,0,0)), ((0,1,1,1,0), # Q (1,0,0,0,1), (1,0,1,0,0), (1,0,0,1,0), (0,1,1,0,1)), ((1,1,1,1,0), # R (1,0,0,0,1), (1,1,1,1,0), (1,0,0,1,0), (1,0,0,0,1)), ((0,1,1,1,1), # S (1,0,0,0,0), (0,1,1,1,0), (0,0,0,0,1), (1,1,1,1,0)), ((1,1,1,1,1), # T (0,0,1,0,0), (0,0,1,0,0), (0,0,1,0,0), (0,0,1,0,0)), ((1,0,0,0,1), # U (1,0,0,0,1), (1,0,0,0,1), (1,0,0,0,1), (0,1,1,1,0)), ((1,0,0,0,1), # V (1,0,0,0,1), (0,1,0,1,0), (0,1,0,1,0), (0,0,1,0,0)), ((1,0,0,0,1), # W (1,0,0,0,1), (1,0,1,0,1), (1,1,0,1,1), (1,0,0,0,1)), ((1,0,0,0,1), # X (0,1,0,1,0), (0,0,1,0,0), (0,1,0,1,0), (1,0,0,0,1)), ((1,0,0,0,1), # Y (0,1,0,1,0), (0,0,1,0,0), (0,0,1,0,0), (0,0,1,0,0)), ((1,1,1,1,1), # Z (0,0,0,1,0), (0,0,1,0,0), (0,1,0,0,0), (1,1,1,1,1)), ((0,1,0,0,0), # ! (0,1,0,0,0), (0,1,0,0,0), (0,0,0,0,0), (0,1,0,0,0)), ((0,0,0,0,0), # : (0,1,0,0,0), (0,0,0,0,0), (0,1,0,0,0), (0,0,0,0,0)), ((0,0,0,0,0), # ' ' (0,0,0,0,0), (0,0,0,0,0), (0,0,0,0,0), (0,0,0,0,0)), ((0,0,0,0,0), # . (0,0,0,0,0), (0,0,0,0,0), (0,0,0,0,0), (1,0,0,0,0)), ((0,0,0,0,0), # - (0,0,0,0,0), (1,1,1,1,1), (0,0,0,0,0), (0,0,0,0,0)), ((0,0,0,0,0), # / (0,0,0,1,0), (0,0,1,0,0), (0,1,0,0,0), (0,0,0,0,0)), ((0,0,0,0,0), # + (0,0,1,0,0), (0,1,1,1,0), (0,0,1,0,0), (0,0,0,0,0))) #-------------------------------------------------------------- game engine def game_engine(): global game global extra_time_counter global clamp_count global falling global light_level global led_color global loop_count global led_timer global led_unit global p_led_timer global warning global lifes global player_x global player_y global player_x_speed global player_y_speed global p_player_block global new_player_x global new_player_y global player_block_x global p_player_block_x global player_block_y global p_player_block_y global block_below global p_block_below global playfield global player_on_blocks global teleporting global p_teleporting global tele_dest_index global tele_dest_x global tele_dest_y global tele_orig_x global tele_orig_y global tele_distance global tele_block_below global max_time global extra_time_counter global bonus global winning global winning_time global x_player_screen global y_player_screen global show_bonus_timer global pf_start_lighted loop_count+=1 #.................................... extra time effect counter if extra_time_counter>0: extra_time_counter-=1; #.................................... clamp player if clamp_count > 0: clamp_count-=1 #....................................................... light fading / general playfield lighting / light_level goes from 0=normal light to -255=full dark, playfield renderer off if falling>=3: # fade light out to -255 light_level = constrain(int((-256 + light_level*7)/8),-255,0) if game==WON or game==OVER or game==TIMEOUT : # dim light down light_level = int((-50 + light_level*2)/3) elif game==PAUSED: # switch light off light_level=-255 elif game==RUNNING: # fade light in if light_level<0: light_level = constrain(int(light_level/3*2+1),-255,0) #.................................... ambient leds if game==WON: led_color = ( constrain(pf_start_lighted[0] +10-winning*2,0,255), constrain(pf_start_lighted[1] +10-winning*2,0,255), constrain(pf_start_lighted[2] +10-winning*2,0,255)) for led in range(11,15): leds.prep(led, led_color) else: for led in range(11,15): # ambient effect reset leds.prep(led, (0,0,0)) #.................................... timer / led bar if game==RUNNING: led_unit = max_time//11 p_led_timer = led_timer led_timer = 0 warning = 0 if p_led_timer < 2: # blink when little time is left led_h =int (((max_time - loop_count)*2)%led_unit/led_unit*60) # create led blink color led_color=(constrain(playfield_color[0]+led_h-30,0,255), constrain(playfield_color[1]+led_h-30,0,255), constrain(playfield_color[2]+led_h-30,0,255)) warning =int (((max_time - loop_count)*2)%led_unit/led_unit*100) # create synchronized warning oscillator else: led_color = playfield_color for led in range(11): if led_unit * led > max_time - loop_count or show_bonus_timer > led: leds.prep(led, (0,0,0)) else: leds.prep(led, led_color) if(extra_time_counter>0): if abs(12-(extra_time_counter*3)-led)<2: leds.prep(led, start_color) led_timer = led if led_timer < 2 and warning==0: vibra.vibrate(25) if max_time < loop_count: game=TIMEOUT lifes += 1 vibra.vibrate(250) #.................................... calculate speed of player if falling==0 and winning==0 and game!=TIMEOUT: # normal game slip=0 if block_below == ICE: slip=20 player_x_speed = (player_x_speed*(2+slip) + gx/2)/(3.2+slip) player_y_speed = (player_y_speed*(2+slip) + gy/2)/(3.2+slip) if falling==2: # starting to fall: move away from center of last block if abs(p_player_block_x*BLOCK_SIZE+BLOCK_SIZE//2 - player_x) > abs(p_player_block_y*BLOCK_SIZE+BLOCK_SIZE//2 - player_y): if player_x_speed>0: player_x_speed+=1 else: player_x_speed-=1 else: if player_y_speed>0: player_y_speed+=1 else: player_y_speed-=1 #.................................... calculate potential position of player in new loop if falling<20 and winning==0: new_player_x = player_x + constrain(player_x_speed,-BLOCK_SIZE/2+.1,BLOCK_SIZE/2-.1) # center of player in pixels on playfield new_player_y = player_y + constrain(player_y_speed,-BLOCK_SIZE/2+.1,BLOCK_SIZE/2-.1) #---------------------------------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------- S U R F A C E detection #---------------------------------------------------------------------------------------------------------------- if falling==0 and winning==0 and teleporting==0: p_player_block_x = player_block_x # previous block coordinates of player p_player_block_y = player_block_y player_has_moved = False player_block_x = int(new_player_x)//BLOCK_SIZE # block coordinates of player player_block_y = int(new_player_y)//BLOCK_SIZE player_hblock_x = int(new_player_x-BLOCK_SIZE/2)//BLOCK_SIZE # half grid coordinates of player (shift grid by half blocksize) player_hblock_y = int(new_player_y-BLOCK_SIZE/2)//BLOCK_SIZE p_block_below = block_below # remember block of previous loop block_below = VOID # content of block below player if ( player_block_x >= 0 and player_block_x < x_array_max and player_block_y >= 0 and player_block_y < y_array_max ) : block_below=playfield[player_block_x][player_block_y] if(p_player_block_x != player_block_x or p_player_block_y != player_block_y): # moved to new tile? player_has_moved = True # then tick the motor if (p_block_below != DROPPER or p_block_below != DROPPER+1) and block_below==DROPPER: vibra.vibrate(7) # dropping 1 px down elif (p_block_below==DROPPER or p_block_below==DROPPER+1) and block_below!=DROPPER: vibra.vibrate(6) # jumping up 1 px else: vibra.vibrate(4) # crossing tiles #.................................... teleporter p_teleporting = teleporting if game==TIMEOUT: teleporting = 0 p_teleporting = 0 if ((block_below>=65 and block_below<=67) or (block_below>=97 and block_below<=99)): if tele_block_below==False: # happens once when player enters tele block tele_block_below = True if teleporting==0: # teleporter: ABC,abc teleporting = 1 tele_dest_index = 0 if (block_below<97): tele_dest_index = block_below - 62 else: tele_dest_index = block_below - 97 tele_dest_x = tele_block_x[tele_dest_index]* BLOCK_SIZE + BLOCK_SIZE//2 # 0:A, 1:B, 2:C, 3:a, 4:b, 5:c tele_dest_y = tele_block_y[tele_dest_index]* BLOCK_SIZE + BLOCK_SIZE//2 tele_orig_x = new_player_x # center of this teleporter in px tele_orig_y = new_player_y tele_distance = int(math.sqrt((tele_dest_x-tele_orig_x)**2 + (tele_dest_y-tele_orig_y)**2)/10) if (tele_distance<3): tele_distance=3 else: tele_block_below = False # . . . . . . . . . . . . . . . . . . teleporting if teleporting>0: # happens during teleporting teleporting +=1; if teleporting <= tele_distance: # moving to destination teleporter tele_move = teleporting/tele_distance new_player_x = int(tele_dest_x * tele_move + tele_orig_x *(1-tele_move)) new_player_y = int(tele_dest_y * tele_move + tele_orig_y *(1-tele_move)) else: teleporting=0 # reset teleport counter for next teleportation #.................................... booster if block_below==BOOST_U: player_y_speed-=55 vibra.vibrate(15) elif block_below==BOOST_D: player_y_speed+=55 vibra.vibrate(15) elif block_below==BOOST_L: player_x_speed-=55 vibra.vibrate(15) elif block_below==BOOST_R: player_x_speed+=55 vibra.vibrate(15) #.................................... osc stage elif block_below>=OSC_ST1 and block_below<=OSC_ST4: block_i = block_below - OSC_ST1 block_osc = abs((((loop_count//15)+block_i)%4)-2) if block_osc==0: block_below = VOID player_on_blocks = False #.................................... dropper elif block_below >= DROPPER and block_below <=DROPPER+7: if block_below==DROPPER: playfield[player_block_x][player_block_y] = DROPPER+1 elif block_below>DROPPER+1: block_below = VOID player_on_blocks = False #.................................... extra time elif block_below==EXTRA_T and game!=TIMEOUT: vibra.vibrate(12) playfield[player_block_x][player_block_y]=TRACK max_time += 50 extra_time_counter = 5 #.................................... void? -> falling if block_below==VOID and falling==0 and winning==0: falling=1 bonus = 0 lifes +=1 vibra.vibrate(10) if falling >0 and (game==RUNNING or game==TIMEOUT or game==OVER): falling+=1 if falling==20: vibra.vibrate(20) #.................................... goal reached? -> winning if block_below==GOAL and winning==0 and game!=TIMEOUT: winning = 1 # winning state counter, frame based winning_time = loop_count bonus = 0 if winning>0 and game!= PAUSED: winning+=1 player_x_speed=0 player_y_speed=0 this_goal_x = player_block_x*BLOCK_SIZE+BLOCK_SIZE//2 this_goal_y = player_block_y*BLOCK_SIZE+BLOCK_SIZE//2 if abs(player_x-this_goal_x)>1: if player_x > this_goal_x: new_player_x-=1 if player_x < this_goal_x: new_player_x+=1 else: player_x = this_goal_x if abs(player_y-this_goal_y)>1: if player_y > this_goal_y: new_player_y-=1 if player_y < this_goal_y: new_player_y+=1 else: player_y = this_goal_y if winning==9: vibra.vibrate(8) if winning==11: vibra.vibrate(10) if winning==12: vibra.vibrate(25) if winning>10: game = WON #.................................... update player if clamp_count==0: player_x = new_player_x player_y = new_player_y if falling>0: if abs(p_player_block_x*BLOCK_SIZE+BLOCK_SIZE//2 - player_x) > BLOCK_SIZE: player_on_blocks=False if abs(p_player_block_y*BLOCK_SIZE+BLOCK_SIZE//2 - player_y) > BLOCK_SIZE: player_on_blocks=False #.................................... calculate and render playfield ( only if light is on ) if light_level>-250: #.................................... calculate viewport in screen and array pf_orig_x = - player_x + WIDTH/2 - constrain(int(gx),-65,65) # calculate origin of playfield relative to screen origin pf_orig_y = - player_y + HEIGHT/2 - constrain(int(gy),-40,40) x_fine_shift = int(pf_orig_x) % BLOCK_SIZE # shift for fine scrolling y_fine_shift = int(pf_orig_y) % BLOCK_SIZE # #.................................... draw background bgnd_col=constrain(40+(light_level//5),0,40) for bx in range(int(pf_orig_x/3)%12,WIDTH,12): disp.line(bx,0,bx,HEIGHT,col=(bgnd_col,bgnd_col,bgnd_col)) for by in range(int(pf_orig_y/3)%12,HEIGHT,12): disp.line(0,by,WIDTH,by,col=(bgnd_col,bgnd_col,bgnd_col)) #.................................... calculate player x_player_screen = constrain(int(pf_orig_x + player_x),0,WIDTH+1) # in pixels y_player_screen = constrain(int(pf_orig_y + player_y),0,HEIGHT+1) if p_block_below >= DROPPER and p_block_below<=DROPPER+7: falling_gfx = constrain(falling//4+1,1,6) else: falling_gfx = constrain(falling//4,0,6) #.................................... draw player background (if falling) if player_on_blocks==False: draw_player(x_player_screen,y_player_screen,falling_gfx,warning,clamp_count) #.................................... calculate playfield b=abs((loop_count*40)%600-300)-150 # sawtooth oscillator +-75 c1= (constrain(start_color[0]+b+light_level,0,255),constrain(start_color[1]+b+light_level,0,255),constrain(start_color[2]+b+light_level,0,255)) c2= (constrain(start_color[0]-b+light_level,0,255),constrain(start_color[1]-b+light_level,0,255),constrain(start_color[2]-b+light_level,0,255)) teleporters_visible = 0 for x in range(-1,WIDTH//BLOCK_SIZE+1): for y in range(-1,HEIGHT//BLOCK_SIZE+1): #l-r x_array = x - int( pf_orig_x) // BLOCK_SIZE y_array = y - int( pf_orig_y) // BLOCK_SIZE block = VOID if ( x_array >= 0 and x_array < x_array_max and y_array >= 0 and y_array < y_array_max ) : block = playfield[x_array][y_array] if block != VOID : x_start = x * BLOCK_SIZE + x_fine_shift # start and end position of block in pixels on screen x_end = x * BLOCK_SIZE + x_fine_shift + BLOCK_SIZE -2 y_start = y * BLOCK_SIZE + y_fine_shift y_end = y * BLOCK_SIZE + y_fine_shift + BLOCK_SIZE -2 x_start_c = constrain(x_start, 0 , WIDTH) # start and end position constrained to screen limits x_end_c = constrain(x_end , 0 , WIDTH) y_start_c = constrain(y_start, 0 , HEIGHT) y_end_c = constrain(y_end , 0 , HEIGHT) #................................................................................................... #................................................................... D R A W P L A Y F I E L D . #................................................................................................... #.................................................................... lighted playfield_colors pf_col_lighted = (constrain(playfield_color[0]+light_level,0,255), constrain(playfield_color[1]+light_level,0,255), constrain(playfield_color[2]+light_level,0,255)) pf_start_lighted = (constrain(start_color[0]+light_level,0,255), constrain(start_color[1]+light_level,0,255), constrain(start_color[2]+light_level,0,255)) #.................................................................... TILE/TRACK if block == TRACK: disp.rect(x_start_c , y_start_c , x_end_c , y_end_c , col = pf_col_lighted , filled=True) #.................................................................... EXTRA TIME elif block == EXTRA_T: disp.rect(x_start_c , y_start_c , x_end_c , y_end_c , col = pf_col_lighted , filled=True) hlx=constrain(-int(gx),-1,1) # highlight / shadow offset based on gyro sensor hly=constrain(-int(gy),-1,1) xh =x_start + BLOCK_SIZE//2 yh =y_start + BLOCK_SIZE//2-1 ll=int(light_level/2) tx = x_start_c+BLOCK_SIZE//2-2+hlx ty = y_start_c+BLOCK_SIZE//2+2+hly if (tx>=0 and tx<=WIDTH and ty>=0 and ty<=HEIGHT): disp.circ(tx,ty, rad=3, col = (0,0,0), filled=True) #shadow tx = xh ty = yh if (tx>=0 and tx<=WIDTH and ty>=0 and ty<=HEIGHT): cl = constrain(190 + ll,0,255) disp.circ(tx,ty, rad=3, col = (cl,cl,cl), filled=True) # little ball #.................................................................... BOOSTER elif block == BOOST_D: disp.rect(x_start_c , y_start_c , x_end_c , y_end_c , col = pf_col_lighted , filled=True) for i in range(1,6,3): disp.line(constrain( x_start +7 -i , 0 , WIDTH), constrain( y_start +10 -i , 0 , HEIGHT), constrain( x_start +7 +i , 0 , WIDTH), constrain( y_start +10 -i , 0 , HEIGHT),col= c1) elif block == BOOST_U: disp.rect(x_start_c , y_start_c , x_end_c , y_end_c , col = pf_col_lighted , filled=True) for i in range(1,6,3): disp.line(constrain( x_start +7 -i , 0 , WIDTH), constrain( y_start +3 +i , 0 , HEIGHT), constrain( x_start +7 +i , 0 , WIDTH), constrain( y_start +3 +i , 0 , HEIGHT),col= c2) elif block == BOOST_L: disp.rect(x_start_c , y_start_c , x_end_c , y_end_c , col = pf_col_lighted , filled=True) for i in range(1,6,3): disp.line(constrain( x_start +3 +i , 0 , WIDTH), constrain( y_start +7 -i , 0 , HEIGHT), constrain( x_start +3 +i , 0 , WIDTH), constrain( y_start +7 +i , 0 , HEIGHT),col= c1) elif block == BOOST_R: disp.rect(x_start_c , y_start_c , x_end_c , y_end_c , col = pf_col_lighted , filled=True) for i in range(1,6,3): disp.line(constrain( x_start +11 -i , 0 , WIDTH), constrain( y_start +7 -i , 0 , HEIGHT), constrain( x_start +11 -i , 0 , WIDTH), constrain( y_start +7 +i , 0 , HEIGHT),col= c2) #.................................................................... START elif block == START: disp.rect(x_start_c , y_start_c , x_end_c , y_end_c , col = pf_start_lighted , filled=True) #.................................................................... GOAL elif block == GOAL: disp.rect(x_start_c,y_start_c,x_end_c,y_end_c,col = pf_start_lighted, filled=True) disp.rect(constrain(x_start+1,0,WIDTH+1),constrain(y_start+1,0,HEIGHT+1),constrain(x_end-1,0,WIDTH+1),constrain(y_end-1,0,HEIGHT+1),col = c1, filled=False) disp.rect(constrain(x_start+3,0,WIDTH+1),constrain(y_start+3,0,HEIGHT+1),constrain(x_end-3,0,WIDTH+1),constrain(y_end-3,0,HEIGHT+1),col = c2, filled=False) #.................................................................... OSC STAGE elif block >= OSC_ST1 and block <= OSC_ST4: block_i = block - OSC_ST1 block_osc = abs((((loop_count//15)+block_i)%4)-2) if block_osc>=1: osc_col = (constrain(pf_col_lighted[0]-(2-block_osc)*40,0,255), constrain(pf_col_lighted[1]-(2-block_osc)*40,0,255), constrain(pf_col_lighted[2]-(2-block_osc)*40,0,255)) disp.rect(x_start_c , y_start_c , x_end_c , y_end_c , col = osc_col , filled=True) osc_start_x = constrain(x_start+2,0,WIDTH) osc_start_y = constrain(y_start+2,0,HEIGHT) osc_end_x = constrain(x_end-2,0,WIDTH) osc_end_y = constrain(y_end-2,0,HEIGHT) #.................................................................... ICE elif block == ICE: disp.rect(x_start_c , y_start_c , x_end_c , y_end_c , col = pf_start_lighted , filled=False) #.................................................................... DROPPER elif block >= DROPPER and block<=DROPPER+6: drop = block-DROPPER # 0...4 d_x_start = constrain(x_start + drop ,0,WIDTH) d_y_start = constrain(y_start + drop ,0,HEIGHT) d_x_end = constrain(x_end - drop ,0,WIDTH) d_y_end = constrain(y_end - drop ,0,HEIGHT) d_col = (constrain(pf_col_lighted[0]-drop*10,0,255), constrain(pf_col_lighted[1]-drop*10,0,255), constrain(pf_col_lighted[2]-drop*10,0,255)) disp.rect(d_x_start , d_y_start , d_x_end , d_y_end , col = d_col , filled=True) if block >= DROPPER+1 and (player_block_x!=x_array or player_block_y!=y_array): playfield[x_array][y_array]+=1 #.................................................................... TELEPORTER elif (block>=65 and block<=67) or (block>=97 and block<=99): # teleporter: ABC,abc disp.rect(x_start_c , y_start_c , x_end_c , y_end_c , col = pf_start_lighted , filled=False) disp.rect(constrain(x_start_c +3,0, WIDTH), constrain(y_start_c +3,0, HEIGHT), constrain(x_end_c -3,0, WIDTH), constrain(y_end_c -3,0, HEIGHT), col = pf_start_lighted , filled=False) teleporters[teleporters_visible][0] = x_start+BLOCK_SIZE//2 # remember positions for foreground drawing teleporters[teleporters_visible][1] = y_start+BLOCK_SIZE//2 teleporters_visible+=1; #.................................... draw player foreground if player_on_blocks==True: draw_player(x_player_screen,y_player_screen,falling_gfx,warning,clamp_count) #................................................................................................... #................................................................. D R A W F O R E G R O U N D . #................................................................................................... #.................................... teleporter if (teleporters_visible>0): tele_osc = (loop_count%20) tele_color = ( constrain(pf_start_lighted[0] + tele_osc*3 ,0,255), constrain(pf_start_lighted[1] + tele_osc*3 ,0,255), constrain(pf_start_lighted[2] + tele_osc*3 ,0,255)) for i in range(teleporters_visible): x_tele = teleporters[i][0]-1-int(gx/3) y_tele = teleporters[i][1]-1-int(gy/3) tele_size = BLOCK_SIZE // 2 + 6 - (20-tele_osc)//2 disp.circ( constrain( x_tele ,0,WIDTH) ,constrain( y_tele,0,HEIGHT) ,rad = tele_size ,col = tele_color, filled=False) #-------------------------------------------------------------- load score def load_score (): global score global level global lifes global hiscore global hilevel global hilifes global totaltime try: # check if there's a score file with open('/apps/micromarble/score.txt') as stats: score = int(stats.read(8)) level = int(stats.read(4)) lifes = int(stats.read(5)) hiscore = int(stats.read(8)) hilifes = int(stats.read(5)) totaltime = int(stats.read(10)) except: save_score() return #-------------------------------------------------------------- save score def save_score (): with open('/apps/micromarble/score.txt','w+') as stats: stats.write('%08d'%score) stats.write('%04d'%level) stats.write('%05d'%lifes) stats.write('%08d'%hiscore) stats.write('%05d'%hilifes) stats.write('%010d'%totaltime) return #-------------------------------------------------------------- show time out def show_timeout(bx_pos, by_pos): warning='TIME' size = 2 # size of pixels 3=9chars c_pos = bx_pos -14 - timeout_timer color= constrain((10-abs(timeout_timer-10))*40,0,255) for i in range(len(warning)): c = ord(warning[i])-54 if c==-21: #'!' c=37 for x in range(5): # show character for y in range(5): if (alphabet[c][y][x]==1): x_start = x * size + c_pos - int(gx * .2) y_start = y * size + by_pos -20 - int(gy * .2) if x_start >=0 and x_start <=WIDTH and y_start>=0 and y_start<=HEIGHT: disp.pixel(x_start, y_start, col=(color,color,color)) c_pos += 7 * size # increment start position of next character / writing from left to right warning='OUT' size = 2 # size of pixels 3=9chars c_pos = bx_pos - 28 + timeout_timer for i in range(len(warning)): c = ord(warning[i])-54 if c==-21: #'!' c=37 for x in range(5): # show character for y in range(5): if (alphabet[c][y][x]==1): x_start = x * size + c_pos - int(gx * .2) y_start = y * size + by_pos +14 - int(gy * .2) if x_start >=0 and x_start <=WIDTH and y_start>=0 and y_start<=HEIGHT: disp.pixel(x_start, y_start, col=(color,color,color)) c_pos += 7 * size # increment start position of next character / writing from left to right return #-------------------------------------------------------------- show bonus def show_bonus(number, bx_pos, by_pos, bonus_counter): if bonus_counter==9: vibra.vibrate(15) size = 2 # size of pixels 3=9chars digits=len(str(number)) c_pos = bx_pos + (digits*6//2) + 3 for i in range(digits): digit = number % 10 number //= 10 c = digit # c is character index in alphabet list for x in range(5): # show number for y in range(5): if (alphabet[c][y][x]==1): x_start = x * size + c_pos - int(gx * .2) y_start = y * size + by_pos - 37 + (bonus_counter**2)//6- int(gy * .2) if x_start >=0 and x_start <WIDTH and y_start>=0 and y_start<HEIGHT: disp.pixel(x_start, y_start, col=(150+bonus_counter*10,150+bonus_counter*10,150+bonus_counter*10)) c_pos -= 7 * size # increment start position of next character / writing from right to left for x in range(5): # show '+' for y in range(5): if (alphabet[10][y][x]==1): x_start = x * size + c_pos - int(gx * .2) y_start = y * size + by_pos - 37 + (bonus_counter**2)//6- int(gy * .2) if x_start >=0 and x_start <WIDTH and y_start>=0 and y_start<HEIGHT: disp.pixel(x_start, y_start, col=(150+bonus_counter*10,150+bonus_counter*10,150+bonus_counter*10)) return #-------------------------------------------------------------- write text def write_text(text,x_text,y_text,text_col, px_space , fat=False , top_bound=0, bottom_bound=HEIGHT, left_bound=0, right_bound=WIDTH): for i in range(len(text)): c = ord(text[i]) if c>=65: # 'A-Z' c=c-54 elif c>=48 and c<=57: #'0...9' c=c-48 elif c==33: # '!' c=37 elif c==58: # ':' c=38 elif c==32: # ' ' c=39 elif c==46: # '.' c=40 elif c==ord('-'): # '-' c=41 for x in range(5): # show character for y in range(5): if (alphabet[c][y][x]==1): x_start = x * px_space + x_text y_start = y * 2 + y_text if x_start >=left_bound and x_start <=right_bound and y_start>=top_bound and y_start<=bottom_bound: disp.pixel(x_start, y_start, col=text_col) if fat==True: disp.pixel(x_start+1, y_start, col=text_col) x_text += 7 * px_space # increment start position of next character return #-------------------------------------------------------------- draw one 3d line, rotated in x,y,z def draw_3d_line(x1,y1,z1,x2,y2,z2,l_color=(255,255,255),rx = 0,ry = 0,rz = 0,persp = 8, zoom=3 ): zoom = -zoom l_start = (x1,y1,z1) l_end = (x2,y2,z2) l_start = rot_z(l_start, rz) l_end = rot_z(l_end , rz) l_start = rot_x( l_start , rx) l_end = rot_x( l_end , rx) l_start = rot_y(l_start, ry) l_end = rot_y(l_end , ry) screen_s_x = int( ( l_start[0] * zoom * ( l_start[2] + persp ) ) + 80) screen_s_y = int( ( l_start[1] * zoom * ( l_start[2] + persp ) ) + 40) screen_e_x = int( ( l_end[0] * zoom * ( l_end[2] + persp ) ) + 80) screen_e_y = int( ( l_end[1] * zoom * ( l_end[2] + persp ) ) + 40) r_line( screen_s_x, screen_s_y, screen_e_x, screen_e_y, color=l_color) return #-------------------------------------------------------------- draw 3d rectangle, rotated in x,y,z def draw_3d_square(size_x=1, size_y=1, x_pos=0, y_pos=0, z_pos=0, square_col=(255,255,255),rx = 0,ry = 0,rz = 0, persp = 8, zoom=3 , shade=False): #p5z4.5 #size x, size y, pos x, pos y, pos z, color x_pos-=.5 y_pos-=.5 v_start = ( ( x_pos * size_x , y_pos * size_y , z_pos ) , ( x_pos * size_x , ( 1 + y_pos ) * size_y , z_pos ) ) v_end = ( ( (1 + x_pos) * size_x , y_pos * size_y , z_pos ) , ( ( 1 + x_pos ) * size_x , ( 1 + y_pos ) * size_y , z_pos ) ) h_start = ( ( x_pos * size_x , y_pos * size_y , z_pos) , ( ( 1 + x_pos ) * size_x , y_pos * size_y , z_pos ) ) h_end = ( ( x_pos * size_x , ( 1 + y_pos ) * size_y , z_pos) , ( ( 1 + x_pos ) * size_x , ( 1 + y_pos ) * size_y , z_pos ) ) zoom = -zoom #draw square which is rotated in x and y for p in range(2): #............................................. vertical lines v_s = rot_z( v_start[p] , rz) v_e = rot_z( v_end[p] , rz) v_s = rot_x(v_s, rx) v_e = rot_x(v_e, rx) v_s = rot_y(v_s, ry) v_e = rot_y(v_e, ry) screen_v_s_x = int( ( v_s[0] * zoom * ( v_s[2] + persp ) ) + 80) screen_v_s_y = int( ( v_s[1] * zoom * ( v_s[2] + persp ) ) + 40) screen_v_e_x = int( ( v_e[0] * zoom * ( v_e[2] + persp ) ) + 80) screen_v_e_y = int( ( v_e[1] * zoom * ( v_e[2] + persp ) ) + 40) if shade==True: draw_color = ( ( constrain( int( square_col[0] + ( v_s[2] + v_e[2] ) * 20 ) , 0 , 255 )), ( constrain( int( square_col[1] + ( v_s[2] + v_e[2] ) * 20 ) , 0 , 255 )), ( constrain( int( square_col[2] + ( v_s[2] + v_e[2] ) * 20 ) , 0 , 255 ))) else: draw_color = square_col r_line( screen_v_s_x , screen_v_s_y , screen_v_e_x , screen_v_e_y , color = draw_color) #............................................. horizontal lines h_s = rot_z( h_start[p] , rz) h_e = rot_z( h_end[p] , rz) h_s = rot_x(h_s, rx) h_e = rot_x(h_e, rx) h_s = rot_y(h_s, ry) h_e = rot_y(h_e, ry) screen_h_s_x = int( ( h_s[0] * zoom * ( h_s[2] + persp ) ) + 80) screen_h_s_y = int( ( h_s[1] * zoom * ( h_s[2] + persp ) ) + 40) screen_h_e_x = int( ( h_e[0] * zoom * ( h_e[2] + persp ) ) + 80) screen_h_e_y = int( ( h_e[1] * zoom * ( h_e[2] + persp ) ) + 40) if shade==True: draw_color = ( ( constrain( int( square_col[0] + ( h_s[2] + h_e[2] ) * 30 ) , 0 , 255 ) ) , ( constrain( int( square_col[1] + ( h_s[2] + h_e[2] ) * 30 ) , 0 , 255 ) ) , ( constrain( int( square_col[2] + ( h_s[2] + h_e[2] ) * 30 ) , 0 , 255 ) ) ) else: draw_color = square_col r_line( screen_h_s_x , screen_h_s_y , screen_h_e_x , screen_h_e_y , color=draw_color) return #-------------------------------------------------------------- robust line (coordinates can be floats and outside screen - line will still be displayed) def r_line(x1,y1,x2,y2,color=(255,255,255)): if x1>=0 and x1<= WIDTH and x2>=0 and x2<= WIDTH and y1>=0 and y1<= HEIGHT and y2>=0 and y2<= HEIGHT: # line is on screen disp.line(int(x1),int(y1),int(x2),int(y2),col=color) else: if x1>WIDTH: dxa = x1 - x2 # x-distance dxb = WIDTH - x2 r=1 if dxa>0: r = dxb / dxa dy = y1 - y2 # y-distance dy = dy * r y1 = y2 + dy x1 = WIDTH elif x1<0: dxa = x2 - x1 # x-distance dxb = 0 - x2 r=1 if dxa>0: r = dxb / dxa dy = y2 - y1 # y-distance dy = dy * r y1 = y2 + dy x1 = 0 if x2>WIDTH: dxa = x2 - x1 # x-distance dxb = WIDTH - x1 r=1 if dxa>0: r = dxb / dxa dy = y2 - y1 # y-distance dy = dy * r y2 = y1 + dy x2 = WIDTH elif x2<0: dxa = x1 - x2 # x-distance dxb = 0 - x1 r=1 if dxa>0: r = dxb / dxa dy = y1 - y2 # y-distance dy = dy * r y2 = y1 + dy x2 = 0 if y1>HEIGHT: dya = y1 - y2 # y-distance dyb = HEIGHT - y2 r=1 if dya>0: r = dyb / dya dx = x1 - x2 # x-distance dx = dx * r x1 = x2 + dx y1 = HEIGHT elif y1<0: dya = y2 - y1 # y-distance dyb = 0 - y2 r=1 if dya>0: r = dyb / dya dx = x2 - x1 # x-distance dx = dx * r x1 = x2 + dx y1 = 0 if y2>HEIGHT: dya = y2 - y1 # y-distance dyb = HEIGHT - y1 r=1 if dya>0: r = dyb / dya dx = x2 - x1 # x-distance dx = dx * r x2 = x1 + dx y2 = HEIGHT elif y2<0: dya = y1 - y2 # y-distance dyb = 0 - y1 r=1 if dya>0: r = dyb / dya dx = x1 - x2 # x-distance dx = dx * r x2 = x1 + dx y2 = 0 disp.line(constrain(int(x1),0,WIDTH),constrain(int(y1),0,HEIGHT),constrain(int(x2),0,WIDTH),constrain(int(y2),0,HEIGHT),col=color) return #-------------------------------------------------------------- calibrate def show_calib_screen(): global calib_x global calib_y global calib_z global game global calib_count global calib_return_count global p_initial_gx global p_initial_gy global p_initial_gz global initial_gx global initial_gy global initial_gz global start_screen_b_speed global start_screen_b_pos global start_screen_b_p_pos global calib_return_ax global calib_return_ay global calib_return_az global scroll_text #.............................................. init if calib_count == 0: print('calib init') scroll_text = 0 calib_return_count = 0 calib_return_ax = (gx%360)/180*3.1415 calib_return_ay = (gy%360)/180*3.1415 calib_return_az = (gz%90)/180*3.1415 calib_count = 1 calib_x = 0 calib_y = 0 calib_z = 0 p_initial_gx = 0 p_initial_gy = 0 p_initial_gz = 0 initial_gx = 0 initial_gy = 0 initial_gz = 0 start_screen_b_speed = -35 start_screen_b_pos = 45 start_screen_b_p_pos = 45 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ calibration 3d view else: calib_count += 1 trans_in = constrain(40 - calib_count,0,40) trans_fg = ((calib_return_count+ trans_in) ** 2 ) / 6 # foreground transition counter (overlay) 0... trans_bg = ( calib_return_count+ trans_in) * .75 # background transition counter (cube) 0 ... p_initial_gx = initial_gx p_initial_gy = initial_gy p_initial_gz = initial_gz if calib_return_count == 0: initial_gx = (gx%360)/180*3.1415 initial_gy = (gy%360)/180*3.1415 initial_gz = (initial_gz + ((gz%90)-(p_gz%90))/180*3.1415)*.92 rx = initial_gx ry = initial_gy rz = initial_gz #.......................................... draw scale for mx in range(30,WIDTH-9,20): r_line(mx, 15-trans_fg, mx, 19-trans_fg, (0,100,25)) # | l r_line(mx, 60+trans_fg, mx, 64+trans_fg, (0,100,25)) # | r r_line(80,15-trans_fg,80,24-trans_fg,(0,100,25)) # | t r_line(80,37+trans_fg,80,43+trans_fg,(0,100,25)) # | b if trans_fg==0: r_line(80,55,80,64,(0,100,25)) # | c for my in range(20,65,10): r_line(10-trans_fg, my, 14-trans_fg, my,(0,100,25)) # - l r_line(WIDTH-10+trans_fg, my, WIDTH-14+trans_fg, my,(0,100,25)) # - r r_line(21-trans_fg, 40, 30-trans_fg, 40,(0,150,50)) # - l r_line(WIDTH-21+trans_fg, 40, WIDTH-30+trans_fg, 40,(0,100,25)) # - r if trans_fg==0: r_line(77, 40, 83, 40,(0,100,25)) # - c for ri in range(5,20 + constrain(trans_fg*2 ,0,10),10): # dashed circle segments ric1=rot_z((45+trans_fg/2,-2- trans_fg/20 ,0),ri/40) ric2=rot_z((45+trans_fg/2, 2+ trans_fg/20 ,0),ri/40) r_line(80 + ric1[0], 40 + ric1[1], 80 + ric2[0], 40 + ric2[1],(0,100,25)) r_line(80 - ric1[0], 40 + ric1[1], 80 - ric2[0], 40 + ric2[1],(0,100,25)) r_line(80 + ric1[0], 40 - ric1[1], 80 + ric2[0], 40 - ric2[1],(0,100,25)) r_line(80 - ric1[0], 40 - ric1[1], 80 - ric2[0], 40 - ric2[1],(0,100,25)) xs = constrain( int(10-trans_fg) , 0, WIDTH) # rectangle xe = constrain( int(WIDTH-10+trans_fg) , 0, WIDTH) ys = constrain( int(15-trans_fg) , 0, HEIGHT) ye = constrain( int(64+trans_fg) , 0, HEIGHT) disp.rect(xs,ys,xe,ye,col=(0,150,50),filled=False) #.......................................... draw cube for i in range(-1,2): sc = constrain(int((i*30+160)),0,255) div = constrain(trans_bg/26,0,1) draw_3d_square(size_x=1.5+trans_bg/20, size_y=1.5+trans_bg/40, x_pos=0, y_pos=0, z_pos=i*.75+trans_bg/20, square_col=(sc,sc,sc), rx = rx*(1-div) + calib_return_ax*div, ry = ry*(1-div) + calib_return_ay*div, rz = rz*(1-div) + calib_return_az*div, persp = 3-trans_bg/2, zoom=8+trans_bg/12, shade=True ) #...................................................... moving markers mark_x = (int(gx+540)%360) - 180 # -180...180 mx=WIDTH//2-mark_x*140//360 # centered at screen overlay mark_y = (int(gy+540)%360) - 180 # -180...180 my=HEIGHT//2 - mark_y * 50//360 # centered at screen overlay r_line(mx,14-trans_fg/2,mx,21-trans_fg,(0,250,150)) # | marker x r_line(mx,58+trans_fg/2,mx,65+trans_fg,(0,250,150)) # | r_line(9-trans_fg, my, 18-trans_fg/2, my,(0,250,150)) # - marker y r_line(WIDTH-9+trans_fg, my, WIDTH-18+trans_fg/2, my,(0,250,150)) # - if trans_fg==0: r_line(mx-2,my,mx+2,my,(0,250,150)) # +:- r_line(mx,my-2,mx,my+2,(0,250,150)) # +:| rzc = rx # rotary marker rzc1 = rot_z((38+trans_fg/4,0,0),rzc) rzc2 = rot_z((47+trans_fg/3,0,0),rzc) r_line(80 + rzc1[0] , 40 + rzc1[1] , 80 + rzc2[0] , 40 + rzc2[1],(0,250,150)) r_line(80 - rzc1[0] , 40 - rzc1[1] , 80 - rzc2[0] , 40 - rzc2[1],(0,250,150)) #...................................................... black rectangle mask during transition bl_mask=constrain((trans_bg - 16)**2/2,0,100) if bl_mask>0: r_line( 80-bl_mask, 0, 80+bl_mask, 0, (0,0,0) ) r_line( 80-bl_mask, HEIGHT, 80+bl_mask, HEIGHT, (0,0,0) ) r_line( WIDTH, 40-bl_mask, WIDTH, 40+bl_mask,(0,0,0) ) r_line( 0, 40-bl_mask, 0, 40+bl_mask,(0,0,0) ) #...................................................... text overlay write_text('CALIBRATE' , 20 , int(2-trans_fg * 1.33) , (0,250,150),2, False ) write_text('OK' , 17 , int( 69 + trans_fg * 1.33 ) , (0,250,150), 2, True ) if trans_fg == 0: #.................................................. ok arrow for i in range(0,6,2): r_line(10-i ,68+i,10-i ,78-i,(0,100+((calib_count-i)//4)%5*30,30+(((calib_count-i)//4)%5)*30)) #.......................................... vibrate if trans_fg > 0 : vibra.vibrate(5) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ calibration is set - transit to start screen if calib_return_count > 0: calib_return_count += 1 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end of transit return to screen where user came from if calib_return_count == 40: vibra.vibrate(8) calib_return_count = 0 calib_count = 0 game = calib_return disp.clear() #.......................................................... if key is pressed: remember calibration values and prepare transition pressed = buttons.read(buttons.BOTTOM_LEFT) if ( pressed & buttons.BOTTOM_LEFT != 0 ) and calib_return_count == 0 and p_pressed==0: calib_return_count = 1 calib_x = gx calib_y = gy calib_z = gz if rx>3.1415: calib_return_ax = 6.28 else: calib_return_ax = 0 if ry>3.1415: calib_return_ay = 6.28 else: calib_return_ay = 0 print('calibration values: x:'+str(gx)+' y:'+str(gy)+' z:'+str(gz)) return #-------------------------------------------------------------- show start screen def show_start_screen(): global start_screen_count global game global level global score global lifes global loop_count global start_screen_b_pos global start_screen_b_speed global start_screen_b_p_pos start_screen_count+=1 #.................................... draw background for x in range( (int(-gx/3)+100)%12 , WIDTH , 12): disp.line(x,0,x,HEIGHT,col=(40,40,40)) for y in range((int(-gy/3)+100)%12 , HEIGHT , 12): disp.line(0,y,WIDTH,y,col=(40,40,40)) #.................................... microball start_screen_b_p_pos = start_screen_b_pos start_screen_b_speed = (start_screen_b_speed*2 + gx)/3 start_screen_b_pos = start_screen_b_pos + start_screen_b_speed v_time=0 if start_screen_b_pos<0: start_screen_b_pos=0 start_screen_b_speed=abs(start_screen_b_speed*.85) v_time=int(abs(start_screen_b_speed)) if start_screen_b_pos>46: start_screen_b_pos=46 start_screen_b_speed=-abs(start_screen_b_speed*.85) v_time=int(abs(start_screen_b_speed)) if v_time>2 and start_screen_b_p_pos != start_screen_b_pos : vibra.vibrate(constrain(v_time+3,3,8)) draw_player(102+int(start_screen_b_pos),17,-1) #.......................................................... title gfx xs = constrain(int (- gx /12 ),-15, 15 ) for y in range(11): # show title tile for x in range(30): if (title[y][x]>0): tile_color=title_colors[title[y][x]-1] x_start = x * 4 + 21 y_start = y * 4 + 8 if x_start >=0 and x_start <=WIDTH-3 and y_start>=0 and y_start<=HEIGHT-3: disp.rect(x_start, y_start, x_start+2, y_start+2,col=tile_color, filled=True) #.......................................................... draw menu #.......................................................... play arrow xs = 0 # xshift disp.rect(85 + xs ,54,148 + xs ,64,col=(85,85,85),filled=True) for i in range(6): r_line( 149 + i + xs, 54 + i, 149 + i + xs, 64 - i , (110,110,110) ) write_text('PLAY' , 92 + xs , 55 , (255,255,255), 2,True ) #.......................................................... new arrow if (score!=0 or lifes!=1): disp.rect(98 + xs ,68,148 + xs,78,col=(60,60,60),filled=True) for i in range(6): r_line(149+i + xs,68+i,149+i + xs,78-i,(85,85,85)) write_text('NEW' , 106 + xs , 69 , (255,255,255), 2 ) #.......................................................... calib arrow disp.rect(11 + xs ,68,94 + xs ,78,col=(60,60,60),filled=True) for i in range(6): r_line(10-i + xs ,68+i,10-i + xs ,78-i,(85,85,85)) write_text('CALIB.' , 17 + xs , 69 , (255,255,255), 2 ) return #-------------------------------------------------------------- write fx text def fx_text(text,x_text,y_text,text_col, top_bound=0, bottom_bound=HEIGHT, left_bound=0, right_bound=WIDTH): for i in range(len(text)): c = ord(text[i]) if c>=65: # 'A-Z' c=c-54 elif c>=48 and c<=57: #'0...9' c=c-48 elif c==33: # '!' c=37 elif c==58: # ':' c=38 elif c==32: # ' ' c=39 elif c==46: # '.' c=40 elif c==ord('-'): # '-' c=41 elif c==ord('/'): # '/' c=42 for x in range(5): # show character for y in range(5): if (alphabet[c][y][x]==1): x_start = x * 3 + x_text y_start = y * 3 + y_text #y_start += int(math.sin(x_start/12 - pause_count/5)*3) if x_start >=left_bound and x_start <=right_bound and y_start>=top_bound and y_start<=bottom_bound: disp.rect(x_start, y_start,x_start+1,y_start+1, col=text_col, filled=True) x_text += 7 * 3 # increment start position of next character return #-------------------------------------------------------------- draw scroll text line def write_scroll_text(text_line, text_color): global scroll_y if scroll_y>1 and scroll_y<52: fx_text(text_line, WIDTH//2 - (len(text_line) * 21) //2 + 3 , scroll_y , text_color ,top_bound=15 , bottom_bound=49 ) scroll_y += 20 return #-------------------------------------------------------------- draw dashed line (only horizontal and vertical from small coordinate value to large value) def dashed_line(sx,sy,ex,ey, distance, offset, color): offset = offset%(distance*2) if sx == ex: for y in range(sy+offset-distance,ey,distance*2): disp.line(sx,constrain(y,sy,ey),sx,constrain(y+distance,sy,ey),col=color) if sy == ey: for x in range(sx+offset-distance,ex,distance*2): disp.line(constrain(x,sx,ex),sy,constrain(x+distance,sx,ex),sy,col=color) return #-------------------------------------------------------------- show pause screen def show_pause_screen(): global start_screen_count global game global level global score global lifes global loop_count global pause_count global scroll_text global scroll_y pause_count+=1 if pause_count==1: disp.clear() disp.rect(0, 0, WIDTH, 50, col=(0,0,0), filled=True) #--------------------------- headline and frame write_text('GAME PAUSED +++', (333 - pause_count)% 444 - WIDTH - 80, 2 , start_color, 2, True ) write_text('GAME PAUSED +++', (111 - pause_count)% 444 - WIDTH - 80, 2 , start_color, 2, True ) #.......................................................... scroll text text_lines = 12 scroll_text += 1 if scroll_text > text_lines * 20 + 16: scroll_text = 0 scroll_y = 52 - int(scroll_text) write_scroll_text('STAGE' , (200,200,200) ) write_scroll_text(str(level) , (200,200,200) ) write_scroll_text('///' , start_color ) write_scroll_text('MARBLES' , (200,200,200) ) write_scroll_text(str(lifes) , (200,200,200) ) write_scroll_text('///' , start_color ) write_scroll_text('SCORE' , (200,200,200) ) write_scroll_text(str(score) , (200,200,200) ) write_scroll_text('///' , start_color ) write_scroll_text('HISCORE' , (200,200,200) ) write_scroll_text(str(hiscore) , (200,200,200) ) disp.rect(0, 15, WIDTH, 50, col=start_color, filled=False) dashed_line( 0 , 15 , WIDTH , 15 , 5 , pause_count , playfield_color ) dashed_line( WIDTH , 15 , WIDTH , 50 , 5 , pause_count , playfield_color ) dashed_line( 0 , 50 , WIDTH , 50 , 5 , -pause_count , playfield_color ) dashed_line( 0 , 15 , 0 , 50 , 5 , -pause_count , playfield_color ) #.......................................................... draw menu if pause_count==1: scroll_text=0 #--------------------------- play arrowxs = 0 # xshift for i in range(6): r_line( 154 + i , 54 + i, 154 + i , 64 - i , start_color ) write_text('RESUME' , 68 , 55 , (255,255,255), 2,True ) #--------------------------- new arrow if (score!=0 or lifes!=1): for i in range(6): r_line(154+i ,68+i,154+i ,78-i, start_color ) write_text('NEW' , 111 , 69 , start_color , 2, True ) #--------------------------- calib arrow for i in range(6): r_line(5-i ,68+i,5-i ,78-i, start_color ) write_text('CALIB.' , 12 , 69 , start_color , 2 , True) return #-------------------------------------------------------------- load playfield def load_playfield(level): global playfield global x_array_max global y_array_max global player_origin_x global player_origin_y x_array_max = 0 y_array_max = 0 global playfield_color global start_color global playfield_bgnd global max_time global next_level next_level=False clamp_count = 10 # ball clamp counter global tele_block_x # block coordinates of teleporters in playfield global tele_block_y global teleporting global player_x global player_y global new_player_x global new_player_y print('.............................') print(playfield) print('.............................') print('loading file') with open('/apps/micromarble/'+str(level)+'.txt') as field: #........................................ header field.read(2) max_time = int(field.read(4)) field.read(3) red = int(field.read(3)) field.read(3) green = int(field.read(3)) field.read(3) blue = int(field.read(3)) field.read(6) playfield_bgnd = int(field.read(1)) field.read(2) playfield_color = (red,green,blue) start_color = (constrain(red+50,0,255),constrain(green+50,0,255),constrain(blue+50,0,255)) #........................................ load map into array # (here happens a swap between x- and y- axis. It's a bug, but it doesn't really bug me ;) x=0 read_line=True while read_line==True: playfield.append([]) read_char=True y=0 while read_char==True: tile=field.read(1) tile_num=ord(tile) if(tile_num==EOF): #found 'e'? (== end of file) read_char=False read_line=False if(tile_num==START): #found starting point? player_origin_x = x * BLOCK_SIZE + BLOCK_SIZE // 2 player_origin_y = y * BLOCK_SIZE + BLOCK_SIZE // 2 if ((tile_num>=65 and tile_num<=67) or (tile_num>=97 and tile_num<=99)): # found teleporter?! (A,B,C,a,b,c) tele_index = tile_num if tele_index >=97: tele_index -= 94 else: tele_index -= 65 tele_block_x [tele_index] = x # 0:A, 1:B, 2:C, 3:a, 4:b, 5:c tele_block_y [tele_index] = y if(tile_num!=13 and read_char==True): # no new line playfield[x].append(tile_num) # add value to array y+=1 if y>y_array_max: y_array_max=y else: read_char=False if read_line==True: field.read(1) x+=1 x_array_max=x #print('.............................') #print(playfield) #print('.............................') #print('xmax:%i ymax:%i'%(x_array_max,y_array_max)) #print('.............................') try: # check if there's a next level with open('/apps/micromarble/'+str(level+1)+'.txt') as field: next_level=True print('Next level found!') except: next_level=False print('This was the final level!') player_x = player_origin_x player_y = player_origin_y new_player_x = player_origin_x new_player_y = player_origin_y return #-------------------------------------------------------------- reset playfield def reset_playfield(): global playfield global x_array_max global y_array_max for x in range(x_array_max): playfield[x]=[] playfield=[] x_array_max=0 y_array_max=0 print('.......destroyed:..........') print(playfield) print('.............................') print('xmax:%i ymax:%i'%(x_array_max,y_array_max)) print('.............................') return #-------------------------------------------------------------- constrain def constrain(value, minimum, maximum): if value<minimum: value=minimum if value>maximum: value=maximum return value #-------------------------------------------------------------- rotatation matrices def rot_x(p=(1,1,1),a=0): x = math.cos(a) * p[0] + math.sin(a) * p[2] y = p[1] z = -math.sin(a) * p[0] + math.cos(a) * p[2] return (x,y,z) def rot_y(p=(1,1,1),a=0): x = p[0] y = math.cos(a) * p[1] + math.sin(a) * p[2] z = -math.sin(a) * p[1] + math.cos(a) * p[2] return (x,y,z) def rot_z(p=(1,1,1),a=0): x = math.cos(a) * p[0] + math.sin(a) * p[1] y = -math.sin(a) * p[0] + math.cos(a) * p[1] z = p[2] return (x,y,z) #-------------------------------------------------------------- read gyro def read_gyro(): return_value=False samples = sensors[sensor]["sensor"].read() if len(samples) > 0: #get orientation sensor samples sample = samples[0] global gx global gy global gz global p_gx global p_gy global p_gz p_gx = gx p_gy = gy p_gz = gz gx=((-sample.z-calib_x)+3600)%720-360 gy=((-sample.y-calib_y)+3600)%720-360 gz=(( sample.x-calib_z)+3600)%720-360 return_value=True return return_value #-------------------------------------------------------------- draw crosshair def draw_crosshair(x_pos=0,y_pos=0): x=int(constrain(gx/2+10,0,20)) y=int(constrain(gy/2+10,0,20)) disp.rect(x_pos, y_pos, x_pos+20, y_pos+20, col=(64,64,64)) disp.line(x_pos+x, y_pos, x+x_pos, y_pos+20, col=(255,0,0)) disp.line(x_pos, y_pos+y, x_pos+20, y_pos+y, col=(255,0,0)) return #-------------------------------------------------------------- draw player def draw_player(x_pos,y_pos,p_size,warning=0,clamp_count=0): hlx=constrain(-int(gx),-1,1) hly=constrain(int(gy),-1,1) ll=int(light_level/2-falling*4-warning) fill_val = teleporting==0 if teleporting != p_teleporting and (teleporting == 0 or p_teleporting ==0): p_size-=1 vibra.vibrate(320) if teleporting==0: #...................................................... normal player rendering if(extra_time_counter==5): p_size-=1 #for led in range(11,15): #leds.prep(led, (140,140,140)) if p_size<6: disp.circ(constrain(x_pos-2+hlx,0,WIDTH+1),constrain(y_pos+2+hly,0,HEIGHT+1),rad=8-p_size, col = (0,0,0), filled=True)#shadow cl = constrain(190 + ll,0,255) disp.circ(x_pos,y_pos,rad=8-p_size, col = (cl,cl,cl), filled=True) cl = constrain(120 + ll,0,255) disp.circ(x_pos+hlx,y_pos+hly,rad=6-p_size, col = (cl,cl,cl), filled=True) cl = constrain(200 + ll,0,255) disp.circ(x_pos+1,y_pos-1,rad=6-p_size, col = (cl,cl,cl), filled=True) if p_size<2: cl = constrain(255 + ll,0,255) disp.circ(x_pos+1-hlx-p_size//4,y_pos-3-hly-p_size,rad=2, col = (cl,cl,cl), filled=True) # highlight #...................................................... clamp if clamp_count>0: cl = constrain(abs(clamp_count*30-150),0,160) disp.circ(x_pos,y_pos,rad=10+clamp_count//3, col = (cl,cl,cl), filled=False) cl = 200-cl disp.circ(x_pos,y_pos,rad=11+clamp_count, col = (cl,cl,cl), filled=False) if clamp_count==1: vibra.vibrate(9) if clamp_count==9: vibra.vibrate(12) else: #...................................................... ghost player rendering [=[[= teleportation =]]=] tele_osc = abs((teleporting%14)-7) # 0...7 if(game==RUNNING): vibra.vibrate(tele_osc+5) cl = constrain(190 + ll,0,255) disp.circ(x_pos,y_pos,rad=7-p_size, col = (cl,cl,cl), filled=False) disp.circ(x_pos+3+hlx-p_size//4,y_pos-3-hly-p_size//4,rad=1, col = (cl,cl,cl), filled=True) # highlight cl = constrain(80+(20*(tele_osc)) + ll,0,255) ring_color = ( constrain(pf_start_lighted[0] + tele_osc*20 ,0,255), constrain(pf_start_lighted[1] + tele_osc*20 ,0,255), constrain(pf_start_lighted[2] + tele_osc*20 ,0,255)) disp.circ(x_pos,y_pos,rad=12, col = ring_color, filled=False) led_color = ( constrain(pf_start_lighted[0] +(tele_osc*20) -70,0,255), constrain(pf_start_lighted[1] +(tele_osc*20) -70,0,255), constrain(pf_start_lighted[2] +(tele_osc*20) -70,0,255)) for led in range(11,15): leds.prep(led, led_color) return #-------------------------------------------------------------- main with display.open() as disp: pf_orig_x = 0 # origin of playfield (top,left) relative to screen origin (top,left) pf_orig_y = 0 # origin of playfield relative to screen origin pf_width = x_array_max * BLOCK_SIZE # playfield width in pixels pf_height = y_array_max * BLOCK_SIZE # playfield height in pixels player_block_x = 0 # block coordinates of player player_block_y = 0 p_player_block_x = 0 # previous block coordinates of player p_player_block_y = 0 player_x_speed = 0.0 # speed of player player_y_speed = 0.0 loop_count=0 falling = 0 winning = 0 player_on_blocks = True led_timer=11 p_led_timer=11 next_level = False winning_time = 0 show_bonus_timer = 0 bonus = 0 score = 0 warning = 0 lifes = 1 light_level=0 teleporting = False tele_block_below = False # remembers if the block below player is a teleporter or not block_below = 32 # block below player p_block_below = 32 # block below player in previous loop tele_distance = 0 # distance to next teleporter pf_col_lighted = (0,0,0) pf_start_lighted = (0,0,0) load_score () #============================================================================================= Let's go! ============ while True: #---------------------------------------- read orientation sensor if read_gyro(): #updates gx,gy,gz #................................................................................................. #............................................................................. STATE MACHINE ..... #................................................................................................. #---------------------------------------- read brightness sensor and adapt display & led brightness if game!=p_game: bri=light_sensor.get_reading()*4 disp.backlight(constrain(bri,50,100)) led_bri=(bri)/100*8 leds.dim_top(constrain(int(led_bri),4,8)) leds.dim_bottom(constrain(int(led_bri+1),4,8)) p_game = game #.................................... update all buttons p_pressed = pressed pressed = buttons.read(buttons.TOP_RIGHT | buttons.BOTTOM_RIGHT | buttons.BOTTOM_LEFT ) button_top_right = pressed & buttons.TOP_RIGHT != 0 button_bottom_right = pressed & buttons.BOTTOM_RIGHT != 0 button_bottom_left = pressed & buttons.BOTTOM_LEFT != 0 if pressed!=0 and p_pressed==0 and game!=CALIB: vibra.vibrate(15) #.................................... calib if game == CALIB: disp.clear() show_calib_screen() #.................................... start screen if game == START_SCREEN: light_level=0 disp.clear() show_start_screen() #----- check buttons ----- if p_pressed == 0 and button_bottom_left == True: # calibrate print('calib!') game = CALIB disp.clear() if p_pressed == 0 and button_top_right == True: # play p_pressed = pressed print('play!') loop_count = 0 light_level=-75 load_playfield(level) game = RUNNING print ('start screen exit --> loading level %i'%level) disp.clear() if p_pressed == 0 and button_bottom_right == True and (score!=0 or lifes!=1): # new game p_pressed = pressed print('new!') light_level=-75 level = 1 score = 0 lifes = 1 save_score() loop_count = 0 game = RUNNING load_playfield(level) print ('start screen exit --> loading level %i'%level) disp.clear() #.................................... game is running if game == RUNNING: disp.clear() game_engine() if pressed!=0 and p_pressed==0: disp.clear() scroll_text=0 pause_count=0 game = PAUSED #.................................... game is paused if game == PAUSED: if pause_count==0: save_score() calib_return = PAUSED show_pause_screen() #----- check buttons ----- if pause_count>3 and p_pressed == 0 and button_bottom_left == True: # calibrate print('calib!') game = CALIB disp.clear() if pause_count>3 and p_pressed == 0 and button_top_right == True: # play p_pressed = pressed print('play!') clamp_count = 10 light_level=-75 game = RUNNING disp.clear() if pause_count>3 and p_pressed == 0 and button_bottom_right == True and (score!=0 or lifes!=1): # new p_pressed = pressed print('new!') clamp_count = 10 light_level=-75 level = 1 score = 0 lifes = 1 loop_count = 0 save_score() reset_playfield() load_playfield(level) print ('pause screen exit --> loading level %i'%level) game = RUNNING disp.clear() else: pause_count=0 #.................................... game over [ because of falling ] if (falling > 21): save_score() reset_playfield() load_playfield(level) clamp_count = 10 player_x = player_origin_x player_y = player_origin_y player_x_speed = 0.0 # speed of player player_y_speed = 0.0 loop_count=0 falling = 0 winning = 0 player_on_blocks = True led_timer=11 p_led_timer=11 #.................................... game over [ because of timeout ] elif (game==TIMEOUT): disp.clear() game_engine() timeout_timer += 1 if (timeout_timer<20 and timeout_timer>1): show_timeout(x_player_screen,y_player_screen) if (timeout_timer>20): reset_playfield() load_playfield(level) clamp_count = 10 timeout_timer = 0 player_x = player_origin_x player_y = player_origin_y player_x_speed = 0.0 # speed of player player_y_speed = 0.0 loop_count=0 falling = 0 winning = 0 player_on_blocks = True led_timer=11 p_led_timer=11 save_score() game = RUNNING #.................................... game is won: calculate and show score elif (game==WON): disp.clear() game_engine() #.................................... show bonus next to player if winning_time <= max_time: # add up bonus bonus += 2+level//2 winning_time += 20 show_bonus_timer = 10 if(loop_count%2==0): vibra.vibrate(7) for led in range(11): # reduce remaining led bar if led_unit*led > max_time - winning_time: leds.prep(led, (0,0,0)) else: leds.prep(led, playfield_color) led_timer = led leds.update() if show_bonus_timer==0: # bonus is counted up / save score score += bonus bonus = 0 if score > hiscore: # save hiscore hiscore = score hilifes = lifes if next_level==True: level += 1 # level up, reset values clamp_count = 10 print ('level up:%i'%level) reset_playfield() load_playfield(level) player_x = player_origin_x player_y = player_origin_y player_x_speed = 0.0 player_y_speed = 0.0 loop_count=0 falling = 0 winning = 0 player_on_blocks = True led_timer=11 p_led_timer=11 save_score() game = RUNNING else: print("Game complete" , posx=0, posy=20, font=display.FONT16) if show_bonus_timer>3 and winning>12: # draw bonus on screen show_bonus(bonus, x_player_screen, y_player_screen, show_bonus_timer) show_bonus_timer-=1 #..................................... update display and led's #disp.print("%i " % (pause_count) , posx=15, posy=30, font=display.FONT16) disp.update() leds.update()