Page 1 sur 2

[jeu] 2D : faire un zoom sur une map

Publié : mer. 04/mai/2011 7:22
par blendman
salut

Je me demandais s'il y avait un moyen de faire un zoom sur une map sur laquelle sont affichées des sprites et sprites3D, autrement qu'en utilisant des zoomsprites() sur chaque sprite, ce qui en plus ne suffirait car il faudrait aussi décaler les sprites en fonction de l'intensité du zoom/dézoom... bref, le bean's :D.

Alors, existe-t-il une solution plus "simple" et générale ? :D

Merciche biench

Re: [jeu] 2D : faire un zoom sur une map

Publié : mer. 04/mai/2011 7:55
par Cool Dji
Salut Blendam,

Pas à ma connaissance.
J'avais commencé un truc dans le genre.
Tous les graphismes étaient dessinés de la taille pour être affiché dans le zoom (donc gros sprites)

En préambule, je réduisais les graphismes qui devaient être affiché à l'écran...

Sinon, il te reste la 3D...

Re: [jeu] 2D : faire un zoom sur une map

Publié : mer. 04/mai/2011 17:25
par Fig
Pas mieux...
Mais c'est faisable et peut être pas si compliqué que cela... Il faut juste limiter le zoom parce que si tu as plus de 2200 tiles affichés simultanément, chez moi, ça rame... (petite configuration)
J'ai un petit prog 2d iso, je vais essayer de rajouter le zoom dessus.

Re: [jeu] 2D : faire un zoom sur une map

Publié : mer. 04/mai/2011 17:32
par djes
Il y a une solution toute simple mais un peu coûteuse en temps machine : dessiner au pixel en prenant la couleur selon un intervalle régulier sur ta carte.
Sinon, la mini-carte (grabsprite) est ce qu'il y a de plus rapide, il y a juste à afficher quelques points pour les éléments à suivre. Trois images correspondraient à trois niveaux de zoom par exemple. Après tu peux en faire des intermédiaires par calcul.

Re: [jeu] 2D : faire un zoom sur une map

Publié : mer. 04/mai/2011 17:35
par Cool Dji
'tain Djes, t'as fumé ou c'est moi :D
J'ai rien compris !!! :lol: :lol:

Re: [jeu] 2D : faire un zoom sur une map

Publié : mer. 04/mai/2011 18:29
par Fig
Ouais, Djes, ça à l'air sympa, fais tourner !!

Ou alors tu as mis un troyen et tu vois ce que je fais... 8O

Perso la mini carte j'ai fais un sprite rempli au départ (en prétraitement) de pixels correspondant aux tiles de ma carte. Comme ma carte est plus grande que ma mini-map en pixel, je prend des carrés de tiles et je garde pour la couleur du pixel de la minimap l'élément qui est en moins grand nombre. Par exemple si il y a 7 tiles vide et 1 avec une ressource pierre, je met le pixel correspondant en gris (pierre)
Ensuite, j'affiche la minimap et je rafraichis juste les élements qui bougent dessus.

Mais bon effectivement ça n'a pas grand chose à voir avec la question initiale :mrgreen:

... En te relisant je me rend compte que je n'ai rien compris :?

Re: [jeu] 2D : faire un zoom sur une map

Publié : mer. 04/mai/2011 18:50
par djes
Arf, c'est mon esprit de synthèse qui a encore frappé. En plus je me suis trompé, j'ai cru qu'il voulait faire une mini carte dans un coin de l'écran.
Donc pour répondre un peu mieux à la question, ça va être difficile de faire autrement qu'avec des ZoomSprite(). C'est aussi pour cela que tu as intérêt à ce que toutes tes coordonnées soient calculées en relatif, avec des variables que tu n'auras qu'à ajuster en fonction du zoom. Surtout pas de nombres codés en dur!

Re: [jeu] 2D : faire un zoom sur une map

Publié : mer. 04/mai/2011 23:32
par Fig
Voila, ça donne une idée.
Le -4 et +4 c'est la vitesse du zoom, à ajuster... (zoom avec les fleches clavier avant et arriere)

Amélioration à faire demain si je n'ai pas trop de boulot:
1-Optimisation de la vitesse de zoom parceque franchement avec mon système de calcul des coordonnées de toutes les tiles ça craint niveau vitesse la mise à jour des 1024x1024 tiles :roll: Je peux juste calculer au fur et à mesure les coordonnées de chacune des tiles affichés. Je ne sais pas pourquoi j'avais fait comme cela.Ca ne devrait pas être trop dur.[FAIT, maintenant c'est rapide+ code épuré des artefacts du code complet]
2- Faut que les arbres ils grossissent proportionnellement bien sûr[Fait]
3- Adapter le système de selection pour la taille variable des sprite (système que j'ai retiré du code pour ne pas l'encombrer, mais qui permet de sélectionner précisément les sprites sans passer par le test 2d de collision, mais en utilisant une table de hashing)
Enfin c'était juste un essais pour dire que c'est faisable.
Bonne soirée. :o



Code : Tout sélectionner

;***
;***   @Fig 12/05/2011
;***        PB 4.51
If InitSprite() = 0 Or InitKeyboard()=0 Or InitMouse()=0 Or InitSprite3D()=0 Or InitSound()=0:MessageRequester("Error","Error DirectX",0):EndIf
ExamineDesktops():Sprite3DQuality(#PB_Sprite3D_BilinearFiltering)
;{-structures
Structure carte1
  tile.i
  *element
  X.i
  Y.i
EndStructure
Structure ordre_affichage1
  X.i
  Y.i
EndStructure
Structure sprite1
  spritedebase.i
  biasX.i
  biasY.i
EndStructure
;}
;{- Taille d'origine des tiles
X_Tilesize=64
Y_Tilesize=X_Tilesize/2
;}
;{-déclare les variables globales
Global xmax=DesktopWidth(0),ymax=DesktopHeight(0)
Global xscroll,yscroll,Xscrolliso,Yscrolliso
Global nbcaseX=Round(xmax/X_Tilesize,1);nombre de Case en hauteur en diagonal à afficher
Global nbcaseY=Round(ymax/Y_Tilesize,0);nombre de Case en largeur en diagonal à afficher
Global Scroll_X=80,Scroll_Y=80,IsoScroll_X=1,IsoScroll_Y=80,XX,YY
Global Scroll_X=80,Scroll_Y=80,IsoScroll_X=1,IsoScroll_Y=80,XX,YY
Global vitesse_scroll=32,miliscrol_X,miliscrol_Y,zoom_carte=4
;}
;{-déclare les variables "temporaires"
Global T_i,T_j,T_nb,T_DecX=0,T_DecY=0,T_offset=0
;}
;déclare l'aire de jeu
Global Dim carte.carte1(1023,1023)
;déclare le tableau d'ordre d'affichage des tiles
Global Dim ordre_affichage.ordre_affichage1(20000)
;liste des caractéristiques de l'animation des arbres
Global NewList sprite.sprite1()
;ouvre un écran
OpenScreen(xmax,ymax, DesktopDepth(0), "test")

;{-rempli la carte
;rempli de Tiles
For t_i=0 To 1023
  For t_j=0 To 1023
    carte(t_i,t_j)\tile=Random(2)+1
  Next t_j
Next t_i
;initialise les arbres
For t_i=0 To 10000
  Repeat
    X=Random(1021)+1
    Y=Random(1021)+1
    AddElement(sprite())
    sprite()\spritedebase=150
    sprite()\biasX=-64
    sprite()\biasY=-224
  Until carte(x,y)\element=0
  carte(X,Y)\element=@sprite()
Next t_i
;}

;pré-calcul l'ordre d'affichage des tiles à l'écran
Macro ordredaffichage
  T_nb=0
  ReDim ordre_affichage(60000)
  For T_j=nbcaseY To -nbcaseY Step -1
    For T_i=nbcaseX To -nbcaseX Step -1
      T_nb+1
      ordre_affichage(T_nb)\X=-T_j-T_i
      ordre_affichage(T_nb)\Y=T_i-T_j
    Next T_i
    For T_i=nbcaseX To -nbcaseX+1 Step -1
      T_nb+1
      ordre_affichage(T_nb)\X=-T_j-T_i+1
      ordre_affichage(T_nb)\Y=T_i-T_j
    Next T_i
  Next T_j
  ReDim ordre_affichage(T_nb)
EndMacro
ordredaffichage

;{-création des sprites
T_T=100000
For t_j=1 To 3
  ;sprite de terrain :herbe verte, herbe sèche et terre nue
  CreateSprite(t_j,256,256,#PB_Sprite_Texture)
  StartDrawing(SpriteOutput(t_j))
  Box(0,0,256,256,RGB(0,0,0))
  Box(0,0,256,256,RGB(196, 178, 86))
  For T_i=1 To T_T
    Plot(Random(256-1),Random(256-1),RGB(0,200,50))
    Plot(Random(256-1),Random(256-1),RGB(0,127,0))
  Next T_i
  T_T/2
  StopDrawing()
Next T_j
;sprite arbre
CreateSprite(150,256,256,#PB_Sprite_Texture)
StartDrawing(SpriteOutput(150))
Box(107,64,42,255,RGB(1,1,1))
Box(108,64,40,255,RGB(173, 103, 82))
Circle(128,65,66,RGB(1,1,1))
Circle(128,65,64,RGB(0,200,0))
Circle(128,65,30,RGB(1,1,1))
Circle(128,65,28,RGB(0,0,0))
StopDrawing()
;sprite de la souris
CreateSprite(100,16,16,#PB_Sprite_Texture)
StartDrawing(SpriteOutput(100))
LineXY(0,0,15,5,RGB(255,255,255))
LineXY(0,0,5,15,RGB(255,255,255))
LineXY(15,5,5,15,RGB(255,255,255))
StopDrawing()

;transforme les sprites carrées en tiles losanges isométriques rapport 1/2
For T_i=1 To 3
  CreateSprite3D(T_i,T_i)
  TransformSprite3D(T_i,X_Tilesize/2,0,X_Tilesize,Y_Tilesize/2,X_Tilesize/2,Y_Tilesize,0,Y_Tilesize/2)
Next T_i
CreateSprite3D(150,150)
CreateSprite3D(100,100)
;}

;boucle principale
Repeat
  FlipBuffers()
  ClearScreen(RGB(0,0,0))
  Delay(3)
  ExamineKeyboard()
  ExamineMouse()
  XX=MouseX()
  YY=MouseY()
  ;{-scroll+zoom de la carte
  ;zoomIN
  If KeyboardPushed(#PB_Key_Up)
    x_tilesize+zoom_carte
    y_tilesize=x_tilesize/2
    nbcaseX=Round(xmax/x_tilesize,1);nombre de Case en hauteur en diagonal à afficher
    nbcaseY=Round(xmax/y_tilesize,1)
    Start3D()
    ;change la taille des tiles
    For T_i=1 To 3
      TransformSprite3D(T_i,X_Tilesize/2,0,X_Tilesize,Y_Tilesize/2,X_Tilesize/2,Y_Tilesize,0,Y_Tilesize/2)
    Next T_i
    ;change la taille des arbres
    ratiox.f=X_tilesize/64
    ratioy.f=y_tilesize/32
    ZoomSprite3D(150,256*ratiox,256*ratioy)
    Stop3D()
    ordredaffichage
  EndIf
  ;zoomOut
  If KeyboardPushed(#PB_Key_Down) And x_tilesize>32
    x_tilesize-zoom_carte
    y_tilesize=x_tilesize/2
    nbcaseX=Round(xmax/x_tilesize,1);nombre de Case en hauteur en diagonal à afficher
    nbcaseY=Round(xmax/y_tilesize,1)
    Start3D()
    ;change la taille des tiles
    For T_i=1 To 3
      TransformSprite3D(T_i,X_Tilesize/2,0,X_Tilesize,Y_Tilesize/2,X_Tilesize/2,Y_Tilesize,0,Y_Tilesize/2)
    Next T_i
    ;change la taille des arbres
    ratiox.f=X_tilesize/64
    ratioy.f=y_tilesize/32
    ZoomSprite3D(150,256*ratiox,256*ratioy)    
    Stop3D()
    ordredaffichage
  EndIf
  
  If XX>xmax-20
    If Scroll_X<1023 And Scroll_Y>0
      miliscrol_X-vitesse_scroll
      If miliscrol_X<=0
        Scroll_X+1:Scroll_Y-1
        IsoScroll_X+1
        miliscrol_X=X_Tilesize
      EndIf
    EndIf
  EndIf
  
  If XX<20
    If Scroll_X>0 And Scroll_Y<1023
      miliscrol_X+vitesse_scroll
      If miliscrol_X>=X_Tilesize
        miliscrol_X=0
        Scroll_X-1:Scroll_Y+1
        IsoScroll_X-1
      EndIf
    EndIf
  EndIf    
  
  If YY>ymax-20
    If Scroll_X<1023 And Scroll_Y<1023
      miliscrol_Y-vitesse_scroll/2
      If miliscrol_Y<=0
        Scroll_X+1:Scroll_Y+1:IsoScroll_Y+1:miliscrol_Y=Y_Tilesize
      EndIf
    EndIf
  EndIf
  
  If YY<20
    If Scroll_X>0 And Scroll_Y>0
      miliscrol_Y+vitesse_scroll/2
      If miliscrol_Y>=Y_Tilesize
        Scroll_X-1:Scroll_Y-1:IsoScroll_Y-1:miliscrol_Y=0
      EndIf
    EndIf
  EndIf
  ;}
  
  ;{-Affichage sprites 3D
  Start3D()
  ;affichage des tiles
  For i=0 To T_nb
    sx=Scroll_X+ordre_affichage(i)\X
    sy=Scroll_Y+ordre_affichage(i)\Y
    ;Si dans le tableau de jeu...
    If sx>=0 And sy>=0 And sy<=1023 And sx<=1023
      T_Cases=carte(sx,sy)\tile
      sxx=-sy*(X_Tilesize/2)+ sx*(X_Tilesize/2)-IsoScroll_X*X_Tilesize+xmax/2-X_Tilesize+miliscrol_X
      syy=sy*(Y_Tilesize/2) + sx*(Y_Tilesize/2)-IsoScroll_Y*Y_Tilesize+ymax/2-Y_Tilesize-Y_Tilesize/2+miliscrol_Y
      ;affiche la case de terrain
      DisplaySprite3D(T_Cases,sxx,syy)
    EndIf
  Next i
  
  ;affichage des éléments sur les tiles
  For i=0 To T_nb
    sx=Scroll_X+ordre_affichage(i)\X
    sy=Scroll_Y+ordre_affichage(i)\Y
    ;Si dans le tableau de jeu...
    If sx>=0 And sy>=0 And sy<=1023 And sx<=1023
      sxx=-sy*(X_Tilesize/2)+ sx*(X_Tilesize/2)-(IsoScroll_X*X_Tilesize)+xmax/2-X_Tilesize+miliscrol_X
      syy=sy*(Y_Tilesize/2) + sx*(Y_Tilesize/2)-IsoScroll_Y*Y_Tilesize+ymax/2-Y_Tilesize-Y_Tilesize/2+miliscrol_Y
      If carte(sx,sy)\element
        ;affiche l'élément sur cette case
        ChangeCurrentElement(sprite(),carte(sx,sy)\element)
        sxx1=sxx+sprite()\biasX*ratiox
        syy1=syy+sprite()\biasY*ratioy
        DisplaySprite3D(sprite()\spritedebase,sxx1,syy1)
      EndIf
    EndIf
  Next i
  ;affichage de la souris
  DisplaySprite3D(100,XX,YY)
  Stop3D()
  ;}
  
  ;{-affiche le texte
  If Val(FormatDate("%ss", Date()))=sek
    FPS+1
  Else
    FPS$=Str(FPS)
    FPS=0
  EndIf
  sek=Val(FormatDate("%ss", Date()))
  StartDrawing(ScreenOutput())
  DrawText(1,1,"FPS: "+FPS$)
  DrawText(1,15,"nombre de tiles affichées: "+Str(T_nb))
  StopDrawing()
  ;}  
Until KeyboardPushed(#PB_Key_Escape)

Re: [jeu] 2D : faire un zoom sur une map

Publié : jeu. 05/mai/2011 17:48
par SPH
Merci fig pour ton exemple. Moi perso, j'avais mal lu l'intitulé; croyant que blendman voulait une mini map. Mais effectivement, il ne veux pas ca mais un zoom. :oops:

Re: [jeu] 2D : faire un zoom sur une map

Publié : jeu. 05/mai/2011 20:04
par blendman
Fig : merci pour ton exemple :) mais finalement, je ne pense pas faire de zoom, c'est un peu galère à mettre en place :p.

Sinon, pour la mini-map, la technique que je pense utiliser par la suite, c'est simple un clipsprite() sur une image de la map pré-rendue et quelques sprites de couleur en carré genre 8*8 pour les objets importants : mobs, perso, porte, etc.., qui bougeraient en pourcentage par rapport à leur déplacement.

A ce propos, djes, tu parles de position en relatif, c'est à dire ?

Ah oui, une autre question :
- j'utilise des variables dont le type est .point
exemple position.point
et j'accède comme ça :
position\x
position\x

Mais c'est quoi le type de x et y car du coup, j'ai des bugs dans le déplacement de certains mobs, etc.. c'est space..

Re: [jeu] 2D : faire un zoom sur une map

Publié : jeu. 05/mai/2011 20:15
par djes
En relatif, ça veut dire utiliser des variables au lieu de valeurs "en dur", et n'avoir si possible qu'une valeur absolue, et tout faire en rapport à celle-ci.
Par exemple, quand tu fais un champ d'étoiles, tu définis un début et une fin : tu peux dire qu'elles vont par exemple de 0 à 1024. Si tu prends comme référence le début (0), la fin devient "debut + 1024" ; ceci te permet de déplacer le champ d'étoile en changeant la variable début. Si maintenant tu remplaces 1024 par une variable "largeur", tu peux adapter ton champ à n'importe quel écran en changeant cette largeur. Si maintenant tu mets la fin à "Début + FacteurZoom * Largeur", tu peux encore faciliter le contrôle. Enfin tu vois le truc quoi ;)

Au delà de ça, avec des matrices on peut facilement jouer sur toutes les variables d'un espace à n dimensions.

Sinon, pour la structure point, va dans le menu outils -> visualisateur de structures.

Re: [jeu] 2D : faire un zoom sur une map

Publié : ven. 06/mai/2011 0:13
par Fig
Voila j'ai mis à jour mon code, il est plus lisible car j'ai retiré les bouts de codes inutiles, il est optimisé pour le zoom, les arbres ont la bonne taille. 8)

Blendman> C'est la méthode que j'emploie. Rien n'est en dur ce qui permet d'afficher sur n'importe quel résolution d'écran et de zoomer avec n'importe quel taille de tile. :wink: Evidamment il faut imaginer avec des jolis graphiques...

Re: [jeu] 2D : faire un zoom sur une map

Publié : ven. 06/mai/2011 8:58
par Cool Dji
Nice Fig :D

Re: [jeu] 2D : faire un zoom sur une map

Publié : ven. 06/mai/2011 9:05
par blendman
FIG : merci pour la mise à jour, finalement, j'essaierai peut être par la suite d'intégrer un zoom avec ta méthode, (mais ce ne sera pas pour tout de suite, j'ai encore beaucoup à faire :)).

DJES : merci pour l'explication, je comprends mieux. par contre, il est difficile pour la position de mes objets (décors, arbres, buissons, sol, etc..) d'utiliser des variables, à moins comme tu le dis d'utiliser la variable origine(0,0)+position(x,y) par exemple.

pour la structure point, c'est donc du .l
J'imagine que c'est la raison pour laquelle le déplacement ne marche que pour certains mobs et pas d'autres, car il faut que le déplacement soit en .f pour que ça marche pour certains mobs, c'est bizarre...

Je vais poster un code pour voir s'il y a une autre technique :).

Re: [jeu] 2D : faire un zoom sur une map

Publié : ven. 06/mai/2011 9:09
par case
pourquois tu definie pas une structure avec un x et y en .f et que tu remplace pas tout le point par celle ci ?

structure cord
x.f
y.f
endstructure

et ensuite search >.point replace >.cord


ca te prendra 5 minutes a faire en changeant manuellement ou 10 secondes en remplacer tout si tu as confiance dans le fait que .point n'est utilisé que dans ce cas la

fais une backup de ton source avant si tu flippe vraiment :)