""" CyclopeSnake v0.5 by Fime https://workshop.numworks.com/python/fime/cyclope_snake """ from kandinsky import * from random import randint from ion import * from time import * LOGO=[ "011101001001100101101111", "110001101010010110001100", "001101011011110101101000", "111001001010010100101111"] INSTRUCTIONS="""Eat the maximum food you can,but dont touch the edges or an other part of the snake ! → arrows : move → if you wait a too long time, the snake gonna be crazy and will go in the opposite direction ! """ #screen config SCREEN_W=320 SCREEN_H=180 #game vars START_SPEED=0.2 SIZE=14 HALF_SIZE=SIZE//2 DIRECTION={"L":[-1,0],"U":[0,-1],"R":[1,0],"D":[0,1]} ANGRY_TIME=5 #colors BG_COLOR=(255,255,255) SDW_COLOR=(150,150,150) EDGE_COLOR=(50,50,50) COLORS=[[205,150,0],[100,175,0],[0,205,100],[0,150,205],[150,0,205],[205,0,50]] #grid config GRID_W=SCREEN_W//SIZE GRID_H=SCREEN_H//SIZE OFFSET_X=SCREEN_W%SIZE OFFSET_Y=SCREEN_H%SIZE LIMIT_X=[OFFSET_X,SCREEN_W-OFFSET_X] LIMIT_Y=[OFFSET_Y,SCREEN_H-OFFSET_Y] START_PO=[GRID_W//2*SIZE+HALF_SIZE+OFFSET_X//2,GRID_H//2*SIZE+HALF_SIZE+OFFSET_Y//2] def game(): """The game fonction. snake parts: list of the snake parts ([x],[y],[part color]) snake length: actual limit size of the snake game score: score best score: best score. saved on snake.sav snake position: head's position snake direction: head's direction food info: food infos ([x],[y],[color]) food timer: for the limit of the angry timer: game timer fps: frame par seconds """ global s_part,s_len,score,best,po,vec,f_info,f_timer,timer,fps #draw the (n) element of snake def drawElement(n): #get element info inf=list(s_part[n]) inf.append((inf[2][0]+50,inf[2][1]+50,inf[2][2]+50)) #fill the main square and the detail fill_rect(inf[0]-HALF_SIZE,inf[1]-HALF_SIZE,SIZE,SIZE,inf[3]) fill_rect(inf[0]-HALF_SIZE//2,inf[1]-HALF_SIZE//2,HALF_SIZE//2*2,HALF_SIZE//2*2,inf[2]) drawShadow(inf) def drawEye(): inf=list(s_part[-1]) fill_rect(inf[0]-HALF_SIZE//2,inf[1]-HALF_SIZE//2,HALF_SIZE//2*2,HALF_SIZE//2*2,BG_COLOR) fill_rect(inf[0]-HALF_SIZE//3+vec[0],inf[1]-HALF_SIZE//3+vec[1],HALF_SIZE//3*2,HALF_SIZE//3*2,EDGE_COLOR) def drawShadow(inf): #draw shadow if get_pixel(inf[0],inf[1]+HALF_SIZE)==(248, 252, 248):#if nothing below, draw shadow fill_rect(inf[0]-HALF_SIZE,inf[1]+HALF_SIZE,SIZE,SIZE//2,SDW_COLOR) def hideElement(n): inf=list(s_part[n])#get part info fill_rect(inf[0]-HALF_SIZE,inf[1]-HALF_SIZE,SIZE,SIZE,BG_COLOR)#hide part hideShadow(inf) def hideShadow(inf): if get_pixel(inf[0]-HALF_SIZE,inf[1]+HALF_SIZE)==(144,148,144):#if shadow below fill_rect(inf[0]-HALF_SIZE,inf[1]+HALF_SIZE,SIZE,SIZE//2,BG_COLOR) if (get_pixel(inf[0],inf[1]-HALF_SIZE-1)!=(248,252,248)) and not(inf[1]-HALF_SIZE-1<OFFSET_Y):#if part above fill_rect(inf[0]-HALF_SIZE,inf[1]-HALF_SIZE,SIZE,HALF_SIZE,SDW_COLOR) def drawFood(): #get element info inf=list(f_info) inf.append([inf[2][0]+50,inf[2][1]+50,inf[2][2]+50]) #fill the main square and the detail fill_rect(inf[0]-HALF_SIZE,inf[1]-HALF_SIZE,SIZE,SIZE,inf[3]) fill_rect(inf[0]-HALF_SIZE,inf[1]-HALF_SIZE,HALF_SIZE//2,SIZE,inf[2]) fill_rect(inf[0],inf[1]-HALF_SIZE,HALF_SIZE//2,SIZE,inf[2]) fill_rect(inf[0]-HALF_SIZE//2-1,inf[1]-HALF_SIZE,HALF_SIZE+1,HALF_SIZE//2+1,EDGE_COLOR) fill_rect(inf[0]-HALF_SIZE//2,inf[1]-HALF_SIZE,HALF_SIZE//2,HALF_SIZE//2,(0,200,100)) fill_rect(inf[0],inf[1]-HALF_SIZE,HALF_SIZE//2,HALF_SIZE//2,(0,150,75)) drawShadow(inf) def hideFood(): inf=list(f_info)#get part info fill_rect(inf[0]-HALF_SIZE,inf[1]-HALF_SIZE,SIZE,SIZE,BG_COLOR)#hide part hideShadow(inf) def randPo(): x=OFFSET_X//2+HALF_SIZE+randint(1,GRID_W-2)*SIZE y=OFFSET_Y//2+HALF_SIZE+randint(1,GRID_H-2)*SIZE return x,y def drawScore(): fill_rect(0,SCREEN_H,320,20,EDGE_COLOR) draw_string("Time: {}s".format(int(monotonic()-timer)),0,SCREEN_H,BG_COLOR,EDGE_COLOR) draw_string("Score: {} ({})".format(score,best),110,SCREEN_H,BG_COLOR,EDGE_COLOR) def drawFoodTmr(val): lenght=int(val*300/ANGRY_TIME) if val<ANGRY_TIME else 300 fill_rect(10,SCREEN_H+20,lenght,20,f_info[2]) if val>=2.5: draw_string("ANGRY",10,SCREEN_H+20,BG_COLOR,f_info[2]) def death_annimation(): for n in range(s_len): #hide the elements from the last to the fist hideElement(n) #s_part.remove(s_part[n]) sleep(1/s_len) for y in range(0,222,10): fill_rect(0,y,SCREEN_W,10,EDGE_COLOR) sleep(0.05) dead_msg="GAME OVER" for y in range(-10,222//2-10,10): draw_string(dead_msg,SCREEN_W//2-5*len(dead_msg),y,BG_COLOR,EDGE_COLOR) sleep(0.05) fill_rect(SCREEN_W//2-5*len(dead_msg),y,10*len(dead_msg),20,EDGE_COLOR) draw_string(dead_msg,SCREEN_W//2-5*len(dead_msg),y,BG_COLOR,EDGE_COLOR) x,y=SCREEN_H//2,SCREEN_H//2-40 #init vars s_part,s_len,s_color,hue,f_hue,po=[],5,COLORS[0],0,0,list(START_PO) f_info, f_timer,angry=[randPo()[0],randPo()[1],COLORS[0]],float(monotonic()),0 score,key,frame,frame_count,timer,speed=0,"L",1,0,float(monotonic()),START_SPEED best=int(readBestScore()) print(str(po)) #init screen fill_rect(0,0,320,222,EDGE_COLOR) fill_rect(OFFSET_X//2,OFFSET_Y//2,SCREEN_W-OFFSET_X,SCREEN_H-OFFSET_Y,(BG_COLOR)) drawFood() print("Starting game...") while True: frame_count+=1 #frame for move if monotonic()-frame>=speed: #fps fps=int(frame_count/(monotonic()-timer)) #reset second count frame=monotonic() vec=list(DIRECTION[key])#get direction po[0]+=vec[0]*SIZE#change position po[1]+=vec[1]*SIZE #score drawScore() #dead hitbox dead=0 if LIMIT_X[0]>po[0] or po[0]>LIMIT_X[1]:#out of area dead=1 elif LIMIT_Y[0]>po[1] or po[1]>LIMIT_Y[1]: dead=1 if po[0:2] in [s_part[n][0:2] for n in range(len(s_part))]: dead=1 print("touch") if dead: print("Game over...\nFrame count : {}\nGame during : {}\nFps : {}\nScore : {}\nSpeed : {}".format(frame_count,monotonic()-timer,fps,score,speed)) death_annimation()#game over saveScore(best) break else:#normal move #actualize position s_part.append([po[0],po[1],s_color]) change_color=0 #food hitbox if po[0:2]==f_info[0:2]: hideFood() s_len+=1 score+=1000 speed=speed/1.02 f_timer=monotonic() fill_rect(0,SCREEN_H+20,320,20,EDGE_COLOR) change_color=1 loop=0 f_hue=0 if f_hue==len(COLORS)-1 else f_hue+1 f_info[2]=COLORS[f_hue] while True: f_info[0:2]=randPo()[0],randPo()[1] loop+=1 if not f_info[0:2] in [i[0:2] for i in s_part]: break if loop>GRID_W*GRID_H: break hue=f_hue for n in range(len(s_part)): s_part[n][2]=COLORS[hue] drawElement(n) drawFood() score+=20 if score>best: best=score if monotonic()-f_timer>=ANGRY_TIME: angry=1 change_color=1 hue=0 if hue==len(COLORS)-1 else hue+1 draw_string("CRAZY !",10,SCREEN_H+20,BG_COLOR, f_info[2]) else: angry=0 drawFoodTmr(monotonic()-f_timer) s_color=COLORS[hue] if len(s_part)>=2: drawElement(-2) drawElement(-1) drawEye() if len(s_part)>s_len:#len limit hideElement(0) s_part.remove(s_part[0]) #controls if keydown(KEY_LEFT) and vec[0]==0: key="R" if angry else "L" elif keydown(KEY_UP) and vec[1]==0: key="D" if angry else "U" elif keydown(KEY_RIGHT) and vec[0]==0: key="L" if angry else "R" elif keydown(KEY_DOWN) and vec[1]==0: key="U" if angry else "D" ######game over text="\t\tScore :{}\n\t\tBest Score :{}".format(score,best) x=320//2-(len(LOGO[0])*10)//2 drawLogo(x,10,10,BG_COLOR) draw_string(text,0,150,BG_COLOR,EDGE_COLOR) while True: if keydown(KEY_OK): while keydown(KEY_OK): pass break if int(monotonic())%2==1: draw_string("press <OK>",220,200,(255,100,100),EDGE_COLOR) else: fill_rect(220,200,140,20,EDGE_COLOR) game() def main_menu(): """the main menu""" fill_rect(0,0,320,222,EDGE_COLOR) x=320//2-(len(LOGO[0])*10)//2 drawLogo(x,5,10,BG_COLOR) draw_string(INSTRUCTIONS,0,60,(150,150,150),EDGE_COLOR) while True: if keydown(KEY_OK): while keydown(KEY_OK): pass break if int(monotonic())%2==1: draw_string("press <OK>",220,200,(255,50,50),EDGE_COLOR) else: fill_rect(220,200,140,20,EDGE_COLOR) game() def drawLogo(x,y,size,color): """draw the logo at [x,y] with the specified size for each pixel and the specified color """ for yOf in range(len(LOGO)): for xOf in range(len(LOGO[yOf])): if LOGO[yOf][xOf]=="1": fill_rect(x+xOf*size,y+yOf*size,size,size,color) def readBestScore(): """ read and return the best score saved in snake.sav return 0 if reading failed """ try: file=open("snake.sav","r") best=file.readline() file.close() return int(best) except: return 0 def saveScore(score): """ erase the actual best score in snake.sav then write [score] on it. """ try: file=open("snake.sav","w") file.truncate(0) file.write(str(score)) file.close() except: pass main_menu()