PureBasic

Forums PureBasic
Nous sommes le Mer 17/Juil/2019 15:42

Heures au format UTC + 1 heure




Poster un nouveau sujet Répondre au sujet  [ 20 messages ]  Aller à la page 1, 2  Suivante
Auteur Message
 Sujet du message: [TUTO] Structures et Listes Chainées, fond etoilé (MaJ 5.42)
MessagePosté: Ven 04/Juin/2004 17:03 
Hors ligne
Avatar de l’utilisateur

Inscription: Mar 27/Jan/2004 10:07
Messages: 877
Voici un nouveau tutoriel que je vous ai concocté pour expliquer comment fonctionnent les listes chaînées.




Déjà pourquoi une liste chainée ? Prenons un exemple simple. Vous êtes en train de programmer un shoot'em up. Vous avez votre vaisseau et vous devez gérer les tirs du joueur. Il faut savoir que vous ne pouvez pas savoir combien de fois le joueur va tirer au cours de la partie. De ce fait si vous demandez à Purebasic de vous afficher un sprite de tir alors qu'il n'y en a plus à l'écran, le jeu va planter.

Damned ! Incroyable ! et pourtant...Quelques programmeurs utiliseront des tableaux pour gérer les tirs du joueurs. C'est à dire qu'il vont initialiser un tableau qui comptabilisera le nombre de tir à l'écran.

Seulement comme je vous l'ai dit vous ne pouvez pas prévoir le nombre de tir à l'avance, le joueur peut tirer 500 fois comme 10 000 fois si c'est un mega bourrin. De ce fait il faudra prévoir un tableau énorme (genre 10 000 en taille) par exemple. Résultat des opérations, vous avez un énorme tableau et en plus, il prend énormement de place en ressources. Donc pas très optimisée comme solution...

C'est ici qu'interviennent les Listes Chaînées (ou Linked List). Comme son nom l'indique, on crée une liste qui sera dynamique. C'est à dire que, dans notre exemple, la liste sera aussi grande qu'il n'y a de tirs dans le jeu. D'autres part ces tirs seront détruits de manière dynamiques aussi. Donc, la liste va s'agrandir, pour devenir plus petite et tout cela sans que vous n'ayez presque rien à faire.

Donc en résumé, une liste chaînée, c'est une liste d'éléments (comme les tirs) qui est gérée de manière dynamique et suivant les évènements du jeu. L'avantages, c'est que les listes ne prennent pas autant de essources qu'un énorme tableau et la liste s'adapte selon les évènements.

A quoi peuvent elles servir sinon ? A gérer par ex une liste d'ennemis (Invaders) ou des étoiles etc...

Généralement, même si ce n'est pas obligatoire, on couple les listes chaînées avec les structures. Alors kesako ca encore lol.

Je ne sais pas si vous avez déjà entendu de la programmation orientée objet ? Bon déjà ce n'est pas tout à fait la même chose, mais les objets ont quelques points communs. Un objet que vous créé en programmation, aura ses propres propriétés (par ex la position en x, en y, la vitesse...). Quand vous créez une structure, vous créez en fait un "objet" (entre "" car ce n'est pas le terme exact), auquel vous attribuez des propriétés qui pourront être utilisées par la suite.

Laissons la liste chaînée de côté, nous allons essayé de comprendre les structures. Admettons que vous vouliez faire un carnet d'adresse. Vous allez avoir dedans, le nom, le prénom et le numéro de téléphone par ex. Si vous voulez stocker ses données dans un tableau, vous imaginez le nb de dimensions que devra avoir le tableau pour tout stocker ? Pourquoi ne pas faire alors une structure qui se présenterait comme ceci :

Structure Carnet
nom.s
prenom.s
numero.w
EndStructure

Ensuite vous avez votre "objet" Carnet avec toutes ses propriétés et vous pourrez stocker dans une unique case d'un tableau, une occurence de cette structure. Par exemple, la case 1 du tableau stockera en même temps le nom, prénom et numero de quelqu'un. Tout ca d'un coup. Pratique non ? Dans le cas contraire vous auriez à créer plus dimensions dans votre tableau en disant par ex que la première ligne c'est la nom, la
seconde les prénoms, un vrai foutoir quoi...Vive les structures.

Les structures fonctionnent de la même manière avec les listes chaînées. Bon assez de blabla passons à la pratique. Pour comprendre les structures et les listes je vous propose de créer un simple scrolling paralaxe d'étoiles, un fond étoilé animé en somme.

Un fond à deux niveaux pour simuler la profondeur de la galaxie. C'est plus joli et plus réaliste. Pour cela nous avons besoin de deux sprites : une étoile claire (blanche), et une étoile un peu plus foncée pour mettre au second niveau et simuler la profondeur. Je vous laisse les faires ca se fait en 5 mns avec un soft de dessin.

Nommez l'étoile clair : star.bmp et l'étoile foncée : star2.bmp

ou telechargez celles-ci ;)

http://michel.dobro.fee.fr/Forum_PB/tut ... e/star.bmp
http://michel.dobro.fee.fr/Forum_PB/tut ... /star2.bmp

Ca y est ? vous avez vos deux petites images ? Magnifique, player one shoots again ! sinon c'est GameOver lol

Je le dis tout de suite je ne vais pas m'attarder sur les bases, donc je prend en considération que vous connaissez les bases (intialisation des sprites création de la fenêtre de jeu etc...)

Bien commencez par créer un nouveau projet avec PureBasic et mettez les lignes de code suivantes :

Code:
;Tutorial Listes Chaînées

;Initialisation des composants
InitSprite()
InitKeyboard()
InitMouse()
InitSound()


;Constantes
#Star = 1
#Star2 = 2

;Création de la fenêtre principale
SetRefreshRate(60)
MaFenetre = OpenScreen(800,600,32,"Test")
If MaFenetre  = 0
    MessageRequester("Erreur", "Impossible d'ouvrir une fenêtre DirectX", #PB_MessageRequester_Ok)
EndIf



Ici rien de bien difficile je ne reviendrai pas sur ces instructions : au départ on initialise les composants obligatoires du programme. La création de la fenêtre de jeu en 800 X 600 avec test si jamais le programme n'arrive pas à l'ouvrir.

Par contre j'ai créé deux constantes qui définiront nos sprites, à savoir : #Star et #Star2 qui identifieront les deux étoiles que vous avez dessinées précédemment.

Parfait continuons :

Code:
;Chargement des sprites
LoadSprite(#Star,"star.bmp")
TransparentSpriteColor(#Star,0)
Structure Etoile
    posx.f
    posy.f
    vitesse.f
EndStructure
Global NewList Stars.Etoile()
LoadSprite(#Star2,"star2.bmp")
TransparentSpriteColor(#Star2,0)
Structure Etoile2
    posx.f
    posy.f
    vitesse.f
EndStructure
Global NewList Stars2.Etoile2()


On commence par charger nos étoiles avec la commande LoadSprite, rien de difficile donc, on charge chaque étoile en lui attribuant la constante définie tout à l'heure. Dans mon exemple l'étoile se trouve sur un fond rouge. J'ai donc défini la couleur de transparence avec TransparentSpriteColor.

Pour chaque étoile nous avons créé une structure. Aaaaah voilà que cela devient intéressant. Ainsi une étoile aura une position en X (posx), une position en Y (posy) et une vitesse (vitesse). Vous remarquerez que à côté de chaque variable se trouve ".f" il s'agit en fait du type de variable, dans notre exemple des nombres flotants. Une étoile aura alors chacune de ces propriétés. Enfin pour chaque étoile nous créeons une liste avec l'instruction NewList (une liste chaînée donc). Prenons la première :

NewList Stars.Etoile()

Cette ligne signifie qu'on crée une liste du nom de Stars et utilisant la structure Etoile. Facile n'est ce pas ?

Nous avons effectué cette opération pour nos deux étoiles.

il serait temps maintenant de donner un mouvement à nos étoiles. Dans notre exemple, le scroll étoilé se fera à la verticale. Donc les étoiles vont évoluer suivant une position sur l'axe des Y (et donc verticale).

Apprenons directement à structurer nos programmes. Vu qu'il faut faire le mouvement pour les deux types d'étoiles, nous allons créer une procédure, qui sera appelé dans le programme principale. Ajoutez ces lignes de code :

Code:
Procedure DisplayEtoile()
    ResetList(Stars())
    While NextElement(Stars())
        If Stars()\posy > 600
            Stars()\posy = -5
        EndIf
        DisplayTransparentSprite(#Star, Stars()\posx, Stars()\posy)
        Stars()\posy + Stars()\vitesse
    Wend
   
    ResetList(Stars2())
    While NextElement(Stars2())
        If Stars2()\posy > 600
            Stars2()\posy = -5
        EndIf
        DisplayTransparentSprite(#Star2, Stars2()\posx, Stars2()\posy)
        Stars2()\posy + Stars2()\vitesse
    Wend
EndProcedure



Les procédures permettent de classer les instructions pour une action précise. C'est à dire que dans votre programme principale, au lieu d'avoir 5 000 lignes de code, vous appelerez juste le nom de la procédure qui regroupe l'ensemble des instructions nécessaire à l'action voulue. Ici cela sera de déplacer chaque étoile qui sera crée dans notre démo. Nous avons effectué l'opération pour les deux étoiles donc je vais vous expliquer la première partie, la seconde fonctionnant sur le même shémas que la première. Bon prêt ? ha non qu'est ce que je vois là ! on ne code pas sans une bonne bière et une pizza, alors ca c pas vrai ces newbie hein, bon bon on vous attend allez chercher, et viiite hein !

Bon ca y est ? et on parle pas la bouche pleine ! Donc je reprends....Bon les deux au fond la bas !

Répetez ce que je viens dire ? Et voilà yen a 2 qui suivent ! Donc commençons l'explication de ces lignes.

Rappelez vous que notre première liste (de la première étoile), s'appelle Stars. L'instruction ResetList demande à Purebasic de prendre la liste par le début (bah oui hein vous regardez pas votre liste de courses à l'envers !).

Nous avons ensuite une boucle While Wend. Elle signifie "Pour chaque élément Stars faire..." ou même "Tant qu'il y a des éléments Stars faire". En clair tant qu'on a dans la liste des étoiles alors...C pas dur mais que fais t'on ? Très simple on dit que si la position de notre étoile en Y est supérieure à 600 alors on la replace à une coordonnée Y de -5 donc en clair si elle sort de l'écran paf on la remet hors de l'écran, en haut. Ensuite on affiche l'étoile avec la commande DisplayTransparentSprite et on change la coordonnée Y en ajoutant la variable vitesse,que nous définirons tout à l'heure. Et voilà c fini, le mouvement de nos étoiles est programmé.

Au niveau de la syntaxe avec les listes chainées, sachez que pour appeler une variable qui a été définie dans une structure on fait : nomliste()\variable le "\" est important !

Bon c'est bien beau tout ca mais maintenant les étoiles, va bien falloir leur donner une position initiale et puis donner une valeur à la variable vitesse non ? Allons y en dessous ajoutez ceci :

Code:

For i  = 1 To 150
    AddElement(Stars())
    AddElement(Stars2())
    Stars()\posx = Random(800)
    Stars()\posy = Random(600)
    Stars()\vitesse = 2
    Stars2()\posx = Random(800)
    Stars2()\posy = Random(600)
    Stars2()\vitesse = 1
Next



Ici on initialise le tableau. En clair la boucle FOR NEXT va tourner 150 fois et crée à chaque fois deux étoiles (avec les deux sprites) à des coordonnées aléatoires. Ce qui nous fait au total 300 étoiles.

Ensuite nous définissons la vitesse à 2 pour les étoiles claires, et à 1 pour les étoiles foncées, c ce qui va donner l'effet de profondeur. Remarquez que pour définir les variables on utilise toujours la syntaxe des listes chainée (c un coup à prendre mais vous verrez vous vous y ferez très vite).

Parfait, il ne reste plus qu'à programmer la boucle principale :

Code:
Repeat
    ClearScreen(RGB(0,0,0))
    DisplayEtoile()
    ExamineKeyboard()
    FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)


Très simple, on efface l'écran avec ClearScreen puis on appelle notre procédure pour afficher les étoiles, vous savez celle qu'on a créée tout à l'heure DisplayEtoile(). Ensuite on demande au programme d'examiner le clavier (si on appuie sur ECHAP on sort) et évidemment on fait un FlipBuffers() pour rafraichir l'image et là c magique, faites F5 ca marche waaaaaaaaaaaaaaa !

Je reste à votre disposition pour des infos complémentaires sur ce tutoriel, si vous avez des questions !

bon code !



------ EDIT ----- Mise à jour en PB 5.42 LTS en gardant au maximum le code de Crystal Noir
- Mise à jour de certaines commandes
- Création des 2 sprites plutôt qu'un chargement d'images (sans compter que les liens sont morts dans l'exemple ci dessus)
- Utilisation d'une seule structure pour les 2 sprites

J'ai commenté les modifs dans le code

Code:
;Tutorial Listes Chaînées
; Original code : Crystal Noir
; MaJ 5.42 : Ar-S

;Initialisation des composants
InitSprite()
InitKeyboard()
InitMouse()
InitSound()

; On déclare les futures procédures pour qu'elles soient repérées en début et/ou fin de code
Declare Creation_Etoile()
Declare DisplayEtoile()

; On va déclarer les 2 constantes étoile en commençant par 1
Enumeration 1
#Star
#Star2
EndEnumeration

Global NombreEtoile = 50

; 1 structure peut servir à plusieurs sprites

Structure Etoile
    posx.f
    posy.f
    vitesse.f
EndStructure

 
Global NewList Stars.Etoile()
Global NewList Stars2.Etoile()


;Création de la fenêtre principale

MaFenetre = OpenScreen(800,600,32,"Test",#PB_Screen_SmartSynchronization,60)

If MaFenetre  = 0
  MessageRequester("Erreur", "Impossible d'ouvrir une fenêtre DirectX", #PB_MessageRequester_Ok)
  End ; on quitte
 
 
Else
 
  Creation_Etoile()

; Boucle principale
  Repeat
    ClearScreen(RGB(0,0,0))
    DisplayEtoile()
    ExamineKeyboard()
    FlipBuffers()
  Until KeyboardPushed(#PB_Key_Escape)
 
EndIf


 
 
 
 
 
  ; /// PROCEDURES ////////////////////
Procedure Creation_Etoile()
  ; // Création des sprites
  ; Etoile 1
  ; - Creation du sprite vide
  CreateSprite(#Star,2,2)
  ; On remplit ce sprite d'une étoile blanche de 2x2 pixels
  StartDrawing(SpriteOutput(#Star))
  Box(0,0,2,2,RGB(255,255,255) )
  StopDrawing()
 
  ; Etoile 2
  ; - Creation du sprite vide
  CreateSprite(#Star2,2,2)
  ; On remplit ce sprite d'une étoile rouge de 2x2 pixels
  StartDrawing(SpriteOutput(#Star2))
  Box(0,0,2,2,RGB(255,0,0) )
  StopDrawing()
EndProcedure





Procedure DisplayEtoile()
    ResetList(Stars())
   
    For i  = 1 To NombreEtoile
      AddElement(Stars())
      AddElement(Stars2())
      Stars()\posx = Random(800)
      Stars()\posy = Random(600)
      Stars()\vitesse = 2
      Stars2()\posx = Random(800)
      Stars2()\posy = Random(600)
      Stars2()\vitesse = 1
    Next
   
   
    While NextElement(Stars())
        If Stars()\posy > 600
            Stars()\posy = -5
        EndIf
        DisplaySprite(#Star, Stars()\posx, Stars()\posy)
        Stars()\posy + Stars()\vitesse
    Wend
   
    ResetList(Stars2())
    While NextElement(Stars2())
        If Stars2()\posy > 600
            Stars2()\posy = -5
        EndIf
        DisplaySprite(#Star2, Stars2()\posx, Stars2()\posy)
        Stars2()\posy + Stars2()\vitesse
    Wend
  EndProcedure
 
  ; /////////FIN PROCEDURES ////////////////////////////////////


Dernière édition par Crystal Noir le Mar 09/Nov/2004 9:52, édité 1 fois.

Haut
 Profil  
Répondre en citant le message  
 Sujet du message:
MessagePosté: Lun 07/Juin/2004 13:31 
Hors ligne
Site Admin

Inscription: Mer 21/Jan/2004 11:03
Messages: 2564
Tres clair, nickel.


Haut
 Profil  
Répondre en citant le message  
 Sujet du message:
MessagePosté: Lun 07/Juin/2004 13:35 
Hors ligne
Avatar de l’utilisateur

Inscription: Mar 27/Jan/2004 10:07
Messages: 877
merci :)


Haut
 Profil  
Répondre en citant le message  
 Sujet du message:
MessagePosté: Jeu 19/Aoû/2004 17:07 
Hors ligne

Inscription: Mer 18/Aoû/2004 21:09
Messages: 10
Localisation: Paris
Je sais que j'suis en retard, mais je trouve ton tuto très bien fait. C'est le premier que j'ai lu, et il m'a motivé pour apprendre ce langage :D

C'est écrit avec des mots simples et ça rentre plus facilement qu'avec des termes tordus.

Continues comme ça si tu refais d'autres tutos à l'avenir stp :)


Haut
 Profil  
Répondre en citant le message  
 Sujet du message:
MessagePosté: Jeu 26/Aoû/2004 4:57 
Hors ligne
Avatar de l’utilisateur

Inscription: Lun 23/Aoû/2004 18:47
Messages: 131
Localisation: Jupiter ?
Plusieurs choses a dire :
- remet en forme le texte pour supprimer les espacements.
- indique quelle taille a peu pret doit avoir les 2 etoiles a dessiner (car a premiere vu, on pourrais croire que tu parles de simple point.... et dessiner un point en le sauvegardant en BMP, ca fait zarb)
- tu dis que les etoiles sont sur fond rouge. On ne sais pas d'ou viens ce rouge (est ce le dessinateur des etoiles qui DEVAIT les faire sur fond rouge ????)


Haut
 Profil  
Répondre en citant le message  
 Sujet du message:
MessagePosté: Ven 15/Oct/2004 14:50 
Hors ligne
Avatar de l’utilisateur

Inscription: Mar 27/Jan/2004 10:07
Messages: 877
En fait la taille n'a pas d'importance. Evidemment si tu fais une étoile énorme de 10 cm de diamètre ca devient un ballon :lol:

Non je ne parle pas forcément de points, mais pour faire un test on peut faire un point si on veut, moi j'ai peaufiné un peu en faisant un chtite étoie avec des branches ou alors un point avec à coté une nance de clair (pour la brillance) c'est à chacun de voir il n'y a pas de règle.

Pour le fond rouge non plus ca n'a pas d'importance. En fait si tu regardes le tuto, j'explique que moi, mes étoiles étaient sur fond rouge c ma manière à moi de travailler. Le fond rouge c'était pour expliquer tout simplement la commande TransparentSpriteColor rien d'autre. C'est pour expliquer à quoi servait cette commande. Bien sur si vous dessinez sous fond noir le paramètre de TransparentSpriteColor va changer :p


Haut
 Profil  
Répondre en citant le message  
 Sujet du message:
MessagePosté: Dim 07/Nov/2004 9:25 
Hors ligne

Inscription: Dim 31/Oct/2004 15:17
Messages: 11
Localisation: Maine et loire
Très bien fait ce tuto. :)
Mais surtout pour l'utilisation simple des listes chainées.
Un simple tableau aurait rempli la même fonction. :wink:
Ce qui m'interesse, c'est surtout comment ajouter et supprimer dynamiquement les éléments de la liste. Et que ce soit "propre" :!:


Haut
 Profil  
Répondre en citant le message  
 Sujet du message:
MessagePosté: Dim 07/Nov/2004 10:17 
Hors ligne
Avatar de l’utilisateur

Inscription: Mar 27/Jan/2004 10:07
Messages: 877
merci :)

oui la particularité des listes c bien de pouvoir changer dynamiquement son contenu quelque soit la taille de la liste.

Sur un tableau un changement de dimensionnement fait un reset des données contenues dedans....


Haut
 Profil  
Répondre en citant le message  
 Sujet du message:
MessagePosté: Dim 07/Nov/2004 12:35 
Hors ligne
Avatar de l’utilisateur

Inscription: Mer 26/Mai/2004 0:33
Messages: 683
Tu peux allez voir mon jeux aussi qui utilisent les liste chainer à fond ( Aranoîde )

_________________
http://garzul.tonsite.biz

Ancien site PB :
http://www.garzul.ca.cx


Haut
 Profil  
Répondre en citant le message  
 Sujet du message:
MessagePosté: Ven 24/Juin/2005 21:12 
Hors ligne

Inscription: Ven 18/Juin/2004 17:58
Messages: 5
D'une clarté limpide !

Bravo pour ces explications... et merci

(je sais je suis en retard d'un siècle mais bon c'est dit)

_________________
Une dernière après j'arrête


Haut
 Profil  
Répondre en citant le message  
 Sujet du message:
MessagePosté: Sam 25/Juin/2005 8:59 
Hors ligne
Avatar de l’utilisateur

Inscription: Mar 27/Jan/2004 10:07
Messages: 877
merci :D


Haut
 Profil  
Répondre en citant le message  
 Sujet du message:
MessagePosté: Ven 02/Sep/2005 10:34 
Hors ligne
Avatar de l’utilisateur

Inscription: Jeu 25/Aoû/2005 22:59
Messages: 445
Localisation: 974
super ton tuto !

maintenant je sais exactement comment utiliser les structures et les listes chainée !

_________________
Quelques manoucheries : I can't give you anything but love / Stompin' at decca


Haut
 Profil  
Répondre en citant le message  
 Sujet du message: Trop kool!
MessagePosté: Mar 07/Mar/2006 0:36 
Hors ligne

Inscription: Jeu 20/Jan/2005 22:00
Messages: 317
Trop kool se tuto j'en avait grave besoin j'ai enfin bien compris merci beaucoup!


Haut
 Profil  
Répondre en citant le message  
 Sujet du message:
MessagePosté: Mer 08/Mar/2006 16:21 
Hors ligne
Avatar de l’utilisateur

Inscription: Jeu 05/Fév/2004 19:57
Messages: 53
Bonjour,

J'ai une question (peut-être bête) pour les créateurs de PB au sujet des "Structures" :

Pourquoi avoir utiliser l'antislash ("\") pour délimiter les propriétés de leur structure parente, plutôt qu'un point (".") comme dans bcp de langages ? :|


Haut
 Profil  
Répondre en citant le message  
 Sujet du message:
MessagePosté: Mer 08/Mar/2006 16:46 
Hors ligne
Avatar de l’utilisateur

Inscription: Ven 23/Jan/2004 18:10
Messages: 2527
Parce que le point sert à définir le type des variables.
Pourquoi avoir choisi le point pour le type des variables ?

Dri :?:


Haut
 Profil  
Répondre en citant le message  
Afficher les messages postés depuis:  Trier par  
Poster un nouveau sujet Répondre au sujet  [ 20 messages ]  Aller à la page 1, 2  Suivante

Heures au format UTC + 1 heure


Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 1 invité


Vous ne pouvez pas poster de nouveaux sujets
Vous ne pouvez pas répondre aux sujets
Vous ne pouvez pas éditer vos messages
Vous ne pouvez pas supprimer vos messages

Rechercher:
Aller à:  
cron

 


Powered by phpBB © 2008 phpBB Group | Traduction par: phpBB-fr.com
subSilver+ theme by Canver Software, sponsor Sanal Modifiye