Problème calcul avec des float

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
bombseb
Messages : 445
Inscription : jeu. 25/août/2005 22:59
Localisation : 974
Contact :

Problème calcul avec des float

Message par bombseb »

Salut les copains,

J'essaye de convertir des coordonnées écran en coordonnées isométrique....

scrCoord est une structure de type Point qui contient la coordonnée à l'écran
tileHeight et tileWidth sont de type .a

En faisant comme ca, ca ne fonctionne pas, les coordonnées sont mal calculées :

Code : Tout sélectionner

*tileCoord\x = (*scrCoord\y / *m\tileSets (0)\tileHeight) + (*scrCoord\x / *m\tileSets (0)\tileWidth)
*tileCoord\y = (*scrCoord\y / *m\tileSets (0)\tileHeight) - (*scrCoord\x / *m\tileSets (0)\tileWidth)

Je pense que les divisions qui sont entre parenthèses sont arrondies.

J'ai réglé le problème en faisant comme ca :

Code : Tout sélectionner

a.f = *scrCoord\y / *m\tileSets (0)\tileHeight
b.f = *scrCoord\x / *m\tileSets (0)\tileWidth
    
*tileCoord\x = a + b
*tileCoord\y = a - b
Ma question : y a t-il un moyen plus simple de régler ce problème ?

Merci d'avance pour votre aide
PAPIPP
Messages : 534
Inscription : sam. 23/févr./2008 17:58

Re: Problème calcul avec des float

Message par PAPIPP »

Bonjour bombseb

Comme je ne vois pas la structure utilisée. je pense que tu as utilisé la structure point

Structure POINT
x.l
y.l
EndStructure

utilise la structure suivante plus précise en *.d que celle en *.f

structure pointd
x.d
y.d
endstructure

A+
Il est fort peu probable que les mêmes causes ne produisent pas les mêmes effets.(Einstein)
Et en logique positive cela donne.
Il est très fortement probable que les mêmes causes produisent les mêmes effets.
bombseb
Messages : 445
Inscription : jeu. 25/août/2005 22:59
Localisation : 974
Contact :

Re: Problème calcul avec des float

Message par bombseb »

Oui c'est bien une structure de type Point...
utilise la structure suivante plus précise en *.d que celle en *.f
Ok merci je vais regarder ca je ne savais pas que ca existait...
bombseb
Messages : 445
Inscription : jeu. 25/août/2005 22:59
Localisation : 974
Contact :

Re: Problème calcul avec des float

Message par bombseb »

Salut Papi,

Je remonte ce sujet car j'aimerai utiliser ton astuce...mais j'ai une question
Ces structures n'existent pas (contrairement à la structure .Point) ? Il faut donc les créer j'imagine ?
Avatar de l’utilisateur
Fig
Messages : 1176
Inscription : jeu. 14/oct./2004 19:48

Re: Problème calcul avec des float

Message par Fig »

Je te propose un code tout fait ((c'est un vieux truc à moi, ce n'est peut être pas optimal car j'ai progressé depuis, je n'ai pas regardé) si tu veux regarder un peu les macros de convertion de coodonnées ecran=>Iso et Iso=>ecran... Pas besoin de float.
Zoom avec la roulette de la souris... En fenetre du debugger des infos sur la position de la souris et le nombre de tuile affichées...

Code : Tout sélectionner

     ;windows' resolution
    #x=1024:#y=768
    If InitSprite() = 0 Or InitKeyboard()=0 Or InitMouse()=0:MessageRequester("Error","Error DirectX",0):EndIf
    If OpenWindow(0,200,0,#x,#y, "test carte isometric zoomable ", #PB_Window_SystemMenu|#PB_Window_MinimizeGadget)
        If OpenWindowedScreen(WindowID(0),0,0,#x,#y,0,0,0,#PB_Screen_WaitSynchronization)=0:MessageRequester("Erreur", "Impossible d'ouvrir un écran dans la fenêtre!", 0):End:EndIf
    EndIf
    ;size of the map
    #xmax=512:#ymax=512
    ;colors constants usefull for nonwindows Os.
    ;#yellow=$FFFF00:#red=$FF0000:#blue=$0000FF:#black=$000000
    ;cste ground
    ;max size tile:320
    Global GroundTileWidth.i=320
    Global GroundTilewidthInit.i=GroundTileWidth
    Global GroundTileWidthHalf.i=GroundTileWidth/2
    Global GroundTileHeight.i=GroundTileWidth/2
    Global GroundTileHeightHalf.i=GroundTileHeight/2
    ;scroll speed
    Global CameraSpeed.i=10
    Global zoom.i=100

    #herbe1=0
    #mouse=101

    ;camera starting point
    Global XCamera.i=-#x/2
    Global YCamera.i=-#y/2

    Dim ground(#xmax-1,#ymax-1)

    ;convertcoordonate from screen to iso
    Macro XScreenToMap(x,y)
    Int(((X/GroundTileWidthhalf) + (Y/GroundTileheighthalf))/2)
    EndMacro
    Macro YScreenToMap(x,y)
    Int(((Y/GroundTileheighthalf) - (X/GroundTilewidthhalf))/2)
    EndMacro
    ;reverse from iso to screen
    Macro XMapToScreen(x,y)
    (x-y)*GroundTileWidthHALf
    EndMacro
    Macro YMapToScreen(x,y)
    (x+y)*GroundTileheightHALF
    EndMacro


    ;{ CreateIsoSprite()
    CreateSprite(#mouse,10,10)
    StartDrawing(SpriteOutput(#mouse))
    Box(0,0,10,10,#Yellow)
    StopDrawing()
    LoadImage(0,#PB_Compiler_Home + "examples/sources/Data/PureBasic.bmp")
    ResizeImage(0,GroundTileWidth,GroundTileHeight)
    CreateSprite(#herbe1,GroundTileWidth,GroundTileheight)
    StartDrawing(SpriteOutput(#herbe1))
    DrawImage(ImageID(0),0,0)
    LineXY(0,0,GroundTileWidth,0,#Yellow)
    LineXY(GroundTileWidth,0,GroundTileWidth,GroundTileheight,#Yellow)
    LineXY(GroundTileWidth,GroundTileheight,0,GroundTileheight,#Yellow)
    LineXY(0,GroundTileheight,0,0,#Yellow)
    StopDrawing()

    TransformSprite(#herbe1,GroundTileWidthHalf,0,GroundTileWidth,GroundTileheightHalf,GroundTileWidthHalf,GroundTileHeight,0,GroundTileHeightHalf)
    ;}

    Macro affiche_dimetric()
    nbtile.i=0
      x1 =XScreenToMap(Xcamera,ycamera)-2
      y1 =YScreenToMap(xcamera,ycamera)
      x2=x1
      y2=y1
      Repeat
          Repeat
              If x1>-1 And x1<#Xmax And y1>-1 And y1<#ymax
                  DisplaySprite(ground(x1,y1),XMapToScreen(x1,y1)-GroundTileWidthHalf-xcamera,yMapToScreen(x1,y1)-ycamera)
                  nbtile+1
              EndIf
              x1+1
              y1-1
          Until XMapToScreen(x1,y1)-GroundTileWidthHalf-xcamera>#X
          y2+1
          x1=x2:y1=y2
          Repeat
              If x1>-1 And x1<#Xmax And y1>-1 And y1<#ymax
                  DisplaySprite(ground(x1,y1),XMapToScreen(x1,y1)-GroundTileWidthHalf-xcamera,yMapToScreen(x1,y1)-ycamera)
                  nbtile+1
              EndIf
              x1+1
              y1-1
          Until XMapToScreen(x1,y1)-GroundTileWidthHalf-xcamera>#X
          x2+1
          x1=x2:y1=y2
      Until yMapToScreen(x1,y1)-ycamera>#y
    EndMacro

    Macro Mouse()
    ExamineMouse()
    Mx=MouseX()+XCamera
    My=MouseY()+YCamera
    DisplayTransparentSprite(#mouse,MouseX(),MouseY())
    ;tile coordonate of the mouse. Usefull !
    IsoMouseX=XScreenToMap(Mx,My)
    IsoMouseY=YScreenToMap(Mx,My)
    Debug "Mouse map coordinate X "+ Str(XScreenToMap(Mx,My))
    Debug "Mouse map coordinate Y "+ Str(YScreenToMap(Mx,My))
    Debug "Tile's Width: "+Str(GroundTileWidth)
    Debug "nb tiles displayed :"+Str(nbtile)
    Debug " "
    ;offset Camera
    If MouseX()=0 And IsoMouseX>-1 And IsoMouseY<#ymax:XCamera-CameraSpeed:EndIf
    If MouseX()=#X-1 And IsoMouseX<#xmax And IsoMouseY>-1:XCamera+CameraSpeed:EndIf
    If MouseY()=0 And IsoMouseX>-1 And IsoMouseY>-1:YCamera-CameraSpeed:EndIf
    If MouseY()=#Y-1 And IsoMouseX<#xmax And IsoMouseY<#ymax:YCamera+CameraSpeed:EndIf
    ;zoom
    wheel=MouseWheel()
    If (Wheel>0 And zoom<100) Or (Wheel<0 And zoom>5)
    Zoom+Wheel
    GroundTileWidth.i=GroundTilewidthInit*zoom/100
    GroundTileWidthHalf.i=GroundTileWidth/2
    GroundTileHeight.i=GroundTileWidth/2
    GroundTileHeightHalf.i=GroundTileHeight/2
    TransformSprite(#herbe1,GroundTileWidthHalf,0,GroundTileWidth,GroundTileheightHalf,GroundTileWidthHalf,GroundTileHeight,0,GroundTileHeightHalf)
    EndIf
    EndMacro

    Repeat
    FlipBuffers()
    ClearScreen(#Black)
    ExamineKeyboard()
    WindowEvent()

    affiche_dimetric()
    Mouse()
    Until KeyboardPushed(#PB_Key_Escape)
Il y a deux méthodes pour écrire des programmes sans erreurs. Mais il n’y a que la troisième qui marche.
Version de PB : 6.00LTS - 64 bits
bombseb
Messages : 445
Inscription : jeu. 25/août/2005 22:59
Localisation : 974
Contact :

Re: Problème calcul avec des float

Message par bombseb »

Salut Fig, oui c'est vrai j'étais déjà tombé sur ton code...
Je vais tester avec tes macro pourquoi pas... C'est vrai que j'ai pas l'habitude d'utiliser les macros

Par contre pour les float j'en ai besoin car mon personnage se déplace pixel par pixel et non tile par tile, donc je ne sais pas je vais voir ca...
bombseb
Messages : 445
Inscription : jeu. 25/août/2005 22:59
Localisation : 974
Contact :

Re: Problème calcul avec des float

Message par bombseb »

Je vais poster un message sur le forum dès que j'ai un peu de temps car j'ai un problème avec ma map isométrique et c'est pas facile à expliquer...
Avatar de l’utilisateur
Fig
Messages : 1176
Inscription : jeu. 14/oct./2004 19:48

Re: Problème calcul avec des float

Message par Fig »

bombseb a écrit :Salut Fig, oui c'est vrai j'étais déjà tombé sur ton code...
Je vais tester avec tes macro pourquoi pas... C'est vrai que j'ai pas l'habitude d'utiliser les macros

Par contre pour les float j'en ai besoin car mon personnage se déplace pixel par pixel et non tile par tile, donc je ne sais pas je vais voir ca...
Tout d'abord, on s'en fout que j'ai fait une macro pour ça, ça peut être une procedure ou juste tu rajoute la/les lignes dans le code, ça ne change rien.

L'affichage de ton personnage se fait pixel par pixel, donc avec des pixels entiers, même si sa vitesse et position sont des floats.
Où qu'il soit, il dépend forcément d'une tuile ou d'une autre, pour chaque tuile il a un offset jusqu'a la limite de la tuile suivante... (il se déplace probablement dans un tableau aussi, non ? C'est pratique de faire correspondre ce tableau avec les tuiles)

Tu veux faire quoi comme jeu exactement ? Comment se déplace ton personnage principal ? (on clic sur la tuile de destination, on le dirige avec les flèches... ?) Il y a des ennemis et des obstacles ?
Il y a deux méthodes pour écrire des programmes sans erreurs. Mais il n’y a que la troisième qui marche.
Version de PB : 6.00LTS - 64 bits
Avatar de l’utilisateur
Ar-S
Messages : 9476
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: Problème calcul avec des float

Message par Ar-S »

+1 avec Fig.
Ton perso, s'il avance pixel par pixel tu n'as pas besoin des floats. Il ne va pas se déplacer de 2,3 pixels :)
Si tu as structuré tes coords de déplacements et les dimensions de tes sprites/décors, ce ne sera pas difficile de gérer la position et les mouvements du sprite en question.
~~~~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
poshu
Messages : 1138
Inscription : sam. 31/juil./2004 22:32

Re: Problème calcul avec des float

Message par poshu »

Ar-S a écrit :Ton perso, s'il avance pixel par pixel tu n'as pas besoin des floats. Il ne va pas se déplacer de 2,3 pixels :)
Si tu as structuré tes coords de déplacements et les dimensions de tes sprites/décors, ce ne sera pas difficile de gérer la position et les mouvements du sprite en question
Tuuuut tut tut. Attention, le JV c'est compliqué et on peut avoir de très mauvaises intuitions quand on ne s'y connaît pas : Instinctivement, c'est vrai qu'on se dit que si on utilise des chiffres ronds, on aura jamais de problème... Et ça a l'air vrai vu de loin, mais c'est du JV donc c'est compliqué et ça se passe pas comme ça, pour deux raisons principales :

Δt vs Frame pacing
Une des premières question qu'on doit se poser : comment le jeu mesure-t-il le temps qui passe? Doit on dire "mon jeu tourne à 60 fps, donc le personnage se déplace de 3 pixels par frame" -aka le frame pacing- ou "Mon jeu tourne a 1 seconde par seconde ( :mrgreen: ) donc mon personnage se déplace de 180 pixels par seconde" -aka le Δt. Comme ça, ça a l'air identique, mais voici les trois plus grandes différences:
  • Si mon jeu rame : En Δt, le jeu va garder son rythme, mais on va "sauter" des étapes. En Frame pacing, le rythme du jeu va ralentir. En fonction du type de jeu, l'un est préférable à l'autre : sur un Danmaku, utilisez exclusivement le frame pacing. Sur un rythme game, seul le Δt compte. Et entre les deux... Bah c'est une question d'importance de vos feedback visuels. Par exemple, sur un jeu de baston, où chaque frame convoie pas mal d'information, on a tendance à préférer le frame pacing (street fighter 5), mais des jeux moins exigents et plus portés sur le spectable font le choix du Δt (Mortal Kombat X).
  • Sur des hardware "spéciaux" : vous connaissez les écrans à 144hz? Des écrans pour joueurs, très très agréables à utiliser puisque tout est plus fluide dessus... Ouiiii, mais pour un développeur de jeu ça devient vite un cauchemar : quand on fait du frame pacing, on a tendance à utiliser 60 fps comme vitesse de base; sauf aue 60 hz n'est pas un multiple de 144hz. Et donc, les jeux en frame pacing sur ce genre d'écran, en particulier si le vsync est activé, ont un rendu très désagréable.
  • Virgule flottante de partout : en frame pacing, pour peu qu'on ait choisi des nombres entier à la base, alors on aura jamais que des nombres entier; parfait! Mais en Δt... Et bien on travail en milliseconde, 180 pixels par seconde, c'est donc 0.18 pixels par milliseconde et... Bah ouais, on va avoir besoin de float partout, il faut donc y penser dès le début; car la conversion serait longue et douloureuse.
Pixel art vs Gros carrés art
Cherchons une définition de pixel... Disons... C'est l'unité indivisible de l'image numérique. Bon, bah de nos jours, bonne partie des jeux en "pixel art" ne respectent pas cette définition du pixel : ils font en fait du gros carré art : après tout, si ton jeu est 640*360, il est en fait probablement affiché sur un écran en 1080p (neuf fois plus de pixels), voir même 1440p (seize fois plus) ou 4k (TRENTE-SIX FOIS PLUS!) :
Image
Par exemple, sur ce sémillant Zero, j'ai compté 44 gros carrés de haut; pourtant vous vous rendez bien compte que chaque gros carré est composé de plusieurs pixels sur votre écran.

Et bien voilà le principe du "gros carrés art" : on reprend l'esthétique du pixel art, mais pas ses limitations.
Pour exploiter ces sous-pixels, l'exemple le plus évident, c'est les rotation : voilà le même sprite sur lequel j'ai appliqué une rotation :
Image
Lequel est le meilleur? Là dessus, y'a débat, l'un est clairement plus lisible, l'autre clairement plus respectueux... C'est au choix. Sauf que, comme vous pouvez vous en douter : pour exploiter au mieux les sous pixels, il va falloir utiliser des floats et donc le prévoir dès le début.

Bref, désolé c'était plus long que je ne le pensais, mais c'était pour montrer que dans le jeu vidéo, tout est toujours beaucoup plus compliqué qu'il n'y parait.
bombseb
Messages : 445
Inscription : jeu. 25/août/2005 22:59
Localisation : 974
Contact :

Re: Problème calcul avec des float

Message par bombseb »

Tu veux faire quoi comme jeu exactement ? Comment se déplace ton personnage principal ? (on clic sur la tuile de destination, on le dirige avec les flèches... ?) Il y a des ennemis et des obstacles ?
Bah là en fait j'affiche un zombie sur une map isométrique sur laquelle il y a des obstacles, je le déplace à la souris, j'ai donc fait un algo de pathfinding.
Et pour en revenir aux float, j'ai défini x et y en float dans ma structure zombie. Si le personnage se trouve en 5.4, 3 il sera affiché sur la 4eme ligne de tuile en Y et sur la 5eme colonne de tuile en X + un léger déplacement. Utiliser des float pour les coordonnées du perso me permet de gérer le déplacement au pixel entre deux tiles...
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Problème calcul avec des float

Message par Ollivier »

Pour les floats/double, pas de suchis, quelqu'en soit l'unité : tile, pixel, sous-pixel, ou bien, à l'inverse, considérer une région, ou carrément la map comme unité 1.0.

Pour les entiers, pas de souci apparent non plus, par contre on s'envahit de modulos dans tous les sens : tout est question de vieillesse du matériel (années 70, 80) et... On n'y est plus!

Le problème est que ce n'est pas unidimensionnel mais bi (voir tri, l'iso n'interdisant rien) dimensionnel. Et une distance calculée ne laisse aucun choix pour les entiers : ou bien l'unité est la plus petite mesure possible et imaginable du moteur avec quelques lourdes gestions d'inclusion, ou bien c'est l'hécatombe des modulos puisqu'il se scinde alors deux familles de modulos : les modulos supérieurs à 1 et les modulos inférieurs à 1. On se retrouve avec deux architectures de calculs pour la même fonction. Donc les floats/doubles prennent un avantage massif puisque cette frontière unitaire n'existe pas.
Répondre