[Tuto] Collision jeu de plateforme simple

Partagez votre expérience de PureBasic avec les autres utilisateurs.
G-Rom
Messages : 3641
Inscription : dim. 10/janv./2010 5:29

[Tuto] Collision jeu de plateforme simple

Message par G-Rom »

Bonjour à tous, j'ai décider de partager une méthode simple pour la gestion de collision
dans un jeu de plateforme, ou n'importe quel autre type de jeu 2D ( rpg par exemple )
le système présenté ici sera simple, pas besoin d'avoir fait math sup pour y arriver.
Avant de commencer , il nous faut une base de travail , voici un squelette d'application simple avec lequel
nous allons travailler :

Code : Tout sélectionner

; Initialisation de l'application
;
;
deltatime.f     = 1/60
oldtime.f       = 0
accumulator.f   = 0
running.a       = #True 

InitSprite() ; si la commande foire, change de pc...
OpenWindow(0,0,0,1024,768,"",#PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget)
OpenWindowedScreen(WindowID(0),0,0,1024,768,1,0,0)



While( running )
  
  ; gestion du deltatime
  ;
  deltatime = (ElapsedMilliseconds() - oldtime) / 1000
  oldtime   = ElapsedMilliseconds()
  accumulator + deltatime
  
  ; gestion des évenement PureBasic
  ;
  Repeat
    event = WindowEvent()
    
    If event = #PB_Event_CloseWindow
      running = #False
    EndIf
    
  Until event = 0
  
  
  ; ON GERERA LES INPUTS ICI
  
  
  ; gestion de la physique
  ;
  While( accumulator > 1/60 )
    ; ON GERERA LA PHYSIQUE ICI      
    accumulator - (1/60)  
  Wend
  
  
  ; on efface l'écran
  ;
  ClearScreen($101010)
  
  
  ; ON FERA LE RENDU ICI
  
  
  ; on fait le rendu dans un sprite
  ;
  rendering_output.i = GrabSprite(#PB_Any,0,0,320,240)
  
  ; on re efface l'écran
  ;
  ClearScreen(0)
  
  
  ZoomSprite(rendering_output,800,600) ; on se fiche du ratio, ce n'est pas le sujet
  DisplaySprite(rendering_output,512-400,384-300) 
  
  ; rendu final
  ;
  FlipBuffers()
  
Wend

CloseScreen()
CloseWindow(0)
End



Rien de bien compliqué ici , on ouvre un screen ( j'aime bien les modes fenetré , on peu facilement passer en plein écran en "resizant"
la fenêtre et en cachant la barre de titre. Le rendu interne sera en 320x240 et rescalé en 800x600 et centré sur la fenêtre ( qui peu aussi être rescalé par l'utilisateur ), oui, j'aime bien le style rétro , autant en profité.
Ici, la gestion du deltatime m'assure que la physique tournera à 60hz (1/60) par seconde , pour le reste , le rendu peut être à 1000fps , le jeu n'ira pas plus vite et cela simplifira
le calcul de la "physique" du jeu.



Maintenant , nous allons représenté le niveau avec une simple datasection , notre écran fait 320x240 pixels , nos tuilles
qui composerons le niveau feront elles , 16x16 pixels, soit un niveau composé de 20x15 tuilles

Code : Tout sélectionner

 
DataSection
  level: ; 20x15  
  Data.l 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
  Data.l 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
  Data.l 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
  Data.l 1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1
  Data.l 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1
  Data.l 1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,2,1
  Data.l 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1
  Data.l 1,0,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,2,1
  Data.l 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1
  Data.l 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1
  Data.l 1,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,2,1
  Data.l 1,0,0,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,2,1
  Data.l 1,1,1,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,2,1
  Data.l 1,2,2,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,2,1
  Data.l 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1  
EndDataSection


Dans notre datasection, chaque numéro correspond à une tuille que nous allons définir dans une petite structure

Code : Tout sélectionner

Structure Tile
  spriteID.l    ; identifiant sprite purebasic
  collide.b     ; flag si la tuile est bloquante ou non
EndStructure


Pour le stockage de notre niveau dans un tableau , 2 lignes de code suffisent :

Code : Tout sélectionner

Global Dim Level.l(20*15)
CopyMemory(?Level,@Level(),(20*15)*4)

Bien faire attention au type de Data dans la datasection et au type du tableau , sinon crash...


Quand à nos tuilles , elles seront définie et stocké de cette manière :

Code : Tout sélectionner

Structure Tile
  spriteID.l    ; identifiant sprite purebasic
  collide.b     ; flag si la tuile est bloquante ou non
EndStructure

Global NewList Tiles.Tile()
Dans le cadre de notre DataSection , il y a seulement 3 chiffres différents, le 0 ( pas de tuille ) le 1 & le 2
ce qui veut dire que notre liste de tuilles contiendra 2 éléments dans cet exemple.
et pour créer une tuille :

Code : Tout sélectionner

AddElement(Tiles())

Tiles()\collide = #True 
Tiles()\spriteID = CreateSprite(#PB_Any,16,16)

StartDrawing(SpriteOutput(Tiles()\spriteID))
  Box(0,0,16,16,RGB(0,192,64))
StopDrawing()
Passons maintenant à une fonction qui nous donne le sprite de chaque index stocké dans la datasection

Code : Tout sélectionner

Procedure.l GetLevelSprite(x,y)
  index = x + 20 * y
  If index >= 0 And index < (20*15)
    tile_id = Level(index)
    If tile_id > 0
      SelectElement(Tiles(),tile_id-1) ; -1 car le 1° élément est à l'index zero 
      ProcedureReturn Tiles()\spriteID      
    Else
      ProcedureReturn 0
    EndIf 
  EndIf 
  ProcedureReturn 0
EndProcedure
Rien de bien sorcier ici non plus. les coordonées x,y, represente une position dans la datasection, autrement dit , le niveau.
la variable index est utilisé car le tableau Level à une seule dimension , on fait donc une operation 2D -> 1D pour savoir quel élément
dans le tableau on recherche , avec bien entendu un garde fou if/endif afin de ne pas dépasser la taille du tableau.

Quand à l'affichage du niveau , il se fait facilement grâce à une petite fonction :

Code : Tout sélectionner

Procedure DisplayLevel()
  For y = 0 To 15-1  
    For x = 0 To 20-1  
      If GetLevelSprite(x,y) <> 0
        DisplaySprite( GetLevelSprite(x,y), x * 16 , y * 16)  
      EndIf
    Next
  Next
EndProcedure

Cette fonction est simple, mais gardez à l'esprit que dans notre exemple elle fonctionne correctement et répond à notre besoin.
si vous voulez avoir des niveaux plus grand avec gestion du scrooling , elle sera à revoir de façon à n'afficher que ce que l'on voit
à l'écran , sinon vous tournerez à 2fps...


Bon, on à notre squelette d'application, un affichage de niveau , reste plus qu'a codé notre "héro"
pour cela une petite structure minimaliste supplémentaire :

Code : Tout sélectionner

Structure Hero
  x.f
  y.f
  w.f
  h.f
  vx.f
  vy.f
EndStructure
x & y represente la position dans le monde en pixels , w&h la taille du héro , nous n'utiliserons pas vraiment ici , car les vitesses seront constante, vx & vy la vélocité sur les différents axes
j'utilise des floats, mais dans l'exemple , nous en avons pas vraiment besoin , comme je l'ai dit plus haut , la vitesse sera fixe, pas d'acceleration par exemple.

Maintenant, pour déplacer le personnage , rien de plus simple :

Code : Tout sélectionner

If KeyboardPushed(#PB_Key_Right)
	Bob\vx =  1
ElseIf KeyboardPushed(#PB_Key_Left)
	Bob\vx = -1
Else 
	Bob\vx =  0
EndIf 

et dans notre boucle while :

Code : Tout sélectionner

; gestion de la physique
;
While( accumulator > 1/60 )
	; ON GERERA LA PHYSIQUE ICI      
	
    Bob\x + Bob\vx
    Bob\y + Bob\vy
	
	accumulator - (1/60)  
Wend
je rapelle que cette boucle assure une execution à 60hz. nous effecturons les collisions dans celle ci.

l'idée maintenant est de connaître sur quel tuile notre héro est , la "formule" est simple , il suffit de diviser les coordonées du héro
par la taille de la tuile :
tuile_x = floor( hero_position_x / taille_tuile_x )
tuile_y = floor( hero_position_y / taille_tuile_y )
la fonction floor n'existe pas en PB tel quel, il faut utiliser Round() avec le flag d'arrondissement vers le bas ( floor )
cela dit , tuile_x & tuile_y sont maintenant des coordonées dans notre tableau Level() qui represente notre niveau.
mais c'est un tableau à une dimension , et nous on a 2 coordonées...
pour cela une autre "formule" à connaitre est le passage de coordonées 2D à un index 1D :
INDEX = X + TAILLE_TABLEAU_2D_LARGEUR * Y
et l'inverse :
X = INDEX % TAILLE_TABLEAU_2D_LARGEUR
Y = INDEX / TAILLE_TABLEAU_2D_LARGEUR
Il nous faut maintenant 2 fonctions pour savoir quel tuile en x,y à comme sprite ou si la tuile est solide ou non :

Code : Tout sélectionner

Procedure.l GetLevelSprite(x,y)
  index = x + 20 * y
  If index >= 0 And index < (20*15)
    tile_id = Level(index)
    If tile_id > 0
      SelectElement(Tiles(),tile_id-1)
      ProcedureReturn Tiles()\spriteID      
    Else
      ProcedureReturn 0
    EndIf 
  EndIf 
  ProcedureReturn 0
EndProcedure

Code : Tout sélectionner

Procedure.l GetLevelCollide(x,y)
  index = x + 20 * y
  If index >= 0 And index < (20*15)
    tile_id = Level(index)
    If tile_id > 0
      SelectElement(Tiles(),tile_id-1)
      ProcedureReturn Tiles()\collide      
    Else
      ProcedureReturn 0
    EndIf 
  EndIf 
  ProcedureReturn 0
EndProcedure
! Les paramètres des procédures plus haut sont en coordonées "tableau" , pas la position en Pixel ( ou coordonées monde ) du héros.
et une petite fonction qui nous permet en "coordonées monde" de savoir si une tuille est solide ou non :

Code : Tout sélectionner

Procedure.b IsSolid(x.f, y.f)
	ProcedureReturn GetLevelCollide( Round(x / 16,#PB_Round_Down) ,  Round(y / 16,#PB_Round_Down) )
EndProcedure
Comme vous le voyez, on prend en paramètres les coordonées x&y , on divise par la taille de la tuille ( 16 ) on arrondi vers et le bas
et on à les coordonées dans le tableau correspondant au niveau. simple.
maintenant , nous allons pouvoir simplement tester les coins de notre héro , savoir si les coins sont en collision ou pas
avec une tuile solide, ici nous allons testé les collisions horizontale :

Image
IsSolid(Bob\x + 15 + Bob\vx , Bob\y + Bob\vy) Or ; coin haut droit -> coté droit ( B & C dans notre schéma)
IsSolid(Bob\x + 15 + Bob\vx , Bob\y + 15 + Bob\vy) Or ; coin bas droit |

IsSolid(Bob\x + Bob\vx , Bob\y + Bob\vy) Or ; coin haut gauche |
IsSolid(Bob\x + Bob\vx , Bob\y + 15 + Bob\vy) ; coine bas gauche -> coté gauche ( A & D dans notre schéma)


ce qui nous donne en pb :

Code : Tout sélectionner

If IsSolid(Bob\x + 15 + Bob\vx , Bob\y + Bob\vy) Or IsSolid(Bob\x + 15 + Bob\vx , Bob\y + 15 + Bob\vy) Or IsSolid(Bob\x + Bob\vx , Bob\y + Bob\vy) Or IsSolid(Bob\x + Bob\vx , Bob\y + 15 + Bob\vy)
	Bob\vx = 0  
EndIf
tout simplement. Pourquoi ajoutons nous 15 au lieu de 16 ( taille de la tuille & du héro ) ? car on prend en compte la velocité.

Ajoutons de la gravité avec une collision vers le bas ( D & C dans le schéma )

Code : Tout sélectionner

If (IsSolid( Bob\x + Bob\vx , Bob\y + 16 + Bob\vy) Or IsSolid( Bob\x + 15 + Bob\vx , Bob\y + 16 + Bob\vy)) And Bob\vy => 0
	Bob\vy = 0
Else
	Bob\vy + 0.2
EndIf 	

Puis un test de collision avec le dessus ( A & B dans le schéma )

Code : Tout sélectionner

If Bob\vy < 0
	If IsSolid( Bob\x + Bob\vx , Bob\y + Bob\vy) Or IsSolid( Bob\x + 15 + Bob\vx , Bob\y + Bob\vy)
		Bob\vy = 0
	EndIf 
EndIf 

And that'all !
vous avez le squelette d'un petit mario-like , a vous d'adaptez suivant vos besoins. Gardez à l'esprit que c'est une technique ( simpliste ) parmis tant d'autres plus ou moins complexe ( collision au pixel avec masque , algo SAT , swept , etc... )
voici le code complet :

Code : Tout sélectionner



Structure Tile
  spriteID.l    ; identifiant sprite purebasic
  collide.b     ; flag si la tuile est bloquante ou non
EndStructure

Global NewList Tiles.Tile()


; contenu du niveau
;
Global Dim Level.l(20*15)
CopyMemory(?Level,@Level(),(20*15)*4)


; Renvois le sprite du tableau déclaré au dessus 
;
Procedure.l GetLevelSprite(x,y)
  index = x + 20 * y
  If index >= 0 And index < (20*15)
    tile_id = Level(index)
    If tile_id > 0
      SelectElement(Tiles(),tile_id-1)
      ProcedureReturn Tiles()\spriteID      
    Else
      ProcedureReturn 0
    EndIf 
  EndIf 
  ProcedureReturn 0
EndProcedure

; Renvois le flag de collision du tableau déclaré au dessus ( Level() )
;
Procedure.l GetLevelCollide(x,y)
  index = x + 20 * y
  If index >= 0 And index < (20*15)
    tile_id = Level(index)
    If tile_id > 0
      SelectElement(Tiles(),tile_id-1)
      ProcedureReturn Tiles()\collide      
    Else
      ProcedureReturn 0
    EndIf 
  EndIf 
  ProcedureReturn 0
EndProcedure

; Affiche le niveau
;
Procedure DisplayLevel()
  For y = 0 To 15-1  
    For x = 0 To 20-1  
      If GetLevelSprite(x,y) <> 0
        DisplaySprite( GetLevelSprite(x,y), x * 16 , y * 16)  
      EndIf
    Next
  Next
EndProcedure

; renvois si la tuile est solide ou pas en "coordonées monde"
;
Procedure.b IsSolid(x.f, y.f)
 ProcedureReturn GetLevelCollide( Round(x / 16,#PB_Round_Down) ,  Round(y / 16,#PB_Round_Down) )
EndProcedure


; notre hero
;
Structure Hero
  x.f
  y.f
  w.f
  h.f
  vx.f
  vy.f
EndStructure

Bob.Hero
Bob\x = 10 * 16
Bob\y = 12 * 16
Bob\w = 16
Bob\h = 16


; Initialisation de l'application
;
;
deltatime.f     = 1/60
oldtime.f       = 0
accumulator.f   = 0
running.a       = #True 
jump_flag       = #False 

InitSprite() : InitKeyboard()
OpenWindow(0,0,0,1024,768,"",#PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget)
OpenWindowedScreen(WindowID(0),0,0,1024,768,1,0,0)




;
; Creation de la tuile 1
;
AddElement(Tiles())

Tiles()\collide = #True 
Tiles()\spriteID = CreateSprite(#PB_Any,16,16)

StartDrawing(SpriteOutput(Tiles()\spriteID))
  Box(0,0,16,16,RGB(0,192,64))
StopDrawing()


;
; Creation de la tuile 2
;
AddElement(Tiles())

Tiles()\collide = #False 
Tiles()\spriteID = CreateSprite(#PB_Any,16,16)

StartDrawing(SpriteOutput(Tiles()\spriteID))
  Box(0,0,16,16,RGB(0,32,8))
StopDrawing()




While( running )
  
  ; gestion du deltatime
  ;
  deltatime = (ElapsedMilliseconds() - oldtime) / 1000
  oldtime   = ElapsedMilliseconds()
  accumulator + deltatime
  
  ; gestion des évenement PureBasic
  ;
  Repeat
    event = WindowEvent()
    
    If event = #PB_Event_CloseWindow
      running = #False
    EndIf
    
  Until event = 0
  
  
  ; ON GERERA LES INPUTS ICI
  ExamineKeyboard()
  
  If KeyboardPushed(#PB_Key_Right)
    Bob\vx =  1
  ElseIf KeyboardPushed(#PB_Key_Left)
    Bob\vx = -1
  Else 
    Bob\vx =  0
  EndIf 
  
  If KeyboardPushed(#PB_Key_Up) And jump_flag = #False And Bob\vy = 0
    jump_flag = #True 
    Bob\vy = -4.5  
  ElseIf Not KeyboardPushed(#PB_Key_Up) And jump_flag = #True 
    jump_flag = #False
  EndIf
  
  
 
  
  
  ; gestion de la physique
  ;
  While( accumulator > 1/60 )
    
    ; collision latérale
    ;
    If IsSolid(Bob\x + 15 + Bob\vx , Bob\y + Bob\vy) Or IsSolid(Bob\x + 15 + Bob\vx , Bob\y + 15 + Bob\vy) Or IsSolid(Bob\x + Bob\vx , Bob\y + Bob\vy) Or IsSolid(Bob\x + Bob\vx , Bob\y + 15 + Bob\vy)
       Bob\vx = 0  
    EndIf
   
    
    ; collision basse
    ;
    If (IsSolid( Bob\x + Bob\vx , Bob\y + 16 + Bob\vy) Or IsSolid( Bob\x + 15 + Bob\vx , Bob\y + 16 + Bob\vy)) And Bob\vy => 0
      Bob\vy = 0
    Else
      Bob\vy + 0.2
    EndIf 
    
    
    ; collision haute
    ;
    If Bob\vy < 0
      If IsSolid( Bob\x + Bob\vx , Bob\y + Bob\vy) Or IsSolid( Bob\x + 15 + Bob\vx , Bob\y + Bob\vy)
        Bob\vy = 0
      EndIf 
    EndIf 
    
    Bob\x + Bob\vx
    Bob\y + Bob\vy
    
    accumulator - (1/60)  
  Wend
  
  
  ; on efface l'écran
  ;
  ClearScreen($101010)
  
  
  ; ON FERA LE RENDU ICI
  
  DisplayLevel()
  
  
  StartDrawing(ScreenOutput())
    Box(Bob\x,Bob\y,Bob\w,Bob\h,$FFFFFF)
  StopDrawing()
  
  
  ; on fait le rendu dans un sprite
  ;
  rendering_output.i = GrabSprite(#PB_Any,0,0,320,240)
  
  ; on re efface l'écran
  ;
  ClearScreen(0)
  
  
  ZoomSprite(rendering_output,800,600) ; on se fiche du ratio, ce n'est pas le sujet
  DisplaySprite(rendering_output,512-400,384-300) 
  
  ; rendu final
  ;
  FlipBuffers()
  
Wend

CloseScreen()
CloseWindow(0)
End


; le niveau
DataSection
  level: ; 20x15  
  Data.l 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
  Data.l 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
  Data.l 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
  Data.l 1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1
  Data.l 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1
  Data.l 1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,2,1
  Data.l 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1
  Data.l 1,0,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,2,1
  Data.l 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1
  Data.l 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1
  Data.l 1,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,2,1
  Data.l 1,0,0,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,2,1
  Data.l 1,1,1,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,2,1
  Data.l 1,2,2,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,2,1
  Data.l 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1  
EndDataSection

Avatar de l’utilisateur
venom
Messages : 3136
Inscription : jeu. 29/juil./2004 16:33
Localisation : Klyntar
Contact :

Re: [Tuto] Collision jeu de plateforme simple

Message par venom »

Salut G-Rom,

Merci pour tes explications et code. Je ne suis pas devant PB mais j'ai hâte d'explorer ton code. Je trouve vraiment cool ce type d'intervention.

Vivement d'autres codes :wink: :P






@++
Windows 10 x64, PureBasic 5.73 x86 & x64
GPU : radeon HD6370M, CPU : p6200 2.13Ghz
Avatar de l’utilisateur
Ar-S
Messages : 9540
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: [Tuto] Collision jeu de plateforme simple

Message par Ar-S »

Excellent. Merci.

Code : Tout sélectionner

CopyMemory(?Level,@Level(),(20*15)*4)
Pourquoi *4 ?
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
G-Rom
Messages : 3641
Inscription : dim. 10/janv./2010 5:29

Re: [Tuto] Collision jeu de plateforme simple

Message par G-Rom »

Parce que Data.l ;)
on stocke sous forme d'integer , mais on aurais pu utilisé un .w ( x2 dans ce cas) ou un .a ( x 1 )
Dernière modification par G-Rom le dim. 22/mars/2020 14:53, modifié 1 fois.
Avatar de l’utilisateur
Ar-S
Messages : 9540
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: [Tuto] Collision jeu de plateforme simple

Message par Ar-S »

Ok je me disais bien que ça devait être une histoire d'octets
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
G-Rom
Messages : 3641
Inscription : dim. 10/janv./2010 5:29

Re: [Tuto] Collision jeu de plateforme simple

Message par G-Rom »

Tu peu même savoir combien fait une données sans connaitre le type à l'avance, il te faut juste connaitre le pointeur de début, de fin, et le nombre d'éléments :

Code : Tout sélectionner

Debug (?level_end - ?level) / (20*15)

DataSection
  level: ; 20x15 
  Data.l 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
  Data.l 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
  Data.l 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
  Data.l 1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1
  Data.l 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1
  Data.l 1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,2,1
  Data.l 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1
  Data.l 1,0,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,2,1
  Data.l 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1
  Data.l 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1
  Data.l 1,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,2,1
  Data.l 1,0,0,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,2,1
  Data.l 1,1,1,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,2,1
  Data.l 1,2,2,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,2,1
  Data.l 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 
  level_end:
EndDataSection
Avatar de l’utilisateur
Ar-S
Messages : 9540
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: [Tuto] Collision jeu de plateforme simple

Message par Ar-S »

Merci. Effectivement en .i on obtient bien 8.
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
G-Rom
Messages : 3641
Inscription : dim. 10/janv./2010 5:29

Re: [Tuto] Collision jeu de plateforme simple

Message par G-Rom »

Faut faire attention avec le .i , il ne faut pas perdre de vue qu'en x64 & x86 le .i ne fait pas la même taille. j'enfonce des portes ouvertes, mais on ne sait jamais, ça peut servir.
Avatar de l’utilisateur
Ar-S
Messages : 9540
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: [Tuto] Collision jeu de plateforme simple

Message par Ar-S »

Oui oui, on a eu pas mal d'exemples par le passé ^^
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Avatar de l’utilisateur
Naheulf
Messages : 193
Inscription : dim. 10/mars/2013 22:22
Localisation : France

Re: [Tuto] Collision jeu de plateforme simple

Message par Naheulf »

Ar-S a écrit :Excellent. Merci.

Code : Tout sélectionner

CopyMemory(?Level,@Level(),(20*15)*4)
Pourquoi *4 ?
G-Rom a écrit :Parce que Data.l ;)
on stocke sous forme d'integer , mais on aurais pu utilisé un .w ( x2 dans ce cas) ou un .a ( x 1 )
Dans ce cas pourquoi ne pas mettre

Code : Tout sélectionner

CopyMemory(?Level,@Level(),(20*15)*SizeOf(Long))
Et plus généralement :

Code : Tout sélectionner

; Pour les types entiers fixes
Debug SizeOf(Byte)    ; 1 octet
Debug SizeOf(Ascii)   ; 1 octet
Debug SizeOf(Word)    ; 2 octets
Debug SizeOf(Unicode) ; 2 octets
Debug SizeOf(Long)    ; 4 octets
Debug SizeOf(Quad)	; 8 octets

; Pour les types entiers changeants
Debug SizeOf(Character) ; 1 octet en Ascii, 2 octets en Unicode/UCS2
Debug SizeOf(Integer)   ; 4 octets en 32-bits, 8 octets en 64-bits
En plus c'est plus explicite sur l'origine de la valeur et ça ne rajoute pas de calculs à l’exécution puisque c'est géré au moment de la compilation.
G-Rom
Messages : 3641
Inscription : dim. 10/janv./2010 5:29

Re: [Tuto] Collision jeu de plateforme simple

Message par G-Rom »

Dans ce cas pourquoi ne pas mettre
Je ne fait pas de la sodomie de coléoptère , * 4 ou sizeof(Integer) reviens exactement au même.
En plus c'est plus explicite sur l'origine de la valeur et ça ne rajoute pas de calculs à l’exécution puisque c'est géré au moment de la compilation.
C'est exactement ce que fait mon code.

Code : Tout sélectionner

A = 4 * SizeOf(Integer)
ou

Code : Tout sélectionner

A = 4 * 4
produit en ASM :

Code : Tout sélectionner

MOV    dword [v_A],16
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: [Tuto] Collision jeu de plateforme simple

Message par Ollivier »

Houlà !!! G-Rom a fait une grosse erreur de langage : il a oublié de mettre un "S" à << Héros >>. C'est pas bien !!
Dernière modification par Ollivier le dim. 22/mars/2020 17:22, modifié 1 fois.
G-Rom
Messages : 3641
Inscription : dim. 10/janv./2010 5:29

Re: [Tuto] Collision jeu de plateforme simple

Message par G-Rom »

Deuxième mouche... :D
Image

Je sais bien que je ne suis pas une flèche en Français , mais Héros en Anglais fait : Hero...
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: [Tuto] Collision jeu de plateforme simple

Message par Ollivier »

Attends un peu... Je me suis pris 400 volts en crête cette nuit, pendant que toi tu enfonces des portes ouvertes. J'ai bien un condo qui doit traîner quelquepart dans mon 5 mètres carré de confinement. Avec un peu de témérité, je vais réussir à avoir du jus en pleine période de merde. Si j'y arrive, je vais aller direct sur ton tuto mario y foot le dawa un peu là ! On n'a qu'une vie... On va se marrer un peu, avant de devoir télé-enterrer ses proches...

@ARSouille, t'es une vraie piplette :D
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: [Tuto] Collision jeu de plateforme simple

Message par Ollivier »

Y'a pas... Tant pis ! Pas de jus. Enfin, bien vu les deux codes source : les codes sont parlants (le 2ème est le Mario de l'autre sujet).

Je ne désespère pas de solution pour faire fonctionner un PC. Il y a plein de choses qui permettent de passer le temps. Mais c'est vrai que la prog, c'est une planète de plus...
Répondre