Étiquette : Jeux

NumApps

Cyclope Snake en python, NumWorks.

Parfois il suffit de rajouter un chrono dans un jeu et un comportement aléatoire pour tout changer. Ce Snake réinvente le gameplay, et reprend les codes graphiques des premiers jeux sur console. Un succès garanti !

Un Snake avec des graphismes évolués

Ce qui fait de cyclope Snake un jeu (un peu) différent, c’est que l’expérience de jeu a été améliorée avec des petits éléments de gameplay ou de graphisme comme par exemple l’interface style arcade, avec des contours et un tableau de score.

Commandes

Croix directionnelleOK
Se déplacerValider

Un peu de technique

Sur gameplay, le meilleur score est enregistré et rechargé à chaque lancement si vous utilisez Omega Os.
Par ailleurs, le serpent a une jauge de faim qui se réinitialise à chaque fois qu’il mange un fruit. Si cette jauge est remplie, il devient affamé et va aller dans le direction opposée de celle désirée, jusqu’à ce qu’il remange un fruit.

Les éléments du jeu possèdent une ombre (ça m’a été plutôt difficile à intégrer, je reviendrai là dessus dans un article futur, peut être), et le serpent a plusieurs détails.

Vous trouverez sur la page de téléchargement du jeu des instructions de personnalisation du jeu (couleurs, taille, difficulté, etc…)

Télécharger

Nous vous proposons 2 liens distincts, le premier est le lien vers la source du créateur de l’application, le deuxième est un lien alternatif en cas de problème. Seul le premier lien garanti de disposer de la dernière version de l’application, ainsi que la documentation écrite directement dans le workshop.

NumApps

Pac-Man en python, NumWorks

Au début des années 80 il y avait sur la console ATARI en jeu de labyrinthe qui connu en grand succès : Pac-Man. Manger des pac-gommes sans se faire manger soit même, tout un programme !

Capture d’écran du jeux

Commandes

FlèchesRetour arrière
Se déplacer sur la grille du jeuInterrompt le jeu,
sans possibilité de le reprendre

Un peu de technique

Si vous souhaitez en savoir plus sur les aspects techniques de ce jeu, lisez l’article de présentation :
Un Pac-Man sur ta Numworks, en python

Télécharger

Nous vous proposons 2 liens distincts, le premier est le lien vers la source du créateur de l’application, le deuxième est un lien alternatif en cas de problème. Seul le premier lien garanti de disposer de la dernière version de l’application.

A noter : Le jeu ne fonctionne correctement sur la calculatrice mais pas sur le workshop 😕

NumApps

Treasure en python, NumWorks

Un trésor a été caché. Déplace-toi et pars à sa recherche. Évite les rochers et les trous. Il te suffit d’appuyer sur OK pour creuser un trou. Un sonar peut t’aider, enfin uniquement si tu sais l’utiliser !

Captures d’écran du jeux

Commandes

FlèchesOK
Se déplacer sur la grille du jeuCreuser un trou pour trouver le trésor

Télécharger

Nous vous proposons 2 liens distincts, le premier est le lien vers la source du créateur de l’application, le deuxième est un lien alternatif en cas de problème. Seul le premier lien garanti de disposer de la dernière version de l’application.

NumApps

Tetris en python, NumWorks

Un incontournable de la Gameboy des années 90. Un jeu de puzzle dans lequel la patience fini par payer ou couter cher. Dans cette version, on peut commencer directement au niveau 42 !

Captures d’écran du jeux

Commandes

FlèchesClearOK
Déplacer les TetrominosRetournerLancer la partie

Un peu de technique

Si vous souhaitez en savoir plus sur les aspects techniques de ce jeu, lisez l’article de présentation :
Un Tetris en python pour la NumWorks

Télécharger

Nous vous proposons 2 liens distincts, le premier est le lien vers la source du créateur de l’application, le deuxième est un lien alternatif en cas de problème. Seul le premier lien garanti de disposer de la dernière version de l’application.

NumApps

Snake en python, NumWorks

Le jeu signature des Nokia 3210 et 3310 au début des années 2000. Il s’agit d’un jeu d’adresse et d’anticipation, il faut aussi résister au stress procuré par l’accélération du serpent !

Captures d’écran du jeux

Commandes

FlèchesMaisonOK
Se déplacer sur la grille du jeuRevenir au menuRejouer

Un peu de technique

Si vous souhaitez en savoir plus sur les aspects techniques de ce jeu, lisez l’article de présentation :
Un Snake codé en python pour la NumWorks

Télécharger

Nous vous proposons 2 liens distincts, le premier est le lien vers la source du créateur de l’application, le deuxième est un lien alternatif en cas de problème. Seul le premier lien garanti de disposer de la dernière version de l’application.

NumApps

Démineur en python, NumWorks

Ce jeu a eu son heure de gloire sur Windows à la fin des années 90. Il s’agit d’un jeu de réflexion qui nécessitera parfois de compter un peu sur sa chance. Attention, il peut y avoir 42 mines à trouver !

Captures d’écran du jeux

Commandes

FlèchesMaisonOKClearShift
Se déplacer sur la grille du jeuRevenir au menuDécouvrir une caseSignaler une bombeActive la triche

Un peu de technique

Si vous souhaitez en savoir plus sur les aspects techniques de ce jeu, lisez l’article de présentation :
Un démineur en python sur la NumWorks

Télécharger

Nous vous proposons 2 liens distincts, le premier est le lien vers la source du créateur de l’application, le deuxième est un lien alternatif en cas de problème. Seul le premier lien garanti de disposer de la dernière version de l’application.

Projets

Cubito’s Adventures, un jeu en Python pour la NumWorks

Le jeu est très simple, il faut ramasser le plus de pièces possible, et pour se déplacer, il suffit d’appuyer sur les flèches de la calculatrice. Mais attention ! Si il n’y a pas de pièce en dessous de Cubito (le personnage que vous incarnez), vous tombez ! Il est impossible de remonter si on en oublie une. Heureusement, il y a des échelles pour vous aider !
Bon courage et amusez vous bien !!

Ce projet a été réalisé par des élèves en spécialité NSI du Lycée Louis Pasteur. Ils sont également les auteurs de ce compte rendu. Pour en savoir plus : Les projets en spécialité NSI

Lien court vers ce document : https://nsi.xyz/cubito

On a tous espéré un jour pouvoir jouer sur sa calculatrice !
C’est pourquoi nous vous présentons le jeu « Cubito’s Adventures » !

Recherche d’idées et présentation du projet

Lorsque nos profs nous ont dit qu’il fallait faire un programme en Python qui tourne sur la NumWorks, on a tout de suite pensé à un petit jeu avec la surcouche graphique de la NumWorks, Kandinsky.
On voulait partir sur un jeu, oui, mais lequel ? Après être passés par une reprise du jeu Rogue sorti en 1980, ou par un Space Invaders comme en 1978, nous sommes finalement partis sur une tout autre idée, et Cubito est né !
Nous nous sommes lancés dans ce projet avec empressement.
Il consiste en un jeu sur la NumWorks avec différents niveaux.
Chaque niveau s’articule particulièrement autour de 4 paramètres que vous pouvez voir dans la capture d’écran ci-contre :

Le jeu Cubito’s Adventures sur NumWorks
  • Le personnage principal, Cubito (carré jaune),
  • L’arrivée (carré bleu),
  • Les pièces (points blancs),
  • L’échelle (rectangle blanc)

Pour gérer chaque niveau, des variables sont actualisées à chaque fois dans la barre du bas, il s’agit du score, ainsi que du niveau.
L’objectif du jeu est d’atteindre l’arrivée en ayant le plus gros score. 
Le choix des couleurs devrait certainement vous rappeler le jeu Pac-Man sorti en 1980 et dont nous nous sommes quelque peu inspiré.

Outils à notre disposition et problèmes rencontrés

On avait hâte oui, mais on n’avait pas de moyens pour tester notre programme autrement que de l’envoyer sur la NumWorks à chaque fois, ce qui est très long !!
Deux possibilités s’ouvraient alors à nous :
Nous pouvions utiliser le Workshop NumWorks, le site officiel de NumWorks qui nous permettait de tester notre programme plus simplement et en ligne mais, le site n’était pas très intuitif et nos professeurs nous ont conseillé d’utiliser Omega IDE, pour avancer plus facilement.
On s’est donc servi de l’IDE en ligne Omega IDE, issu de l’OS alternatif pour la calculatrice du même nom. (Un IDE, de l’anglais « integrated development environment  », est un logiciel en ligne ou non qui intègre toutes les fonctionnalités utiles pour pouvoir développer sur un langage et un produit (ici en l’occurrence Python et sur la NumWorks).)
Omega IDE nous permet un aperçu du rendu sur calculatrice ainsi que l’enregistrement automatique de notre code sur GitHub (plateforme de partage de codes et programmes).
Mais tout ne pouvait pas être parfait. En effet, ce site étant en version alpha (pas vraiment sorti) certains bugs pouvaient être présents dont certains particulièrement embêtant auxquels nous avons eu affaire. 
En effet, si l’on testait notre programme une fois puis qu’on le re testait une seconde fois (même 10 min plus tard) les deux programmes se mélangeaient ce qui rendait le test quasi impossible et nous obligeait à rafraîchir à chaque fois la page web. Nous avons donc dû faire avec !

Un programme bien « carré »

Quand nous avons commencé notre programme, nous avons utilisé le code de l’agent 42, pour les déplacements.

Nous avions déjà réalisé un programme qui permettait les déplacements mais nous ne maîtrisions pas tout le savoir nécessaire sur le module Kandinksy au départ pour pouvoir réaliser ces déplacements.
Grâce à l’abandon de cette partie du programme, nous connaissions déjà les bases du module graphique ce qui nous a permis de mieux avancer dans notre travail par la suite.

Ce qui nous a bien aidé, c’est que dès le début, nous avons tout écrit et définit par des fonctions. Des fonctions pour chaque détails du code. Par exemple une fonction pour se déplacer, une pour la fin des niveaux etc…
Notre jeu était alors beaucoup plus facile à mettre en place, par de simples boucles comme vous pouvez ici le voir grâce à un extrait de notre fonction jeu.

def jeu():
    global niveau
    while niveau!=6:
        fill_rect(0,0,320,222,no)
        sleep(2)
        partie()
#[...]

Avec la boucle while qui teste la valeur de la variable niveau, on peut après une incrémentation (un ajout) de 1 à la variable niveau, appeler à chaque fois la fonction partie qui va à son tour appeler les déplacements, et l’initialisation de l’écran pour le niveau en question.

Évidemment, comme une bonne nouvelle n’arrive jamais seule, on a eu une petite complication car il fallait appeler chaque fonction, oui, mais par ordre d’appel très précis sinon cela ne fonctionne pas !

Notre programme a été centré sur la position des différents objets dans chaque niveau et l’interaction de Cubito avec les autres « objets ».

Un de nos plus grands problèmes dès le début était de faire en sorte que Cubito ne puisse pas sortir de l’écran de la calculatrice ! Il fallait définir le point le plus en haut à gauche et le point le plus en bas à droite, dans lequel le personnage pouvait se déplacer. Au bout de quelques heures (et beaucoup d’échecs), il fallait juste définir la « bordure » qui avait déjà été mise en place (pas avec les mêmes valeurs) par notre agent :

bordure = [0,0,190,310] #x min, y min, y max, x max

Le premier 0 est donc l’abscisse minimale de Cubito, 310 l’abscisse maximale, le deuxième 0 l’ordonnée minimale et 190l’ordonnée maximale.

Voyons maintenant un point central du jeu, la génération des pièces.

#[...]
def initiation(): #Génère les pièces
    fill_rect(0,0,320,222,no)
    for j in range(5,222,10):
        for i in range(5,320,10):
            set_pixel(i,j,bl)
#[...]

Cette fonction va donc au fur et à mesure créer une variable j, correspondant à l’ordonnée ainsi qu’une variable i, correspondant à l’abscisse, en partant de 5 à chaque fois. Puis au fur et à mesure, à chaque avancée, elle va allumer un pixel en blanc (le set_pixel). Pour le for j et i in range, le premier nombre correspond à la valeur de départ, 5 pour qu’à chaque déplacement, la pièce soit au centre de Cubito. Le deuxième nombre est la valeur maximale, car l’écran de la calculatrice est en 320 par 222. Enfin la troisième valeur correspond au « pas », c’est à dire l’avancée à chaque fois.

Pour les déplacements, voici un extrait de la fonction move :

#[...]
def move():
     if keydown(0): #gauche
            mvt[0] = max(position[0]-10, bordure[0])
            is_key_pressed = True
#[...]

Dans cette portion de code (pour aller à gauche), on dit à Cubito de se déplacer de -10 sur l’axe des abscisses. Mais comme notre personnage est un bloc de 10×10, alors il se déplace de 10 pixels par 10 pixels ; en fait il se décale d’une case ! Sans oublier qu’il laisse derrière lui une case noire pour effacer sa dernière position. Comme le fond est noir aussi, on a l’impression qu’il a disparu de son ancienne positon. C’est là toute l’illusion des déplacements !!

Un menu pour notre jeu

Nous avons voulu mettre en place un menu pour notre jeu.
Pour ne pas prendre trop de place dans le poids total du jeu, il n’est que partiellement interactif comme vous pouvez le voir dans la capture d’écran ci-dessous.

def menu():
    #[...]
    while not keydown(5):
        if keydown(4) or keydown(17):
            jeu()
#[...]

Pour afficher ce menu, nous avons juste affiché le texte à l’aide de draw_string.
Pour tout ce qui est interaction avec le joueur, c’est à dire commencer la partie, voici un extrait de code de la fonction menu :

Un problème coloré mais heureusement résolu !

Nous avons néanmoins rencontré durant ce projet, un problème épineux.
En effet, nous avions besoin d’utiliser la fonction get_pixel issue de Kandinsky qui permet de vérifier la couleur d’un pixel donné.
Ainsi, dans l’exemple ci-dessous :

Nous avons néanmoins rencontré durant ce projet, un problème épineux.
En effet, nous avions besoin d’utiliser la fonction get_pixel issue de Kandinsky qui permet de vérifier la couleur d’un pixel donné.
Ainsi, dans l’exemple ci-dessous :

Le programme trace un carré de 10 par 10 aux coordonnées (120 ; 120) et de couleur noire, soit (0,0,0) en RGB (rouge, vert, bleu), la méthode utilisée par la NumWorks pour les couleurs.

La ligne de code :

couleur_carre=get_pixel(120,120)

retournait comme valeur de la variable couleur_carre : (0,0,0).

Néanmoins, si on inversait les couleurs et que le cube était blanc sur un fond noir, le get_pixel ne retournait pas la couleur RGB du blanc : (255,255,255) mais une autre valeur incompréhensible pour nous, (248,252,248).
Après avoir demandé de l’aide à notre agent ainsi qu’aux développeurs d’Omega OS, car nous craignions que ce soit une erreur de notre part, nous avons appris que la calculatrice arrondissait le rouge tous les 8, le vert tous les 4 et le bleu tous les 8. Ce qui veut dire que les couleurs RGB rendues par le get_pixel avançaient de 8 en 8 pour le rouge, de 4 en 4 pour le vert et de 8 en 8 pour le bleu. Cette organisation complexe, nous a semblé plus claire grâce au programme fourni par notre professeur et montrant pour chaque couleur, ce qui ressortait au get_pixel.

Une fois ce souci réglé, nous pouvions enfin mettre en place les chutes et l’échelle !

Le fonctionnement des chutes peut paraître contre-intuitif au premier abord même s’il est tout à fait fonctionnel.
En effet, Cubito chute si en dessous de lui, il n’y a pas une pièce (par exemple s’il l’a déjà ramassée). 
Voici une portion de notre fonction vide qui réalise ceci :

def vide():
    global position, mvt, score, niveau
    while get_pixel(position[0]+5,position[1]+15)!=(248,252,248) and position[1]!=190:
        personnage(0)
        position[0]=position[0]
        position[1]+=10
        mvt[1]=position[1]
        score-=1
        personnage(1)
        sleep(1)
#[...]

Pour vérifier si il y a une pièce en dessous, on utilise le get_pixel que nous avons vu précédemment à la différence qu’on connait la valeur qu’il doit retourner : (248,252,248). 
Nous avons choisi d’utiliser une boucle, ce qui permet de vérifier que tant que la case au dessous n’a pas de pièce, le personnage continue de tomber, ce qui est permis par l’opérateur != (lire : « différent de »). La chute peut continuer jusqu’à arriver à la position maximale de Cubito en ordonnée : 190, sans quoi il irait sur les variables se trouvant dans la barre du bas.
On n’a donc plus qu’à ajouter 10 à l’ordonnée du personnage, à effacer son ancienne position et à créer la nouvelle à chaque tour de boucle.
Petite difficulté supplémentaire : les coordonnées de Cubito sont calculées à partir de son point le plus en haut à gauche, et les pièces sont placées de 10 en 10 mais en partant de 5.
Il faut donc pour savoir si une pièce en dessous de Cubito est présente ou non, faire le get_pixel aux coordonnées de l’abscisse de Cubito + 5 et de l’ordonnée de Cubito + 15 !

Ce get_pixel nous a aussi servi pour l’échelle comme vous pouvez le voir dans le code suivant :

#[...]
if get_pixel(position[0]+4,position[1]-39)==(248,252,248):
        personnage(0)
        position[1]-=longueur_scale+10
        position[0]=position[0]
        mvt[1]=position[1]
        personnage(1)
#[...]

En effet, au début nous avons voulu que l’échelle puisse faire monter le joueur de 40 (-40 car le point 0 est en haut), peut importe où nous étions sur l’échelle.
Mais quand l’échelle était trop proche du haut, Cubito sortait des limites du jeu.
Nous avons donc décidé que l’échelle ne pourrait être prise que du bas et ferait monter jusqu’en haut de cette dernière.
Ainsi pour vérifier que Cubito est bien tout en bas de l’échelle, qui a une longueur définie de 40, nous regardons le 39ème pixel au dessus de Cubito pour voir s’il est blanc. Si c’est le cas, le personnage se retrouve en haut de l’échelle.
Mais pourquoi le 39ème pixel et pas le 40ème, si l’échelle fait 40 de longueur ?
Tout simplement pour éviter de confondre avec une pièce, car pièce et échelle ont la même couleur !

Conclusion

Pour conclure, ce projet était ambitieux, c’était pas toujours facile, on a connu quelques tracas. 
Mais avec de la persévérance et l’aide de nos professeurs, nous avons réussi à créer un jeu qui nous satisfait réellement ! Ce challenge fut très enrichissant pour nous ! Le fait de se dire qu’en Première on a créé de toute pièce un jeu vidéo graphique alors qu’en troisième on n’avait jamais entendu parler de Python nous rend très fiers !

Et pour finir il y a pas un truc à se mettre sous la dent ?
Et bien si, un easter egg, et plus précisément un niveau unique est présent dans le jeu !!!
#[…]
Essayez de le trouver !

COMMENT TÉLÉCHARGER CE JEU POUR Y JOUER SUR MA CALCULATRICE ?

Vous trouverez dans le tableau ci-dessous les différents liens, mis à jour en fonction des évolutions du jeu, pour vous permettre de le télécharger !

ServeurWorkshop NumWorksTi-Planetnsi.xyz
Comment utiliser le codeBrancher sa calculatrice en USB et envoyer le codeTélécharger le code puis l’envoyer sur la NumWorks en passant par Omega IDE (si vous avez Omega OS)Idem
Lien URLCubito’s Adventures WorkshopCubito’s Adventures Ti-PlanetCubito’s Adventures (zip)

PS : Si la programmation sur calculatrice vous intéresse ou que vous voulez voir comment ça marche sur NumWorks, n’hésitez pas à lire : « Programmer en python et porter son code sur la NumWorks » qui vous donnera de précieux conseils pour y arriver !
Vous verrez c’est très plaisant de voir son programme avancer au fur et à mesure !!!

Projets

Une Histoire de plus ou moins

Lancez vous dans le jeu du plus ou moins, et tenter de battre l’ordinateur en devinant le nombre entre 0 et 1000 auquel il pense en moins de 10 coups ! Ou alors faites lui deviner votre nombre, saura t’il le trouver en moins de 10 coups et quelle stratégie adoptera t’il ?

Lancez vous dans le jeu du plus ou moins et tentez de battre l’ordinateur en devinant le nombre, entre 0 et 1000, auquel il pense en moins de 10 coups ! 
Ou alors, faites lui deviner votre nombre, saura t’il le trouver en moins de 10 coups et quelle stratégie adoptera t’il ?

Ce projet est un programme réalisé sur python recréant le célèbre jeu du plus ou moins. Il vous permettra une fois téléchargé sur votre calculatrice Numworks ou à l’aide d’un IDE de trouver ou de faire deviner un nombre entre 0 et 1000 à l’ordinateur. Ce programme a été developpé sur Pycharm et peut être téléchargeable sur la calculatrice Numworks via les liens hypertextes en bas de l’article.

La Naissance du projet

Dès l’annonce du projet nous voulions partir sur un jeu et surtout travailler sur l’interaction entre l’homme et la machine.

C’est alors que le jeu du plus ou moins nous est apparu comme une idée ni trop simple ni trop compliquée à coder avec une interaction importante.

Le projet était comme un mini défi puisque nous devions incrémenter une sorte de mini “intelligence artificielle”, car en effet dans ce jeu il existe une stratégie qui garantit la victoire.

Les différents modes de jeu

  • UN PREMIER MODE DE JEU

Dans ce mode de jeu, l’ordinateur doit trouver un nombre auquel l’utilisateur pense.

La stratégie consiste à diviser par deux le nombre de possibilités allant de 0 à 999, il suffit donc de proposer 500 comme premier choix, 250 ou 750 en deuxième choix et ainsi de suite… Grâce à cette méthode, l’ordinateur a la certitude de trouver le nombre en moins de dix coups.

Le but étant d’intégrer la stratégie à l’ordinateur comme une sorte de mini « intelligence artificielle” pour que l’ordinateur l’adopte et soit donc sûr de gagner à tous les coups.

victoire = False
min = 0
max = 1000
 
def recherche(min, max):
   scoreordi = 0
   scorejoueur = 0
   global victoire
   while not victoire:
       print("Ton chiffre est il plus grand que",int((min + max) / 2),"?")
       reponse = input()
       if reponse == "+":
           recherche(int((min + max) / 2), max)
       elif reponse == "-":
           recherche(min, int((min + max) / 2))
       elif reponse == "=":
           print("J'ai donc trouvé ton chiffre qui est",int((min + max) / 2))
           victoire = True
           print("Partie terminee")
recherche(min,max)

Voici le rendu du 1er mode de jeu :

  • UN DEUXIEME MODE DE JEU

Le deuxième mode de jeu fut bien plus simple à coder que l’autre car il suffisait de faire un script qui génère un nombre aléatoirement et le faire deviner à l’utilisateur à l’aide de phrases tels que “c’est plus !” ou “c’est moins !” .Nous avons intégré des boucles “if” et “while” en réponse au nombre entré par le joueur.

choix = randint(0, 999)
    nb = int(input())
    if nb < 0:
        print("Votre réponse n'est pas valide")
        sleep(3)
        questionordi()
    elif nb > 999:
        print("Votre réponse n'est pas valide")
        sleep(3)
        questionordi()
    cpt = 0
    scoreordi = 0
    scorejoueur = 0
    while cpt < 9:
        if nb > choix:
            print("C'est moins !")
            nb = int(input())
            if nb < 0:
                print("Votre réponse n'est pas valide")
                sleep(3)
                questionordi()
            elif nb > 999:
                print("Votre réponse n'est pas valide")
                sleep(3)
                questionordi()
            cpt += 1
        elif nb < choix:
            print("C'est plus !")
            nb = int(input())
            if nb < 0:
                print("Votre réponse n'est pas valide")
                sleep(3)
                questionordi()
            elif nb > 999:
                print("Votre réponse n'est pas valide")
                sleep(3)
                questionordi()
            cpt += 1
        else:
            print("Tu as trouve")
            cpt = 10
            scorejoueur = scorejoueur + 1
            print("Score ordinateur :", scoreordi, "\nScore joueur  :", scorejoueur)

Voici le rendu du 2ème mode de jeu :

Une ergonomie pensée pour la calculatrice

Un des autres défis de ce projet fut de traduire notre script pour qu’il puisse coller à l’interface limitée de la Numworks, en effet dans la calculatrice on ne peut pas se permettre de faire une phrase trop longue ou encore de mettre trop de texte. Nous avons alors utilisé des IDE Python tels que Numworks ou Omega pour corriger les bugs d’affichage et mettre en forme notre jeu textuel.

La création d’un menu nous a permis de créer un semblant d’interface graphique afin d’ajouter un peu d’esthétique à notre code.

Voici un aperçu du menu :

Conclusion

Comme vous le savez, le langage python nécessite comme tous les langages une extrême rigueur sans quoi le script est immédiatement obsolète.

C’est pourquoi nous avons dû braver certains problèmes qui empiétaient sur la justesse du code et donc du jeu.

Notre obstacle majeur étant que la boucle « while » dans la définition recherche (Voir le mode de jeu 1), était interminable ! Aussi mais pas des moindre nous avons eu aussi de nombreux soucis d’indentation et de syntaxe.

Après avoir résolu ces problèmes et optimiser notre jeu, nous avions l’impression qu’une couche graphique aiderait à rendre le jeu plus vivant.

Malheureusement, nos faibles connaissances pour les modules tels que turtlekandinsky et tkinter ont fait que notre tentative d’amélioration a échoué. Dès lors, nous avons abandonné l’idée d’offrir une interface graphique au joueur pour uniquement nous concentrer sur le script et le menu, qui servirait en remplacement.

Voici un lien vers nos essais graphiques

En somme, ce projet nous aura permis d’étendre nos connaissances en python ainsi que de réaliser notre premier “jeu” interactif.

Vous retrouverez les liens de notre script dans le tableau ci-dessous et pourrez le télécharger.

Télécharger et tester

ServeurWorkshop de NumWorkstiplanet.orgnsi.xyz
RemarquePermet un téléchargement rapide sur la calculatriceTéléchargement .pyTéléchargement .zip
Liens hypertexteslienNumWorks > Physique > Lien(Bouton en dessous)
Projets

Un Pac-Man sur ta Numworks, en python

Rond comme un ballon, et plus jaune qu’un citron, c’est lui Pac-Man ! Pac-Man débarque sur ta NumWorks ! Aide le à manger toutes les pac-gommes en évitant les fantômes et accumule le plus grand score.

Bon jeu !

URL courte de cet article : nsi.xyz/pacman

Pac-Man débarque sur ta NumWorks !

Aide le à manger toutes les pac-gommes en évitant les fantômes et accumule le plus grand score. Pour cela, tu peux :

  • Manger des pac-gommes (10)
  • Manger des super pac-gommes (50)
  • Manger les fantômes (200, 400, 800, puis 1600)

Si tu manges tout les fantômes a chaque super pac-gommes, tu obtiendras même un bonus de 12000 points !

Bon jeu !

Pac-Man, un sacré projet…

Comme toujours, sur nsi.xyz, on aime raconter l’histoire derrière nos projets.

Celle là commence dans une cuisine. Je commençais à faire à manger quand le patron  m’a envoyé un message concernant un bug sur un de ses projets « un jeu en une soirée » : Treasure

L’idée me plaisait, j’avais envie de faire pareil. Mais quel jeu choisir ?

🤓  Je vais tenter de faire un jeu en une nuit aussi vous m’avez motivé. Une idée ?
🧐 Pacman, tout autre jeu serait trop facile pour toi 😅

Pac-Man, ca paraissait infaisable… Des IA différentes pour chaque fantômes, des collisions, des tableaux et encore des tableaux, tout ça dans 32Ko max !

On est parti !

Première étape : Comment stocker la carte ?

Déjà, posons nous la question suivante : C’est quoi la carte dans Pac-Man ?

La carte, c’est soit :

  • Les chemins : On peut se balader dessus, les fantômes aussi.
  • Les murs : Comme on peut le penser, c’est l’inverse des chemins, on ne peut pas les traverser.

Du coup, on est sauvé ! Le tableau contiendra uniquement des 1 (pour les murs) ou des 0 (pour les chemins). Ainsi, on passe d’un tableau 2D de Booléen à un tableau 1D d’entier.
L’astuce est simple mais efficace : Une ligne de 1 et de 0 peut être convertie en entier grâce au fait que l’ordinateur code les entier en binaire.
En plus de réduire la complexité en espace, ça réduit aussi celle en temps, ce qui est pratique quand on parle d’un jeu tel que Pac-Man sur une calculatrice.

Deuxième étape : Construire la carte

Je commence déjà par choisir une taille pour les cases : 10px.
Sachant que la NumWorks dispose d’un écran de 222 px de haut, je sais que ma carte fera 22 cases de haut.Retour ligne automatique
A l’aide d’un logiciel professionnel et d’une image sur Internet, je crée une image blanche de 18x22px (Pourquoi 18 ? Je ne sais pas) que je commence à colorier de façon à obtenir ceci :

Et cette carte se traduit par le tableau suivant :

bits = 18  # Le nombre de bits pour chaque entiers, ce sera utile plus tard
terrain = (262143,131841,187245,187245,131073,186285,135969,252783,249903,251823,1152,251823,249903,251823,131841,187245,147465,219051,135969,195453,131073,262143)

Encore une fois, on utilise des tuple pour gagner en mémoire.

Maintenant, il ne reste plus qu’a rendre la carte à l’écran.
Et pour ca, on utilise une belle fonction :

def render():
    global terrain
    for l in range(len(terrain)):
        for c in range(bits):
            fill_rect(c*10+140,l*10+1,10,10,colors[0])
            if terrain[l]>>(bits-1-c) & 1:
                for d in ((1,0),(0,1),(-1,0),(0,-1)):
                    if 0 <= l + d[0] <= len(terrain) - 1 and 0 <= c + d[1] <= bits - 1 and not terrain[l + d[0]]>>(bits-1-(c+d[1])) & 1:
                        fill_rect(c*10+140+9*(d[1]==1),l*10+1+9*(d[0]==1),1+9*(d[1]==0),1+9*(d[0]==0),colors[1])

Pour faire simple, cette fonction lit les entier comme s’ils était des tableaux de 1 et de 0. Pour chaque case, elle dessine un carré noir. Si la case est un 1, elle regarde dans les 4 direction possibles, si un 0 s’y trouve, alors elle dessine un mur de ce côté.

En rajoutant une petite fonction pour du pré-rendu que je ne détaillerai pas, on obtiens déjà ceci :

Troisième étape : Ajouter de « la classe » au jeu

Outre l’aspect douteux de ce jeu de mot, il est temps de créer une classe pour Pac-Man et ses amis.
Ainsi née la classe Entity qui contiendra, à elle seule, toutes les méthodes pour le jeu. En effet, si on ne considère pas l’entrée des directions, les fantômes et Pac-Man se déplacent de la même manière sur la carte.

Pour faire court, cette classe contient 4 méthodes :

  • Le constructeur : initialise tout les attributs de l’entité.
  • espace : C’est la méthode qui teste les collision, grâce à elle, les fantômes et Pac-Man ne tournent que sur les intersections sans déborder sur les murs. Et évidemment, ils ne traversent pas non plus les murs.
  • move : C’est la méthode qui fait se déplacer les entités, qui réactualise les pac-gommes et super pac-gommes (j’y viendrai plus tard) et qui gère les collisions Pac-Man / Fantômes et Pac-Man / pac-gommes.
  • ia : Détermine la direction des fantômes.

Attardons-nous sur la méthode ia :

def ia(self,x,y):
    if self.f:
        while True:
            d = randint(0,3)
            dx, dy = ((-0.1,0),(0,-0.1),(0,0.1),(0.1,0))[d]
            if d != (3,2,1,0)[self.d] and self.espace(dx,dy):
                self.d = d
                break
    else:
        distances = [9999 for _ in range(4)]
        for i in range(4):
            if i != (3,2,1,0)[self.d]:
                dx, dy = ((-0.1,0),(0,-0.1),(0,0.1),(0.1,0))[i]
                if self.espace(dx,dy):
                    distances[i] = sqrt((self.y + dy - y)**2 + (self.x + dx - x)**2)
        self.d = distances.index(min(distances))

On voit qu’elle comporte deux parties, c’est un des éléments clés de Pac-Man : quand les fantômes sont dans l’état effrayé, ils choisissent une direction au hasard, sinon, ils choisissent la direction qui leur permet d’avoir la plus courte distance euclidienne à un point. Rajoutons que les fantômes n’ont pas le droit de faire demi-tour.

Mais une question se pose : Quel est donc ce point que visent les fantômes ?

Quatrième étape : Les fantômes débarquent !

Dans Pac-Man, il y a quatre fantômes. Mais il n’y a pas que leur couleur qui change, leur comportement aussi !

Petit listing exhaustif :

Blinky poursuit Pac-Man, ainsi le point qu’il cherche à atteindre et le point au centre de Pac-Man.

Pinky est la plus intelligente, ainsi le point qu’elle cherche à atteindre est deux cases devant Pac-Man dans la direction qu’il regarde.

Inky est un peu plus farceur, pour savoir ou il vise, il faut prendre en compte la position de Blinky et de Pac-Man. Posons v le vecteur Blinky-Point deux cases devant Pac-Man dans la direction qu’il regarde, Inky visera le point situé à 2v, ce qui le rend imprévisible.

Clyde quant à lui est un froussard, il agit comme Blinky quand à lui, est à 4 « mètres » de Pac-Man, mais vise un angle de la carte quand il est proche de Pac-Man.

Cinquième étape : Déplacer Pac-Man

Les fantômes maintenant capables de changer de direction, il n’en n’est rien pour Pac-Man…Retour ligne automatique
Comment se déplace Pac-Man ? Pac-Man se déplace jusqu’au bout d’un chemin avant de s’arrêter. Si on lui donne une direction, il la prendra dès qui le pourra sauf si la direction en question est la direction opposée à celle qu’il emprunte déjà.

Du coup, avec nos méthodes et un peu d’astuce, c’est tout simple !

for i in range(4):
    if keydown(i):
        if i == (3,2,1,0)[pacman.d]:
            pacman.d = i
        pacman.nd = i
if pacman.espace():
    pacman.d = pacman.nd

Sixième étape : Gestion des pac-gommes

Vous l’aurez peut-être remarqué mais le jeu est relativement fluide et rapide.Retour ligne automatique
Tout ça repose sur une grosse optimisation sur les pac-gommes, sans cette optimisation, le jeu tourne à 4 IPS.

Une question importante se pose : Comment réussir à afficher et rafraichir les pac-gommes ?

Une première approche innocente serait de stocker les pac-gommes sous forme de tableau de 0, 1 et 2 et le parcourir en affichant ou non les précieuses gommes. Sauf que là, bonjour le temps pour chaque image…

Une deuxième approche est de créer deux listes d’entier et d’utiliser les opérateurs binaires et les soustractions pour stocker les pac-gommes.Retour ligne automatique
Enfin, et c’est la l’énorme gain de temps. Pour chaque entités, après un mouvement, on regarde dans les deux listes si une (super) pac-gomme se trouve sur la case précédente, que ce soit un mur ou non, et on dessine une pac-gomme si besoin. Et c’est comme ça qu’on atteint une fluidité de jeu.

En plus, au lieu d’un parcours de liste, on a juste a implémenter les cinq lignes suivantes :

px, py = int(self.x - 5.5*dx), int(self.y - 5.5*dy)
if pacgommes[py]>>(bits-1-px) & 1:
    fill_rect(px*10+144,py*10+5,2,2,(250, 207, 173))
if superpacgommes[py]>>(bits-1-px) & 1:
    fill_rect(px*10+143,py*10+4,4,4,(250, 207, 173))

Septième étape : Gestion du score et des états des fantômes

Pour le score, on a juste à implémenter les règles citées en début d’article.

Pour la gestion des états des fantômes, c’est un peu plus compliqué qu’une simple variable.
Il faut rajouter un attribut afin que lorsqu’on mange un fantôme, il ne soit plus effrayé sans pour autant que les autres ne le soient plus.
Enfin, il faut rajouter une clock qui nous permettra de rendre leur état normal au fantômes après un certain temps en le rendant blanc juste avant pour alerter le joueur.

Conclusion

Evidemment, je ne me suis pas attardé sur tous les détails car se serait beaucoup trop long. Mais ce sont les éléments principaux pour un Pac-Man.
Je n’ai pas rajouté les changement de phases entre Chase et Scatter, de peur d’impacter les performances ou de dépasser la place disponible en mémoire.
Le Pac-Man fini rend bien :

Code jouable disponible ici :

Projets

Un Sokoban pour la NumWorks

Le Sokoban est un jeu de puzzle inventé au Japon en 1982. Le principe est simple : vous êtes un gardien d’entrepôt et vous devez amener les caisses aux bons emplacement. Pour cela, vous pouvez uniquement pousser les caisses, et une seule à la fois.*

Une partie des informations de cette page sont extraites de la page Wikipédia Sokoban.
Si vous souhaitez creuser le sujet, n’hésitez pas à la consulter.

L’objectif du jeu est de résoudre les niveaux en un nombre minimum de déplacements. Par ailleurs, il existe des milliers de niveaux, pour la majorité créés par la communauté. En fonction de la taille et de la complexité de la grille, ainsi que de l’exigence de l’utilisateur pour réduire son nombre de coups, tous les niveaux de difficultés sont imaginables. Ces éléments donnent une grande durabilité au jeu.

En raison de son apparition rapide dans le monde du jeu vidéo, de sa simplicité apparente et de son intérêt toujours renouvelé, le jeu a connu un grand succès et a été développé sous de nombreuses versions et plateformes. A mon tour de le porter sur la calculatrice NumWorks !

Fonctionnalités

  • Aide (règles, touches, signification des couleurs) affichée au lancement et accessible à tout moment.
  • Ajustement de l’affichage à la taille de la grille.
  • Possibilité d’annuler les mouvements précédents.
  • Déplacement rapide.
  • Détection de la victoire.
  • Ajout et choix de niveaux facile (voir la section correspondante).

Lancer le jeu

Le moteur de jeu et le contenu (les niveaux) sont stockés dans des scripts séparés :

Pour jouer, il faut télécharger ces scripts et exécuter sokoban.py. Il vous est demandé de préciser la cartouche (liste de niveaux) à utiliser ainsi que le niveau auquel vous souhaitez commencer. Il n’est pas nécessaire de remplir ces champs, le jeu commencera par défaut au niveau 1 de la cartouche soko.

Ajouter des niveaux

Si vous venez à bout des 50 niveaux inclus dans la cartouche de base, vous pouvez en télécharger une autre sur le Workshop. Ils sont nommés soko1soko2, … Pour les utiliser, il suffit de rentrer le nom de la cartouche au lancement du jeu.

Une présentation détaillée de ce projet à été publiée sur tiplanet.org