Un Tetris en python pour la NumWorks


Accueil > Projets > Un Tetris en python pour la NumWorks

Par Fedyna Kevin, Robert Vincent en mai 2020

Tout le monde sait qu’une calculatrice programmable sert à jouer à des jeux. Or quand on parle de jeux, un des premiers à nous venir en tête est Tetris, alors pourquoi pas un Tetris pour NumWorks ?

Ainsi, après un démineur, un snake, on vous propose cette fois ci le jeu mythique de la gameboy adapté en flat design et codé en python pour la NumWorks.

Donne moi 32 ko, je te ferai un Tetris !

Jusqu’à la version 13.2 d’Epsilon, l’OS officiel de la NumWorks, faire un jeu en python sur la couche graphique de la NumWorks était impossible et les scripts commençaient à planter dès qu’ils pesaient 3-4 ko.

Avec un tas python heap de 32 ko, on peut enfin commencer à s’amuser et monter des projets dont le code source pèse près de 8ko.

L’histoire de la création d’un jeu en image

Tout commença le 19 avril dans une nuit confinée.

Bon on vient de finir nos trois projets en python, on fait quoi maintenant ?

(...)

Oh on peut acheter des contrefaçon de Gameboy sur Aliexpress pour 10€ ! Et il y a 400 jeux dedans.

(...)

La nuit porte conseil, on en parle demain, enfin dans quelques heures !

Bon on fait un Tetris. Je viens de lire l’article sur Wikipédia, c’est passionnant. Par contre par un mot à Arthur, il va nous piquer notre idée sinon.

Et cette fois, on ne stocke pas coordonnées des cases occupées dans des matrices, et on va utiliser la fonction get_pixel de la NumWorks pour déterminer si une case est occupée ou non.

et c’est ainsi qu’un premier Tétrominos apparaît à l’écran.

J’ai peut être fini la collision.
Hein ?! Mais j’ai pas commencé moi...

Bon je partage l’écran. Qu’est ce qu’on a dit déjà ? 120 pixels pour le menu, 120 pixels pour le score et 42 pixels pour le jeu en lui même c’est bien ça ?

Bon je viens de finir la maquette d’une ébauche de menu, reste à le coder !

Pour les couleurs ça sera délicat et subtil. On va s’écarter du code couleur original.

Et du coup on va faire un rappel dans le menu !

On fixe les points d’ancrage dans les pièces

Et ainsi elle peuvent tourner !

Rendu final souhaité :

Bon la fonctionnalité "ombre" on la laisse tomber, on ne dispose pas d’un tas python de 42 ko non plus hein !

Si tu joues sur l’OS Omega, alors l’interface du jeu n’est plus orange mais rouge, elle s’adapte au fork de Epsilon.

D’ailleurs faudra que je relance l’équipe de développement de Omega, ils m’ont promis un tas python de 120 ko et j’ai l’impression que ce projet n’avance pas !

Bon ils sont encore sur répondeur, ils ont du bloquer mon numéro !

On fait une pause, j’ai envie de jouer un peu :

Bon je vais spoiler Critor & tiplanet mais toujours aucune info à Arthur !

Score codé, avec des fonctions polynôme et les points marqués dépendent du niveau du jeu ...

Niveau max : 99, Score max : 999 999

Vitesse du jeux codé, avec une fonction logarithme népérien car un polynôme n’était pas adapté ...

Bon maintenant s’agit de faire un gros score, histoire d’être certain que Critor ne nous batte pas !

Commencé un dimanche, fini le mercredi suivant, c’était presque trop facile !

Je reviens, je vais conseiller à Critor de commencer level 42, ça plantera son score !

Meilleur Score de la team nsi.xyz : 805 926

Meilleur score de team tiplanet.org : 691 356

Il a commencé sa partie directement au niveau 42, du coup son score est à peine acceptable !

En plus, il a triché ! Il a utilisé une vision prédictive triple et la grille d’aide !

Bien évidemment, il a nié avoir triché :

je ne les ai même pas utilisés, c’était pour mettre à l’écran le maximum d’éléments visuels, car j’étais parti pour l’utiliser également comme photo d’illustration d’article

Mais nous ne sommes pas dupes non plus !

Une anecdote ? Tout le monde aime les anecdotes

Commencé un dimanche, fini le mercredi suivant, c’était presque trop facile !

Ici, presque n’aura jamais été mieux choisi !

Collisions, oh chères collisions...

Durant le développement du Tetris, les collisions auront été officiellement terminées 2 fois ! Une première fois quand les collisions "de base" ont été finies et une deuxième fois, juste avant le release final, quand faire glisser un tétromino a été terminé.

Petit jeu de différences et principes d’algo :

Pouvez vous donner la différence entre ces deux fonctions ? L’une permet de faire glisser les pièces, l’autre non.

  1. def collision(d,piece):
  2.     x,y = ancr(piece)
  3.     for i in rlen(piece[1]):
  4.         for j in rlen(piece[1][i]):
  5.             if piece[1][i][j]:
  6.                 if d in (0,3) and ((0<=j+(d==3)-(d==0)<=len(piece[1][i])-1 and not piece[1][i][j+(d==3)-(d==0)]) or (j,d) in ((0,0),(len(piece[1][i])-1,3))):
  7.                     if get_pixel(x+7+14*(j+(d==3)-(d==0)),y+7+14*i) != (248,252,248) or x+((j+1)*14)*(d!=0) in [77,245]:
  8.                         return 1
  9.                 if d == 2 and ((i != len(piece[1])-1 and not piece[1][i+1][j]) or (i == len(piece[1])-1 and piece[1][i][j])):
  10.                     if get_pixel(x+7+14*j,y+7+14*(i+1)) != (248,252,248) or y+i*14 == 207:
  11.                         return 1
  12.     return 0
  13.  
  14. def collision(d,piece):
  15.     x,y = ancr(piece)
  16.     for i in rlen(piece[1]):
  17.         for j in rlen(piece[1][i]):
  18.             if piece[1][i][j]:
  19.                 if d in (0,3) and (0<=j+(d==3)-(d==0)<=len(piece[1][i])-1 and not piece[1][i][j+(d==3)-(d==0)]) or (j,d) in ((0,0),(len(piece[1][i])-1,3)):
  20.                     if get_pixel(x+7+14*(j+(d==3)-(d==0)),y+7+14*i) != (248,252,248) or x+((j+1)*14)*(d!=0) in [77,245]:
  21.                         return 1
  22.                 if d == 2 and (i != len(piece[1])-1 and not piece[1][i+1][j]) or (i == len(piece[1])-1 and piece[1][i][j]):
  23.                     if get_pixel(x+7+14*j,y+7+14*(i+1)) != (248,252,248) or y+i*14 == 207:
  24.                         return 1
  25.     return 0

Télécharger

Petit indice :

  1. def collision(d,piece):
  2.     x,y = point en haut a gauche de la piece
  3.     for i in indices des y:
  4.         for j in indices des x:
  5.             if la case du tableau contient un element de piece:
  6.                 if gauche/droite and (P(j,i) avec deplacement dans le tableau and pas de case de notre piece a cet endroit or aux extremites du tableau):
  7.                     if il y a une case or aux bord du jeu:
  8.                         return ON PEUT PAS BOUGER
  9.                 if vers le bas and (on est pas sur le bas du tableau and en dessous, il a pas de case de notre piece or on est sur le bas du tableau):
  10.                     if il y a une case or aux bord du jeu:
  11.                         return ON PEUT PAS BOUGER
  12.     return ON PEUT BOUGER
  13.  
  14. def collision(d,piece):
  15.     x,y = point en haut a gauche de la piece
  16.     for i in indices des y:
  17.         for j in indices des x:
  18.             if la case du tableau contient un element de piece:
  19.                 if gauche/droite and P(j,i) avec deplacement dans le tableau and pas de case de notre piece a cet endroit or aux extremites du tableau:
  20.                     if il y a une case or aux bord du jeu:
  21.                         return ON PEUT PAS BOUGER
  22.                 if vers le bas and on est pas sur le bas du tableau and en dessous, il a pas de case de notre piece or on est sur le bas du tableau:
  23.                     if il y a une case or aux bord du jeu:
  24.                         return ON PEUT PAS BOUGER
  25.     return ON PEUT BOUGER

Télécharger

Et oui, il y a juste une parenthèse qui permet le bon fonctionnement !

Car si on assimile and à un * et or a un +, on se rend compte que si on voulait bouger sur le coté, la collision du bas s’activait car le or final choppait le bas de la pièce.

On aura mis deux jours en parallèle avec le reste pour trouver cette erreur :)

Télécharger le jeu

Le jeu nécessite la version 13.2 d’Epsilon ou la dernière version d’Omega.

> Télécharger le Tetris pour la NumWorks

Touches utilisables :

  • Déplacement : Flèches : gauche, droite, bas
  • Rotation : Boite à outil / Retour arrière

Sur le simulateur, il n’y a que "Retour arrière" qui fonctionne pour les rotations.

Par contre on commence à arriver à la limite maximum de la calculatrice coté mémoire d’exécution, et pour que le jeu se lance il faut impérativement qu’il n’y ait aucun autre script sur la calculatrice, peut importe qu’ils soient importés ou pas dans la console, la présence éventuelle d’autres scripts semble gêner la calculatrice qui nous renvoie un message d’erreur.

Les développeurs d’Epsilon auraient partagés la mémoire de stockage des scripts avec la mémoire d’exécution que cela ne nous étonnerait pas...

N’hésitez à réagir à cet article sur le forum tiplanet.org associé (lien à ajouter)
et si vous le souhaitez, vous pouvez également nous suivre sur twitter : https://twitter.com/nsi_xyz.

Mots-clés