Précédent   Forum des professionnels en informatique > Autres langages > Autres langages > Basic > PureBasic
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 26/02/2011, 21h44   #1
Candidat au titre de Membre du Club
 
Inscription : avril 2007
Messages : 46
Détails du profil
Informations forums :
Inscription : avril 2007
Messages : 46
Points : 14
Points : 14
Par défaut Jeu 2D iso (rpg, aventure) - problème de Z-order

salut

En ce moment, j'apprends le purebasic, et j'aimerai réaliser un jeu en 2Diso.
Jusqu'à maintenant, tout se passe plutôt bien, mais je rencontre un problème pour faire le tri de mes sprites suivant y.
Par exemple, lorsque le personnage passe devant un arbre, il doit être affiché devant et non derrière .

Voici donc un essai de code pour du Z-order (ou depth) :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
 
;{ **************** variable, constantes.****************** ..
Enumeration
  #arbre
  #perso
  #WINDOW_MAIN
EndEnumeration
 
ecranX = 1024
ecranY = 768
Global FPS_LIMIT = 120
Global quit = 0
 
Global scroll_x = 0
Global scroll_y = 0
 
Global room_width = 4000
Global room_height  = 3000
;}
 
;{ **************** Structures **************************** 
 
Structure objet
    x.l
    y.l
    newposition_x.l
    newposition_y.l
    centre_x.l
    centre_y.l
  EndStructure
 
  Global nombre_arbre = 500
 
  Global Dim tableau_obj.objet(nombre_arbre)
 
For i = 2 To nombre_arbre
  tableau_obj(i)\y = Random(room_height)
  tableau_obj(i)\x = Random(room_width )
  tableau_obj(i)\centre_y = 80
  tableau_obj(i)\centre_y = 180
  tableau_obj(i)\newposition_x = tableau_obj(i)\x - tableau_obj(i)\centre_x
  tableau_obj(i)\newposition_y = tableau_obj(i)\y - tableau_obj(i)\centre_y
Next i
 
tableau_obj(1)\centre_x = 17
tableau_obj(1)\centre_y = 80
tableau_obj(1)\x = ecranX/2
tableau_obj(1)\y = ecranY/2
 
tableau_obj(1)\newposition_x = tableau_obj(1)\x - tableau_obj(1)\centre_x
tableau_obj(1)\newposition_y = tableau_obj(1)\y - tableau_obj(1)\centre_y
 
;SortStructuredArray(tableau_obj(), #PB_Sort_Ascending, OffsetOf(objet\y), #PB_Sort_Long)
 
;}
 
Declare evenement()
Declare update()
 
;{ **************** initialisation ************************** 
 
InitSprite()
InitSprite3D()
InitKeyboard()
InitMouse()
UsePNGImageDecoder()
 
;}
 
 
;{ ********************** openWindow ************************ 
 
OpenWindow(#WINDOW_MAIN,150,150,EcranX,EcranY,"3 Arks - test",#PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_MinimizeGadget)
OpenWindowedScreen(WindowID(#WINDOW_MAIN),0,0,EcranX,EcranY,0,0,0,#PB_Screen_WaitSynchronization ) 
;ClearScreen(RGB(128,128,128))
 
;}
 
;{ loading (sprites)
 
LoadSprite(#perso, "perso.png",#PB_Sprite_AlphaBlending|#PB_Sprite_Texture )
CreateSprite3D(#perso,#perso)
 
LoadSprite(#arbre, "arbre.png",#PB_Sprite_AlphaBlending|#PB_Sprite_Texture )
CreateSprite3D(#arbre,#arbre)
 
;}
Debug tableau_obj(1)\y
 
Repeat
 
Event.l = WindowEvent()
 evenement()
If (ElapsedMilliseconds() > CheckTime + 1000 / FPS_LIMIT)
            CheckTime = ElapsedMilliseconds()
            FlipBuffers()
            ClearScreen(RGB(128,128,128))
 
            update()                     
 
            Else
            Delay(1)
EndIf
 
 
 
Until Event = #PB_Event_CloseWindow Or quit = 1
 
 
;   
;   For k=0 To 50
 
;   Next
 
 
Procedure evenement()
  If ExamineKeyboard()
 
    If KeyboardPushed(#PB_Key_Up) ;And scroll_y >0
               scroll_y - 1
              EndIf
    If KeyboardPushed(#PB_Key_Right) ;And scroll_x < room_width 
              scroll_x + 1
              EndIf
    If KeyboardPushed(#PB_Key_Down) ;And scroll_y < room_height 
              scroll_y + 1
              EndIf
    If KeyboardPushed(#PB_Key_Left) ;And scroll_x >0
              scroll_x - 1
            EndIf
 
    If KeyboardPushed(#PB_Key_Escape)
              quit = 1
            EndIf
 
EndIf
 
 
 
EndProcedure
 
 
Procedure update()
 
  Start3D() 
 
  DisplaySprite3D(#perso, tableau_obj(1)\newposition_x,tableau_obj(1)\newposition_y)
 
  For i=2 To  nombre_arbre
    DisplaySprite3D(#arbre, tableau_obj(i)\newposition_x - scroll_x,tableau_obj(i)\newposition_y - scroll_y)
    ;DrawText(tableau_obj(i)\newposition_x - scroll_x,tableau_obj(i)\newposition_y- scroll_y,"")
  Next i
 
 Stop3D()
 
EndProcedure
savez-vous comment je peux réussir à faire un tri pour l'affichage de mes arbres et du personnage ?

Car si je laisse
Code :
SortStructuredArray(tableau_obj(), #PB_Sort_Ascending, OffsetOf(objet\y), #PB_Sort_Long)
le tri s'effectue, mais cela change les éléments du tableau (on le remarque avec le debuguer, car le y du personnage n'est plus égal à ecranX/2 (soit 512);

Et si j'enlève ce code, l'affichage des éléments est correct (leur emplacement défini après la structure), mais le Z-order n'est plus correct.

Théoriquement, j'ai trouvé la solution, mais je ne parviens pas à la mettre en pratique :
- je pense que je dois utiliser 2 tableaux (ou listes) : le premier tableau est le tableau que j'ai déjà, avec les objets et leur y.
- un 2ème tableau qui est classé en fonction du Y (ascendant) chaque élément du 1 er tableau.
Cela me fait penser aux pointeurs, mais je ne sais pas comment m'y prendre pour résoudre ce problème .

Cela dit, après, il faudrait que j'affiche les sprites dans l'ordre ascendant de leur y, et donc, j'aurai toujours un problème.

Donc, si quelqu'un sait comment je peux faire ce Z-order (ou depth, ou encore tri), n'hésitez pas à m'en informer .

Merci d'avance.

les images utilisées sont là :
http://blendman.free.fr/dev/pb/arbre.png
http://blendman.free.fr/dev/pb/perso.png
blendman est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/02/2011, 23h58   #2
Responsable Purebasic
 
Avatar de comtois
 
Inscription : avril 2003
Messages : 810
Détails du profil
Informations forums :
Inscription : avril 2003
Messages : 810
Points : 1 856
Points : 1 856
Sauf erreur de ma part, faire un tri sur la position en y des sprites ne pourra pas fonctionner. C'est possible de le faire, mais imagine que ton personnage se déplace de haut en bas devant un arbre :

Prenon le cas où au départ le perso est plus haut qu'un arbre, le perso sera donc affiché en arrière plan selon ta technique.
Ensuite tu diriges vers le bas ton perso, et dès que ses pieds seront plus bas que l'arbre le perso sera affiché en avant plan ! alors que c'est le même arbre, ça va donner un effet assez curieux.

Je pense que tu devrais plutôt gérer des couches sur ta map :
- Une couche inférieure avec un décor statique
- Une couche dynamique avec les persos qui s'y déplacent
- Une couche supérieure avec un décor statique

de cette façon tu n'auras plus de problèmes de calcul de profondeur, tu as juste à afficher tes couches les une après les autres.

Bien sur sur chaque couche statique tu pourras effectivement gérer une profondeur en testant la position en y, tu ne fais le calcul qu'une fois, puisque le décor est statique.

J'ai quand même modifié ton code pour que tu puisses constaté par toi même ce que je raconte plus haut.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
;{ **************** variable, constantes.****************** ..
;Eléments Windows
Enumeration
  #WINDOW_MAIN
EndEnumeration
;Les sprites
Enumeration
  #arbre
  #perso  
EndEnumeration
 
 
ecranX = 1024
ecranY = 768
Global FPS_LIMIT = 120
Global quit = 0
 
Global scroll_x = 0
Global scroll_y = 0
 
Global room_width = 4000
Global room_height  = 3000
;}
 
;{ **************** Structures **************************** 
 
Structure objet
  Sprite.l
  x.l
  y.l
  newposition_x.l
  newposition_y.l
  centre_x.l
  centre_y.l
EndStructure
 
Global nombre_arbre = 500
 
Global Dim tableau_obj.objet(nombre_arbre)
 
For i = 2 To nombre_arbre
  tableau_obj(i)\Sprite = #arbre
  tableau_obj(i)\y = Random(room_height)
  tableau_obj(i)\x = Random(room_width )
  tableau_obj(i)\centre_y = 80
  tableau_obj(i)\centre_y = 180
  tableau_obj(i)\newposition_x = tableau_obj(i)\x - tableau_obj(i)\centre_x
  tableau_obj(i)\newposition_y = tableau_obj(i)\y - tableau_obj(i)\centre_y
Next i
SortStructuredArray(tableau_obj(), #PB_Sort_Ascending, OffsetOf(objet\y), #PB_Sort_Long)
 
tableau_obj(1)\Sprite = #perso
tableau_obj(1)\centre_x = 17
tableau_obj(1)\centre_y = 80
tableau_obj(1)\x = ecranX/2
tableau_obj(1)\y = ecranY/2
 
tableau_obj(1)\newposition_x = tableau_obj(1)\x - tableau_obj(1)\centre_x
tableau_obj(1)\newposition_y = tableau_obj(1)\y - tableau_obj(1)\centre_y
 
 
;}
 
Declare evenement()
Declare update()
 
;{ **************** initialisation ************************** 
 
InitSprite()
InitSprite3D()
InitKeyboard()
InitMouse()
UsePNGImageDecoder()
 
;}
 
 
;{ ********************** openWindow ************************ 
 
OpenWindow(#WINDOW_MAIN,150,150,EcranX,EcranY,"3 Arks - test",#PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_MinimizeGadget)
OpenWindowedScreen(WindowID(#WINDOW_MAIN),0,0,EcranX,EcranY,0,0,0,#PB_Screen_WaitSynchronization ) 
;ClearScreen(RGB(128,128,128))
 
;}
 
;{ loading (sprites)
 
LoadSprite(#perso, "perso.png",#PB_Sprite_AlphaBlending|#PB_Sprite_Texture )
CreateSprite3D(#perso,#perso)
 
LoadSprite(#arbre, "arbre.png",#PB_Sprite_AlphaBlending|#PB_Sprite_Texture )
CreateSprite3D(#arbre,#arbre)
 
;}
Debug tableau_obj(1)\y
 
Repeat
 
  Event.l = WindowEvent()
  evenement()
  If (ElapsedMilliseconds() > CheckTime + 1000 / FPS_LIMIT)
    CheckTime = ElapsedMilliseconds()
    FlipBuffers()
    ClearScreen(RGB(128,128,128))
 
    update()                     
 
  Else
    Delay(1)
  EndIf
 
Until Event = #PB_Event_CloseWindow Or quit = 1
 
 
Procedure evenement()
  If ExamineKeyboard()
 
    If KeyboardPushed(#PB_Key_Up) ;And scroll_y >0
      scroll_y - 1
    EndIf
    If KeyboardPushed(#PB_Key_Right) ;And scroll_x < room_width 
      scroll_x + 1
    EndIf
    If KeyboardPushed(#PB_Key_Down) ;And scroll_y < room_height 
      scroll_y + 1
    EndIf
    If KeyboardPushed(#PB_Key_Left) ;And scroll_x >0
      scroll_x - 1
    EndIf
 
    If KeyboardPushed(#PB_Key_Escape)
      quit = 1
    EndIf
 
  EndIf
 
EndProcedure
 
Procedure update()
  Dim temp.objet(nombre_arbre)
  CopyArray(tableau_obj(), temp())
  For i=1 To nombre_arbre
    If temp(i)\Sprite = #arbre
      temp(i)\newposition_y - scroll_y
    EndIf  
  Next i
  SortStructuredArray(temp(), #PB_Sort_Ascending, OffsetOf(objet\newposition_y), #PB_Sort_Long) 
  For i=1 To nombre_arbre
    If temp(i)\Sprite = #arbre
      temp(i)\newposition_y + scroll_y
    EndIf  
  Next i
  CopyArray(temp(), tableau_obj())
 
  Start3D() 
 
  For i=1 To  nombre_arbre
    If tableau_obj(i)\Sprite = #arbre
      DisplaySprite3D(tableau_obj(i)\Sprite, tableau_obj(i)\newposition_x - scroll_x,tableau_obj(i)\newposition_y - scroll_y)
    Else
      DisplaySprite3D(tableau_obj(i)\Sprite, tableau_obj(i)\newposition_x ,tableau_obj(i)\newposition_y )     
 
    EndIf
  Next i    
 
  Stop3D()
 
EndProcedure
__________________
Vous souhaitez participer à la rubrique PureBasic (tutoriels, FAQ, sources) ? Contactez-moi par MP.
comtois est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/02/2011, 00h04   #3
Responsable Purebasic
 
Avatar de comtois
 
Inscription : avril 2003
Messages : 810
Détails du profil
Informations forums :
Inscription : avril 2003
Messages : 810
Points : 1 856
Points : 1 856
Sinon la gestion d'une caméra serait sympa

c'est à dire que que tu ne déplaces le décor que si le personnage arrive sur les bords de la carte.
__________________
Vous souhaitez participer à la rubrique PureBasic (tutoriels, FAQ, sources) ? Contactez-moi par MP.
comtois est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/02/2011, 08h53   #4
Responsable Purebasic
 
Avatar de comtois
 
Inscription : avril 2003
Messages : 810
Détails du profil
Informations forums :
Inscription : avril 2003
Messages : 810
Points : 1 856
Points : 1 856
un 'tuto' sur le z order

Effectivement quand je vois l'image du perso avec le rocher, c'est peut-être bien de garder le concept du z-order
à condition de gérer les collisions pour éviter de le voir traverser le rocher de haut en bas.
C'est pour ça que ça me faisait bizarre avec les arbres, les collisions ne sont pas encore gérées.
__________________
Vous souhaitez participer à la rubrique PureBasic (tutoriels, FAQ, sources) ? Contactez-moi par MP.
comtois est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/02/2011, 10h37   #5
Candidat au titre de Membre du Club
 
Inscription : avril 2007
Messages : 46
Détails du profil
Informations forums :
Inscription : avril 2007
Messages : 46
Points : 14
Points : 14
salut Comtois.

Merci pour ta correction, j'étais parvenu à faire le tri, mais ton exemple avec le tableau temporaire est bien meilleur niveau performance et c'est ce que je cherchais à faire. Alors, un grand merci à toi !

Concernant le tri en "Z-order", c'est un système utilisé par pas mal d'éditeur de jeu (comme game maker ou construct). Et en général, ça fonctionne plutôt bien, donc, je pensais qu'il serait intéressant d'adapter ce système pour mon jeu .


Citation:
Envoyé par comtois Voir le message
un 'tuto' sur le z order

Effectivement quand je vois l'image du perso avec le rocher, c'est peut-être bien de garder le concept du z-order
à condition de gérer les collisions pour éviter de le voir traverser le rocher de haut en bas.
C'est pour ça que ça me faisait bizarre avec les arbres, les collisions ne sont pas encore gérées.
Effectivement, dans mon exemple, il manque plusieurs choses pour que cela soit correct :
- les block collisions : des sprites invisibles que le personnages doit contourner (par exemple le pied de l'arbre)
- une sorte de pathfinding : j'espère gérer par la suite un "pseudo" pathfinding (peut-être pas un A* complet, mais au moins un système genre : clic & go (on clique et le personnage se dirige à l'endroit souhaité, en contournant les blocks collisions).

Citation:
Envoyé par comtois Voir le message
Sinon la gestion d'une caméra serait sympa

c'est à dire que que tu ne déplaces le décor que si le personnage arrive sur les bords de la carte.
OUi, j'y ai pensé et je suis en train d'essayer de le faire. J'essaierai de poster ça dès que j'aurai avancé .

A ce propos, pour le scrolling, la méthode que j'utilise est la bonne ?
Il existe un système de caméra avec purebasic, ou on doit le faire à la main ?

Autres questions :
- comme on le voit, il y a un problème au niveau du "centre" des objets (ou hotspot). Pour le moment, le personnage passe derrière l'arbre tout en haut (et non à ses pieds). J'essaie de corriger ça, car j'ai bien mis les paramètres pour gérer ça, mais ça ne doit pas être correct car ça ne marche pas
- je pense que pour encore optimiser ça, il ne faudrait vérifier que les arbres qui se trouvent à proximité du joueur (en X et Y) et dans le même écran que le joueur, mais comment dois-je faire pour récupérer le/les coordonnées des arbres proches du joueur ? je dois à nouveau utiliser une boucle for ?
- dernière question : il est possible d'utiliser une liste chainée, mais comment récupère t-on un paramètres précis d'un élément d'une liste chainée (l'équivalent de : If tableau_obj(122)\Sprite = #arbre ,par exemple pour savoir si le sprite de l'ément 122 du tableau tableau_obj =#arbre, mais avec une liste chainée)

En tout cas, encore un grand merci pour toutes ces informations.

Lorsque j'aurai terminé ce système complet, je me disais que j'essaierai peut être de faire un tutoriel pour les débutants (comme moi ), concernant la conception de jeu en 2D iso (ou 3D iso), avec comme notion : l'affichage (aléatoire ou pré-établie de sprites), le tri (Z-order), le hotspot (point central du sprite), le déplacement (en clic and go ou pathfinding A* si j'y parviens), etc..

Des tutoriels complets consacrés à la 3Diso ou plutôt la 2Diso, on n'en trouve assez peu souvent.

EDIT :
voici le code corrigé :
- gestion de la caméra. On doit pouvoir l'optimiser, mais il fonctionne.
- gestion des "hotspots" ou centres des objets : maintenant le personnage passe devant/derière l'arbre quand il est à ses pieds la classe.

Pour changer la taille des bords, ce sont les paramètres horBord et vertbord.
Ce n'est pas génant d'avoir beaucoup de variable globale ?
Je sais que je peux utiliser les "shared", mais les globales ont l'air plutôt facile d'utilisation .

Cela dit, peut être devrai-je créer une structure generale ou "view" et un tableau structuré pour gérer ces variables plutôt que d'avoir beaucoup de variables globales.


Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
 
;{ **************** variable, constantes.****************** ..
;Eléments Windows
Enumeration
  #WINDOW_MAIN
  #text
EndEnumeration
;Les sprites
Enumeration
  #arbre
  #perso  
EndEnumeration
 
;variable général : taille de la vue, de la map (room), etc..
Global room_width = 4000
Global room_height  = 3000 
Global ecranX = 1024
Global ecranY = 768
Global FPS_LIMIT = 120
Global quit = 0
 
;gestion de la "caméra"
; scroll pour tous les objets, sauf le centre de la vue
Global scroll_x = 0
Global scroll_y = 0
; "scroll" pour l'objet central de la vue, lorsque celui-ci se rapproche du bord de l'écran
Global scroll_centre_cam_x = 0
Global scroll_centre_cam_y = 0
 
Global view_centre_x = ecranX /2 ; le centre de la vue
Global view_centre_y = ecranY /2 ; le centre de la vue
 
Global HorBord = 60 ;bordure verticale, au dela de celle-ci le personnage ne se rapproche plus du bord, mais la "caméra" bougede l'écran
Global VertBord = 40 ;bordure verticale, au dela de celle-ci le personnage ne se rapproche plus du bord, mais la "caméra" bougede l'écran
 
; vitesse de déplacement du personnage
Global vitesse = 3 ;* FPS_LIMIT/120
 
 
;}
 
;{ **************** Structures **************************** 
 
Structure objet
  Sprite.l
  x.l
  y.l
  newposition_x.l
  newposition_y.l
  centre_x.l
  centre_y.l
EndStructure
 
Global nombre_arbre = 500
 
Global Dim tableau_obj.objet(nombre_arbre)
 
For i = 2 To nombre_arbre
  tableau_obj(i)\Sprite = #arbre
  tableau_obj(i)\y = Random(room_height)
  tableau_obj(i)\x = Random(room_width )
  tableau_obj(i)\centre_y = 80
  tableau_obj(i)\centre_y = 180
  tableau_obj(i)\newposition_x = tableau_obj(i)\x - tableau_obj(i)\centre_x
  tableau_obj(i)\newposition_y = tableau_obj(i)\y - tableau_obj(i)\centre_y
Next i
SortStructuredArray(tableau_obj(), #PB_Sort_Ascending, OffsetOf(objet\y), #PB_Sort_Long)
 
; le personnage est considéré comme étant le centre de la caméra. Il est donc 
; le seul à avoir comme paramètre les scroll_centre_cam
 
tableau_obj(1)\Sprite = #perso
tableau_obj(1)\centre_x = 17
tableau_obj(1)\centre_y = 80
tableau_obj(1)\x = ecranX/2
tableau_obj(1)\y = ecranY/2
 
tableau_obj(1)\newposition_x = tableau_obj(1)\x - tableau_obj(1)\centre_x - scroll_centre_cam_x
tableau_obj(1)\newposition_y = tableau_obj(1)\y - tableau_obj(1)\centre_y - scroll_centre_cam_y
 
 
;}
 
Declare evenement()
Declare update()
 
;{ **************** initialisation ************************** 
 
InitSprite()
InitSprite3D()
InitKeyboard()
InitMouse()
UsePNGImageDecoder()
 
;}
 
 
;{ ********************** openWindow ************************ 
 
OpenWindow(#WINDOW_MAIN,150,150,EcranX,EcranY,"3 Arks - test",#PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_MinimizeGadget)
OpenWindowedScreen(WindowID(#WINDOW_MAIN),0,0,EcranX,EcranY,0,0,0,#PB_Screen_WaitSynchronization ) 
;ClearScreen(RGB(128,128,128))
 
;}
 
;{ loading (sprites)
 
LoadSprite(#perso, "perso.png",#PB_Sprite_AlphaBlending|#PB_Sprite_Texture )
CreateSprite3D(#perso,#perso)
 
LoadSprite(#arbre, "arbre.png",#PB_Sprite_AlphaBlending|#PB_Sprite_Texture )
CreateSprite3D(#arbre,#arbre)
 
;}
;Debug tableau_obj(1)\y
 
Repeat
 
  Event.l = WindowEvent()
  evenement()
  If (ElapsedMilliseconds() > CheckTime + 1000 / FPS_LIMIT)
    CheckTime = ElapsedMilliseconds()
    FlipBuffers()
    ClearScreen(RGB(128,128,128))
 
    update()                     
 
  Else
    Delay(1)
  EndIf
 
Until Event = #PB_Event_CloseWindow Or quit = 1
 
 
Procedure evenement()
  If ExamineKeyboard()
 
    If KeyboardPushed(#PB_Key_Up) 
      If view_centre_y > HorBord
        scroll_centre_cam_y - vitesse
        view_centre_y - vitesse
      ElseIf scroll_y >0
          scroll_y - vitesse
      EndIf
    EndIf
 
 
    If KeyboardPushed(#PB_Key_Down) And scroll_y < room_height - ecranY 
      If view_centre_y < ecranY - HorBord
        scroll_centre_cam_y + vitesse
        view_centre_y + vitesse
      Else  
          scroll_y + vitesse
      EndIf
    EndIf
 
 
    If KeyboardPushed(#PB_Key_Left) 
      If view_centre_x > VertBord
        scroll_centre_cam_x - vitesse
        view_centre_x - vitesse
      ElseIf  scroll_x >0 
          scroll_x - vitesse
      EndIf
    EndIf
 
 
    If KeyboardPushed(#PB_Key_Right) And scroll_x < room_width - ecranX
      If view_centre_x < ecranX - VertBord
        scroll_centre_cam_x + vitesse
        view_centre_x + vitesse
      Else 
          scroll_x + vitesse
      EndIf
    EndIf
 
 
    If KeyboardPushed(#PB_Key_Escape)
      quit = 1
    EndIf
 
  EndIf
 
EndProcedure
 
Procedure update()
  Dim temp.objet(nombre_arbre)
  CopyArray(tableau_obj(), temp())
 
  For i=1 To nombre_arbre
    If temp(i)\Sprite = #arbre
      temp(i)\newposition_y - scroll_y
 
    ElseIf temp(i)\Sprite = #perso
      temp(i)\newposition_y + scroll_centre_cam_y - temp(1)\centre_y
      temp(i)\newposition_x + scroll_centre_cam_x - temp(1)\centre_x
    EndIf
  Next i
 
  SortStructuredArray(temp(), #PB_Sort_Ascending, OffsetOf(objet\newposition_y), #PB_Sort_Long) 
 
  For i=1 To nombre_arbre
    If temp(i)\Sprite = #arbre
      temp(i)\newposition_y + scroll_y
 
    ElseIf temp(i)\Sprite = #perso
      temp(i)\newposition_y - scroll_centre_cam_y + temp(1)\centre_y
      temp(i)\newposition_x - scroll_centre_cam_x + temp(1)\centre_x
    EndIf
  Next i
 
  CopyArray(temp(), tableau_obj())
 
  Start3D() 
 
  For i=1 To  nombre_arbre
    If tableau_obj(i)\Sprite = #arbre
      DisplaySprite3D(tableau_obj(i)\Sprite, tableau_obj(i)\newposition_x - scroll_x,tableau_obj(i)\newposition_y - scroll_y)
    Else
      DisplaySprite3D(tableau_obj(i)\Sprite, tableau_obj(i)\newposition_x + scroll_centre_cam_x - tableau_obj(i)\centre_x,tableau_obj(i)\newposition_y + scroll_centre_cam_y - tableau_obj(i)\centre_y)     
 
    EndIf
  Next i    
 
  Stop3D()
 
EndProcedure
blendman est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/02/2011, 13h40   #6
Responsable Purebasic
 
Avatar de comtois
 
Inscription : avril 2003
Messages : 810
Détails du profil
Informations forums :
Inscription : avril 2003
Messages : 810
Points : 1 856
Points : 1 856
Tous les exemples de map que je connais utilisent le système de la 'tuile', tous les sprites ont le même format, c'est plus facile à gérer dans un tableau. N'est-ce pas aussi le principe de RPGMaker que tu utilises ? ou il permet aussi de gérer des sprites de différentes tailles ?

Avec ce système tu peux avoir des maps immenses, et ne te soucier que de la portion qui sera affichée, pour tous les tests, comme les collisions, le pathfinding, etc.

Exemple d'affichage (la carte ne ressemble à rien , elle est aléatoire)

Ce code me permet d'afficher la carte dans un cadre, ou d'afficher autant de fois la même carte qu'il y a de joueurs.
ici j'ai mis 2 joueurs le premier se déplace avec le curseur, et le second avec les touches QSDZ.

Sinon oui, évite de mettre des variables globales.
L'exemple ci-dessous n'est pas à suivre, j'ai déclaré un tableau en global

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
; Comtois 
; PB 4.51
 
InitSprite()
InitKeyboard()
OpenScreen(1024,768,32,"Map")
 
KeyboardMode(#PB_Keyboard_International)
Enumeration
  #Herbe
  #Eau
  #Fleur
  #Arbre
  #Bord
EndEnumeration
 
Structure s_Point
  x.i
  y.i
EndStructure
 
Structure s_Screen
  Width.i
  Height.i
EndStructure
Structure S_Box
  x.i
  y.i
  Width.i
  Height.i
EndStructure
 
Structure s_Commande
  Haut.i
  Bas.i
  Gauche.i
  Droite.i
EndStructure
 
Structure s_Camera
  Position.s_Point
  Destination.s_Point
  Speed.i
  Screen.s_Screen ; Dimension de l'écran
  ViewPort.s_Box
  Touche.s_Commande
EndStructure
 
#TailleTitleCarteX=440
#TailleTitleCarteY=440
#TailleTitle=32
 
Declare DessineSprite(Sprite, Couleur)
Declare RandomMap()
Declare CameraEvent(*Camera.s_Camera)
Declare AfficheMap(*Camera.s_Camera)
Declare AfficheBox(*Camera.s_Camera)
 
 
Camera.s_Camera
Camera\Speed = 3
Camera\Position\x = 0
Camera\Position\y = 0
Camera\ViewPort\x = 40
Camera\ViewPort\y = 40
Camera\ViewPort\Width = 300
Camera\ViewPort\Height = 150
Camera\Touche\Bas    = #PB_Key_Down
Camera\Touche\Haut   = #PB_Key_Up
Camera\Touche\Droite = #PB_Key_Right
Camera\Touche\Gauche = #PB_Key_Left
 
Camera2.s_Camera
Camera2\Speed = 3
Camera2\Position\x = 0
Camera2\Position\y = 0
Camera2\ViewPort\x = 40
Camera2\ViewPort\y = 240
Camera2\ViewPort\Width = 300
Camera2\ViewPort\Height = 150
Camera2\Touche\Bas    = #PB_Key_S
Camera2\Touche\Haut   = #PB_Key_Z
Camera2\Touche\Droite = #PB_Key_D
Camera2\Touche\Gauche = #PB_Key_Q
 
DessineSprite(#Bord, $0000FF)
DessineSprite(#Herbe, $00FF00)
DessineSprite(#Eau, $FF0000)
DessineSprite(#Fleur, $00FFFF)
DessineSprite(#Arbre, $000088)
 
Global Dim Map(#TailleTitleCarteX,#TailleTitleCarteY)
RandomMap()
 
Repeat
  ClearScreen(0)
  CameraEvent(@Camera)
  AfficheMap(@Camera)
  AfficheBox(@Camera)
  CameraEvent(@Camera2)
  AfficheMap(@Camera2)
  AfficheBox(@Camera2)
  FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)
 
Procedure DessineSprite(Sprite, Couleur)
  CreateSprite(Sprite,#TailleTitle,#TailleTitle)
  If StartDrawing(SpriteOutput(Sprite))
    Box(0,0,SpriteWidth(Sprite),SpriteHeight(Sprite),Couleur)
    StopDrawing()
    ProcedureReturn #True
  EndIf
EndProcedure
 
Procedure RandomMap()
  For y=0 To #TailleTitleCarteY
    For x=0 To #TailleTitleCarteX
      If x=0 Or x=#TailleTitleCarteX Or y=0 Or y=#TailleTitleCarteY Or x=#TailleTitleCarteX/2 Or y=#TailleTitleCarteY/2
        Map(x,y)=#Bord
      Else
        Map(x,y)=Random(#Arbre)
      EndIf   
    Next x
  Next y   
EndProcedure
 
Procedure AfficheBox(*Camera.s_Camera)
  StartDrawing(ScreenOutput())
    DrawingMode(#PB_2DDrawing_Outlined)
    Box(*Camera\ViewPort\x, *Camera\ViewPort\y, *Camera\ViewPort\Width, *Camera\ViewPort\Height,$FFFFFF)
  StopDrawing()
EndProcedure
 
Procedure CameraEvent(*Camera.s_Camera)
 
  If ExamineKeyboard()
 
    If KeyboardPushed(*Camera\Touche\Droite)
      Key_Right = #True
    EndIf
    If KeyboardReleased(*Camera\Touche\Droite)
      Key_Right = #False
    EndIf     
    If KeyboardPushed(*Camera\Touche\Gauche)
      Key_Left = #True
    EndIf
    If KeyboardReleased(*Camera\Touche\Gauche)
      Key_Left = #False
    EndIf     
    If KeyboardPushed(*Camera\Touche\Haut)
      Key_Up = #True
    EndIf
    If KeyboardReleased(*Camera\Touche\Haut)
      Key_Up = #False
    EndIf 
    If KeyboardPushed(*Camera\Touche\Bas)
      Key_Down = #True
    EndIf
    If KeyboardReleased(*Camera\Touche\Bas)
      Key_down = #False
    EndIf         
  EndIf
    If Key_Right And *Camera\Position\x < (#TailleTitleCarteX + 1) * #TailleTitle - *Camera\ViewPort\Width
      *Camera\Position\x + *Camera\Speed
    ElseIf Key_Left And *Camera\Position\x > 0
      *Camera\Position\x - *Camera\Speed
    EndIf
    If Key_Down And *Camera\Position\y < (#TailleTitleCarteY + 1) * #TailleTitle - *Camera\ViewPort\Height
      *Camera\Position\y + *Camera\Speed
    ElseIf Key_Up And *Camera\Position\y > 0
      *Camera\Position\y - *Camera\Speed
    EndIf 
 
EndProcedure 
 
Procedure AfficheMap(*Camera.s_Camera)
  Define.i Tx, Ty  ; Index sur le tableau DataMap pour récupérer le numéro du Tile à afficher
  Define.i Rx, Ry  ; Position sur le Tile à afficher (entre 0 et la largeur ou hauteur du Tile à afficher)
  Define.i Px, Py  ; Position à l'écran du Tile à afficher
  Define.S_Box Src ; Portion de l'image à récupérer sur le Chipset (Tile à afficher) 
 
  Tx         = *Camera\Position\x / #TailleTitle 
  Ty         = *Camera\Position\y / #TailleTitle
  Ry         = *Camera\Position\y % #TailleTitle
  Src\y      = Ry
  Src\Height = #TailleTitle - Ry
  Py         = *Camera\ViewPort\y
 
 
  While Py < *Camera\ViewPort\y + *Camera\ViewPort\Height
    Px        = *Camera\ViewPort\x   
    Rx        = *Camera\Position\x % #TailleTitle
    Tx        = *Camera\Position\x / #TailleTitle    
    Src\x     = Rx
    Src\Width = #TailleTitle - Rx
 
    While Px < *Camera\ViewPort\x + *Camera\ViewPort\Width
      ClipSprite(Map(Tx,Ty), Src\x, Src\y, Src\Width, Src\Height)
      DisplaySprite(Map(Tx,Ty), Px, Py)
 
      ;On se place après le Tile qui vient d'être affiché      
      Px + Src\Width
      ;On calcule le prochain Tile à afficher 
      Tx + 1
      ;
      Src\x = 0
      ;Tant que l'on n'atteint pas l'extrémité de la carte, le Tile sera complet 
      Src\Width = #TailleTitle
      ;sinon il faut calculer sa largeur
      If (Px + Src\Width) > (*Camera\ViewPort\x + *Camera\ViewPort\Width)
        Src\Width = *Camera\ViewPort\x + *Camera\ViewPort\Width - Px
      EndIf
 
    Wend
    ;On se place après le Tile qui vient d'être affiché
    Py + Src\Height
    ;On calcule le prochain Tile à afficher (index sur le tableau 
    Ty + 1
    ;
    Src\y      = 0
    ;Tant que l'on n'atteint pas l'extrémité de la carte, le Tile sera complet 
    Src\Height = #TailleTitle
    ;sinon il faut calculer sa hauteur
    If Py + Src\Height > *Camera\ViewPort\y + *Camera\ViewPort\Height
      Src\Height = *Camera\ViewPort\y + *Camera\ViewPort\Height - Py
    EndIf
  Wend  
 
EndProcedure
__________________
Vous souhaitez participer à la rubrique PureBasic (tutoriels, FAQ, sources) ? Contactez-moi par MP.
comtois est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/02/2011, 14h19   #7
Candidat au titre de Membre du Club
 
Inscription : avril 2007
Messages : 46
Détails du profil
Informations forums :
Inscription : avril 2007
Messages : 46
Points : 14
Points : 14
Bonjour Comtois, merci de tes réponses, et merci aussi pour ton exemple qui est très intéressant .
J'ai pu apprendre que je pouvais utiliser des structures à l'intérieur de structures, ce qui est vraiment très utile.

Citation:
Envoyé par comtois Voir le message
Tous les exemples de map que je connais utilisent le système de la 'tuile', tous les sprites ont le même format, c'est plus facile à gérer dans un tableau. N'est-ce pas aussi le principe de RPGMaker que tu utilises ?
je ne connais pas bien rpg maker, mais je pense que c'est effectivement un logiciel qui utilise le principe de gestion des tuiles (tiles). Mais même les personnages ou ennemis doivent avoir une taille prédéfinie (32*32,64*64).

Je ne sais pas si tu connais un peu des jeux comme Dofus, mixmaster, Goonzu ou encore t4c, mais je crois que leur système est multiple : utilisation de tuiles (tiles) pour le sol, mais les autres éléments sont des sprites ayant des tailles différentes.
Du coup, je pense qu'ils utilisent la méthode de tri par y sur ces objets-là.

Citation:
ou il permet aussi de gérer des sprites de différentes tailles ?
je ne crois pas que rpg maker permette de gérer des sprites de tailles différentes, si tout se fait par tuiles. Ou alors, comme je disais, les "sprites" gérer doivent alors être dans une taille prédéfinie comme 32*32 ou 64*64, etc..
Mais je ne pense que rpg maker utilise des sprites dans n'importe quelle taille (genre 152*18), comme je le fais .

Citation:
Avec ce système tu peux avoir des maps immenses, et ne te soucier que de la portion qui sera affichée, pour tous les tests, comme les collisions, le pathfinding, etc.
Le système est intéressant effectivement. Mais ne peut -on pas ne se soucier que de ce qui est affiché à l'écran avec l'exemple que j'ai donné ?

Je ferai quelques tests pour voir.

Citation:
Exemple d'affichage (la carte ne ressemble à rien , elle est aléatoire)

Ce code me permet d'afficher la carte dans un cadre, ou d'afficher autant de fois la même carte qu'il y a de joueurs.
ici j'ai mis 2 joueurs le premier se déplace avec le curseur, et le second avec les touches QSDZ.

Sinon oui, évite de mettre des variables globales.
L'exemple ci-dessous n'est pas à suivre, j'ai déclaré un tableau en global
ok, je ferai attention aux variables globales .

Par quoi aurais-tu du remplacer ton tableau global pour y avoir accès ?

J'ai regardé un peu le code, mais il y aune notion que je ne maitrise pas encore très bien, ce sont les pointeurs (* et @). Il va falloir que je fasse plusieurs essais je pense pour bien cerner ce système car visiblement c'est très utile.

une dernière question : sais-tu comment on accède à un champs précis d'un élément d'une liste structurée ?

Encore un grand merci en tout cas .
blendman est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/02/2011, 16h31   #8
Responsable Purebasic
 
Avatar de comtois
 
Inscription : avril 2003
Messages : 810
Détails du profil
Informations forums :
Inscription : avril 2003
Messages : 810
Points : 1 856
Points : 1 856
pour l'accès d'un champ c'est le même principe pour une liste chainée que pour les tableaux.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Structure MaStructure
  x.l
  y.l
  truc.f
  machin.d
EndStructure
 
NewList MaListe.MaStructure()
 
;Ajoute un élément à la liste
AddElement(MaListe())
With MaListe()
  \x = 23
  \y = 34
  \truc = 45.76
  \machin = 2345.866556
EndWith 
;Ou alors sans utiliser With
AddElement(MaListe())
MaListe()\machin = 7656
 
;Affiche la liste
ForEach MaListe()
  With MaListe()
    Debug \machin
    Debug "****"
  EndWith
Next
Oui tu peux utiliser une structure dans une structure, et aussi des tableaux, des listes chainées et des maps.

Citation:
Par quoi aurais-tu du remplacer ton tableau global pour y avoir accès ?
Plusieurs méthodes possibles, soit mettre le tableau dans une structure :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 
Structure Title
  x.l
  y.l
  Collision.l
EndStructure
 
Structure MaMap
  Array Tableau.Title(0)
  AutreInfo.l
EndStructure
 
Define Carte1.MaMap
 
Declare ModifieCarte(*Carte.MaMap)
 
ModifieCarte(@Carte1)
;Affiche le résultat
Debug Carte1\Tableau(4)\Collision
Debug Carte1\Tableau(4)\x
 
Procedure ModifieCarte(*Carte.MaMap)
  ;Change la taille du tableau
  ReDim *Carte\Tableau(30)
  ;Ajoute des trucs dans le tableau
  *Carte\Tableau(4)\Collision = #True
  *Carte\Tableau(4)\x = 65
EndProcedure
ou alors en passant mon tableau en paramètre de la procédure :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Structure Title
  x.l
  y.l
  Collision.l
EndStructure
 
Dim MonTableau.Title(1)
 
Declare ModifieTableau(Array Ptr.Title(1)) ; 1 indique le nombre de dimension du tableau
 
ModifieTableau(@MonTableau())
;Affiche le résultat
Debug MonTableau(4)\Collision 
Debug MonTableau(4)\x
 
Procedure ModifieTableau(Array Ptr.Title(1))
  ReDim Ptr.Title(35)
  Ptr(4)\Collision = #True
  Ptr(4)\x = 65
EndProcedure
__________________
Vous souhaitez participer à la rubrique PureBasic (tutoriels, FAQ, sources) ? Contactez-moi par MP.
comtois est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/02/2011, 16h43   #9
Responsable Purebasic
 
Avatar de comtois
 
Inscription : avril 2003
Messages : 810
Détails du profil
Informations forums :
Inscription : avril 2003
Messages : 810
Points : 1 856
Points : 1 856
Citation:
Mais ne peut -on pas ne se soucier que de ce qui est affiché à l'écran avec l'exemple que j'ai donné ?
Je ne l'ai jamais fait, mais en réfléchissant il doit être possible d'utiliser ma méthode avec tes sprites. C'est à dire gérer un tableau qui découpe ta carte, et tu stockes le point chaud et le type de sprite. Ensuite c'est ta caméra qui se déplace, ça t'évite de recalculer en permanence la position de tous tes objets, tu ne recalcules que ceux qui sont dans le cadre de ta caméra. Comme je le fais dans mon exemple précédent.
__________________
Vous souhaitez participer à la rubrique PureBasic (tutoriels, FAQ, sources) ? Contactez-moi par MP.
comtois est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/02/2011, 13h50   #10
Candidat au titre de Membre du Club
 
Inscription : avril 2007
Messages : 46
Détails du profil
Informations forums :
Inscription : avril 2007
Messages : 46
Points : 14
Points : 14
salut Comtois, merci de tes réponses.

Citation:
Envoyé par comtois Voir le message
Citation:
Mais ne peut -on pas ne se soucier que de ce qui est affiché à l'écran avec l'exemple que j'ai donné ?
Je ne l'ai jamais fait, mais en réfléchissant il doit être possible d'utiliser ma méthode avec tes sprites. C'est à dire gérer un tableau qui découpe ta carte, et tu stockes le point chaud et le type de sprite. Ensuite c'est ta caméra qui se déplace, ça t'évite de recalculer en permanence la position de tous tes objets, tu ne recalcules que ceux qui sont dans le cadre de ta caméra. Comme je le fais dans mon exemple précédent.
je vais regarder attentivement ton exemple pour comprendre comment tu déplaces ta caméra au lieu de déplacer les sprites.
Ce serait effectivement plus intéressant .

J'essaierai aussi par la suite faire comme ton exemple, c'est à dire de tout gérer dans un tableau qui découperait la carte, peut être en plusieurs écrans liés à la résolution de la fenêtre par exemple.

Imaginons que la map fasse 4000*3000 et la résolution de la fenêtre fasse 800*600, je découperai donc en 5*5, soit 25 partie (ou sous-écran).

Je n'aurai alors qu'à en gérer au maximum 4 (si on est en haut à droite par exemple, entre plusieurs sous-écrans).


Citation:
Envoyé par comtois Voir le message
pour l'accès d'un champ c'est le même principe pour une liste chainée que pour les tableaux.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Structure MaStructure
  x.l
  y.l
  truc.f
  machin.d
EndStructure
 
NewList MaListe.MaStructure()
 
;Ajoute un élément à la liste
AddElement(MaListe())
With MaListe()
  \x = 23
  \y = 34
  \truc = 45.76
  \machin = 2345.866556
EndWith 
;Ou alors sans utiliser With
AddElement(MaListe())
MaListe()\machin = 7656
 
;Affiche la liste
ForEach MaListe()
  With MaListe()
    Debug \machin
    Debug "****"
  EndWith
Next
Merci pour les informations, j'avais un peu regardé du coté des listes (la documentation), mais en fait ce que je n'avais pas trouvé était ceic : modifier un champs d'un élément précis de la liste (par exemple, le champs vie de l'élément 23)

Avec un tableau c'est facile pour modifier le champs "vie" de l'élément 23 du tableau personnage, on fait ceci :
Pour une liste, je crois que je dois utiliser cette technique-ci (par exemple, pour modifier le 1er élément dans ton exemple):
Code :
1
2
3
4
5
6
 
ResetList(MaListe())          
    If SelectElement(MaListe(), 0)
      MaListe()\machin= 12    
    EndIf 
ChangeCurrentElement(MaListe(), 0)
j'ai modifié le code trouvé dans la documentation, c'était ça que je cherchais. Je suppose qu'il n'y a pas d'autres méthodes pour faire ça (plus simple)?


Citation:
Oui tu peux utiliser une structure dans une structure, et aussi des tableaux, des listes chainées et des maps.
J'ai regardé la définition des map (je ne connaissais pas encore).

Si j'ai bien compris, c'est une sorte de dictionnaire, mais concrètement, dans un jeu d'aventure/rpg, je pourrais m'en servir pour faire quoi par exemple ?

Stocker le nom des personnages par exemple ? ou des objets de drop ?
blendman est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/02/2011, 19h41   #11
Responsable Purebasic
 
Avatar de comtois
 
Inscription : avril 2003
Messages : 810
Détails du profil
Informations forums :
Inscription : avril 2003
Messages : 810
Points : 1 856
Points : 1 856
Citation:
Imaginons que la map fasse 4000*3000 et la résolution de la fenêtre fasse 800*600, je découperai donc en 5*5, soit 25 partie (ou sous-écran).

Je n'aurai alors qu'à en gérer au maximum 4 (si on est en haut à droite par exemple, entre plusieurs sous-écrans).
Pourquoi pas une seule carte ?
Dim Carte(800, 600) ; Avec une grille 5x5 tu obtiens bien ta carte de 4000x3000.

De cette façon tu peux parcourir l'ensemble de ta carte avec un seul tableau. Par contre ça t'impose de positionner tes sprites en fonction de cette grille. C'est gênant d'avoir un quadrillage pour positionner tes objets ?

Tu auras juste à désigner les cases qui sont infranchissables pour gérer ton Pathfinding.

Un exemple de pathfinding avec PureBasic.


Citation:
Pour une liste, je crois que je dois utiliser cette technique-ci (par exemple, pour modifier le 1er élément dans ton exemple):

Code :
1
2
3
4
5
ResetList(MaListe())          
    If SelectElement(MaListe(), 0)
      MaListe()\machin= 12    
    EndIf 
ChangeCurrentElement(MaListe(), 0)
j'ai modifié le code trouvé dans la documentation, c'était ça que je cherchais. Je suppose qu'il n'y a pas d'autres méthodes pour faire ça (plus simple)?
Je ne sais pas, faudrait savoir à quoi te sert ta liste, et ce que tu cherches à faire exactement.

Mais c'est clair que c'est le principe d'une liste, il faut parcourir chaque élément jusqu'à trouver celui qui t'intéresse, car ils sont chainés.

Pour les tables de hachages, je manque de connaissance et de pratique. Comme je comprends la chose pour l'instant, je dirais que c'est utile quand on doit gérer beaucoup de données, et qu'on a besoin de retrouver rapidement une de ces données sans avoir à parcourir toutes la liste.

Pour m'exercer j'avais récupéré des listes de mots de la langue françaises sur le net et j'avais codé un dictionnaire. Utile pour tricher dans les jeux de lettres

Pour un jeu type RPG, j'avoue que je ne me suis pas encore penché sur la question. Mais ça doit sûrement servir. Je crois que tu en sentiras le besoin quand tu seras saturé de données à gérer

Tu peux toujours demander sur le forum jeux de dvp, y'a des calés qui trainent par là.
__________________
Vous souhaitez participer à la rubrique PureBasic (tutoriels, FAQ, sources) ? Contactez-moi par MP.
comtois est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/03/2011, 09h29   #12
Candidat au titre de Membre du Club
 
Inscription : avril 2007
Messages : 46
Détails du profil
Informations forums :
Inscription : avril 2007
Messages : 46
Points : 14
Points : 14
Citation:
Envoyé par comtois Voir le message
Pourquoi pas une seule carte ?
Dim Carte(800, 600) ; Avec une grille 5x5 tu obtiens bien ta carte de 4000x3000.
oui c'est ce que je voulais dire.
Une seule grande carte découpée dans un tableau par exemple.

Citation:
De cette façon tu peux parcourir l'ensemble de ta carte avec un seul tableau. Par contre ça t'impose de positionner tes sprites en fonction de cette grille. C'est gênant d'avoir un quadrillage pour positionner tes objets ?

Tu auras juste à désigner les cases qui sont infranchissables pour gérer ton Pathfinding.
en fait, dans mon précédent jeu et mon éditeur de map, seules les block collisions sont "snappés" à une grille. Pour les objets ce n'est pas nécessaire et c'est même problématique pour avoir une jolie carte, car en général, la grille ne peut pas faire 1*1, mais plutôt 32*32 ou 64*32 (ou 32*16) pour un pseudo iso.

cela dit, les sprites seront "contenus" dans une case du tableau (ou à cheval, et je peux peut être faire une condition pour l'affichage du genre : j'affiche telle case du tableau à l'écran, si le sprite est contenu dans la case, j'affiche le sprite.


cool pour cet exemple, mais je n'ai pas encore la version complète de PB (je vais bientôt l'acheter je pense ).
Je pourrais tester cet exemple prochainement.




Citation:
Je ne sais pas, faudrait savoir à quoi te sert ta liste, et ce que tu cherches à faire exactement.
imaginons que je m'en serve pour trouver les images présentes sur la map, par exemple exemple, pour les sorts ou les monstres : ceux-ci disparaissent, donc la liste permet d'être actualisés plus facilement qu'un tableau je crois (une liste est dynamique si j'ai bien compris)


Citation:
Pour les tables de hachages, je manque de connaissance et de pratique. Comme je comprends la chose pour l'instant, je dirais que c'est utile quand on doit gérer beaucoup de données, et qu'on a besoin de retrouver rapidement une de ces données sans avoir à parcourir toutes la liste.

Pour m'exercer j'avais récupéré des listes de mots de la langue françaises sur le net et j'avais codé un dictionnaire. Utile pour tricher dans les jeux de lettres

Pour un jeu type RPG, j'avoue que je ne me suis pas encore penché sur la question. Mais ça doit sûrement servir. Je crois que tu en sentiras le besoin quand tu seras saturé de données à gérer
oui, j'imagine. D'autant que l'on compte le passer en mode multijoueurs, donc, c'est plutôt au niveau du serveur que les données risquent de se bousculer .

Citation:
Tu peux toujours demander sur le forum jeux de dvp, y'a des calés qui trainent par là.
Il y a des jeux réalisé en PB sur ce forum ?

J'avais déjà posté il y a quelques années (2007 si je me rappelle bien), toujours pour se même projet .
blendman est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/03/2011, 19h39   #13
Candidat au titre de Membre du Club
 
Inscription : avril 2007
Messages : 46
Détails du profil
Informations forums :
Inscription : avril 2007
Messages : 46
Points : 14
Points : 14
j'ai essayé de corriger mon exemple, mais je rencontre un problème avec le centre de mes sprite (arbre) et je ne comprends pas.

Le code :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
 
;{ **************** variable, constantes.****************** ..
;Eléments Windows
Enumeration
  #WINDOW_MAIN
  #text
  #ui
EndEnumeration
 
 
; ---------------------------------------------------------------------
 
; NOTE  :
 
;il faut que je change toutes ces variables globales, en une Structure,
;et ajouter à cette structures soit un tableau Dim Global,
;soit utiliser des pointeurs, pour éviter d'avoir trop de choses globales.
 
; ---------------------------------------------------------------------
 
;variable générales : taille de la vue, de la map (room), etc..
;taille de la "map" (ou Room)
Global room_width = 4000
Global room_height  = 3120
 
; on vérifie si l'écran est suffisamment grand (pour les netbooks, pour toi, Dobro ;))
ExamineDesktops()
dw=DesktopWidth(0)
dh=DesktopHeight(0)
dc=DesktopDepth(0)
 
If dw<1024 Or dh<768
  Global ecranX =dw
  Global ecranY =dc
Else
  Global ecranX = 1024
  Global ecranY = 768
EndIf
 
; ici, on peut changer le "FPS". En dessous de 60, chez moi, ça commence à saccader
Global FPS_LIMIT = 120
Global CheckTime
 
Global quit = 0 ; pour quitter
 
;gestion de la "caméra"
 
 
; scroll pour tous les objets, sauf le centre de la vue
Global scroll_x = 0
Global scroll_y = 0
; "scroll" pour l'objet central de la vue, lorsque celui-ci se rapproche du bord de l'écran
Global scroll_centre_cam_x = 0
Global scroll_centre_cam_y = 0
 
Global view_centre_x = ecranX /2 ; le centre de la vue
Global view_centre_y = ecranY /2 ; le centre de la vue
 
Global HorBord = 60 ;bordure verticale, au dela de celle-ci le personnage ne se rapproche plus du bord, mais la "caméra" bougede l'écran
Global VertBord = 40 ;bordure verticale, au dela de celle-ci le personnage ne se rapproche plus du bord, mais la "caméra" bougede l'écran
 
; vitesse de déplacement du personnage
Global vitesse = 2 ;* FPS_LIMIT/120
 
 
;}
 
;{ **************** Structures ****************************
 
Structure objet
  Sprite.l
  x.l
  y.l
  newposition_x.l
  newposition_y.l
  centre_x.l
  centre_y.l
EndStructure
 
Global nombre_arbre = 200
 
Global Dim tableau_obj.objet(nombre_arbre)
 
;on crée le tableau contenant les données de chaque "objet" décor (sprite, x, y, centre,etc..)
For i = 0 To nombre_arbre
    tableau_obj(i)\Sprite = 1+Round(Random(2),0)
 
  If tableau_obj(i)\Sprite = 1
    tableau_obj(i)\centre_x = 104
    tableau_obj(i)\centre_y = 256
  ElseIf tableau_obj(i)\Sprite = 2
    tableau_obj(i)\centre_x = 52
    tableau_obj(i)\centre_y = 159
  ElseIf tableau_obj(i)\Sprite = 3
    tableau_obj(i)\centre_x = 83
    tableau_obj(i)\centre_y = 188
  EndIf
 
  tableau_obj(i)\y = Random(room_height)
  tableau_obj(i)\x = Random(room_width )
  tableau_obj(i)\newposition_x = tableau_obj(i)\x - tableau_obj(i)\centre_x
  tableau_obj(i)\newposition_y = tableau_obj(i)\y - tableau_obj(i)\centre_y
Next i
SortStructuredArray(tableau_obj(), #PB_Sort_Ascending, OffsetOf(objet\y), #PB_Sort_Long); on tri par le y
 
; le personnage est considéré comme étant le centre de la caméra. Il est donc
; le seul à avoir comme paramètre les scroll_centre_cam
 
tableau_obj(0)\Sprite = 0
tableau_obj(0)\centre_x = 17
tableau_obj(0)\centre_y = 80
tableau_obj(0)\x = ecranX/2
tableau_obj(0)\y = ecranY/2
 
tableau_obj(0)\newposition_x = tableau_obj(0)\x - tableau_obj(0)\centre_x - scroll_centre_cam_x
tableau_obj(0)\newposition_y = tableau_obj(0)\y - tableau_obj(0)\centre_y - scroll_centre_cam_y
 
 
;}
 
Declare evenement()
Declare update()
 
;{ **************** initialisation **************************
 
InitSprite()
InitSprite3D()
InitKeyboard()
InitMouse()
UsePNGImageDecoder()
 
;}
 
 
;{ ********************** openWindow ************************
 
OpenWindow(#WINDOW_MAIN,150,150,EcranX,EcranY,"3 Arks - test - "+Str(CheckTime),#PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_MinimizeGadget)
OpenWindowedScreen(WindowID(#WINDOW_MAIN),0,0,EcranX,EcranY,0,0,0,#PB_Screen_WaitSynchronization )
;ClearScreen(RGB(128,128,128))
 
;}
 
;{ loading (sprites)
 
 
LoadSprite(0,"perso.png",#PB_Sprite_AlphaBlending|#PB_Sprite_Texture )
CreateSprite3D(0,0)
 
For i = 1 To 3
LoadSprite(i, "arbre"+Str(i)+".png",#PB_Sprite_AlphaBlending|#PB_Sprite_Texture )
CreateSprite3D(i,i)
Next i
 
;interface
;LoadSprite(#ui, "message.png",#PB_Sprite_AlphaBlending|#PB_Sprite_Texture )
;CreateSprite3D(#ui,#ui)
 
 
 
;}
 
 
Repeat
 
  Event.l = WindowEvent()
  evenement()
  If (ElapsedMilliseconds() > CheckTime + 1000 / FPS_LIMIT)
    CheckTime = ElapsedMilliseconds()
    update()
    FlipBuffers()
    ClearScreen(RGB(128,128,128))
 
  Else
    Delay(1)
  EndIf
 
Until Event = #PB_Event_CloseWindow Or quit = 1
 
 
Procedure evenement()
  ;ExamineMouse()
  If ExamineKeyboard()
 
    If KeyboardPushed(#PB_Key_Up)
      If view_centre_y > HorBord
        scroll_centre_cam_y - vitesse
        view_centre_y - vitesse
      ElseIf scroll_y >0
          scroll_y - vitesse
      EndIf
    EndIf
 
 
    If KeyboardPushed(#PB_Key_Down) And scroll_y < room_height - ecranY
      If view_centre_y < ecranY - HorBord
        scroll_centre_cam_y + vitesse
        view_centre_y + vitesse
      Else 
          scroll_y + vitesse
      EndIf
    EndIf
 
 
    If KeyboardPushed(#PB_Key_Left)
      If view_centre_x > VertBord
        scroll_centre_cam_x - vitesse
        view_centre_x - vitesse
      ElseIf  scroll_x >0
          scroll_x - vitesse
      EndIf
    EndIf
 
 
    If KeyboardPushed(#PB_Key_Right) And scroll_x < room_width - ecranX
      If view_centre_x < ecranX - VertBord
        scroll_centre_cam_x + vitesse
        view_centre_x + vitesse
      Else
          scroll_x + vitesse
      EndIf
    EndIf
 
 
    If KeyboardPushed(#PB_Key_Escape)
      quit = 1
    EndIf
 
  EndIf
 
EndProcedure
 
Procedure update()
  Dim temp.objet(nombre_arbre)
  CopyArray(tableau_obj(), temp())
 
  For i=0 To nombre_arbre
    If temp(i)\Sprite <> 0
      temp(i)\newposition_y - scroll_y
    ElseIf temp(i)\Sprite = 0
      temp(i)\newposition_y + scroll_centre_cam_y - temp(i)\centre_y
      temp(i)\newposition_x + scroll_centre_cam_x - temp(i)\centre_x
    EndIf
  Next i
 
  SortStructuredArray(temp(), #PB_Sort_Ascending, OffsetOf(objet\newposition_y), #PB_Sort_Long)
 
  For i=0 To nombre_arbre
    If temp(i)\Sprite <> 0
      temp(i)\newposition_y + scroll_y
    ElseIf temp(i)\Sprite = 0
      temp(i)\newposition_y - scroll_centre_cam_y + temp(i)\centre_y
      temp(i)\newposition_x - scroll_centre_cam_x + temp(i)\centre_x
    EndIf
  Next i
 
  CopyArray(temp(), tableau_obj())
 
  Start3D()
 
  For i=0 To  nombre_arbre
    If tableau_obj(i)\Sprite <> 0
      DisplaySprite3D(tableau_obj(i)\Sprite, tableau_obj(i)\newposition_x - scroll_x,tableau_obj(i)\newposition_y - scroll_y)
    ElseIf tableau_obj(i)\Sprite = 0
      DisplaySprite3D(tableau_obj(i)\Sprite, tableau_obj(i)\newposition_x + scroll_centre_cam_x,tableau_obj(i)\newposition_y + scroll_centre_cam_y)     
 
    EndIf
  Next i   
   ; DisplaySprite3D(#ui,0,0)    ;interface 
 
  Stop3D()
 
EndProcedure
Le problème : lorsque je bouge au niveau de l'arbre 2, c'est correct, mais pour l'arbre 1 et le 3, le centre n'est pas correct. pourtant, les centre sont bien défini au début.

une idée du problème ?

les images pour ce test :
http://blendman.free.fr/dev/pb/arbre1.png
http://blendman.free.fr/dev/pb/arbre2.png
http://blendman.free.fr/dev/pb/arbre3.png
http://blendman.free.fr/dev/pb/perso.png

Merci
blendman est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/03/2011, 20h58   #14
Responsable Purebasic
 
Avatar de comtois
 
Inscription : avril 2003
Messages : 810
Détails du profil
Informations forums :
Inscription : avril 2003
Messages : 810
Points : 1 856
Points : 1 856
Comme le sujet m'intéresse, j'avais commencé sur une idée, que je vient de tester, ça fonctionne presque sauf que je n'avais pas pensé à un truc ! donc c'est à revoir !

L'idée consiste à tester les arbres en collision avec la caméra, pour ne prendre en compte que ceux là.
Ensuite je teste les arbres en collision avec le perso, en me disant que je n'ai besoin de calculer le Zorder que pour ceux là, et c'est là mon erreur

Donc il faudra recalculer le Zorder pour tous les arbres en collision avec la camera.

Je te mets le code tel qu'il est aujourd'hui pour que tu puisses te faire une idée , en sachant que le résultat n'est pas encore satisfaisant

J'utilise tes 3 types d'arbres
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
;- Constantes
#FPS_LIMIT = 120
 
;Eléments Windows
Enumeration
  #WINDOW_MAIN
  #text
EndEnumeration
 
;Les sprites
Enumeration
  #arbre1
  #arbre2
  #arbre3
  #perso  
EndEnumeration
 
;- Structures
Structure s_Objet
  Id.l
  Largeur.l
  Hauteur.l
  Position.Point
  PointChaud.Point
  ZOrder.i
EndStructure
 
Structure s_Carte
  Largeur.l
  Hauteur.l
  NbObjet.l
  Array Objet.s_Objet(0)
EndStructure
 
Structure s_Sprite Extends s_Objet
  Vitesse.i
EndStructure
 
Structure s_Camera
  Position.Point
  Largeur.l
  Hauteur.l
  ViewPort.Point
EndStructure
 
;- Macro
Macro  BorneValeurMini(Var, valeur)
  If (Var) < (valeur)
    Var = (valeur)
  EndIf  
EndMacro
 
Macro  BorneValeurMaxi(Var, valeur)
  If (Var) > (valeur)
    Var = (valeur)
  EndIf  
EndMacro
 
;-Declare
Declare Main()
Declare Init(Width.i, Height.i)
Declare InitPerso(*Carte.s_Carte, *Perso.s_Sprite)
Declare InitCamera(*Camera.s_Camera, *Perso.s_Sprite)
Declare InitCarte(*Carte.s_Carte)
Declare ChargeSprites()
Declare evenement(*Carte.s_Carte, *Camera.s_Camera, *Sprite.s_Sprite, *Quit.Integer)
Declare update(*Carte.s_Carte, *Sprite.s_Sprite, *Camera.s_Camera)
 
;- ** Le programme ici **
 
Init(800, 600)
ChargeSprites()
Main()
 
End
;- ** Fin du programme **
 
;- Procédures
Procedure Main()
  Define Quit.i, CheckTime.i
  Define Carte.s_Carte
  Define Perso.s_Sprite
  Define Camera.s_Camera
 
  InitCarte(@Carte)
  InitPerso(@Carte, @Perso)
  InitCamera(@Camera, @Perso)
 
  Repeat
    Event.l = WindowEvent()
    evenement(@Carte, @Camera, @Perso, @Quit)
    If (ElapsedMilliseconds() > CheckTime + 1000 / #FPS_LIMIT)
      CheckTime = ElapsedMilliseconds()
      FlipBuffers()
      ClearScreen(RGB(128,128,128))
      update(@Carte, @Perso, @Camera)                     
    Else
      Delay(5)
    EndIf
 
  Until Event = #PB_Event_CloseWindow Or Quit = 1
EndProcedure
 
Procedure Init(Width.i, Height.i)
  InitSprite()
  InitSprite3D()
  InitKeyboard()
  InitMouse()
  UsePNGImageDecoder()
  OpenWindow(#WINDOW_MAIN,150,150,Width,Height,"3 Arks - test",#PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_MinimizeGadget)
  OpenWindowedScreen(WindowID(#WINDOW_MAIN),0,0,Width,Height,0,0,0,#PB_Screen_WaitSynchronization ) 
EndProcedure
 
Procedure ChargeSprites()
  LoadSprite(#perso, "perso.png",#PB_Sprite_AlphaBlending|#PB_Sprite_Texture )
  CreateSprite3D(#perso,#perso)
 
  LoadSprite(#arbre1, "arbre1.png",#PB_Sprite_AlphaBlending|#PB_Sprite_Texture )
  CreateSprite3D(#arbre1,#arbre1)  
  LoadSprite(#arbre2, "arbre2.png",#PB_Sprite_AlphaBlending|#PB_Sprite_Texture )
  CreateSprite3D(#arbre2,#arbre2)  
  LoadSprite(#arbre3, "arbre3.png",#PB_Sprite_AlphaBlending|#PB_Sprite_Texture )
  CreateSprite3D(#arbre3,#arbre3)  
EndProcedure
 
Procedure InitCamera(*Camera.s_Camera, *Perso.s_Sprite)
  With *Camera
    \Largeur = 800
    \Hauteur = 600
    \Position\x = *Perso\Position\x - \Largeur / 2
    \Position\y = *Perso\Position\y - \Hauteur / 2
    \ViewPort\x = 0
    \ViewPort\y = 0
  EndWith
EndProcedure
 
Procedure InitPerso(*Carte.s_Carte, *Perso.s_Sprite)
  With *Perso
    \Id = #perso
    \Largeur = SpriteWidth(\Id)
    \Hauteur = SpriteHeight(\Id)
    \Position\x = Random(*Carte\Largeur) 
    \Position\y = Random(*Carte\Hauteur) 
    \PointChaud\x = \Largeur/2
    \PointChaud\y = \Hauteur-15
    \Vitesse = 3
  EndWith
EndProcedure
 
Procedure InitCarte(*Carte.s_Carte)
  Define i.i
  *Carte\NbObjet = 150
  ReDim *Carte\Objet(*Carte\NbObjet)
  Dim Temp.s_Objet(*Carte\NbObjet)
  *Carte\Largeur = 4000
  *Carte\Hauteur = 3000
  For i=0 To *Carte\NbObjet-1
    With *Carte\Objet(i)
      \Id = Random(#arbre3)
      \Largeur = SpriteWidth(\Id)
      \Hauteur = SpriteHeight(\Id)
      \Position\x = Random(*Carte\Largeur-\Largeur*2) + \Largeur
      \Position\y = Random(*Carte\Hauteur-\Hauteur*2) + \Hauteur
      \PointChaud\x = \Largeur/2
      Select \Id
        Case #arbre1   
          \PointChaud\y = \Hauteur-5
        Case #arbre2
          \PointChaud\y = \Hauteur-1
        Case #arbre3
          \PointChaud\y = \Hauteur-20
      EndSelect  
      \ZOrder = \Position\y + \PointChaud\y
    EndWith
  Next i 
  ;Tri des arbres
  CopyArray(*Carte\Objet(), Temp())
  SortStructuredArray(Temp(), #PB_Sort_Ascending, OffsetOf(s_Objet\ZOrder), #PB_Sort_Long) 
  CopyArray(Temp(), *Carte\Objet())
EndProcedure
 
 
 
Procedure evenement(*Carte.s_Carte, *Camera.s_Camera, *Sprite.s_Sprite, *Quit.Integer)
  If ExamineKeyboard()
 
    If KeyboardPushed(#PB_Key_Up) And *Sprite\Position\y > 0
      *Sprite\Position\y - *Sprite\Vitesse
      BorneValeurMini(*Sprite\Position\y, 0)
    EndIf
 
 
    If KeyboardPushed(#PB_Key_Down) 
      *Sprite\Position\y + *Sprite\Vitesse
      BorneValeurMaxi(*Sprite\Position\y, *Carte\Hauteur - *Sprite\Hauteur)
    EndIf
 
 
    If KeyboardPushed(#PB_Key_Left) And *Sprite\Position\x > 0
      *Sprite\Position\x - *Sprite\Vitesse
      BorneValeurMini(*Sprite\Position\x, 0)
    EndIf
 
 
    If KeyboardPushed(#PB_Key_Right) 
      *Sprite\Position\x + *Sprite\Vitesse
      BorneValeurMaxi(*Sprite\Position\x, *Carte\Largeur - *Sprite\Largeur)
    EndIf
 
    ;Centre la caméra sur le perso
    *Camera\Position\x = *Sprite\Position\x - *Camera\Largeur / 2
    *Camera\Position\y = *Sprite\Position\y - *Camera\Hauteur / 2
    BorneValeurMini(*Camera\Position\x, 0)
    BorneValeurMini(*Camera\Position\y, 0)
    BorneValeurMaxi(*Camera\Position\x, *Carte\Largeur - *Camera\Largeur)
    BorneValeurMaxi(*Camera\Position\y, *Carte\Hauteur - *Camera\Hauteur)
    If KeyboardPushed(#PB_Key_Escape)
      *quit\i = 1
    EndIf
 
  EndIf
 
EndProcedure
 
 
Procedure update(*Carte.s_Carte, *Sprite.s_Sprite, *Camera.s_Camera)
  Define Position.Point
  NewList AvantPlan.s_Objet()
  Start3D() 
 
  For i=0 To  *Carte\NbObjet-1
    ;Test collision des arbres avec la caméra
    If *Camera\Position\x + *Camera\Largeur > *Carte\Objet(i)\Position\x And *Camera\Position\x < *Carte\Objet(i)\Position\x + *Carte\Objet(i)\Largeur And *Camera\Position\y + *Camera\Hauteur > *Carte\Objet(i)\Position\y And *Camera\Position\y < *Carte\Objet(i)\Position\y + *Carte\Objet(i)\Hauteur
      ;Test collision des arbres avec le perso
      If *Sprite\Position\x + *Sprite\Largeur > *Carte\Objet(i)\Position\x And *Sprite\Position\x < *Carte\Objet(i)\Position\x + *Carte\Objet(i)\Largeur And *Sprite\Position\y + *Sprite\Hauteur > *Carte\Objet(i)\Position\y And *Sprite\Position\y < *Carte\Objet(i)\Position\y + *Carte\Objet(i)\Hauteur   
        ;Test si l'objet est en avant plan
        *Sprite\ZOrder = *Sprite\Position\y + *Sprite\PointChaud\y
        If *Carte\Objet(i)\ZOrder > *Sprite\ZOrder
          ;Ajoute l'objet dans la liste des objets à afficher après le sprite
          AddElement(AvantPlan())
          CopyMemory(*Carte\Objet(i), @AvantPlan(), SizeOf(s_Objet))
        Else
          ;Affiche l'objet en arrière plan
          Position\x = *Camera\ViewPort\x + *Carte\Objet(i)\Position\x - *Camera\Position\x
          Position\y = *Camera\ViewPort\y + *Carte\Objet(i)\Position\y - *Camera\Position\y
          DisplaySprite3D(*Carte\Objet(i)\Id, Position\x, Position\y)
        EndIf
      Else
        ;Affiche l'objet en arrière plan
        Position\x = *Camera\ViewPort\x + *Carte\Objet(i)\Position\x - *Camera\Position\x
        Position\y = *Camera\ViewPort\y + *Carte\Objet(i)\Position\y - *Camera\Position\y
        DisplaySprite3D(*Carte\Objet(i)\Id, Position\x, Position\y)            
      EndIf
 
    EndIf   
 
  Next i 
  Position\x = *Camera\ViewPort\x + *Sprite\Position\x - *Camera\Position\x
  Position\y = *Camera\ViewPort\y + *Sprite\Position\y - *Camera\Position\y
  DisplaySprite3D(*Sprite\Id, Position\x, Position\y)
 
  ForEach AvantPlan()
 
    ;Affiche les objets en avant plan
    Position\x = *Camera\ViewPort\x + AvantPlan()\Position\x - *Camera\Position\x
    Position\y = *Camera\ViewPort\y + AvantPlan()\Position\y - *Camera\Position\y
    DisplaySprite3D(AvantPlan()\Id, Position\x, Position\y)    
  Next
 
  Stop3D()
  ClearList(AvantPlan())
EndProcedure
__________________
Vous souhaitez participer à la rubrique PureBasic (tutoriels, FAQ, sources) ? Contactez-moi par MP.
comtois est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/03/2011, 21h15   #15
Responsable Purebasic
 
Avatar de comtois
 
Inscription : avril 2003
Messages : 810
Détails du profil
Informations forums :
Inscription : avril 2003
Messages : 810
Points : 1 856
Points : 1 856
voila avec cette procédure ça devrait être mieux, tu peux remplacer la procédure update() par celle ci :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Procedure update(*Carte.s_Carte, *Sprite.s_Sprite, *Camera.s_Camera)
  Define Position.Point
  NewList AvantPlan.s_Objet()
  Start3D() 
 
  For i=0 To  *Carte\NbObjet-1
    ;Test collision des arbres avec la caméra
    If *Camera\Position\x + *Camera\Largeur > *Carte\Objet(i)\Position\x And *Camera\Position\x < *Carte\Objet(i)\Position\x + *Carte\Objet(i)\Largeur And *Camera\Position\y + *Camera\Hauteur > *Carte\Objet(i)\Position\y And *Camera\Position\y < *Carte\Objet(i)\Position\y + *Carte\Objet(i)\Hauteur
      *Sprite\ZOrder = *Sprite\Position\y + *Sprite\PointChaud\y
      If *Carte\Objet(i)\ZOrder > *Sprite\ZOrder
        ;Ajoute l'objet dans la liste des objets à afficher après le sprite
        AddElement(AvantPlan())
        CopyMemory(*Carte\Objet(i), @AvantPlan(), SizeOf(s_Objet))
      Else
        ;Affiche l'objet en arrière plan
        Position\x = *Camera\ViewPort\x + *Carte\Objet(i)\Position\x - *Camera\Position\x
        Position\y = *Camera\ViewPort\y + *Carte\Objet(i)\Position\y - *Camera\Position\y
        DisplaySprite3D(*Carte\Objet(i)\Id, Position\x, Position\y)
      EndIf
 
    EndIf   
 
  Next i 
  ;Affiche le perso
  Position\x = *Camera\ViewPort\x + *Sprite\Position\x - *Camera\Position\x
  Position\y = *Camera\ViewPort\y + *Sprite\Position\y - *Camera\Position\y
  DisplaySprite3D(*Sprite\Id, Position\x, Position\y)
 
  ForEach AvantPlan()
 
    ;Affiche les objets en avant plan
    Position\x = *Camera\ViewPort\x + AvantPlan()\Position\x - *Camera\Position\x
    Position\y = *Camera\ViewPort\y + AvantPlan()\Position\y - *Camera\Position\y
    DisplaySprite3D(AvantPlan()\Id, Position\x, Position\y)    
  Next
 
  Stop3D()
  ClearList(AvantPlan())
EndProcedure
__________________
Vous souhaitez participer à la rubrique PureBasic (tutoriels, FAQ, sources) ? Contactez-moi par MP.
comtois est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/03/2011, 21h22   #16
Responsable Purebasic
 
Avatar de comtois
 
Inscription : avril 2003
Messages : 810
Détails du profil
Informations forums :
Inscription : avril 2003
Messages : 810
Points : 1 856
Points : 1 856
Si tu as beaucoup d'objets dans ton projet, peut-être que plus tard tu devras songer au QuadTree ou à un autre système qui te permet d'organiser tes données.

Exemple ici
__________________
Vous souhaitez participer à la rubrique PureBasic (tutoriels, FAQ, sources) ? Contactez-moi par MP.
comtois est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/03/2011, 21h33   #17
Candidat au titre de Membre du Club
 
Inscription : avril 2007
Messages : 46
Détails du profil
Informations forums :
Inscription : avril 2007
Messages : 46
Points : 14
Points : 14
salut Comtois, super ton exemple, il fonctionne super bien et sera encore mieux, avec la petite correction !

Citation:
Envoyé par comtois Voir le message
Comme le sujet m'intéresse, j'avais commencé sur une idée, que je vient de tester, ça fonctionne presque sauf que je n'avais pas pensé à un truc ! donc c'est à revoir !

L'idée consiste à tester les arbres en collision avec la caméra, pour ne prendre en compte que ceux là.
Ensuite je teste les arbres en collision avec le perso, en me disant que je n'ai besoin de calculer le Zorder que pour ceux là, et c'est là mon erreur

Donc il faudra recalculer le Zorder pour tous les arbres en collision avec la camera.

Je te mets le code tel qu'il est aujourd'hui pour que tu puisses te faire une idée , en sachant que le résultat n'est pas encore satisfaisant

J'utilise tes 3 types d'arbres
Effectivement, il faut que le tri se fasse visiblement sur toute la map (enfin ce qui est visible "dans" la caméra), sinon, certains arbres peuvent passer devant un autre.

Ou alors, , il faut vérifier la collision entre le joueur et l'arbre non pas rapport au sprite, mais par rapport à un bloc collision invisible situé aux pieds de l'arbre (et du joueur) qui aurait cette forme-ci :
http://blendman.free.fr/dev/pb/blockCollision.png

L'idée étant la suivante :
on ne déplace pas le jouer, mais le block collision du joueur.
Et le sprite joueur, quand à lui a son x =blockColision.x et y=blockCollision.y

enfin, je schématise, mais je pense qu'on comprend .

l'avantage, c'est ensuite pour calculer une sorte de pathfinding, avec d'autres blocks collisions (invisibles, toujours).

Le joueur n'évitera donc pas les collisions avec les arbres, mais c'est son block collision à lui qui verifiera les collision avec les block collision invisibles de la map.

Autre chose :
j'avais commencé à tester un chargement de map, issu d'un fichier texte, mais pour le moment, je n'ai pas réussi. est-il possible d'intégrer cela ?

par exemple, imaginons qu'une map ressemblerait à ceci (si on utilise un fichier type ini/pref (ce n'est sans doute pas la meilleure solution):
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[map]
map = 1
lib = 1
nbre_obj = 2
 
[obj1]
x= 152
y=135
n = 1
t = arbre
 
[obj2]
x= 236
y= 685
n = 2
t =arbre
ou bien à ceci :
Code :
1
2
3
4
5
6
 
arbre,1,152, 135, 
arbre2,122,162,
arbre,3,569,478,
plante,3,698,365
arbre,4,369,548
le 1er mot de la ligne c'est pour le type de décor (pour le png du sprite par exemple), le 2ème est le N° de ce sprite, et les 2 derniers : le x et le Y de l'objet.

Donc, la 1ère ligne signifierait :
un sprite (arbre1.png) se situe en (152,135)

Que penses-tu de cette méthode ?

Encore une dernière chose :
- étant donné que je vais avoir à charger énormément de sprite par map (disons au moins 100), ne faut -il pas envisager d'utiliser un tableau de sprites, dans lequel on ne chargerait que les sprites de la map, et on viendrait chercher dans ce tableau le sprite à afficher pour notre "objet".
Ainsi, je pense qu'il ne faudrait pas utiliser de constante comme #arbre1, #arbre2, etc..
car on risque d'avoir un nombre de constantes par map qui évolue ou change en fonction des maps et du nombre de sprite différents à charger par map.
A moins de les enregistrer dans un fichier bibliotheque1.txt > la bibliotheque des sprite à charger pour la map 1

bibliotheque2.txt > bibliotheque de sprite à charger pour la map2, etc..

En tout cas, encore merci .
blendman est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/03/2011, 21h35   #18
Candidat au titre de Membre du Club
 
Inscription : avril 2007
Messages : 46
Détails du profil
Informations forums :
Inscription : avril 2007
Messages : 46
Points : 14
Points : 14
Citation:
Envoyé par comtois Voir le message
voila avec cette procédure ça devrait être mieux, tu peux remplacer la procédure update() par celle ci :
superbe !
C'est beau, c'est fluide, c'est magique !
Un immense merci !
blendman est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/03/2011, 21h37   #19
Candidat au titre de Membre du Club
 
Inscription : avril 2007
Messages : 46
Détails du profil
Informations forums :
Inscription : avril 2007
Messages : 46
Points : 14
Points : 14
Citation:
Envoyé par comtois Voir le message
Si tu as beaucoup d'objets dans ton projet, peut-être que plus tard tu devras songer au QuadTree ou à un autre système qui te permet d'organiser tes données.

Exemple ici
merci, je vais regarder ça, même si je n'ai encore le niveau pour tout comprendre, ça me semble très intéressant !
blendman est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/03/2011, 21h39   #20
Responsable Purebasic
 
Avatar de comtois
 
Inscription : avril 2003
Messages : 810
Détails du profil
Informations forums :
Inscription : avril 2003
Messages : 810
Points : 1 856
Points : 1 856
J'ai un peu corrigé la procédure update() pour retirer des boucles les calculs qui ne sont à faire qu'une seule fois.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Procedure update(*Carte.s_Carte, *Sprite.s_Sprite, *Camera.s_Camera)
  Define Box.Point, Delta.Point
  NewList AvantPlan.s_Objet()
  Start3D() 
  *Sprite\ZOrder = *Sprite\Position\y + *Sprite\PointChaud\y  
  Box\x = *Camera\Position\x + *Camera\Largeur
  Box\y = *Camera\Position\y + *Camera\Hauteur
 
  Delta\x = *Camera\ViewPort\x - *Camera\Position\x
  Delta\y = *Camera\ViewPort\y - *Camera\Position\y
  For i=0 To  *Carte\NbObjet-1
    ;Test collision des arbres avec la caméra
    If  Box\x > *Carte\Objet(i)\Position\x And *Camera\Position\x < *Carte\Objet(i)\Position\x + *Carte\Objet(i)\Largeur And Box\y > *Carte\Objet(i)\Position\y And *Camera\Position\y < *Carte\Objet(i)\Position\y + *Carte\Objet(i)\Hauteur
 
      If *Carte\Objet(i)\ZOrder > *Sprite\ZOrder
        ;Ajoute l'objet dans la liste des objets à afficher après le sprite
        AddElement(AvantPlan())
        CopyMemory(*Carte\Objet(i), @AvantPlan(), SizeOf(s_Objet))
      Else
        ;Affiche l'objet en arrière plan
        DisplaySprite3D(*Carte\Objet(i)\Id, Delta\x + *Carte\Objet(i)\Position\x, Delta\y + *Carte\Objet(i)\Position\y)
      EndIf
 
    EndIf   
 
  Next i 
  ;Affiche le perso
  DisplaySprite3D(*Sprite\Id, Delta\x + *Sprite\Position\x, Delta\y + *Sprite\Position\y)
 
  ForEach AvantPlan()
 
    ;Affiche les objets en avant plan
    DisplaySprite3D(AvantPlan()\Id, Delta\x + AvantPlan()\Position\x, Delta\y + AvantPlan()\Position\y)    
  Next
 
  Stop3D()
 
EndProcedure
__________________
Vous souhaitez participer à la rubrique PureBasic (tutoriels, FAQ, sources) ? Contactez-moi par MP.
comtois est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 17h15.


 
 
 
 
Partenaires

Hébergement Web