PureBasic:Souris et Sprite3D



PureBasic:Souris et Sprite3D

<< Précédent | Sommaire | Suivant >>


Sommaire

[modifier] Introduction

Dans ce tut vous apprendrez à utiliser :

  • La souris dans le mode plein écran.
  • Les sprites 3D
  • La rotation et le déplacement d'un sprite 3D.

[modifier] Initialisation

Ce tutoriel reprend le programme minimal déjà évoqué au cours du tutoriel Premiers pas avec PureBasic.

Puisqu'il s'agit cette fois ci d'utiliser la souris et les sprites 3D, ajoutons les lignes suivantes :

;Initialise l'environnement propre à la gestion de la souris. 
InitMouse()
;Initialise l'environnement propre à la gestion des sprites 3D. 
InitSprite3D() 

Ce qui donne

;Initialise l'environnement nécessaire au fonctionnement des sprites et pour ouvrir un écran.
InitSprite()
;Initialise l'environnement propre à la gestion du clavier. 
InitKeyboard()
;Initialise l'environnement propre à la gestion de la souris. 
InitMouse()
;Initialise l'environnement propre à la gestion des sprites 3D. 
InitSprite3D() 
;Ouvre un nouvel écran avec les caractéristiques Largeur, Hauteur et Profondeur. 
OpenScreen(800,600,32,"Tut Sprite3D et Souris")

Repeat
    ;Inverse le buffer d'arrière plan avec le buffer visible à l'écran. 
    ;La partie invisible du buffer remplace alors complètement La partie visible. 
    FlipBuffers()
    
    ;Efface l'écran courant avec la couleur specifiée. 
    ClearScreen(0,0,100)
    
    ;Met à jour l'état du clavier.Cette fonction doit être appelée avant d'utiliser les commandes 
    ;KeyboardInkey(), KeyboardPushed() et KeyboardReleased(). 
    ExamineKeyboard()
    
Until KeyboardPushed(#PB_Key_Escape)

[modifier] La souris

Dans le mode plein écran , il est nécessaire d'utiliser un sprite pour visualiser la souris.
On pourrait charger un sprite représentant la flèche traditionnelle , ou n'importe quelle autre forme , mais pour cet exemple nous n'utiliserons pas de média .

;Sprite pour la souris
CreateSprite(1,5,5)
StartDrawing(SpriteOutput(1))
Box(0,0,5,5,RGB(0,255,0))
StopDrawing() 

ensuite il suffit de tester la position de la souris dans la boucle principale du programme avec les fonctions ExamineMouse(), MouseX() et MouseY().

If ExamineMouse()
   Destination\x = MouseX()
   Destination\y = MouseY()
EndIf


[modifier] Sprite 3D

Un sprite 3D est un simple rectangle sur lequel on applique une texture. La texture est en fait un sprite classique chargé avec LoadSprite() ou CreateSprite() en utilisant le mode #PB_Sprite_Texture.

;Creation d'une texture
CreateSprite(0,64,64,#PB_Sprite_Texture)

;On dessine un triangle plein dans la texture
StartDrawing(SpriteOutput(0))
LineXY(1, 1, 1, SpriteHeight(0)-2,RGB(255,255,0))
LineXY(1, 1, SpriteWidth(0)-2, SpriteHeight(0)/2,RGB(255,255,0))
LineXY(1, SpriteHeight(0)-2, SpriteWidth(0)-2, SpriteHeight(0)/2,RGB(255,255,0))
FillArea(SpriteWidth(0)/2,SpriteHeight(0)/2,RGB(255,255,0),RGB(255,155,0))
StopDrawing()

;Creation d'un sprite3D utilisant la texture définie précédemment 
CreateSprite3D(0,0)  

Il est bien sûr possible de charger un sprite pour servir de texture au sprite3D.
il suffit de remplacer

;Creation d'une texture
CreateSprite(0,64,64,#PB_Sprite_Texture)

par

;Charge une texture
LoadSprite(0,"NomDeLaTexture.Bmp") 

Rappel : L'image peut être au format BMP , JPEG, TIFF, PNG ou TGA (voir ImagePlugin)

Maintenant que notre sprite 3D est créé, il reste à l'afficher à l'écran aux coordonnées de la souris. Il faut activer le moteur 3D par la commande Start3D() , Stop3D() indique que le traitement des sprites 3D est terminé.

If ExamineMouse()
   If Start3D()
      DisplaySprite3D(0,  MouseX(), MouseY())
      Stop3D()
   EndIf
EndIf

[modifier] Programme de base

On obtient enfin un sprite 3D qui se déplace à l'écran .

;Initialise l'environnement nécessaire au fonctionnement des sprites et pour ouvrir un écran.
InitSprite()
;Initialise l'environnement propre à la gestion du clavier. 
InitKeyboard()
;Initialise l'environnement propre à la gestion de la souris. 
InitMouse()
;Initialise l'environnement propre à la gestion des sprites 3D. 
InitSprite3D() 
;Ouvre un nouvel écran avec les caractéristiques Largeur, Hauteur et Profondeur. 
OpenScreen(800,600,32,"Tut Sprite3D et Souris")

;Creation d'une texture
CreateSprite(0,64,64,#PB_Sprite_Texture)

;On dessine un triangle plein dans la texture
StartDrawing(SpriteOutput(0))
LineXY(1, 1, 1, SpriteHeight(0)-2,RGB(255,255,0))
LineXY(1, 1, SpriteWidth(0)-2, SpriteHeight(0)/2,RGB(255,255,0))
LineXY(1, SpriteHeight(0)-2, SpriteWidth(0)-2, SpriteHeight(0)/2,RGB(255,255,0))
FillArea(SpriteWidth(0)/2,SpriteHeight(0)/2,RGB(255,255,0),RGB(255,155,0))
StopDrawing()

;Creation d'un sprite3D utilisant la texture définie précédemment 
CreateSprite3D(0,0)

;Sprite pour la souris
CreateSprite(1,5,5)
StartDrawing(SpriteOutput(1))
Box(0,0,5,5,RGB(0,255,0))
StopDrawing() 

Repeat
    ;Inverse le buffer d'arrière plan avec le buffer visible à l'écran. 
    ;La partie invisible du buffer remplace alors complètement La partie visible. 
    FlipBuffers()
    
    ;Efface l'écran courant avec la couleur specifiée. 
    ClearScreen(0,0,100)
    
    ;Met à jour l'état du clavier.Cette fonction doit être appelée avant d'utiliser les commandes 
    ;KeyboardInkey(), KeyboardPushed() et KeyboardReleased(). 
    ExamineKeyboard()
    
    If ExamineMouse()
	If Start3D()
	    DisplaySprite3D(0,  MouseX(), MouseY())
    	    Stop3D()
	EndIf    
    EndIf
	
    ;Affiche la souris
    DisplaySprite(1, MouseX(), MouseY())
    
Until KeyboardPushed(#PB_Key_Escape)

[modifier] Un peu de math

On va s'efforcer ici d'améliorer le déplacement de notre sprite 3D. L'objectif est de déplacer le sprite 3D vers la souris , mais avec la vitesse propre du sprite.

Vitesse.f=3.0
  • Sprite = Position du sprite 3D.
  • Destination = Destination à atteindre pour le sprite 3D.
  • Direction = Direction que le sprite 3D doit prendre pour rejoindre la destination (souris).
Structure Vecteur
    x.f
    y.f
EndStructure
Direction.Vecteur
Sprite.Vecteur
Destination.Vecteur

[modifier] Destination

On recopie la position de la souris dans destination.

    ;Destination 
    If ExamineMouse()
    	Destination\x = MouseX()
    	Destination\y = MouseY()
    EndIf

[modifier] Direction

Nous connaissons deux points , la destination et la position du sprite , nous pouvons déterminer le vecteur direction entre ces deux points.
Le vecteur est ensuite normé ( norme du vecteur = 1 )

    ;Direction
    Direction\x = Destination\x - Sprite\x 
    Direction\y = Destination\y - Sprite\y
    Norme(@Direction)

Normalise un vecteur

Procedure Norme(*V.Vecteur)
    Norme.f = Sqr(*V\x * *V\x + *V\y * *V\y)
    If Norme <> 0
     	*V\x / Norme
        *V\y / Norme
    EndIf
EndProcedure 

[modifier] Position sprite 3D

Si la distance entre le sprite 3D et la souris est inférieure à la vitesse du sprite 3D , c'est que la destination est atteinte , sinon on se déplace à la vitesse définie précédemment.

    Procedure.f Distance(*p1.Vecteur, *p2.Vecteur)
        ProcedureReturn Sqr((*p1\x - *p2\x) * (*p1\x - *p2\x) + (*p1\y - *p2\y) * (*p1\y - *p2\y))
    EndProcedure
    
    ;Deplacement sprite
    dist.f = Distance(@Destination, @Sprite)
    
    If dist < Vitesse
        Sprite\x + Direction\x * dist
        Sprite\y + Direction\y * dist   
    Else 
        Sprite\x + Direction\x * Vitesse
        Sprite\y + Direction\y * Vitesse
    EndIf

[modifier] Rotation

Il nous reste à calculer l'angle de rotation du sprite 3D .

Procedure.f atan2f(y.f, x.f)
  !fld dword[p.v_y]
  !fld dword[p.v_x]
  !fpatan
  ProcedureReturn
EndProcedure
#RAD = 0.0175 
Angle=atan2f(Direction\y, Direction\x) / #RAD

[modifier] Programme complet

; PB 3.94
Structure Vecteur
    x.f
    y.f
EndStructure

;Declare les procédures
Declare.f Distance(*p1.Vecteur, *p2.Vecteur)
Declare.f atan2f(y.f,x.f)
Declare Norme(*V.Vecteur)

;Initialise l'environnement nécessaire au fonctionnement des sprites et pour ouvrir un écran.
InitSprite()
;Initialise l'environnement propre à la gestion du clavier. 
InitKeyboard()
;Initialise l'environnement propre à la gestion de la souris. 
InitMouse()
;Initialise l'environnement propre à la gestion des sprites 3D. 
InitSprite3D() 
;Ouvre un nouvel écran avec les caractéristiques Largeur, Hauteur et Profondeur. 
OpenScreen(800,600,32,"Tut Sprite3D et Souris")

;Déclaration des variables
Vitesse.f = 3
Direction.Vecteur
Sprite.Vecteur
Destination.Vecteur
#RAD = 0.0175

;Creation d'une texture
CreateSprite(0,64,64,#PB_Sprite_Texture)

;On dessine un triangle plein dans la texture
StartDrawing(SpriteOutput(0))
LineXY(1, 1, 1, SpriteHeight(0)-2,RGB(255,255,0))
LineXY(1, 1, SpriteWidth(0)-2, SpriteHeight(0)/2,RGB(255,255,0))
LineXY(1, SpriteHeight(0)-2, SpriteWidth(0)-2, SpriteHeight(0)/2,RGB(255,255,0))
FillArea(SpriteWidth(0)/2,SpriteHeight(0)/2,RGB(255,255,0),RGB(255,155,0))
StopDrawing()

;Creation d'un sprite3D utilisant la texture définie précédemment 
CreateSprite3D(0,0)

;Sprite pour la souris
CreateSprite(1,5,5)
StartDrawing(SpriteOutput(1))
Box(0,0,5,5,RGB(0,255,0))
StopDrawing() 

Repeat
    ;Inverse le buffer d'arrière plan avec le buffer visible à l'écran. 
    ;La partie invisible du buffer remplace alors complètement La partie visible. 
    FlipBuffers()
    
    ;Efface l'écran courant avec la couleur specifiée. 
    ClearScreen(0,0,100)
    
    ;Met à jour l'état du clavier.Cette fonction doit être appelée avant d'utiliser les commandes 
    ;KeyboardInkey(), KeyboardPushed() et KeyboardReleased(). 
    ExamineKeyboard()
    
    
    ;Destination 
    If ExamineMouse()
    	Destination\x = MouseX()
    	Destination\y = MouseY()
    EndIf
    
    ;Direction
    Direction\x = Destination\x - Sprite\x 
    Direction\y = Destination\y - Sprite\y
    Angle=atan2f(Direction\y, Direction\x) / #RAD
    Norme(@Direction)
    
    ;Deplacement sprite
    dist.f = Distance(@Destination, @Sprite)
    
    If dist < Vitesse
        Sprite\x + Direction\x * dist
        Sprite\y + Direction\y * dist   
    Else 
        Sprite\x + Direction\x * Vitesse
        Sprite\y + Direction\y * Vitesse
    EndIf
    
    ;Affiche le sprite 3D
    If Start3D()
    	DisplaySprite3D(0, Sprite\x, Sprite\y)
    	RotateSprite3D(0,Angle,0)
    	Stop3D()
	EndIf    
	
    ;Affiche la souris
    DisplaySprite(1, Destination\x , Destination\y)
    
Until KeyboardPushed(#PB_Key_Escape)
End

Procedure.f Distance(*p1.Vecteur, *p2.Vecteur)
    ProcedureReturn Sqr((*p1\x - *p2\x) * (*p1\x - *p2\x) + (*p1\y - *p2\y) * (*p1\y - *p2\y))
EndProcedure
 
Procedure Norme(*V.Vecteur)
    Norme.f = Sqr(*V\x * *V\x + *V\y * *V\y)
    If Norme <> 0
     	*V\x / Norme
        *V\y / Norme
    EndIf
EndProcedure 

Procedure.f atan2f(y.f, x.f)
  !fld dword[p.v_y]
  !fld dword[p.v_x]
  !fpatan
  ProcedureReturn
EndProcedure

[modifier] Amélioration

Vous pouvez remplacer le triangle , par un sprite de voiture , et jouer sur la vitesse avec les touches gauche et droite de la souris.

    ;Destination 
    If ExamineMouse()
    	Destination\x = MouseX()
    	Destination\y = MouseY()
	If MouseButton(1)
    	    Vitesse + 0.2
        ElseIf MouseButton(2) And Vitesse > 1
	    Vitesse - 0.2
        EndIf  
    EndIf

[modifier] Mise à jour pour PureBasic 4.0

Comme vous devez sans doute déjà le savoir, PureBasic 4.0 apporte de nombreuses nouveautés mais aussi beaucoup de changements dans la façon d'écrire un code. Rassurez vous, pour adapter le code de ce tutoriel ça ne prend que quelques secondes, rien d'insurmontable.

Les changements dans ce code sont :

  • ClearScreen(RGB(0,0,100)) : Désormais il n'y a plus qu'un paramètre couleur.
  • La fonction assembleur Atan2() : Pour faciliter l'accès aux variables locales, une notation a été mise en place: 'p.v_NomVariable' pour une variable standard et 'p.p_NomPointeur' pour un pointeur.

J'ai profité de cette mise à jour pour ajouter quelques nouveautés :

  • EnableExplicit : Force la déclaration des variables
  • Define : Permet de définir des variables
  • Remplacement de la procédure Distance() par la macro DISTANCE()
;PB 4.02 6 mai 2007
;Modification procédure ATAN2 !

EnableExplicit ; Force la déclaration de toutes les variables 

Structure Vecteur
    x.f
    y.f
EndStructure


;Declare les procédures
Declare.f atan2f(y.f, x.f)
Declare Norme(*V.Vecteur)

;Initialise l'environnement nécessaire au fonctionnement des sprites et pour ouvrir un écran.
InitSprite()
;Initialise l'environnement propre à la gestion du clavier. 
InitKeyboard()
;Initialise l'environnement propre à la gestion de la souris. 
InitMouse()
;Initialise l'environnement propre à la gestion des sprites 3D. 
InitSprite3D() 
;Ouvre un nouvel écran avec les caractéristiques Largeur, Hauteur et Profondeur. 
OpenScreen(800,600,32,"Tut Sprite3D et Souris")

;-Déclaration des variables
Define Angle, dist, Vitesse.f = 3
Define.Vecteur Direction, Sprite, Destination

Macro DISTANCE(p1, p2)
    Sqr((p1\x - p2\x) * (p1\x - p2\x) + (p1\y - p2\y) * (p1\y - p2\y))
EndMacro

#RAD = 0.0175

;Creation d'une texture
CreateSprite(0,64,64,#PB_Sprite_Texture)

;On dessine un triangle plein dans la texture
StartDrawing(SpriteOutput(0))
LineXY(1, 1, 1, SpriteHeight(0)-2,RGB(255,255,0))
LineXY(1, 1, SpriteWidth(0)-2, SpriteHeight(0)/2,RGB(255,255,0))
LineXY(1, SpriteHeight(0)-2, SpriteWidth(0)-2, SpriteHeight(0)/2,RGB(255,255,0))
FillArea(SpriteWidth(0)/2,SpriteHeight(0)/2,RGB(255,255,0),RGB(255,155,0))
StopDrawing()

;Creation d'un sprite3D utilisant la texture définie précédemment 
CreateSprite3D(0,0)

;Sprite pour la souris
CreateSprite(1,5,5)
StartDrawing(SpriteOutput(1))
Box(0,0,5,5,RGB(0,255,0))
StopDrawing() 

Repeat
    ;Inverse le buffer d'arrière plan avec le buffer visible à l'écran. 
    ;La partie invisible du buffer remplace alors complètement La partie visible. 
    FlipBuffers()
    
    ;Efface l'écran courant avec la couleur specifiée. 
    ClearScreen(RGB(0,0,100))
    
    ;Met à jour l'état du clavier.Cette fonction doit être appelée avant d'utiliser les commandes 
    ;KeyboardInkey(), KeyboardPushed() et KeyboardReleased(). 
    ExamineKeyboard()
    
    
    ;Destination 
    If ExamineMouse()
    	Destination\x = MouseX()
    	Destination\y = MouseY()
    EndIf
    
    ;Direction
    Direction\x = Destination\x - Sprite\x 
    Direction\y = Destination\y - Sprite\y
    Angle=atan2f(Direction\y, Direction\x) / #RAD
    Norme(@Direction)
    
    ;Deplacement sprite
    dist = DISTANCE(Destination, Sprite)
    
    If dist < Vitesse
        Sprite\x + Direction\x * dist
        Sprite\y + Direction\y * dist   
    Else 
        Sprite\x + Direction\x * Vitesse
        Sprite\y + Direction\y * Vitesse
    EndIf
    
    ;Affiche le sprite 3D
    If Start3D()
    	DisplaySprite3D(0, Sprite\x, Sprite\y)
    	RotateSprite3D(0,Angle,0)
    	Stop3D()
	EndIf    
	
    ;Affiche la souris
    DisplaySprite(1, Destination\x, Destination\y)
    
Until KeyboardPushed(#PB_Key_Escape)
End


Procedure Norme(*V.Vecteur)
    Define.f Norme
    
    Norme.f = Sqr(*V\x * *V\x + *V\y * *V\y)
    If Norme 
     	*V\x / Norme
      *V\y / Norme
    EndIf
EndProcedure 

Procedure.f atan2f(y.f, x.f)
  !fld dword[p.v_y]
  !fld dword[p.v_x]
  !fpatan
  ProcedureReturn
EndProcedure