Pianota 🎶 Un remix de PianoTiles en Python pour la calculatrice graphique Numworks (Omega/Upsilon). https://git.dynacloud.ynh.fr/lleblanc/pianota
🔥 Installation Pianota dépend de la bibliothèque graphique NwTK, disponible à cette adresse : https://git.dynacloud.ynh.fr/lleblanc/nwtk
🐛 Suggestions ou bug trouvé Si jamais vous avez une merveilleuse idée d’amélioration ou bien que vous tombez subitement sur un fonctionnement anormal, n’hésitez surtout pas à ouvrir un ticket ! Merci d’avance de votre contribution ! 😉
from kandinsky import * from random import randint from ion import * from time import sleep from os import listdir ##################################### # At first we define some constants # ##################################### PROG_VER = "1.9.2" SCREEN_W = 320 SCREEN_H = 222 KEYS = [KEY_COSINE,KEY_TANGENT,KEY_PI,KEY_SQRT] COLORS = [([22,102,222],[80,160,255]), ([140,80,180],[215,155,255]), ([180,50,50],[255,125,125]), ([180,60,30],[255,135,100]), ([180,140,0],[255,215,75]), ([0,180,40],[75,255,115]), ([180,180,180],[240,240,240])] BG_COLOR = [0,0,0] NOTE_SPEED = 2 NOTE_SPACE = 6 NOTE_H = 46 POLY_MODE = 0 POLY_ACCURACY = 9 PERFECT_MODE = 1 PERFECT_NB = 5 INFINITE_MODE = 0 LVL_LEN = 100 ######################### # We define our classes # ######################### class Button(): """Aiming at replace the one define in NWTK""" def __init__(self,x,y,txt,txt_color,btn_color,bg_color): self.focused = False self.x,self.y = x,y self.txt = txt self.txt_color = txt_color self.btn_color = btn_color self.bg_color = bg_color def draw(self): real_btn_color = self.btn_color real_txt_color = self.txt_color if self.focused: real_btn_color = self.txt_color real_txt_color = self.btn_color fill_rect(self.x,self.y,len(self.txt)*7 + 4,14 + 4,real_btn_color) draw_string(self.txt,self.x + 2,self.y + 2,real_txt_color,real_btn_color,1) set_pixel(self.x,self.y,self.bg_color) set_pixel(self.x + len(self.txt)*7 + 4 - 1,self.y,self.bg_color) set_pixel(self.x + len(self.txt)*7 + 4 - 1,self.y + 14 + 4 - 1,self.bg_color) set_pixel(self.x,self.y + 14 + 4 - 1,self.bg_color) class NoteGrid(): """Defines a grid and its geometry for tiles""" def __init__(self,w,total_column_nb,padding): self.total_column_nb = total_column_nb self.padding = padding self.w = w self.x = int(SCREEN_W/2-self.w/2) self.col_w = int(self.w/self.total_column_nb) self.draw() def draw(self): draw_line(self.x,0,self.x,SCREEN_H,[60,60,60]) draw_line(int(self.x+self.col_w*1),0,int(self.x+self.col_w*1),SCREEN_H,[60,60,60]) draw_line(int(self.x+self.col_w*2),0,int(self.x+self.col_w*2),SCREEN_H,[60,60,60]) draw_line(int(self.x+self.col_w*3),0,int(self.x+self.col_w*3),SCREEN_H,[60,60,60]) draw_line(int(self.x+self.col_w*4),0,int(self.x+self.col_w*4),SCREEN_H,[60,60,60]) class Note(): """Defines a single tile""" def __init__(self,Grid,column_nb,y,h,color,active_color,bg_color): self.Grid = Grid self.column_nb = column_nb self.x = Grid.x + Grid.col_w * column_nb + Grid.padding self.w = Grid.col_w - Grid.padding * 2 self.y,self.h = y,h self.color,self.bg_color = color,bg_color self.active_color = active_color self.speed = 1 self.active = False def step(self): if self.y < 200: if self.active: fill_rect(self.x,self.y,self.w,self.speed,self.active_color) else: fill_rect(self.x,self.y,self.w,self.speed,self.color) fill_rect(self.x,self.y-self.h,self.w,self.speed,self.bg_color) def flash(self): if not self.active: fill_rect(self.x,self.y-self.h,self.w,self.h,self.color) else: fill_rect(self.x,self.y-self.h,self.w,self.h,self.active_color) if self.y > 200: fill_rect(self.x,200,self.w,self.y-200,self.bg_color) class TouchLine(): """Defines the deadline for the tiles""" def __init__(self,y,h,color): self.y,self.h = y,h self.color = color def draw(self): fill_rect(0,self.y,320,self.h,self.color) class ColTxt(): """Defines a single text align within a column""" def __init__(self,y,Grid,column_nb,txt,color,active_color,bg_color): self.y = y self.Grid = Grid self.column_nb = column_nb self.txt = txt self.color = color self.active_color = active_color self.bg_color = bg_color self.active = False def draw(self,color=None): if color == None: color = self.active_color if self.active: draw_string(self.txt,int(self.Grid.x+self.Grid.col_w*self.column_nb)+int(self.Grid.col_w/2-len(self.txt)*7/2),self.y,color,self.bg_color,1) else: draw_string(self.txt,int(self.Grid.x+self.Grid.col_w*self.column_nb)+int(self.Grid.col_w/2-len(self.txt)*7/2),self.y,self.color,self.bg_color,1) ####################################### # Now we define some useful functions # ####################################### def transtion(): for i in range(222): draw_line(0,i,80,i,[10,10,40]) sleep(0.0005) for i in range(222): draw_line(240,i,320,i,[10,10,40]) sleep(0.0005) for i in range(222): draw_line(80,i,160,i,[10,10,40]) sleep(0.0005) for i in range(222): draw_line(160,i,240,i,[10,10,40]) sleep(0.0005) sleep(0.2) def load_score(): if "nota.score" in listdir(): file = open("nota.score","r") score = file.readline() file.close() else: file = open("nota.score","w+") score = 0 file.close() if score == "": score = 0 return score def save_score(score): file = open("nota.score","w") file.truncate(0) file.write(str(score)) file.close() def main_menu(): fill_rect(0,0,320,222,"black") notes = [] color_nb = 0 pixel = 0 note_grid = NoteGrid(180,4,4) touch_line = TouchLine(200,2,[212,42,26]) txt = "PiaNOTA" for i in range(len(txt)): draw_string(txt[i],int(125+i*10),50,[0,0,0],COLORS[i][1]) draw_string("A PianoTiles remix!",92,70,[200,200,200],[0,0,0],1) keys = [ColTxt(160,note_grid,0,"[cos]",[100,100,100],[240,240,240],[0,0,0]), ColTxt(160,note_grid,1,"[tan]",[100,100,100],[240,240,240],[0,0,0]), ColTxt(160,note_grid,2,"[pi]",[100,100,100],[240,240,240],[0,0,0]), ColTxt(160,note_grid,3,"[sqrt]",[100,100,100],[240,240,240],[0,0,0])] keys_colors = [] for i in keys: i.draw() keys_colors.append(COLORS[randint(0,6)][1]) play_bt = Button(134,120,"PLAY !",[255,255,255],[32,112,232],[0,0,0]) play_bt.draw() draw_string("Best score: ",10,198,[220,60,70],[0,0,0],1) draw_string(str(load_score()),90,195,[255,80,90],[0,0,0]) draw_string("V "+str(PROG_VER),320-12-int((2+len(str(PROG_VER)))*7),198,[255,140,70],BG_COLOR,1) while True: for i in KEYS: if keydown(i): keys[KEYS.index(i)].active = True keys_colors[KEYS.index(i)] = COLORS[randint(0,6)][1] else: keys[KEYS.index(i)].active = False keys[KEYS.index(i)].draw(keys_colors[KEYS.index(i)]) if keydown(KEY_OK): play_bt.focused = True play_bt.draw() while keydown(KEY_OK): pass play() break def down_message(txt_color,color,txt): for i in range(24): draw_line(0,200-i,320,200-i,color) sleep(0.01) draw_string(txt,int(SCREEN_W/2-len(txt)*10/2),180,txt_color,color) sleep(2.5) def game_over(msg=""): down_message([220,220,220],[212,42,26],"Game Over") print(msg) transtion() ################################ # And here is the main program # ################################ def play(starting_score=0): #TODO: Remove these (awful!) global variables global INFINITE_MODE,POLY_MODE transtion() fill_rect(0,0,320,222,[0,0,0]) note_grid = NoteGrid(180,4,4) touch_line = TouchLine(200,2,[212,42,26]) notes = [] notes_active_screen_nb = 0 color_nb = 0 waiting = 0 score = starting_score perfect = 0 lvl_nb = 1 best_score = int(load_score()) pixel = 0 sleep_time = 0.007 col_active = {0:0,1:0,2:0,3:0} remains = {} for i in KEYS: remains[i] = [False,0] draw_string("Score :",0,0,[220,220,220],[0,0,0],1) draw_string(str(score),0,14,[200,120,80],[0,0,0]) draw_string("Level :",320-49,0,[220,220,220],[0,0,0],1) if INFINITE_MODE: draw_string("...",320-30-14,14,[0,0,0],COLORS[6][1]) else: draw_string(str(lvl_nb),320-30,14,[0,0,0],COLORS[color_nb][0]) if NOTE_SPEED % 2 != 0: note_speed_margin = NOTE_SPEED-1 else: note_speed_margin = NOTE_SPEED while True: # Note adding if not waiting: if pixel % (NOTE_H+NOTE_SPACE+note_speed_margin) == 0: last_note_col = randint(0,3) if INFINITE_MODE: color_nb = randint(0,len(COLORS)-1) notes.append(Note(note_grid,last_note_col,-(NOTE_H+NOTE_SPACE),NOTE_H,COLORS[color_nb][0],COLORS[color_nb][1],[0,0,0])) # Poly-Mode feature ! if POLY_MODE: if randint(0,6)+randint(0,6) == POLY_ACCURACY: note_col = randint(0,3) while note_col - last_note_col < 2 and note_col - last_note_col > -2: note_col = randint(0,3) notes.append(Note(note_grid,note_col,-(NOTE_H+NOTE_SPACE),NOTE_H,COLORS[color_nb][0],COLORS[color_nb][1],[0,0,0])) # Key listener for i in KEYS: if keydown(i) and not remains[i][0]: col_active[KEYS.index(i)] = 1 remains[i] = [True,pixel] if remains[i][0]: if remains[i][1]+int(NOTE_SPACE*NOTE_SPEED*2) < pixel: remains[i][0] = False # Pause feature if keydown(KEY_OK): while keydown(KEY_OK): pass draw_string("Game Paused",int(320/2-11*7/2),int(222/2-14/2),[0,0,0],[200,200,200],1) while not keydown(KEY_OK): pass while keydown(KEY_OK): pass draw_string("Game Paused",int(320/2-11*7/2),int(222/2-14/2),[0,0,0],[0,0,0],1) for i in notes: i.flash() touch_line.draw() # Note step for i in notes: i.step() i.speed = NOTE_SPEED i.y += NOTE_SPEED # Note activation if not i.active: if i.y > 5 and i.y-i.h < touch_line.y: # Note is visible if col_active[i.column_nb]: i.active = True notes_active_screen_nb += 1 col_active[i.column_nb] = False i.flash() # Check if this is the last note if notes.index(i) > notes_active_screen_nb -1 and not POLY_MODE: if score > best_score: save_score(score) game_over("GO: Note activated was not the last one !") print("DBG: Note index was "+str(notes.index(i))) return # Update score score += 1 if score > best_score: draw_string(str(score),0,14,[0,0,0],[220,120,80]) else: draw_string(str(score),0,14,[220,120,80],[0,0,0]) # Pixel perfect feature if PERFECT_MODE: if i.y+NOTE_SPACE > touch_line.y and i.y-i.h < touch_line.y: perfect += 1 elif perfect != 0: perfect = 0 draw_string("Perfect!",2,120,BG_COLOR,BG_COLOR,1) if perfect > PERFECT_NB: score += 1 if perfect == PERFECT_NB+1: draw_string("Perfect!",2,120,BG_COLOR,COLORS[color_nb][1],1) # Note escape if i.y > 280: if not i.active: if score > best_score: save_score(score) game_over("GO: Note still active !") return notes_active_screen_nb -= 1 notes.remove(i) # Check for active columns for i in col_active: if col_active[i]: if score > best_score: save_score(score) game_over("GO: Column activated without reason !") return # Level change if (score/lvl_nb > LVL_LEN) and score != 0: if not INFINITE_MODE: waiting = 1 if waiting: if len(notes) == 0: color_nb += 1 lvl_nb += 1 sleep_time -= 0.001 waiting = 0 perfect = 0 draw_string("Perfect!",2,120,BG_COLOR,BG_COLOR,1) if lvl_nb > 7: down_message([0,0,0],[255,140,70],"INFINITE MODE Enabled !") save_score(score) transtion() sleep(0.5) INFINITE_MODE = 1 POLY_MODE = 1 play(score) return else: draw_string(str(lvl_nb),320-30,14,BG_COLOR,COLORS[color_nb][0]) pixel += NOTE_SPEED touch_line.draw() if not INFINITE_MODE: sleep(sleep_time) # The game loop... while True: main_menu()