PureBasic Forum
http://forums.purebasic.com/english/

Drawing an area on a Screen()
http://forums.purebasic.com/english/viewtopic.php?f=16&t=72914
Page 2 of 2

Author:  #NULL [ Mon Jun 03, 2019 12:54 pm ]
Post subject:  Re: Drawing an area on a Screen()

I just saw there is a bug in the initialized3 part
Code:
              x = zoom * i * #regionSize
              y = zoom * k * #regionSize

should be instead this, without zoom:
Code:
              x = i * #regionSize
              y = k * #regionSize
otherwise the region sprites are wrong when you change the zoom before using mode 3 for the first time.

Another remark:
The various TransformSrite()s need only be called when the zoom actually changes, not every frame like in my code.

Author:  #NULL [ Mon Jun 03, 2019 1:04 pm ]
Post subject:  Re: Drawing an area on a Screen()

Well, there was another bug, ww should be wh in the offsetY line.
Here is the complete code again:
Code:
EnableExplicit

InitSprite()
InitMouse()
InitKeyboard()

RandomSeed(1)

Define ww=800
Define wh=600
Define style
style | #PB_Window_ScreenCentered
style | #PB_Window_SystemMenu
style | #PB_Window_MinimizeGadget
Define win, event, em, quit
Define i, k

If 01
  win=OpenWindow(#PB_Any, 50,100, ww,wh, "", style)
  AddKeyboardShortcut(win, #PB_Shortcut_Escape, 10)
  OpenWindowedScreen(WindowID(win), 0,0, ww, wh)
  ;SetFrameRate(9999)
Else
  OpenScreen(ww,wh,32,"", #PB_Screen_NoSynchronization)
EndIf

#tileSize = 32
#tileMapSize = 100

#regionSize = 128
#regionMapSize = #tileMapSize * #tileSize / #regionSize

Define cursor = CreateSprite(#PB_Any, 10, 10, #PB_Sprite_AlphaBlending)
StartDrawing(SpriteOutput(cursor))
  DrawingMode(#PB_2DDrawing_AllChannels)
  Box(0, 0, 5, 5, $ffffffff)
StopDrawing()

Define tile = CreateSprite(#PB_Any, #tileSize, #tileSize, #PB_Sprite_AlphaBlending)
StartDrawing(SpriteOutput(tile))
  DrawingMode(#PB_2DDrawing_AllChannels)
  Box(1, 1, #tileSize-2, #tileSize-2, $ff886600)
StopDrawing()

Dim tileMap(#tileMapSize, #tileMapSize)
For k=0 To #tileMapSize
  For i=0 To #tileMapSize
    tileMap(k, i) = Random(1) * tile
  Next
Next

Dim regionMap(#regionMapSize, #regionMapSize)
For k=0 To #regionMapSize
  For i=0 To #regionMapSize
    regionMap(k, i) = CreateSprite(#PB_Any, #regionSize, #regionSize, #PB_Sprite_AlphaBlending)
  Next
Next

Define sprFR = CreateSprite(#PB_Any, 400,20)
Define FR, FRt, FR$

Define.f offsetX
Define.f offsetY
Define.f zoom.f = 1.0
Define mode = 1

Structure sRegion
  x.f
  y.f
  r.f
 
  ; only used by some modes
  spr.i
  sprW.i
  sprH.i
EndStructure

NewList region.sRegion()
For k=0 To #tileMapSize
  For i=0 To #tileMapSize
    If k%8=0 And i%8=0
      AddElement(region())
      region()\x = i * #tileSize - 20 + Random(40)
      region()\y = k * #tileSize - 20 + Random(40)
      region()\r = Random(#tileSize * 6)
    EndIf
  Next
Next

Define.f x
Define.f y
Define initialized2
Define initialized3
Define RegionMinX
Define RegionMaxX
Define RegionMinY
Define RegionMaxY


Repeat
  ExamineMouse()
  ExamineKeyboard()
 
  If KeyboardPushed(#PB_Key_1) : mode = 1 : EndIf
  If KeyboardPushed(#PB_Key_2) : mode = 2 : EndIf
  If KeyboardPushed(#PB_Key_3) : mode = 3 : EndIf
 
  ; events
  If IsWindow(win) ;{
    Repeat
      event = WindowEvent()
      em = EventMenu()
      Select event
        Case #PB_Event_CloseWindow
          quit = #True
        Case #PB_Event_Menu
          Select em
          Case 10
            quit = #True
          EndSelect
      EndSelect
    Until Not event
    ;}
  EndIf
 
  ; scroll/zoom
  offsetX + MouseDeltaX()
  offsetY + MouseDeltaY()
  Define.f zoomPrevious = zoom
  If MouseButton(1)
    zoom + 0.01
  ElseIf MouseButton(2)
    zoom - 0.01
  EndIf
  If zoom <> zoomPrevious
    offsetX - ((((offsetX + ww/2) / zoom) - ((offsetX + ww/2) / zoomPrevious)) * zoom)
    offsetY - ((((offsetY + wh/2) / zoom) - ((offsetY + wh/2) / zoomPrevious)) * zoom)
  EndIf
 
  TransformSprite(tile,
                  0, 0,
                  zoom * #tileSize, 0,
                  zoom * #tileSize, zoom * #tileSize,
                  0, zoom * #tileSize)
 
  ; draw tilemap
  For k=0 To #tileMapSize
    For i=0 To #tileMapSize
      x = zoom * i * #tileSize - offsetX
      y = zoom * k * #tileSize - offsetY
      If tileMap(k, i)
        If (x >= zoom*-#tileSize) And (x <= ww) And (y >= zoom*-#tileSize) And (y <= wh)
          DisplayTransparentSprite(tileMap(k, i), x, y)
        EndIf
      EndIf       
    Next
  Next
 
  Select mode
     
    Case 1
      ; draw all regions directly
     
      StartDrawing(ScreenOutput())
      ForEach region()
        DrawingMode(#PB_2DDrawing_Outlined)
        Circle(zoom * region()\x - offsetX,
               zoom * region()\y - offsetY,
               zoom * region()\r,
               $ffffbbbb)
      Next
      StopDrawing()
     
    Case 2
      ; use sprite per region
     
      If Not initialized2
        initialized2 = #True
        ; create sprite for each region
        ForEach region()
          region()\sprW = 2 * region()\r + 1
          region()\sprH = 2 * region()\r + 1
          region()\spr = CreateSprite(#PB_Any, region()\sprW, region()\sprH, #PB_Sprite_AlphaBlending)
          StartDrawing(SpriteOutput(region()\spr))
          DrawingMode(#PB_2DDrawing_Outlined | #PB_2DDrawing_AllChannels)
          Box(0, 0, OutputWidth(), OutputHeight(), $aa00aa00)
          Circle(region()\r,
                 region()\r,
                 region()\r,
                 $ffffbbbb)
          StopDrawing()
        Next
      EndIf
     
      ; display each region sprite
      ForEach region()
        TransformSprite(region()\spr,
                        0, 0,
                        zoom * region()\sprW, 0,
                        zoom * region()\sprW, zoom * region()\sprH,
                        0, zoom * region()\sprH)
        DisplayTransparentSprite(region()\spr,
                                 zoom*(region()\x - region()\sprW/2) - offsetX,
                                 zoom*(region()\y - region()\sprH/2) - offsetY)
      Next
     
    Case 3
      ; use regionmap
     
      If Not initialized3
        initialized3 = #True
        ; create regionmap
        For k=0 To #regionMapSize
          For i=0 To #regionMapSize
            If regionMap(k, i)
              x = i * #regionSize
              y = k * #regionSize
              StartDrawing(SpriteOutput(regionMap(k, i)))
              DrawingMode(#PB_2DDrawing_Outlined | #PB_2DDrawing_AllChannels)
              Box(0, 0, OutputWidth(), OutputHeight(), $aa00aa00)
              ForEach region()
                RegionMinX = region()\x - region()\r - 1
                RegionMaxX = region()\x + region()\r + 1
                RegionMinY = region()\y - region()\r - 1
                RegionMaxY = region()\y + region()\r + 1
                ; draw region if in current regionmap area
                If (x <= RegionMaxX) And ((x+#regionSize) >= RegionMinX) And (y <= RegionMaxY) And ((y+#regionSize) >= RegionMinY)
                  Circle(region()\x - x,
                         region()\y - y,
                         region()\r,
                         $ffffbbbb)
                EndIf
              Next
              StopDrawing()
            EndIf
          Next
        Next
      EndIf
     
      ; display each regionmap area sprite
      For k=0 To #regionMapSize
        For i=0 To #regionMapSize
          If regionMap(k, i)
            x.f = zoom * i * #regionSize - offsetX
            y.f = zoom * k * #regionSize - offsetY
            If (x >= zoom*-#regionSize) And (x <= ww) And (y >= zoom*-#regionSize) And (y <= wh)
             
              TransformSprite(regionMap(k, i),
                              0, 0,
                              zoom * #regionSize, 0,
                              zoom * #regionSize, zoom * #regionSize,
                              0, zoom * #regionSize)
             
              DisplayTransparentSprite(regionMap(k, i), x, y)
            EndIf
          EndIf
        Next
      Next
     
  EndSelect
 
  ; display cursor
  DisplayTransparentSprite(cursor, MouseX(), MouseY())
 
  ; update fps/info sprite
  FR+1
  If ElapsedMilliseconds()>FRt
    FRt=ElapsedMilliseconds()+500
    FR$=Str(FR*2)
    FR=0
    StartDrawing(SpriteOutput(sprFR))
      DrawingMode(#PB_2DDrawing_Transparent)
      Box(0,0, OutputWidth(), OutputHeight(), $ff0000)
      DrawText(0,0, "fps:" + FR$ + " mode:" + mode)
    StopDrawing()
  EndIf
 
  ; display fps/info
  DisplaySprite(sprFR, 0,0)
 
  FlipBuffers()
  ClearScreen($333333)
  If IsWindow(win)
    ;Delay(10)
  EndIf
Until quit Or KeyboardPushed(#PB_Key_Escape)

Author:  Joubarbe [ Mon Jun 03, 2019 2:15 pm ]
Post subject:  Re: Drawing an area on a Screen()

Thanks!

Page 2 of 2 All times are UTC + 1 hour
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/