123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353 |
- #!/usr/bin/python
- import time
- import random
- from pad import *
- from serpentdata import *
- from apcmini import APCMini
- """
- Un element du serpent
- contient la position (x et y) et la direction
- """
- class SerpentCase:
- def __init__(self, x, y, dir):
- self.x=x
- self.y=y
- self.dir=dir
-
- # retourne la position dans un tuple
- def pos(self):
- return (self.x, self.y)
-
- #retourne la prochaine position (au pas suivant) sans modifier l'objet
- def peekNext(self):
- if self.dir==SerpentAPCMini.UP:
- return (self.x,(self.y+1)%8)
- elif self.dir==SerpentAPCMini.DOWN:
- return (self.x,(self.y-1)%8)
- elif self.dir==SerpentAPCMini.LEFT:
- return ((self.x-1)%8, self.y)
- elif self.dir==SerpentAPCMini.RIGHT:
- return ((self.x+1)%8, self.y)
- def obstacleFromMatrix(mat):
- out=[]
- for j in range(len(mat)):
- for i in range(len(mat[j])):
- if mat[j][i]:
- out.append((i,len(mat)-j-1))
- return out
-
-
- """
- Classe qui gère le jeu du serpent sur l'AKAI APC Mini
- """
- class SerpentAPCMini(Pad):
- def __init__(self, adapter):
- Pad.__init__(self, adapter)
- SerpentAPCMini.UP=64
- SerpentAPCMini.DOWN=65
- SerpentAPCMini.LEFT=66
- SerpentAPCMini.RIGHT=67
- SerpentAPCMini.EXIT=98
- SerpentAPCMini.EMPTY=0
- SerpentAPCMini.SERPENT=1
- SerpentAPCMini.FRUIT=2
- SerpentAPCMini.OBSTACLE=2
- SerpentAPCMini.SERPENT_COLOR=1
- SerpentAPCMini.FRUIT_COLOR=5
- SerpentAPCMini.OBSTACLE_COLOR=3
-
- self.lastTime=time.time()
- self.dir=SerpentAPCMini.LEFT
- self.changed=False
- self.timeToWait=1
- self.scoreleds=[89,88,87,86,85,84,83,82,71,70]
- self.levels=SERPENT_LEVELS
- self.levelIndex=0
- #self.scoreleds=[70,71,82,83,84,85,86,87,88,89]
-
- """
- Gere les input, notamment l'allumage des leds des boutons directionnels
- """
- def onNoteOn(self, channel, idx, val):
- if idx==SerpentAPCMini.UP and self.serpent[0].dir!=SerpentAPCMini.DOWN:
- self.changed=True
- self.serpent[0].dir=idx;
- self[idx].on()
- elif idx==SerpentAPCMini.DOWN and self.serpent[0].dir!=SerpentAPCMini.UP:
- self.changed=True
- self.serpent[0].dir=idx;
- self[idx].on()
- elif idx==SerpentAPCMini.LEFT and self.serpent[0].dir!=SerpentAPCMini.RIGHT:
- self.changed=True
- self.serpent[0].dir=idx;
- self[idx].on()
- elif idx==SerpentAPCMini.RIGHT and self.serpent[0].dir!=SerpentAPCMini.LEFT:
- self.changed=True
- self.serpent[0].dir=idx;
- self[idx].on()
- elif idx==SerpentAPCMini.EXIT:
- self.stop=True
-
- """
- Gere les input, notamment l'extinction des leds des boutons directionnels
- """
- def onNoteOff(self, channel, idx, val):
- if idx==SerpentAPCMini.UP and self.serpent[0].dir!=SerpentAPCMini.DOWN:
- self[idx].off()
- elif idx==SerpentAPCMini.DOWN and self.serpent[0].dir!=SerpentAPCMini.UP:
- self[idx].off()
- elif idx==SerpentAPCMini.LEFT and self.serpent[0].dir!=SerpentAPCMini.RIGHT:
- self[idx].off()
- elif idx==SerpentAPCMini.RIGHT and self.serpent[0].dir!=SerpentAPCMini.LEFT:
- self[idx].off()
-
- """
- Retourne l'état d'une case d'un jeu (Serpent, fruit, obstacle ou vide)
- """
- def stateAt(self, x, y=None):
- if y==None and (isinstance(x,tuple) or isinstance(x,tuple)):
- y=x[1]
- x=x[0]
-
- for s in self.serpent:
- if s.x==x and s.y==y:
- return SerpentAPCMini.SERPENT
-
- for s in self.fruits:
- if s[0]==x and s[1]==y:
- return SerpentAPCMini.FRUIT
-
- for s in self.obstacle:
- if s[0]==x and s[1]==y:
- return SerpentAPCMini.FRUIT
-
- return SerpentAPCMini.EMPTY
-
-
- """
- Renvoie une position disponible pour un nouveau fruit
- """
- def nextFruit(self):
- for i in range(64):
- x=random.randint(0,7)
- y=random.randint(0,7)
- if self.stateAt(x,y)==SerpentAPCMini.EMPTY:
- return (x,y)
-
- """
- Fonction d'affichage de la grille
- """
- def refresh(self):
- x=[]
- for i in range(8):
- x.append([0,0,0,0,0,0,0,0])
-
- for s in self.fruits:
- x[s[1]][s[0]]=SerpentAPCMini.FRUIT_COLOR
-
- for s in self.serpent:
- x[s.y][s.x]=SerpentAPCMini.SERPENT_COLOR
-
- for s in self.obstacle:
- x[s[1]][s[0]]=SerpentAPCMini.OBSTACLE_COLOR
-
- for j in range(8):
- for i in range(8):
- self[i,j].send(x[j][i])
-
- """
- Vérifie si une collision a lieu
- Retour:
- True -> Collision
- False -> Pas de collision
- """
- def collision(self):
- s=self.serpent[0].pos()
- for i in range(1, len(self.serpent)):
- ss=self.serpent[i].pos()
- if ss[0]==s[0] and ss[1]==s[1]:
- return True
- for o in self.obstacle:
- if o[0]==s[0] and o[1]==s[1]:
- return True
- return False
-
- """
- Affiche les score sur les leds ronde de droite
- """
- def printScore(self): #binary
- for i in range(len(self.scoreleds)):
- if (self.score & (1<<i))>0:
- self[self.scoreleds[i]].on()
- else:
- self[self.scoreleds[i]].off()
-
-
- """
- Fait un pas dans le jeu (un mouvement automatique du serpent)
- """
- def step(self):
- s=(self.serpent[0].x, self.serpent[0].y)
-
- #modification de la vitesse en fonction du score
- self.timeToWait=self.levels[self.levelIndex]['speeds'][self.score]
-
- #vérifie si le serpent mange un fruit
- for x in self.fruits:
- if s[0]==x[0] and s[1]==x[1]:
- l=self.serpent[0]
- self.serpent.append(SerpentCase(l.x, l.y, l.dir))
- for fi in range(len(self.fruits)):
- f=self.fruits[fi]
- if f[0]==l.x and f[1]==l.y:
- self.fruits[fi]=self.nextFruit()
- self.timeToWait*=0.9
- self.score+=1
-
- #bouge le serpent d'un pas
- for xx in reversed(range(len(self.serpent))):
- x=self.serpent[xx]
- if xx==0:
- if x.dir==SerpentAPCMini.UP:
- x.y=(x.y+1)%8
- elif x.dir==SerpentAPCMini.DOWN:
- x.y=(x.y-1)%8
- elif x.dir==SerpentAPCMini.LEFT:
- x.x=(x.x-1)%8
- elif x.dir==SerpentAPCMini.RIGHT:
- x.x=(x.x+1)%8
- else:
- y=self.serpent[xx-1]
- x.x=y.x
- x.y=y.y
- x.dir=y.dir
-
-
- """
- Affiche l'écran de Game Over:
- TODO: Permettre de passer l'écran en appuyant sur une touche
- """
- def gameOver(self):
- self.stop=False
- self.changed=False
-
- # etape 1 affichage score et game over
- txt = Text(" Score:"+str(self.score)+" Game Over! ", (8,4), (0,2))
- txt.setColor(LedButton.RED)
- self.fill(LedButton.RED_BLINK)
- time.sleep(2)
- self.clear()
- for x in range(txt.stepCount()):
- self.showText(txt)
- if self.pollInput()!=None: break
- time.sleep(0.2)
-
-
- # etape 2 affichage score et try again, avec les input pour
- # quitter ou recommencer
- txt = Text(" Score:"+str(self.score)+" Try Again? ", (8,4), (0,4))
- txt.setColor(LedButton.YELLOW)
- yes=Text.letterVector('Y', LedButton.GREEN_BLINK)
- no=Text.letterVector('N', LedButton.RED_BLINK)
- self.mapSubRect(yes, (0,0), (4,4))
- self.mapSubRect(no, (5,0), (9,4))
-
- i=0
- while self.stop==False:
- if i%4==0:
- self.showText(txt)
- self.printScore()
- i=i+1
-
- yesIdx=[0,1,2,3,8,9,10,11,16,17,18,19,24,25,26,27]
- for v in yesIdx:
- if self.getInputState(v):
- return True
-
- noIdx=[4,5,6,7,12,13,14,15,20,21,22,23,28,29,30,31,98]
- for v in noIdx:
- if self.getInputState(v):
- return False
-
- time.sleep(0.05)
-
- """
- Initialise une nouvelle partie
- Retour:
- True: si tous les niveaux sont finis (pas de partie à charger)
- False: si un niveau a été trouvé
- """
- def __newGame(self):
- self.score=0
- self.stop=False
- self.loose=False
- self.serpent=[]
- self.fruits=[]
- if self.levelIndex >= len(self.levels):
- return True
- self.obstacle=obstacleFromMatrix(self.levels[self.levelIndex]['obstacles'])
- self.serpent.append(SerpentCase(4,3,SerpentAPCMini.RIGHT))
- self.serpent.append(SerpentCase(3,3,SerpentAPCMini.RIGHT))
- self.serpent.append(SerpentCase(2,3,SerpentAPCMini.RIGHT))
- self.fruits.append(self.nextFruit())
- self.timeToWait=self.levels[self.levelIndex]['speeds'][self.score]
- return False
-
-
-
- """
- Démarre le jeu, cette fonction boucle durant tout le jeu sur elle même
- TODO: Pouvoir recommencer ou arreter quand on gagne le jeu
- """
- def start(self):
- continuer=True
- nextLevel=False
- while continuer:
- #if self.levelIndex<len(self.levels): ## gagné
- # pass
- #else:
- nextLevel=False
-
- self.__newGame()
-
- self.lastTime=time.time()
- self.clear()
- txt = Text(" Level "+str(self.levelIndex+1)+" ", (8,4), (0,2))
- for x in range(txt.stepCount()-2):
- self.showText(txt)
- if self.pollInput()!=None: break
- time.sleep(0.1)
-
- self.fill(LedButton.GREEN_BLINK)
- time.sleep(2)
-
- while self.loose==False and self.stop==False:
- while self.timeToWait+self.lastTime>time.time() and self.changed==False:
- time.sleep(0.001)
-
- self.step()
- self.refresh()
- self.printScore()
-
- if self.collision():
- break
- self.changed=False
-
- if self.score>=len(self.levels[self.levelIndex]['speeds']):
- self.levelIndex+=1
- nextLevel=True
- break
-
- self.lastTime=time.time()
- if not nextLevel:
- continuer=self.gameOver()
- self.clear()
- return False
|