Sokoban ultracommenté (MAJ annulation+reset+STATS)

Programmation avancée de jeux en PureBasic
Avatar de l’utilisateur
Huitbit
Messages : 940
Inscription : jeu. 08/déc./2005 5:19
Localisation : Guadeloupe

Re: Sokoban ultracommenté ! (MAJ Le Soldat Inconnu+ pb son)

Message par Huitbit »

Hello,

Merci le Soldat Inconnu, c'est exactement ce que je souhaitais faire !

@Geo Trouvpatou
Merci d'avoir testé, désolé pour les .l(long) et pour ton super écran.
J'ai un tube cathodique noir et blanc de 80 kg, si ça t'intéresse :mrgreen:
La version de LSI est impeccable concernant les déplacements.
Tout à fait d'accord !
D'ailleurs, j'ai mis à jour le code ! J'ai même remplacé les "long" par des "integer" :wink:

@Geo Trouvpatou et Dobro
J'ai testé sur plusieurs postes (XP pro et XP familial) et ... ça marche, RAS :? .
Je crois que ça vient des constantes #musique1 et #musique2, elles ne doivent pas être sur 1 octet et ça déborde sur les autres data :?: .
Je les ai virées. Si vous pouvez tester à nouveau :P

@Dobro
Impossible d'installer ta lib.Le dossier Userlibs reste VIDE :cry: .Ca m'énerve.
Voilà ma configuration :
Système:
Microsoft Windows XP
Version 2002
Service Pack 3

Fabricant et support technique:
Hewlett-Packard Company
HP Pavilion
Intel(R)
Celeron(R) D CPU 3.20GHz
3.20 GHz, 960 Mo de RAM
ATI RADEON XPRESS200

Avec Norton2010

Je suis impatient de voir le résultat.
Je compte faire un truc du genre avec les .mod


Hasta la vista !
Elevé au MSX !
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Re: Sokoban ultracommenté(MAJ Le Soldat Inconnu+ pb son+long

Message par Backup »

as tu retelechargé ma lib ? parcequ'hier j'ai mis une nouvelle archive
ou mon installateur te demande le dossier de ton purebasic (apres t'avoir proposé celui par

defaut) :)

si tu as bien retelechargé mon installateur avec le choix du dossier
il est probable que ton Norton efface les fichiers pondu par mon install !! :?
Avatar de l’utilisateur
Ar-S
Messages : 9540
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: Sokoban ultracommenté(MAJ Le Soldat Inconnu+ pb son+long

Message par Ar-S »

Au pire Dobro tu fait une version Insatallable et une version simplement zippé.
Beaucoup font ça, ça évite ce genre de soucis (parfois du à ces xxxxxx d'antivirus.
Surtout si tu utilises ?fin - ?debut pour extraire un fichier.

Dobro tu prends ou la clé du registre ? as tu essayer avec celle là ?

Code : Tout sélectionner

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\PureBasic_is1

avec comme valeur :

Code : Tout sélectionner

Inno Setup: App Path
Comme ça on a forcement le bon chemin de la dernière version d'installé aussi.

Mais je pense que ça vient de l'antivirus. Huitbit, as tu essayé de l'installer en desactivant l'analyse heuristique ? C'est la cause majeur pour des soucis de ce genre.

P.S : HP Pavilion ( :twisted: que de mauvais souvenirs chez des clients avec ses tours, elles se sont améliorées depuis.)
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Re: Sokoban ultracommenté(MAJ Le Soldat Inconnu+ pb son+long

Message par Backup »

c'est bien cette clef que j'utilise deja ;)
Avatar de l’utilisateur
Huitbit
Messages : 940
Inscription : jeu. 08/déc./2005 5:19
Localisation : Guadeloupe

Re: Sokoban ultracommenté(MAJ Le Soldat Inconnu+ pb son+long

Message par Huitbit »

Aloha !

J'utilise la dernière version (d'ailleurs je préfère choisir moi-même l'endroit d'installation !).
Nondidju, j'espère que c'est pas Norton. Il est capable de supprimer purebasic, ça m'étonnerait pas de lui ! "M'enfin !"

Avez-vous testé la dernière version avec le son ? Est-ce que c'était bien les constantes qui mettaient le souk ?

Hasta la vista !
Elevé au MSX !
Avatar de l’utilisateur
Ar-S
Messages : 9540
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: Sokoban ultracommenté(MAJ Le Soldat Inconnu+ pb son+long

Message par Ar-S »

4.50 non testé pour ma part
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Geo Trouvpatou
Messages : 471
Inscription : dim. 23/déc./2007 18:10

Re: Sokoban ultracommenté(MAJ Le Soldat Inconnu+ pb son+long

Message par Geo Trouvpatou »

Salut
J'ai un tube cathodique noir et blanc de 80 kg, si ça t'intéresse
Gardes-le, ça va me couter le prix de deux 24" rien qu'en transport :lol:.
En plus il me semble que tu n'es pas en France.
Quoique quand je vois certains produits alimentaires qui coûtent moins cher en prenant l'avion que le train d'un département à l'autre...

Pour le problème de crash, je viens de comprendre.
J'imagine que Dobro à du faire la même chose que moi.

N'ayant pas de son sous la patte, je n'ai fait que "commenter" les lignes me saoûlant en me disant sound ceci, sound cela et du coup cela foire le truc au niveau des datas.

Je vais retester, mais je suis presque sûr que c'est ça, parce que c'est seulement maintenant que je viens de voir tes comms de la 1ère ligne des datas.

Bye.

(EDIT] Comme la 1ère fois j'ai supprimé tout ce qui était lié au son et là plus de problème.
Et j'ai exactement la même map que la version sans son, ce qui n'était pas le cas avant.
Hormis le fait que comme ce que j'avais déjà dit, le messageRequester de victoire arrive trop tôt. Il devrait s'activer lorsque la dernière caisse est réellement recouverte.

Bon je sais que tu es contraint par la limite des 800 lignes, mais je ne sais plus si dans le jeu original, les déplacements de caisse n'étaient pas comptés eux aussi?
Vu la petitesse des niveaux, un mauvais déplacement = jeux impossible à finir, mais comme tu comptes ajouter la possibilité de revenir en arrière, cela pourrait être intéressant à ajouter à ce moment là, pour voir ceux qui finissent un niveau avec le moins de coup possible.
eventuellement (Ou à la place) compter aussi le nombre de déplacement du joueur.
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Re: Sokoban ultracommenté(MAJ Le Soldat Inconnu+ pb son+long

Message par Backup »

Geo Trouvpatou a écrit : Pour le problème de crash, je viens de comprendre.
J'imagine que Dobro à du faire la même chose que moi.
:lol: +1 carrement :lol:
Avatar de l’utilisateur
Huitbit
Messages : 940
Inscription : jeu. 08/déc./2005 5:19
Localisation : Guadeloupe

Annulation des actions...

Message par Huitbit »

Hugh !

J'ai rajouté une liste chaînée pour sauvegarder les actions effectuées.
Barre d'espace pour "remonter le temps"
Return pour recommencer le niveau
J'ai mis un 3ème niveau (23ème niveau du jeu original).
Pour la version sonore, il faudra trouver une troisième musique !

Planche de sprites à charger et à mettre dans le même dossier que le code :
Image

Version sans le son (celle que tout le monde préfère :mrgreen: )

Code : Tout sélectionner

;sokoban avec annulation des actions et reset
;auteur Huitbit
;amélioration des déplacements par Le Soldat Inconnu 
;pb v4.41
;une partie des sprites est tirée du site ci-dessous
;http://www.brothersoft.com/games/soukoban.html
;*********************************
;-___________________________________
;-déclaration des variables et des constantes
;-___________________________________
;-L'énumération permet de travailler avec des noms plutôt qu'avec des chiffres
Enumeration
  #spr_planche
  #mur
  #sol
  #but
  #caisse
  #caisse_rouge
  #soko1
  #soko2
  #eau
  #spr_decor
  #action_caisse_vers_sol
  #action_caisse_vers_but
  #action_caisserouge_vers_sol
  #action_caisserouge_vers_but
EndEnumeration

;-déclaration des variables
niveau.b;numéro du niveau
musique.b
largeur_niveau.b
hauteur_niveau.b
y.b;variable utilisée pour les lignes du tableau
x.b;variable utilisée pour les colonnes du tableau
type_tuile.b;variable utilisée pour le contenu de la case du tableau
nbre_caisses.b
compteur.b;permet de vérifier si les caisses sont rangées
x_soko.b;colonne où se trouve le personnage
y_soko.b;ligne où se trouve le personnage
soko.b;sprite choisi pour le personnage, soit #soko1, soit #soko2
chrono_soko.i; variable utilisée pour temporiser l'animation du personnage
chrono_keyboard.i;variable utilisée pour temporiser la fonction KeyboardPushed()
largeur_ecran.i
hauteur_ecran.i
x_clip_eau.i;variable utilisée pour découper le sprite "planche" pixel par pixel au niveau de l'eau
chrono_eau.i; variable utilisée pour temporiser l'animation de l'eau
;-_____________________________________________
;-structure utilisée pour la liste chaînée 
Structure infos_action
  varx.b
  vary.b
  action.i
EndStructure

;- Cette macro "clavier", permet en une seule fois de gérer les quatre directions,
;-il suffit de l'appeler en changeant les valeurs des paramètres direction, dx et dy.
Macro clavier(dx,dy)

;-si la place est libre devant, on avance dans la direction choisie
If carte(x_soko+dx,y_soko+dy)=#sol Or carte(x_soko+dx,y_soko+dy)=#but
  x_soko=x_soko+dx
  y_soko=y_soko+dy
  AddElement(sauvegarde_actions())
  sauvegarde_actions()\varx=dx
  sauvegarde_actions()\vary=dy
  sauvegarde_actions()\action=0
  ;-s'il y a une caisse   
ElseIf carte(x_soko+dx,y_soko+dy)=#caisse
  ;-si la place est libre devant la caisse, on peut la pousser
  If carte(x_soko+2*dx,y_soko+2*dy)=#sol
    carte(x_soko+dx,y_soko+dy)=#sol
    carte(x_soko+2*dx,y_soko+2*dy)=#caisse
    x_soko=x_soko+dx
    y_soko=y_soko+dy
    AddElement(sauvegarde_actions())
    sauvegarde_actions()\varx=dx
    sauvegarde_actions()\vary=dy
    sauvegarde_actions()\action=#action_caisse_vers_sol
    ;-si la place libre devant la caisse est un point d'arrivée, on bouge la caisse et on l'affiche en rouge
  ElseIf carte(x_soko+2*dx,y_soko+2*dy)=#but
    carte(x_soko+dx,y_soko+dy)=#sol
    carte(x_soko+2*dx,y_soko+2*dy)=#caisse_rouge
    x_soko=x_soko+dx
    y_soko=y_soko+dy
    AddElement(sauvegarde_actions())
    sauvegarde_actions()\varx=dx
    sauvegarde_actions()\vary=dy
    sauvegarde_actions()\action=#action_caisse_vers_but
  EndIf
  
  ;-si la caisse poussée est rouge
ElseIf carte(x_soko+dx,y_soko+dy)=#caisse_rouge
  ;-si on la déplace, on fera apparaître une case arrivée et elle redeviendra de couleur normale
  If carte(x_soko+2*dx,y_soko+2*dy)=#sol
    carte(x_soko+dx,y_soko+dy)=#but
    carte(x_soko+2*dx,y_soko+2*dy)=#caisse
    x_soko=x_soko+dx
    y_soko=y_soko+dy
    AddElement(sauvegarde_actions())
    sauvegarde_actions()\varx=dx
    sauvegarde_actions()\vary=dy
    sauvegarde_actions()\action=#action_caisserouge_vers_sol
    
    ;-si on la déplace on fera apparaître une case arrivée et elle restera rouge
  ElseIf carte(x_soko+2*dx,y_soko+2*dy)=#but
    carte(x_soko+dx,y_soko+dy)=#but
    carte(x_soko+2*dx,y_soko+2*dy)=#caisse_rouge
    x_soko=x_soko+dx
    y_soko=y_soko+dy
    AddElement(sauvegarde_actions())
    sauvegarde_actions()\varx=dx
    sauvegarde_actions()\vary=dy
    sauvegarde_actions()\action=#action_caisserouge_vers_but
    
  EndIf
  
EndIf
EndMacro

;-on prévient le compilateur que l'on va utiliser les sprites et le clavier
InitSprite()
InitKeyboard()
InitSound()

;-on choisit le niveau de départ
niveau=1
MessageRequester("Infos !", ">Barre d'espace : annuler une  action."+Chr(13)+">Return : réinitialiser le niveau"+Chr(13)+Chr(13)+"Attention, le niveau 3 ça devient sérieux !")


;-"jeu:" s'appelle un label, c'est une adresse, un numéro de ligne où l'on peut renvoyer le programme
jeu:

;-création d'une liste chaînée sauvegarde_actions() pour pouvoir revenir en arrière dans le jeu
NewList sauvegarde_actions.infos_action()
AddElement(sauvegarde_actions())
sauvegarde_actions()\varx=0
sauvegarde_actions()\vary=0
sauvegarde_actions()\action=0

;-en fonction du niveau, on se place au bon endroit pour lire les informations correspondantes
Select niveau
  Case 1
    Restore niveau1
  Case 2
    Restore niveau2
  Case 3
    Restore niveau3
EndSelect

;-lecture des  dimensions (en nombre de cases) de la zone de jeu
Read.b largeur_niveau
Read.b hauteur_niveau
;-transformation des dimensions en nombre de pixels, sachant que chaque image fait 32 pixels
largeur_ecran=(largeur_niveau+1)*32
hauteur_ecran=(hauteur_niveau+1)*32

;-lecture du nombre de caisses
Read.b nbre_caisses

;-création du tableau pour y ranger toutes les informations
Dim carte.b(largeur_niveau,hauteur_niveau)

;-utilisation de deux boucles pour remplir le tableau
For y=0 To hauteur_niveau
  For x=0 To largeur_niveau
    ;-lecture des data 
    Read.b type_tuile
    carte(x,y)=type_tuile
    ;-récupération des coordonnées de départ du personnage
    If type_tuile=#soko1
      x_soko=x
      y_soko=y
      carte(x,y)=#sol
    EndIf
  Next x
Next y

;-______________________
;-PROGRAMME PRINCIPAL
;-______________________
OpenWindow(0,0,0,largeur_ecran,hauteur_ecran,"Sokoban niveau "+Str(niveau),#PB_Window_ScreenCentered|#PB_Window_SystemMenu  )
OpenWindowedScreen(WindowID(0),0,0,largeur_ecran,hauteur_ecran,0,0,0)

;-on précise le type d'image utilisée
UsePNGImageDecoder()
;-on charge l'image de taille 352*32 pixels
;-Remarque : j'ai choisi une image où tous les sprites sont présents, dans la suite du programme, je la "découpe" avec clipsprite() en fonction de mes besoins.
;-j'aurais pu charger plusieurs images pour ne pas  avoir à utiliser ClipSprite() !
LoadSprite(#spr_planche,"planche.png")

;-on dessine le décor (c'est dire, tout ce qui est immobile) en utilisant les sprites et les informations du tableau carte(x,y)
ClearScreen(RGB(0,0,0))
For y=0 To hauteur_niveau
  For x=0 To largeur_niveau
    If carte(x,y)>0;quand carte(x,y)=0, on affiche rien
      If carte(x,y)<4;affichage des murs et du sol, caisses, soko,eau non affichés
        ClipSprite(#spr_planche,(carte(x,y)-1)*32,0,32,32)
        DisplaySprite(#spr_planche,x*32,y*32)
      Else;si carte(x,y) supérieur ou égal à 4 on affiche le sol  à la place
        If carte(x,y)=5;caisse rouge, on affiche donc une case arrivée à la place
          ClipSprite(#spr_planche,(#but-1)*32,0,32,32)
          DisplaySprite(#spr_planche,x*32,y*32)
        Else
          ClipSprite(#spr_planche,(#sol-1)*32,0,32,32)
          DisplaySprite(#spr_planche,x*32,y*32)
        EndIf
      EndIf
    EndIf
  Next x
Next y
;-on prend une "photo" du sprite crée et on l'appelle #spr_decor
GrabSprite(#spr_decor,0,0,largeur_ecran,hauteur_ecran)

;-choix de l'image de départ du personnage "soko"
soko=#soko1
;-choix  de l'abscisse de départ de l'image  "eau"
x_clip_eau=(#eau-1)*32


;-_________________________________
;-BOUCLE PRINCIPALE
;-_________________________________

Repeat
  FlipBuffers() ;voir l'aide pour cette fonction
  ;-on affiche le décor
  DisplaySprite(#spr_decor,0,0)
  ;-on affiche les éléments restants
  For y=0 To hauteur_niveau
    For x=0 To largeur_niveau
      ;-affichage des caisses
      If carte(x,y)=#caisse Or carte(x,y)=#caisse_rouge
        ClipSprite(#spr_planche,(carte(x,y)-1)*32,0,32,32)
        DisplaySprite(#spr_planche,x*32,y*32)
      EndIf
      ;-cas de l'eau
      If carte(x,y)=#eau 
        ;-animation de l'eau
        If ElapsedMilliseconds()-chrono_eau>60
          chrono_eau=ElapsedMilliseconds()
          x_clip_eau=x_clip_eau+1
          If x_clip_eau>(#eau-1+3)*32
            x_clip_eau=(#eau-1)*32
          EndIf
        EndIf
        ;-affichage de l'eau
        ClipSprite(#spr_planche,x_clip_eau,0,32,32)
        DisplayTranslucentSprite(#spr_planche,x*32,y*32,128)
      EndIf
      
      ;-enlevez les points virgules et vous verrez !
      ;       StartDrawing(ScreenOutput())
      ;       DrawText(x*32,y*32,Str(carte(x,y)))
      ;       StopDrawing()
      
    Next x
  Next y
  
  ;-animation du personnage
  If ElapsedMilliseconds()-chrono_soko>500
    chrono_soko=ElapsedMilliseconds()
    soko=soko+1
    ;-test  pour revenir à la première image
    If soko>#soko2
      soko=#soko1
    EndIf
  EndIf
  ;-affichage du personnage
  ClipSprite(#spr_planche,(soko-1)*32,0,32,32)
  DisplaySprite(#spr_planche,x_soko*32,y_soko*32)
  
  ;-vérification du nombre de caisses placées
  compteur=0
  For y=0 To hauteur_niveau
    For x=0 To largeur_niveau
      If carte(x,y)=#caisse_rouge
        compteur=compteur+1
        If compteur=nbre_caisses
          Flipbuffers()
          MessageRequester("Victoire !",Str(nbre_caisses)+" caisses rangées")
          ;-passage au niiveau suivant
          niveau=niveau+1
          If niveau=4
            niveau=1
          EndIf
          ;-retour au label "jeu:"
          Goto jeu
        EndIf
      EndIf
    Next x
  Next y
  
  ;-gestion du clavier
  If ElapsedMilliseconds()-chrono_keyboard>200
    ExamineKeyboard()
    ;-appel de la macro clavier
    If KeyboardPushed(#PB_Key_Right)
      clavier(1, 0)
      chrono_keyboard=ElapsedMilliseconds()
    EndIf
    If KeyboardPushed(#PB_Key_Left)
      clavier(-1, 0)
      chrono_keyboard=ElapsedMilliseconds()
    EndIf
    If KeyboardPushed(#PB_Key_Down)
      clavier(0, 1)
      chrono_keyboard=ElapsedMilliseconds()
    EndIf
    If KeyboardPushed(#PB_Key_Up)
      clavier(0, -1)
      chrono_keyboard=ElapsedMilliseconds()
    EndIf
  EndIf
  
  If KeyboardReleased(#PB_Key_Space)
    If ListIndex(sauvegarde_actions())<>0
      x_soko=x_soko-sauvegarde_actions()\varx
      y_soko=y_soko-sauvegarde_actions()\vary
      
      Select sauvegarde_actions()\action
        
        Case 0
          DeleteElement(sauvegarde_actions())
        Case #action_caisse_vers_sol
          carte(x_soko+sauvegarde_actions()\varx,y_soko+sauvegarde_actions()\vary)=#caisse
          carte(x_soko+2*sauvegarde_actions()\varx,y_soko+2*sauvegarde_actions()\vary)=#sol
          DeleteElement(sauvegarde_actions())
        Case #action_caisse_vers_but
          carte(x_soko+sauvegarde_actions()\varx,y_soko+sauvegarde_actions()\vary)=#caisse
          carte(x_soko+2*sauvegarde_actions()\varx,y_soko+2*sauvegarde_actions()\vary)=#but
          DeleteElement(sauvegarde_actions())
        Case #action_caisserouge_vers_sol
          carte(x_soko+sauvegarde_actions()\varx,y_soko+sauvegarde_actions()\vary)=#caisse_rouge
          carte(x_soko+2*sauvegarde_actions()\varx,y_soko+2*sauvegarde_actions()\vary)=#sol
          DeleteElement(sauvegarde_actions())
        Case #action_caisserouge_vers_but
          carte(x_soko+sauvegarde_actions()\varx,y_soko+sauvegarde_actions()\vary)=#caisse_rouge
          carte(x_soko+2*sauvegarde_actions()\varx,y_soko+2*sauvegarde_actions()\vary)=#but
          DeleteElement(sauvegarde_actions())
          
      EndSelect 
    EndIf
  EndIf
  
  If KeyboardReleased(#PB_Key_Return)
    Goto jeu
  EndIf 
  
  Delay(10)
Until WindowEvent() = #PB_Event_CloseWindow  
End 
;-____________________________
;-FIN DU PROGRAMME PRINCIPAL
;-____________________________
;-____________________________
;-DONNEES SUR LES NIVEAUX
;-____________________________
DataSection
;mur=1;sol=2;but=3;caisse=4;caisse_rouge=5;soko1=6;soko2=7;eau=8
niveau1:
Data.b 9,7,3;dimensions 10*8; 3 caisses
Data.b 1,1,1,1,1,0,0,0,0,0
Data.b 1,2,2,6,1,0,0,0,0,0
Data.b 1,2,2,2,1,1,0,0,0,0
Data.b 1,2,4,2,2,1,1,1,1,1
Data.b 1,2,4,2,4,2,2,8,8,1
Data.b 1,1,1,2,2,2,2,3,8,1
Data.b 8,8,1,2,2,2,3,3,2,1
Data.b 8,8,1,1,1,1,1,1,1,1

;mur=1;sol=2;but=3;caisse=4;caisse_rouge=5;soko1=6;soko2=7;eau=8
niveau2:
Data.b  11,5,4 ;dimensions 12*6; 4 caisses
Data.b 1,1,1,1,1,1,1,1,1,1,1,1
Data.b 1,8,1,8,1,8,8,2,8,2,8,1
Data.b 1,6,2,2,2,2,8,2,2,2,8,1
Data.b 1,2,4,4,2,2,4,2,4,2,2,1
Data.b 1,2,3,2,3,2,3,2,3,2,2,1
Data.b 1,1,1,1,1,1,1,1,1,1,1,1

;mur=1;sol=2;but=3;caisse=4;caisse_rouge=5;soko1=6;soko2=7;eau=8
niveau3:
Data.b 8,6,6;  dimensions 9*7; 6 caisses
Data.b 8,1,1,1,1,1,8,8,8
Data.b 8,1,2,2,2,1,1,1,1
Data.b 1,1,2,1,4,2,2,2,1
Data.b 1,2,4,2,2,4,4,2,1
Data.b 1,2,1,4,1,3,5,3,1
Data.b 1,2,2,2,6,3,3,3,1
Data.b 1,1,1,1,1,1,1,1,1

EndDataSection
Version avec le son :

Code : Tout sélectionner

;sokoban avec son, annulation des actions et reset
;auteur Huitbit
;amélioration des déplacements par Le Soldat Inconnu 
;pb v4.41
;une partie des sprites est tirée du site ci-dessous
;http://www.brothersoft.com/games/soukoban.html
;*********************************
;-___________________________________
;-déclaration des variables et des constantes
;-___________________________________
;-L'énumération permet de travailler avec des noms plutôt qu'avec des chiffres
Enumeration
  #spr_planche
  #mur
  #sol
  #but
  #caisse
  #caisse_rouge
  #soko1
  #soko2
  #eau
  #spr_decor
  #son_caisse_poussee
  #action_caisse_vers_sol
  #action_caisse_vers_but
  #action_caisserouge_vers_sol
  #action_caisserouge_vers_but
EndEnumeration

;-déclaration des variables
niveau.b;numéro du niveau
musique.b
largeur_niveau.b
hauteur_niveau.b
y.b;variable utilisée pour les lignes du tableau
x.b;variable utilisée pour les colonnes du tableau
type_tuile.b;variable utilisée pour le contenu de la case du tableau
nbre_caisses.b
compteur.b;permet de vérifier si les caisses sont rangées
x_soko.b;colonne où se trouve le personnage
y_soko.b;ligne où se trouve le personnage
soko.b;sprite choisi pour le personnage, soit #soko1, soit #soko2
chrono_soko.i; variable utilisée pour temporiser l'animation du personnage
chrono_keyboard.i;variable utilisée pour temporiser la fonction KeyboardPushed()
largeur_ecran.i
hauteur_ecran.i
x_clip_eau.i;variable utilisée pour découper le sprite "planche" pixel par pixel au niveau de l'eau
chrono_eau.i; variable utilisée pour temporiser l'animation de l'eau
;-_____________________________________________
;-structure utilisée pour la liste chaînée 
Structure infos_action
  varx.b
  vary.b
  action.i
EndStructure

;- Cette macro "clavier", permet en une seule fois de gérer les quatre directions,
;-il suffit de l'appeler en changeant les valeurs des paramètres direction, dx et dy.
Macro clavier(dx,dy)

;-si la place est libre devant, on avance dans la direction choisie
If carte(x_soko+dx,y_soko+dy)=#sol Or carte(x_soko+dx,y_soko+dy)=#but
  x_soko=x_soko+dx
  y_soko=y_soko+dy
  AddElement(sauvegarde_actions())
  sauvegarde_actions()\varx=dx
  sauvegarde_actions()\vary=dy
  sauvegarde_actions()\action=0
  ;-s'il y a une caisse   
ElseIf carte(x_soko+dx,y_soko+dy)=#caisse
  ;-si la place est libre devant la caisse, on peut la pousser
  If carte(x_soko+2*dx,y_soko+2*dy)=#sol
    carte(x_soko+dx,y_soko+dy)=#sol
    carte(x_soko+2*dx,y_soko+2*dy)=#caisse
    x_soko=x_soko+dx
    y_soko=y_soko+dy
    AddElement(sauvegarde_actions())
    sauvegarde_actions()\varx=dx
    sauvegarde_actions()\vary=dy
    sauvegarde_actions()\action=#action_caisse_vers_sol
    PlaySound(#son_caisse_poussee)
    ;-si la place libre devant la caisse est un point d'arrivée, on bouge la caisse et on l'affiche en rouge
  ElseIf carte(x_soko+2*dx,y_soko+2*dy)=#but
    carte(x_soko+dx,y_soko+dy)=#sol
    carte(x_soko+2*dx,y_soko+2*dy)=#caisse_rouge
    x_soko=x_soko+dx
    y_soko=y_soko+dy
    AddElement(sauvegarde_actions())
    sauvegarde_actions()\varx=dx
    sauvegarde_actions()\vary=dy
    sauvegarde_actions()\action=#action_caisse_vers_but
    PlaySound(#son_caisse_poussee)
  EndIf
  
  ;-si la caisse poussée est rouge
ElseIf carte(x_soko+dx,y_soko+dy)=#caisse_rouge
  ;-si on la déplace, on fera apparaître une case arrivée et elle redeviendra de couleur normale
  If carte(x_soko+2*dx,y_soko+2*dy)=#sol
    carte(x_soko+dx,y_soko+dy)=#but
    carte(x_soko+2*dx,y_soko+2*dy)=#caisse
    x_soko=x_soko+dx
    y_soko=y_soko+dy
    AddElement(sauvegarde_actions())
    sauvegarde_actions()\varx=dx
    sauvegarde_actions()\vary=dy
    sauvegarde_actions()\action=#action_caisserouge_vers_sol
    PlaySound(#son_caisse_poussee)
    
    ;-si on la déplace on fera apparaître une case arrivée et elle restera rouge
  ElseIf carte(x_soko+2*dx,y_soko+2*dy)=#but
    carte(x_soko+dx,y_soko+dy)=#but
    carte(x_soko+2*dx,y_soko+2*dy)=#caisse_rouge
    x_soko=x_soko+dx
    y_soko=y_soko+dy
    AddElement(sauvegarde_actions())
    sauvegarde_actions()\varx=dx
    sauvegarde_actions()\vary=dy
    sauvegarde_actions()\action=#action_caisserouge_vers_but
    PlaySound(#son_caisse_poussee)
    
  EndIf
  
EndIf
EndMacro

;-on prévient le compilateur que l'on va utiliser les sprites et le clavier
InitSprite()
InitKeyboard()
InitSound()
;-on charge le son et les musiques
LoadSound(#son_caisse_poussee,"son_caisse_poussee.wav")
LoadSound(1,"musique1.wav")
LoadSound(2,"musique2.wav")
LoadSound(3,"musique3.wav")

;-on choisit le niveau de départ
niveau=1
MessageRequester("Infos !", ">Barre d'espace : annuler une  action."+Chr(13)+">Return : réinitialiser le niveau"+Chr(13)+Chr(13)+"Attention, le niveau 3 ça devient sérieux !")

;-"jeu:" s'appelle un label, c'est une adresse, un numéro de ligne où l'on peut renvoyer le programme
jeu:

;-création d'une liste chaînée sauvegarde_actions() pour pouvoir revenir en arrière dans le jeu
NewList sauvegarde_actions.infos_action()
AddElement(sauvegarde_actions())
sauvegarde_actions()\varx=0
sauvegarde_actions()\vary=0
sauvegarde_actions()\action=0

;-en fonction du niveau, on se place au bon endroit pour lire les informations correspondantes
Select niveau
  Case 1
    Restore niveau1
  Case 2
    Restore niveau2
  Case 3
    Restore niveau3
EndSelect

;-lecture et lancement de la musique de fond
Read.b musique
PlaySound(musique,#PB_Sound_Loop)
SoundVolume(musique,70)

;-lecture des  dimensions (en nombre de cases) de la zone de jeu
Read.b largeur_niveau
Read.b hauteur_niveau
;-transformation des dimensions en nombre de pixels, sachant que chaque image fait 32 pixels
largeur_ecran=(largeur_niveau+1)*32
hauteur_ecran=(hauteur_niveau+1)*32

;-lecture du nombre de caisses
Read.b nbre_caisses

;-création du tableau pour y ranger toutes les informations
Dim carte.b(largeur_niveau,hauteur_niveau)

;-utilisation de deux boucles pour remplir le tableau
For y=0 To hauteur_niveau
  For x=0 To largeur_niveau
    ;-lecture des data 
    Read.b type_tuile
    carte(x,y)=type_tuile
    ;-récupération des coordonnées de départ du personnage
    If type_tuile=#soko1
      x_soko=x
      y_soko=y
      carte(x,y)=#sol
    EndIf
  Next x
Next y

;-______________________
;-PROGRAMME PRINCIPAL
;-______________________
OpenWindow(0,0,0,largeur_ecran,hauteur_ecran,"Sokoban niveau "+Str(niveau),#PB_Window_ScreenCentered|#PB_Window_SystemMenu  )
OpenWindowedScreen(WindowID(0),0,0,largeur_ecran,hauteur_ecran,0,0,0)

;-on précise le type d'image utilisée
UsePNGImageDecoder()
;-on charge l'image de taille 352*32 pixels
;-Remarque : j'ai choisi une image où tous les sprites sont présents, dans la suite du programme, je la "découpe" avec clipsprite() en fonction de mes besoins.
;-j'aurais pu charger plusieurs images pour ne pas  avoir à utiliser ClipSprite() !
LoadSprite(#spr_planche,"planche.png")

;-on dessine le décor (c'est dire, tout ce qui est immobile) en utilisant les sprites et les informations du tableau carte(x,y)
ClearScreen(RGB(0,0,0))
For y=0 To hauteur_niveau
  For x=0 To largeur_niveau
    If carte(x,y)>0;quand carte(x,y)=0, on affiche rien
      If carte(x,y)<4;affichage des murs et du sol, caisses, soko,eau non affichés
        ClipSprite(#spr_planche,(carte(x,y)-1)*32,0,32,32)
        DisplaySprite(#spr_planche,x*32,y*32)
      Else;si carte(x,y) supérieur ou égal à 4 on affiche le sol  à la place
        If carte(x,y)=5;caisse rouge, on affiche donc une case arrivée à la place
          ClipSprite(#spr_planche,(#but-1)*32,0,32,32)
          DisplaySprite(#spr_planche,x*32,y*32)
        Else
          ClipSprite(#spr_planche,(#sol-1)*32,0,32,32)
          DisplaySprite(#spr_planche,x*32,y*32)
        EndIf
      EndIf
    EndIf
  Next x
Next y
;-on prend une "photo" du sprite crée et on l'appelle #spr_decor
GrabSprite(#spr_decor,0,0,largeur_ecran,hauteur_ecran)

;-choix de l'image de départ du personnage "soko"
soko=#soko1
;-choix  de l'abscisse de départ de l'image  "eau"
x_clip_eau=(#eau-1)*32

;-_________________________________
;-BOUCLE PRINCIPALE
;-_________________________________

Repeat
  FlipBuffers() ;voir l'aide pour cette fonction
  ;-on affiche le décor
  DisplaySprite(#spr_decor,0,0)
  ;-on affiche les éléments restants
  For y=0 To hauteur_niveau
    For x=0 To largeur_niveau
      ;-affichage des caisses
      If carte(x,y)=#caisse Or carte(x,y)=#caisse_rouge
        ClipSprite(#spr_planche,(carte(x,y)-1)*32,0,32,32)
        DisplaySprite(#spr_planche,x*32,y*32)
      EndIf
      ;-cas de l'eau
      If carte(x,y)=#eau 
        ;-animation de l'eau
        If ElapsedMilliseconds()-chrono_eau>60
          chrono_eau=ElapsedMilliseconds()
          x_clip_eau=x_clip_eau+1
          If x_clip_eau>(#eau-1+3)*32
            x_clip_eau=(#eau-1)*32
          EndIf
        EndIf
        ;-affichage de l'eau
        ClipSprite(#spr_planche,x_clip_eau,0,32,32)
        DisplayTranslucentSprite(#spr_planche,x*32,y*32,128)
      EndIf
      
      ;-enlevez les points virgules et vous verrez !
      ;       StartDrawing(ScreenOutput())
      ;       DrawText(x*32,y*32,Str(carte(x,y)))
      ;       StopDrawing()
      
    Next x
  Next y
  
  ;-animation du personnage
  If ElapsedMilliseconds()-chrono_soko>500
    chrono_soko=ElapsedMilliseconds()
    soko=soko+1
    ;-test  pour revenir à la première image
    If soko>#soko2
      soko=#soko1
    EndIf
  EndIf
  ;-affichage du personnage
  ClipSprite(#spr_planche,(soko-1)*32,0,32,32)
  DisplaySprite(#spr_planche,x_soko*32,y_soko*32)
  
  ;-vérification du nombre de caisses placées
  compteur=0
  For y=0 To hauteur_niveau
    For x=0 To largeur_niveau
      If carte(x,y)=#caisse_rouge
        compteur=compteur+1
        If compteur=nbre_caisses
          Flipbuffers()
          MessageRequester("Victoire !",Str(nbre_caisses)+" caisses rangées")
          ;-passage au niiveau suivant
          niveau=niveau+1
          StopSound(musique)
          If niveau=4
            niveau=1
          EndIf
          ;-retour au label "jeu:"
          Goto jeu
        EndIf
      EndIf
    Next x
  Next y
  
  ;-gestion du clavier
  If ElapsedMilliseconds()-chrono_keyboard>200
    ExamineKeyboard()
    ;-appel de la macro clavier
    If KeyboardPushed(#PB_Key_Right)
      clavier(1, 0)
      chrono_keyboard=ElapsedMilliseconds()
    EndIf
    If KeyboardPushed(#PB_Key_Left)
      clavier(-1, 0)
      chrono_keyboard=ElapsedMilliseconds()
    EndIf
    If KeyboardPushed(#PB_Key_Down)
      clavier(0, 1)
      chrono_keyboard=ElapsedMilliseconds()
    EndIf
    If KeyboardPushed(#PB_Key_Up)
      clavier(0, -1)
      chrono_keyboard=ElapsedMilliseconds()
    EndIf
  EndIf
  
  If KeyboardReleased(#PB_Key_Space)
    If ListIndex(sauvegarde_actions())<>0
      x_soko=x_soko-sauvegarde_actions()\varx
      y_soko=y_soko-sauvegarde_actions()\vary
      
      Select sauvegarde_actions()\action
        
        Case 0
          DeleteElement(sauvegarde_actions())
        Case #action_caisse_vers_sol
          carte(x_soko+sauvegarde_actions()\varx,y_soko+sauvegarde_actions()\vary)=#caisse
          carte(x_soko+2*sauvegarde_actions()\varx,y_soko+2*sauvegarde_actions()\vary)=#sol
          DeleteElement(sauvegarde_actions())
        Case #action_caisse_vers_but
          carte(x_soko+sauvegarde_actions()\varx,y_soko+sauvegarde_actions()\vary)=#caisse
          carte(x_soko+2*sauvegarde_actions()\varx,y_soko+2*sauvegarde_actions()\vary)=#but
          DeleteElement(sauvegarde_actions())
        Case #action_caisserouge_vers_sol
          carte(x_soko+sauvegarde_actions()\varx,y_soko+sauvegarde_actions()\vary)=#caisse_rouge
          carte(x_soko+2*sauvegarde_actions()\varx,y_soko+2*sauvegarde_actions()\vary)=#sol
          DeleteElement(sauvegarde_actions())
        Case #action_caisserouge_vers_but
          carte(x_soko+sauvegarde_actions()\varx,y_soko+sauvegarde_actions()\vary)=#caisse_rouge
          carte(x_soko+2*sauvegarde_actions()\varx,y_soko+2*sauvegarde_actions()\vary)=#but
          DeleteElement(sauvegarde_actions())
          
      EndSelect 
    EndIf
  EndIf
  
  If KeyboardReleased(#PB_Key_Return)
    StopSound(musique)
    Goto jeu
  EndIf 
  
  Delay(10)
Until WindowEvent() = #PB_Event_CloseWindow  
End 
;-____________________________
;-FIN DU PROGRAMME PRINCIPAL
;-____________________________
;-____________________________
;-DONNEES SUR LES NIVEAUX
;-____________________________
DataSection
;mur=1;sol=2;but=3;caisse=4;caisse_rouge=5;soko1=6;soko2=7;eau=8
niveau1:
Data.b 1,9,7,3; musique n°1,dimensions 10*8; 3 caisses
Data.b 1,1,1,1,1,0,0,0,0,0
Data.b 1,2,2,6,1,0,0,0,0,0
Data.b 1,2,2,2,1,1,0,0,0,0
Data.b 1,2,4,2,2,1,1,1,1,1
Data.b 1,2,4,2,4,2,2,8,8,1
Data.b 1,1,1,2,2,2,2,3,8,1
Data.b 8,8,1,2,2,2,3,3,2,1
Data.b 8,8,1,1,1,1,1,1,1,1

;mur=1;sol=2;but=3;caisse=4;caisse_rouge=5;soko1=6;soko2=7;eau=8
niveau2:
Data.b  2,11,5,4; musique n°2, dimensions 12*6; 4 caisses
Data.b 1,1,1,1,1,1,1,1,1,1,1,1
Data.b 1,8,1,8,1,8,8,2,8,2,8,1
Data.b 1,6,2,2,2,2,8,2,2,2,8,1
Data.b 1,2,4,4,2,2,4,2,4,2,2,1
Data.b 1,2,3,2,3,2,3,2,3,2,2,1
Data.b 1,1,1,1,1,1,1,1,1,1,1,1

;mur=1;sol=2;but=3;caisse=4;caisse_rouge=5;soko1=6;soko2=7;eau=8
niveau3:
Data.b 3,8,6,6; musique n°3, dimensions 9*7; 6 caisses
Data.b 8,1,1,1,1,1,8,8,8
Data.b 8,1,2,2,2,1,1,1,1
Data.b 1,1,2,1,4,2,2,2,1
Data.b 1,2,4,2,2,4,4,2,1
Data.b 1,2,1,4,1,3,5,3,1
Data.b 1,2,2,2,6,3,3,3,1
Data.b 1,1,1,1,1,1,1,1,1

EndDataSection
Hasta la vista !
Dernière modification par Huitbit le sam. 10/juil./2010 14:20, modifié 2 fois.
Elevé au MSX !
Avatar de l’utilisateur
Huitbit
Messages : 940
Inscription : jeu. 08/déc./2005 5:19
Localisation : Guadeloupe

Re: Sokoban ultracommenté (MAJ annulation déplacements+reset

Message par Huitbit »

Hello !

Pendant les tests, j'ai résolu le n°23 et le n°24 de l'original, voici donc le n°24 et le n°25 :
Il n'y a qu'à remplacer ces data à la place de n'importe quel niveau ! Pour la version avec son ne pas oublier de rajouter une valeur pour le choix du morceau !

Code : Tout sélectionner

Data.b 8,7,6;  dimensions 9*8; 6 caisses
Data.b 8,8,8,1,1,1,1,1,8
Data.b 1,1,1,1,2,2,2,1,1
Data.b 1,2,4,2,4,2,2,2,1
Data.b 1,6,1,3,5,3,1,2,1
Data.b 1,2,1,3,5,3,1,2,1
Data.b 1,2,2,2,4,2,4,2,1
Data.b 1,1,2,2,2,1,1,1,1
Data.b 8,1,1,1,1,1,8,8,8

Code : Tout sélectionner

Data.b 8,7,7; dimensions 9*8; 7 caisses
Data.b 8,8,8,1,1,1,1,1,8
Data.b 1,1,1,1,3,2,2,1,1
Data.b 1,2,4,3,4,3,2,2,1
Data.b 1,6,4,1,2,1,4,2,1
Data.b 1,2,4,3,2,3,2,2,1
Data.b 1,1,1,1,4,1,4,2,1 
Data.b 8,8,1,3,2,3,2,2,1
Data.b 8,8,1,1,1,1,1,1,1
Hasta la vista !
Elevé au MSX !
Geo Trouvpatou
Messages : 471
Inscription : dim. 23/déc./2007 18:10

Re: Sokoban ultracommenté (MAJ annulation déplacements+reset

Message par Geo Trouvpatou »

Salut.
Huitbit a écrit :Hello !
...
Il n'y a qu'à remplacer ces data à la place de n'importe quel niveau ! Pour la version avec son ne pas oublier de rajouter une valeur pour le choix du morceau !

Code : Tout sélectionner

Data.b 8,7,6;  dimensions 9*8; 6 caisses
Data.b 8,8,8,1,1,1,1,1,8
...
Ben justement l'intérêt ne serait-il pas d'automatiser ceci, c'est à dire de pouvoir ajouter autant de niveau que l'on veut sans que cela fasse planter le programme.

Je viens de m'aperçevoir que j'avais un Sokoban sur ma teloch et que pour certains niveaux, certaines caisses sont déjà en place sur un objectif, mais qu'il faut malgré tout les déplacer si l'on veut résoudre le niveau.

Un fois que tes élèves auront fini avec ça, tu pourras (les obliger, forçer) leur demander de faire un éditeur de niveau. Ca devrait tenir dans les 800 lignes.

Au passage, M@teo21 auteur du SDZ a fait un tuto pour faire un Sokoban en C avec la SDL

Bye.

[EDIT]Malgré uniquement du code natif PB, le jeu ne fonctionne pas sous Linux.
Avatar de l’utilisateur
Huitbit
Messages : 940
Inscription : jeu. 08/déc./2005 5:19
Localisation : Guadeloupe

Re: Sokoban ultracommenté (MAJ annulation déplacements+reset

Message par Huitbit »

Hello,

@Geo Trouvpatou,
De bonnes idées mais le temps me manque ! J'aborde la programmation dans la partie thématique du programme.
La partie principale (électricité, électronique, numération...) doit avancer aussi !
Mon premier objectif était de faire un "jeu jouable" avec plusieurs niveaux et du son(on met rarement de la musique et des effets sonores dans les petits codes de jeux. Pour ma part, c'est la première fois. Un spécialiste pourrait faire un tuto ? Je suis sûr que ça intéresserait pas mal de monde).
Malgré uniquement du code natif PB, le jeu ne fonctionne pas sous Linux
Dommage, il faudrait demander à un linuxien les modifications à effectuer (il ne doit pas y en avoir des tonnes car j'utilise peu de mots-clef en général)

Pour la version jeu+éditeur, je pense que ça tient largement dans les 800 lignes (en première estimation, ~200 pour le jeu, ~200 pour l'éditeur). Je n'aurai pas le temps avec les élèves mais si ça intéresse quelqu'un, je le ferai.
Au passage, M@teo21 auteur du SDZ a fait un tuto pour faire un Sokoban en C avec la SDL
Merci pour le lien, c'est intéressant de voir une autre manière de faire (notamment les tests pour les déplacements).
J'aurais bien aimé qu'il code "la marche arrière" (barre d'espace sur mon code) pour comparer.

Par contre, rien que pour un tout petit Sokoban...
constantes.h : les définitions de constantes globales à tout le programme
main.c : le fichier qui contient la fonction main (fonction principale du programme).
jeu.c : fonctions gérant une partie de Sokoban
jeu.h : prototypes des fonctions de jeu.c
editeur.c : fonctions gérant l'éditeur de niveaux
editeur.h : prototypes.
fichiers.c : fonctions gérant la lecture et l'écriture de fichiers de niveaux (niveaux.lvl par exemple).
fichiers.h : prototypes.
et la tête du dossier Mario Sokoban :
http://www.siteduzero.com/uploads/fr/fi ... /10234.jpg

...le C, ça ne donne pas envie :mrgreen: (c'est peut être super efficace mais ça ne donne pas envie) .
Si un jour j'en ai besoin, je m'y mettrai mais pour l'instant PureBasic répond à toutes mes attentes :P


Hasta la vista !
Elevé au MSX !
Avatar de l’utilisateur
flaith
Messages : 1487
Inscription : jeu. 07/avr./2005 1:06
Localisation : Rennes
Contact :

Re: Sokoban ultracommenté (MAJ annulation déplacements+reset

Message par flaith »

Salut Huitbit, testé et résolument accroc à ton jeu, il est nikel :D
G-Rom
Messages : 3641
Inscription : dim. 10/janv./2010 5:29

Re: Sokoban ultracommenté (MAJ annulation déplacements+reset

Message par G-Rom »

Pour Linux :


Ligne 201 :

Code : Tout sélectionner

DisplayTranslucentSprite(#spr_planche,x*32,y*32,128)
remplacer par

Code : Tout sélectionner

DisplaySprite(#spr_planche,x*32,y*32)
Rajouté avant Repeat ( ligne 175 )

Code : Tout sélectionner

KeyboardMode(#PB_Keyboard_International)
Compilé avec le subsystem opengl & Enjoy ! :mrgreen:


Bien joué Huitbit !
Avatar de l’utilisateur
Huitbit
Messages : 940
Inscription : jeu. 08/déc./2005 5:19
Localisation : Guadeloupe

Re: Sokoban ultracommenté (MAJ annulation déplacements+reset

Message par Huitbit »

Trouvez-moi un forum plus efficace sur la toile et je mange mon clavier !
:lol: :lol: :lol:
Elevé au MSX !
Répondre