Sprite & mathématique

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

Sprite & mathématique

Message par G-Rom »

En discutant avec Blendman ce matin, je me suis souvenu que j'avais un vieux code qui permet de choisir facilement le point d'ancrage d'un sprite ou de n'importe quel composant affichable. Le code se base sur des calcul matriciels , comme le fait n'importe quel api multimedia de haut niveau ( SFML , Ogre3D, etc...)
de mémoire, le code reprends la philosophie de la sfml.

Tout d'abord le fichier Vector2.pbi , regroupe toute les fonctions sur les vecteurs 2D
http://pastebin.com/GJDZz71d

une fonction intéressante à l'intérieur : lerpVector2f(*result.sVector2f, *a.sVector2f, *b.sVector2f, val.f)
cela permet au vecteur A(x,y) d'aller au vecteur B(x,y) en fonction de val.f ( 0.0f à 1.0f ) , le résultat sera dans *result , c'est une interpolation linéaire entre 2 vecteurs 2D.

Viens ensuite le fichier Matrix3.pbi , regroupe toute les fonctions matricielle
http://pastebin.com/fdF7NZG5
ne vous laissez pas abuser ni impressionner par son nom compliqué, la réalité est beaucoup plus simple, les calculs dit matricielles servent aussi bien en 2D qu'en 3D , les matrices permettent d'effectuer des rotations , des translations , des mise à l'échelle , etc... , en gros , une matrice c'est ni plus ni moins qu'un tableau
contenant divers éléments : échelle , position , angle , etc...
Ce qui est pratique & indispensable avec les matrices , c'est qu'elle permettent facilement de créer une hiérarchie parent / enfant, prenons le cas d'un bras humain, l'arrière bras ( relié à l'épaule donc... ) quand il tourne sur son axe de rotation , influe sur l'avant bras. si l'avant bras est parallèle au sol et que l'arrière bras et dans l'axe du tronc , le fait de bouger l'arrière bras de 90° vers l'avant , l'avant bras pointera vers le haut.
Les matrices nous permet de faire cela par le biais de leur multiplications.

Viens ensuite la partie drawable , qui regroupe les calculs trigonométrique des objets qui seront à dessiner :
http://pastebin.com/RXFniPyx

Cette partie est à amélioré dans le sens , ou je n'ai pas mis le système parent/enfant en place entre deux objets Drawable.
un objet Drawable ne peut pas être dessiner directement, cette structure (Drawable) n'est qu'un regroupement de donnée mathématique ( liste des vertex )


Maintenant , passons au sprite , il a cette structure toute bête :
c'est une structure spécialisé dans le dessin, ne fait rien d'autre, spriteID est l'id du sprite purebasic.

Code : Tout sélectionner

Structure Sprite3D Extends Drawable
  spriteID.l
EndStructure
le sprite 3D n'a que 2 fonctions :

Code : Tout sélectionner

Structure Sprite3D Extends Drawable
  spriteID.l
EndStructure


Procedure.i CreateSprite3D(x.i, y.i, width.i, height.i, pbSprite.i)
  *spr.Sprite3D = AllocateMemory(SizeOf(Sprite3D))
    
  InitializeStructure(*spr,Sprite3D)
  *spr\scale\x = 1
  *spr\scale\y = 1
  *spr\transformUpdate = #True 
  
  addVertex(*spr, x, y)
  addVertex(*spr, x+width, y)
  addVertex(*spr, x+width, y+height)
  addVertex(*spr, x, y+height)
  
  *spr\spriteID   = pbSprite
  *spr\transform  = AllocateMemory(SizeOf(sMatrix))
  
  TranformDrawable(*spr)
  
  ProcedureReturn *spr
EndProcedure

Procedure DrawSprite3D(*s.Sprite3D)
  TranformDrawable(*s)
  
  A.sVector2f : B.sVector2f : C.sVector2f : D.sVector2f
  
  FirstElement(*s\transformed())
    A\x = *s\transformed()\x
    A\y = *s\transformed()\y
  NextElement(*s\transformed())
    B\x = *s\transformed()\x
    B\y = *s\transformed()\y
  NextElement(*s\transformed())
    C\x = *s\transformed()\x
    C\y = *s\transformed()\y
  NextElement(*s\transformed())
    D\x = *s\transformed()\x
    D\y = *s\transformed()\y
   

  TransformSprite(*s\spriteID, A\x,A\y,B\x,B\y,C\x,C\y,D\x,D\y)
  DisplaySprite(*s\spriteID,0,0)
EndProcedure
pour pouvoir le bouger , le tourné , changé son origine , voila un exemple d'utilisation :

Code : Tout sélectionner

InitSprite() : InitKeyboard()

OpenWindow(0,0,0,1024,768,"Sprite3D")
OpenWindowedScreen(WindowID(0),0,0,1024,768)


CreateSprite(0,256,256)
StartDrawing(SpriteOutput(0))
  Box(0,0,128,128,$FFFFFF)
  Box(128,128,128,128,$FFFFFF)
StopDrawing()


*MonSprite = CreateSprite3D(0, 0, 256,256, pbSprite.i)
setOriginPoint(*MonSprite, 128, 128)
setPosition(*MonSprite,512,384)

deltatime.f = 0
While #True 
  clock = ElapsedMilliseconds()
  Repeat 
    event = WindowEvent()
    If event = #PB_Event_CloseWindow
      End
    EndIf 
  Until event = 0
  
  angle + 45 * deltatime
  
  setRotation(*MonSprite,angle )
  
  ClearScreen($FF00FF)
    DrawSprite3D(*MonSprite )
  FlipBuffers()
  deltatime = (ElapsedMilliseconds() - clock)/1000
Wend
G-Rom
Messages : 3627
Inscription : dim. 10/janv./2010 5:29

Re: Sprite & mathématique

Message par G-Rom »

un petit exemple du code du dessus avec l'interpolation linéaire pour le mouvement :

Code : Tout sélectionner

InitSprite() : InitKeyboard()

OpenWindow(0,0,0,1024,768,"Sprite3D")
OpenWindowedScreen(WindowID(0),0,0,1024,768)


CreateSprite(0,256,256)
StartDrawing(SpriteOutput(0))
  Box(0,0,128,128,$FFFFFF)
  Box(128,128,128,128,$FFFFFF)
StopDrawing()


*MonSprite = CreateSprite3D(0, 0, 256,256, pbSprite.i)
setOriginPoint(*MonSprite, 128, 128)
setPosition(*MonSprite,512,384)


*Depart   = createVector2f(128, 384)
*Arrive   = createVector2f(896, 384)
*Position.sVector2f = createVector2f(0,0)

deltatime.f = 0
interpolation.f = 0

While #True 
  clock = ElapsedMilliseconds()
  Repeat 
    event = WindowEvent()
    If event = #PB_Event_CloseWindow
      End
    EndIf 
  Until event = 0
  
  angle + 45 * deltatime
  
  
  interpolation = (50 + 50 * Cos(clock/1000))/100 ; 0 & 1
  lerpVector2f(*Position,*Depart,*Arrive,interpolation)
      
  setPosition(*MonSprite,*Position\x,*Position\y)
  setRotation(*MonSprite,angle )

  
  ClearScreen($FF00FF)
    DrawSprite3D(*MonSprite )
  FlipBuffers()
  deltatime = (ElapsedMilliseconds() - clock)/1000
Wend
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: Sprite & mathématique

Message par blendman »

Merci, je vais regarder ça très vite, car je pourrais en avoir besoin (notamment pour les rotations avec un centre différent du milieu ;).
Répondre