fromkandinskyimport*fromrandomimportrandintfromionimport*fromtimeimportsleepfromosimportlistdir#####################################
# At first we define some constants #
#####################################
PROG_VER="1.9.1"SCREEN_W=320SCREEN_H=222KEYS=[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=2NOTE_SPACE=6NOTE_H=46POLY_MODE=0POLY_ACCURACY=9PERFECT_MODE=1PERFECT_NB=5INFINITE_MODE=0LVL_LEN=100#########################
# We define our classes #
#########################
classVector():"""Describes the structure of a vector"""def__init__(self,x=0,y=0):self.x,self.y=x,yclassColorScheme():"""Defines a simple three-color scheme for tiles"""def__init__(self,primary_color,secondary_color,background_color):self.primary_color=primary_colorself.secondary_color=secondary_colorself.background_color=background_colorclassTile():"""Defines a single tile"""def__init__(self,x:int,start_y:int,end_y:int,size:Vector,speed:int,colors:ColorScheme,order:int):self.x=xself.start_y,self.end_y=start_y,end_yself.size=sizeself.y=self.start_y-self.size.yself.speed=speedself.colors=colorsself.order=orderself.is_active=Falsedefflash(self):color=self.colors.primary_colorhidden_part=self.y+self.size.y-self.end_yifself.is_active:color=self.colors.secondary_colorifhidden_part<0:hidden_part=0ifhidden_part<self.size.y:fill_rect(self.x,self.y,self.size.x,self.size.y-hidden_part,color)defupdate(self):self.y+=self.speedcolor=self.colors.primary_colorhidden_part=self.y+self.size.y-self.end_yifself.is_active:color=self.colors.secondary_colorifhidden_part<0:hidden_part=0ifhidden_part<=self.size.y:fill_rect(self.x,self.y-self.speed,self.size.x,self.speed,self.colors.background_color)ifhidden_part<=self.size.y-self.speed:fill_rect(self.x,self.y+self.size.y-self.speed-hidden_part,self.size.x,self.speed,color)classButton():"""Aiming at replace the one define in NWTK"""def__init__(self,x,y,txt,txt_color,btn_color,bg_color):self.focused=Falseself.x,self.y=x,yself.txt=txtself.txt_color=txt_colorself.btn_color=btn_colorself.bg_color=bg_colordefdraw(self):real_btn_color=self.btn_colorreal_txt_color=self.txt_colorifself.focused:real_btn_color=self.txt_colorreal_txt_color=self.btn_colorfill_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)classNoteGrid():"""Defines a grid and its geometry for tiles"""def__init__(self,w,total_column_nb,padding):self.total_column_nb=total_column_nbself.padding=paddingself.w=wself.x=int(SCREEN_W/2-self.w/2)self.col_w=int(self.w/self.total_column_nb)self.draw()defdraw(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])classNote():"""Defines a single tile"""def__init__(self,Grid,column_nb,y,h,color,active_color,bg_color):self.Grid=Gridself.column_nb=column_nbself.x=Grid.x+Grid.col_w*column_nb+Grid.paddingself.w=Grid.col_w-Grid.padding*2self.y,self.h=y,hself.color,self.bg_color=color,bg_colorself.active_color=active_colorself.speed=1self.active=Falsedefstep(self):ifself.y<200:ifself.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)defflash(self):ifnotself.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)ifself.y>200:fill_rect(self.x,200,self.w,self.y-200,self.bg_color)classTouchLine():"""Defines the deadline for the tiles"""def__init__(self,y,h,color):self.y,self.h=y,hself.color=colordefdraw(self):fill_rect(0,self.y,320,self.h,self.color)classColTxt():"""Defines a single text align within a column"""def__init__(self,y,Grid,column_nb,txt,color,active_color,bg_color):self.y=yself.Grid=Gridself.column_nb=column_nbself.txt=txtself.color=colorself.active_color=active_colorself.bg_color=bg_colorself.active=Falsedefdraw(self,color=None):ifcolor==None:color=self.active_colorifself.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 #
#######################################
deftranstion():foriinrange(222):draw_line(0,i,80,i,[10,10,40])sleep(0.0005)foriinrange(222):draw_line(240,i,320,i,[10,10,40])sleep(0.0005)foriinrange(222):draw_line(80,i,160,i,[10,10,40])sleep(0.0005)foriinrange(222):draw_line(160,i,240,i,[10,10,40])sleep(0.0005)sleep(0.2)defload_score():if"nota.score"inlistdir():file=open("nota.score","r")score=file.readline()file.close()else:file=open("nota.score","w+")score=0file.close()ifscore=="":score=0returnscoredefsave_score(score):file=open("nota.score","w")file.truncate(0)file.write(str(score))file.close()defmain_menu():fill_rect(0,0,320,222,"black")notes=[]color_nb=0pixel=0note_grid=NoteGrid(180,4,4)touch_line=TouchLine(200,2,[212,42,26])txt="PiaNOTA"foriinrange(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=[]foriinkeys: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)whileTrue:foriinKEYS:ifkeydown(i):keys[KEYS.index(i)].active=Truekeys_colors[KEYS.index(i)]=COLORS[randint(0,6)][1]else:keys[KEYS.index(i)].active=Falsekeys[KEYS.index(i)].draw(keys_colors[KEYS.index(i)])ifkeydown(KEY_OK):play_bt.focused=Trueplay_bt.draw()whilekeydown(KEY_OK):passplay()breakdefdown_message(txt_color,color,txt):foriinrange(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)defgame_over(msg=""):down_message([220,220,220],[212,42,26],"Game Over")print(msg)transtion()################################
# And here is the main program #
################################
defplay(starting_score=0):#TODO: Remove these (awful!) global variables
globalINFINITE_MODE,POLY_MODEtranstion()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=0color_nb=0waiting=0score=starting_scoreperfect=0lvl_nb=1best_score=int(load_score())pixel=0sleep_time=0.007col_active={0:0,1:0,2:0,3:0}remains={}foriinKEYS: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)ifINFINITE_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])ifNOTE_SPEED%2!=0:note_speed_margin=NOTE_SPEED-1else:note_speed_margin=NOTE_SPEEDwhileTrue:# Note adding
ifnotwaiting:ifpixel%(NOTE_H+NOTE_SPACE+note_speed_margin)==0:last_note_col=randint(0,3)ifINFINITE_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 !
ifPOLY_MODE:ifrandint(0,6)+randint(0,6)==POLY_ACCURACY:note_col=randint(0,3)whilenote_col-last_note_col<2andnote_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
foriinKEYS:ifkeydown(i)andnotremains[i][0]:col_active[KEYS.index(i)]=1remains[i]=[True,pixel]ifremains[i][0]:ifremains[i][1]+int(NOTE_SPACE*NOTE_SPEED*2)<pixel:remains[i][0]=False# Pause feature
ifkeydown(KEY_OK):whilekeydown(KEY_OK):passdraw_string("Game Paused",int(320/2-11*7/2),int(222/2-14/2),[0,0,0],[200,200,200],1)whilenotkeydown(KEY_OK):passwhilekeydown(KEY_OK):passdraw_string("Game Paused",int(320/2-11*7/2),int(222/2-14/2),[0,0,0],[0,0,0],1)foriinnotes:i.flash()touch_line.draw()# Note step
foriinnotes:i.step()i.speed=NOTE_SPEEDi.y+=NOTE_SPEED# Note activation
ifnoti.active:ifi.y>5andi.y-i.h<touch_line.y:# Note is visible
ifcol_active[i.column_nb]:i.active=Truenotes_active_screen_nb+=1col_active[i.column_nb]=Falsei.flash()# Check if this is the last note
ifnotes.index(i)>notes_active_screen_nb-1andnotPOLY_MODE:ifscore>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+=1ifscore>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
ifPERFECT_MODE:ifi.y+NOTE_SPACE>touch_line.yandi.y-i.h<touch_line.y:perfect+=1elifperfect!=0:perfect=0draw_string("Perfect!",2,120,BG_COLOR,BG_COLOR,1)ifperfect>PERFECT_NB:score+=1ifperfect==PERFECT_NB+1:draw_string("Perfect!",2,120,BG_COLOR,COLORS[color_nb][1],1)# Note escape
ifi.y>280:ifnoti.active:ifscore>best_score:save_score(score)game_over("GO: Note still active !")returnnotes_active_screen_nb-=1notes.remove(i)# Check for active columns
foriincol_active:ifcol_active[i]:ifscore>best_score:save_score(score)game_over("GO: Column activated without reason !")return# Level change
if (score/lvl_nb>LVL_LEN)andscore!=0:ifnotINFINITE_MODE:waiting=1ifwaiting:iflen(notes)==0:color_nb+=1lvl_nb+=1sleep_time-=0.001waiting=0perfect=0draw_string("Perfect!",2,120,BG_COLOR,BG_COLOR,1)iflvl_nb>7:down_message([0,0,0],[255,140,70],"INFINITE MODE Enabled !")save_score(score)transtion()sleep(0.5)INFINITE_MODE=1POLY_MODE=1play(score)returnelse:draw_string(str(lvl_nb),320-30,14,BG_COLOR,COLORS[color_nb][0])pixel+=NOTE_SPEEDtouch_line.draw()ifnotINFINITE_MODE:sleep(sleep_time)# The game loop...
whileTrue:main_menu()
During your visit to our site, NumWorks needs to install "cookies" or use other technologies to collect data about you in order to:
Ensure the proper functioning of the site (essential cookies); and
Track your browsing to send you personalized communications if you have created a professional account on the site and can be contacted (audience measurement cookies).
With the exception of Cookies essential to the operation of the site, NumWorks leaves you the choice: you can accept Cookies for audience measurement by clicking on the "Accept and continue" button, or refuse these Cookies by clicking on the "Continue without accepting" button or by continuing your browsing. You can update your choice at any time by clicking on the link "Manage my cookies" at the bottom of the page. For more information, please consult our cookies policy.