Maybe use an additional tiling layer for the regions, similar to a tilemap. So the shapes are split up into tiles and you only draw the parts that are in screen.
I made a little test/demo. Moving the mouse to scroll, mouse buttons to zoom. Keys 1, 2, 3 for mode.
I used simple circles as regions.
Mode 1 draws all regions drectly to the screen in a single drawing block.
Mode 3 tiles the world up into equal sized areas (sprites) each containing only parts of the circles
If your world is very large that will create a lot of sprites though, even if each of them is smaller than the screen and only the visible one are actually displayed. Anyway, just zooming sprites may not be enough if you want very large scale/zoom ratios or even infinite zoom. You may need a completely different approach without buffers/sprites, only store abstract shapes (like beziers curves) and rasterize it to pixels as a last step by drawing directly to screen.
Code: Select all
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()
If MouseButton(1)
zoom + 0.01
ElseIf MouseButton(2)
zoom - 0.01
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 = zoom * i * #regionSize
y = zoom * 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)