Grille et zoom curseur

Sujets variés concernant le développement en PureBasic
Joubarbe
Messages : 93
Inscription : sam. 01/juil./2006 16:40

Grille et zoom curseur

Message par Joubarbe »

Salut,

Pas sûr que ce soit le bon endroit pour poster ça, mais allons-y (gaiement) :

Code : Tout sélectionner


;- TODOLIST
; zoom on cursor

Structure s_map
  x.i
  y.i
  zoom.i
EndStructure

Structure s_grid
  w.i
  h.i
  nbW.i
  nbH.i
  offsetX.i
  offsetY.i
EndStructure

;------------------

Procedure DefineConstants()
  
  #resoW = 800
  #resoH = 800
  
  #mapSize = 1024
  #sectorSize = 64
  #zoomInc = 1
  #moveInc = 4
  
EndProcedure

Procedure DefineGlobals()
  
  Global i.i, mouse.i
  Global mmap.s_map, grid.s_grid
  
EndProcedure

Procedure DrawMouse()
  
  mouse = CreateSprite(#PB_Any, 2, 2)
  
  StartDrawing(SpriteOutput(mouse))
  Box(0, 0, OutputWidth(), OutputHeight(), #White)
  StopDrawing()
  
EndProcedure

Procedure DrawGrid()
  
  grid\w = CreateSprite(#PB_Any, #resoW, 1)
  grid\h = CreateSprite(#PB_Any, 1, #resoH)
  
  StartDrawing(SpriteOutput(grid\w))
  Box(0, 0, OutputWidth(), OutputHeight(), #White)
  StopDrawing()
  
  StartDrawing(SpriteOutput(grid\h))
  Box(0, 0, OutputWidth(), OutputHeight(), #White)
  StopDrawing()
  
EndProcedure

Procedure RecalculateGrid()
  
  ; clamp zoom
  If mmap\x + #resoW > (#mapSize / #sectorSize) * (#sectorSize + mmap\zoom)
    mmap\x = ((#mapSize / #sectorSize) * (#sectorSize + mmap\zoom)) - #resoW
  EndIf
  If mmap\y + #resoH > (#mapSize / #sectorSize) * (#sectorSize + mmap\zoom)
    mmap\y = ((#mapSize / #sectorSize) * (#sectorSize + mmap\zoom)) - #resoH
  EndIf
  
  ; grid positioning
  grid\nbW = (mmap\x + #resoW) / (#sectorSize + mmap\zoom)
  grid\nbH = (mmap\y + #resoH) / (#sectorSize + mmap\zoom)
  grid\offsetX = Mod(-mmap\x, #sectorSize + mmap\zoom)
  grid\offsetY = Mod(-mmap\y, #sectorSize + mmap\zoom)
  
EndProcedure

Procedure DisplayGrid()
  
  For i = 0 To grid\nbW
    DisplaySprite(grid\h, i * (#sectorSize + mmap\zoom) + grid\offsetX, 0)
  Next i
  
  For i = 0 To grid\nbH
    DisplaySprite(grid\w, 0, i * (#sectorSize + mmap\zoom) + grid\offsetY)
  Next i
  
EndProcedure

Procedure DisplayDebug()
  
  StartDrawing(ScreenOutput())
  DrawText(5, 5, "x: " + Str(mmap\x), #White)
  DrawText(5, 20, "y: " + Str(mmap\y), #White)
  DrawText(5, 35, "zoom: " + Str(mmap\zoom), #White)
  StopDrawing()
  
EndProcedure

Procedure ManageKeyboard()
  
  If KeyboardPushed(#PB_Key_Q)
    If mmap\x - #moveInc >= 0
      mmap\x - #moveInc
      RecalculateGrid()
    EndIf
  EndIf
  If KeyboardPushed(#PB_Key_D)
    If mmap\x + #moveInc + #resoW <= (#mapSize / #sectorSize) * (#sectorSize + mmap\zoom)
      mmap\x + #moveInc
      RecalculateGrid()
    EndIf
  EndIf
  If KeyboardPushed(#PB_Key_Z)
    If mmap\y - #moveInc >= 0
      mmap\y - #moveInc
      RecalculateGrid()
    EndIf
  EndIf
  If KeyboardPushed(#PB_Key_S)
    If mmap\y + #moveInc + #resoH <= (#mapSize / #sectorSize) * (#sectorSize + mmap\zoom)
      mmap\y + #moveInc
      RecalculateGrid()
    EndIf
  EndIf
  If KeyboardPushed(#PB_Key_A)
    If mmap\zoom - #zoomInc >= 0
      mmap\zoom - #zoomInc
      RecalculateGrid()
    EndIf
  EndIf
  If KeyboardPushed(#PB_Key_E)
    mmap\zoom + #zoomInc
    RecalculateGrid()
  EndIf
  
EndProcedure

Procedure ManageMouse()
  
  If MouseButton(#PB_MouseButton_Right) And MouseDeltaX() <> 0
    If mmap\x + MouseDeltaX() + #resoW <= (#mapSize / #sectorSize) * (#sectorSize + mmap\zoom) And mmap\x + MouseDeltaX() > 0
      mmap\x + MouseDeltaX()
      RecalculateGrid()
    EndIf
  EndIf
  
  If MouseButton(#PB_MouseButton_Right) And MouseDeltaY() <> 0
    If mmap\y + MouseDeltaY() + #resoH <= (#mapSize / #sectorSize) * (#sectorSize + mmap\zoom) And mmap\y + MouseDeltaY() > 0
      mmap\y + MouseDeltaY()
      RecalculateGrid()
    EndIf
  EndIf
  
  If MouseWheel() > 0
    mmap\zoom + #zoomInc
    RecalculateGrid()
  ElseIf MouseWheel() < 0
    If mmap\zoom - #zoomInc >= 0
      mmap\zoom - #zoomInc
      RecalculateGrid()
    EndIf
  EndIf    
  
EndProcedure

;------------------

DefineConstants() : DefineGlobals()
InitSprite() : InitKeyboard() : InitMouse()

OpenWindow(0, 0, 0, #resoW, #resoH, "", #PB_Window_BorderLess | #PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, #resoW, #resoH)
KeyboardMode(#PB_Keyboard_International)

DrawMouse()
DrawGrid() : RecalculateGrid()

Repeat
  
  While WindowEvent() : Wend
  
  ExamineMouse() : ManageMouse()
  
  ExamineKeyboard() : ManageKeyboard()
  
  ClearScreen(0)
  
  DisplayGrid()
  DisplayDebug() ; perf
  
  DisplaySprite(mouse, MouseX(), MouseY())
  
  FlipBuffers()
  
Until KeyboardPushed(#PB_Key_Escape)
Le but de ce code est d'afficher une grille sur une "carte" (qui dans ce cas-ci est très conceptuelle). Plutôt que de faire une vraie caméra, j'ai choisi de redessiner les lignes horizontales et verticales de la grille en fonction de la portion de carte affichée et du niveau de zoom.

A priori, le résultat n'est pas trop mal, mais mon problème concerne le zoom. J'aimerais qu'il soit effectué sur le curseur de la souris, et comme d'habitude avec les caméras et autres scrolling, c'est la partie à laquelle je pige rien !

Donc la question est : kommen-kon-fait ?
Avatar de l’utilisateur
Ar-S
Messages : 9478
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: Grille et zoom curseur

Message par Ar-S »

J'ai testé ton code et mon curseur se retrouve bloqué en bas à droite de la fenetre..
J'ai cherché en vain le soucis.. Du coup j'ai repris l'exemple de PB concernant openwindowsscreen que j'ai adapté pour le mouvement de souris.
Telle ne fut pas ma surprise de voir qu'il se passe le même phénomène en PB5.42

Pouvez vous me confirmer que ça foire ou est ce que ça fonction chez vous ?

Code : Tout sélectionner

If InitSprite() = 0 Or InitMouse() = 0
    MessageRequester("Erreur", "Impossible d'ouvrir l'écran & l'environnement nécessaire aux sprites !", 0)
    End
  EndIf
  
  If OpenWindow(0, 0, 0, 220, 160, "Un écran dans une fenêtre...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    ButtonGadget(0, 170, 135, 45, 20, "Quitter")

    If OpenWindowedScreen(WindowID(0), 0, 0, 160, 160)
      CreateSprite(0, 20, 20)
      If StartDrawing(SpriteOutput(0))
        Box(0, 0, 20, 20, RGB(255, 0, 155))
        Box(5, 5, 10, 10, RGB(155, 0, 255))
        StopDrawing()
      EndIf
    Else
      MessageRequester("Erreur", "Impossible d'ouvrir un écran dans la fenêtre!", 0)
      End
    EndIf
  EndIf
  
  direction = 2
  Repeat
    ; Il est très important de traiter tous les évènements restants dans la file d'attente à chaque tour
    ;
    Repeat
      Event = WindowEvent()
      
      Select Event 
        Case #PB_Event_Gadget
          If EventGadget() = 0
            End
          EndIf
        
        Case #PB_Event_CloseWindow
          End 
      EndSelect
    Until Event = 0
    
    ExamineMouse()
    FlipBuffers() 
    ClearScreen(RGB(0, 0, 0))
    
    MX = MouseX()
    MY = MouseY()
    
; Frontières de l'ecran
    If MX > 140 : MX = 140 : EndIf
    If MY > 140 : MY = 140 : EndIf
    If MX < 0 : MX = 0 : EndIf
    If MY < 0 : MY = 0 : EndIf  
      
    DisplaySprite(0, MX, MY)
    
      
    
    Delay(1)
  ForEver

~~~~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
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: Grille et zoom curseur

Message par blendman »

J'ai testé et ça fonctionne "normalement", en 5.31 aussi, la souris est bloquée dans l'écran, mais c'est normal, tu ne libères pas la souris, donc elle reste bloquée à l'intérieur de l'écran ;).
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: Grille et zoom curseur

Message par falsam »

Blendman a écrit :J'ai testé et ça fonctionne "normalement", en 5.31
Discretement dans le creux de l'oreille "La derniere version de PureBasic est la 5.42" :wink:
Configuration : Windows 11 Famille 64-bit - PB 6.03 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
Ar-S
Messages : 9478
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: Grille et zoom curseur

Message par Ar-S »

blendman a écrit :J'ai testé et ça fonctionne "normalement", en 5.31 aussi, la souris est bloquée dans l'écran, mais c'est normal, tu ne libères pas la souris, donc elle reste bloquée à l'intérieur de l'écran ;).
tu m'as mal lu, j'ai dit bloqué en bas à droite de la fenetre ;)
Par contre je viens de tester sur mon autre PC, ça fonctionne effectivement. Je ne comprends pas pourquoi sur mon portable (ASUS K501UX) ça ne marche pas (CG : geforce GT950M). C'est pourtant une souris de base.
Parfois PB a des réaction bizarre selon le hardware, c'est pénible.

@Joubarde.
Ta méthode donne en effet un jolie rendu mais tu devrais redessiner tes sprites en fonction de Mousex() etMouseY().
C'est probablement dans RecalculateGrid() qu'il y a une coquille.
Peut-être qu'un seul gros sprite grille serait plus facile à traiter. Tu pourrais le redéssiner en utilisant SetOrigin(x,y)
~~~~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
Joubarbe
Messages : 93
Inscription : sam. 01/juil./2006 16:40

Re: Grille et zoom curseur

Message par Joubarbe »

@Ar-S : je confirme, je n'ai aucun problème avec ton précédent code avec la version 5.42.

Non je veux éviter le "gros sprite grille". Déjà essayé, c'est peu élégant et ça amène des soucis.

J'ai essayé d'ajouter diverses formules pour zoomer sur le curseur ici :

Code : Tout sélectionner

If MouseWheel() > 0
  mmap\zoom + #zoomInc
  ; ici notamment, pour recalculer mmap\x et mmap\y en fonction du zoom actuel et de la position de la souris
  RecalculateGrid()
ElseIf MouseWheel() < 0
  If mmap\zoom - #zoomInc >= 0
    mmap\zoom - #zoomInc
    RecalculateGrid()
  EndIf
EndIf
... en vain.
Avatar de l’utilisateur
Micoute
Messages : 2522
Inscription : dim. 02/oct./2011 16:17
Localisation : 35520 La Mézière

Re: Grille et zoom curseur

Message par Micoute »

Pour moi, ça fonctionne merveilleusement bien.
Microsoft Windows 10 Famille 64 bits : Carte mère : ASRock 970 Extreme3 R2.0 : Carte Graphique NVIDIA GeForce RTX 3080 : Processeur AMD FX 6300 6 cœurs 12 threads 3,50 GHz PB 5.73 PB 6.00 LTS (x64)
Un homme doit être poli, mais il doit aussi être libre !
Avatar de l’utilisateur
Kwai chang caine
Messages : 6962
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: Grille et zoom curseur

Message par Kwai chang caine »

Le premier code marche bien sauf que le X et Y ne change que quelque fois de valeur
Le second le curseur de souris est coincé dans la fenetre
W7 et v5.40
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: Grille et zoom curseur

Message par blendman »

Je reformule : j'ai testé le code de Ar-s sur la 5.42 et la 5.31 et j'ai le même comportement ;).

Joubarbe : pour ton zoom sur le cursor, je pense que du doit utiliser un offset (ou centre) à tes sprites.
Je pense que tu devrais essayer la procedure de stargate pour faire une rotation en un centre, ça aide grandement :)

Code : Tout sélectionner

Procedure SpriteTransformation(Sprite.i, X.f, Y.f, W.f, H.f, Angle.f)
   Protected Cos.f = Cos(Radian(Angle))
   Protected Sin.f = Sin(Radian(Angle))
   TransformSprite(Sprite, X*Cos-Y*Sin, X*Sin+Y*Cos, (X+W)*Cos-Y*Sin, (X+W)*Sin+Y*Cos, (X+W)*Cos-(Y+H)*Sin, (X+W)*Sin+(Y+H)*Cos, X*Cos-(Y+H)*Sin, X*Sin+(Y+H)*Cos)
EndProcedure

X et Y c'est pour l'offset, logiquement, pour ta grille ça devrait être mouseX() et mouseY().
Joubarbe
Messages : 93
Inscription : sam. 01/juil./2006 16:40

Re: Grille et zoom curseur

Message par Joubarbe »

Bah je veux bien, mais je n'ai pas de sprites... Sinon les deux lignes qui servent à créer toute la grille.

Pour être plus clair, essayez de remplacer :

Code : Tout sélectionner

  If KeyboardPushed(#PB_Key_A)
    If mmap\zoom - #zoomInc >= 0
      mmap\zoom - #zoomInc
      RecalculateGrid()
    EndIf
  EndIf
  If KeyboardPushed(#PB_Key_E)
    mmap\zoom + #zoomInc
    RecalculateGrid()
  EndIf
par :

Code : Tout sélectionner

  If KeyboardPushed(#PB_Key_A)
    If mmap\zoom - #zoomInc >= 0
      mmap\zoom - #zoomInc
      mmap\x - #moveInc
      mmap\y - #moveInc
      RecalculateGrid()
    EndIf
  EndIf
  If KeyboardPushed(#PB_Key_E)
    mmap\zoom + #zoomInc
    mmap\x + #moveInc
    mmap\y + #moveInc
    RecalculateGrid()
  EndIf
Tout de suite ça paraît plus naturel. Quand x et y sont à zéro, ça zoome au centre de la grille. Sauf que je voudrais que ça zoome sur le curseur ; et il faut une formule magique pour ça :)
Répondre