Page 1 of 2

Maths problem with basic camera

Posted: Wed Feb 26, 2025 4:58 pm
by Joubarbe
I'm trying to reproduce an ATC screen, with squares representing planes. The squares don't rotate, instead they have what I would call a "heading line" that shows where they're heading. This line should be in the middle of the square, which works fine... until I implement the zoom of the camera.

Code: Select all

EnableExplicit

; @doc This demonstrates: delta time, position to destination move, course line and basic camera (bit buggy).

Structure _SpriteStore
  ship.i
  heading_line.i
EndStructure

Structure _XY
  x.d
  y.d
EndStructure

Structure _Object
  position._XY
  destination._XY
  speed.d
  angle.d ; Of the direction.
EndStructure

Structure _Camera
  position._XY
  zoom.d
EndStructure

#_BGR_BACKGROUND = $140502
#_BGR_OBJECTS = $5AE662
#_ABGR_BACKGROUND = $FF140502
#_ABGR_OBJECTS = $FF5AE662

#_SHIP_WIDTH = 10  ; Should be a property in _SpriteStore (original_width).
#_SHIP_HEIGHT = 10
#_HEADING_LINE_WIDTH = 20
#_HEADING_LINE_HEIGHT = 1

#_NB_SHIPS = 50

Global sprite_store._SpriteStore
Global camera._Camera

Global NewList ships._Object()

Procedure RandomNeg(max, min)
  If max < 0 : DebuggerError("RandomNeg(): max cannot be negative.") : EndIf
  Define rng = Random(max + Abs(min))
  ProcedureReturn rng - Abs(min)
EndProcedure

Procedure InitObjects()
  Define cx, cy, vx, vy
  
  Define i : For i = 1 To #_NB_SHIPS
    AddElement(ships())
    ships()\position\x = Random(ScreenWidth()) : ships()\position\y = Random(ScreenHeight())
    ships()\destination\x = Random(ScreenWidth()) : ships()\destination\y = Random(ScreenHeight())
    ships()\speed = 10.0
    ships()\angle = ATan2(ships()\destination\x - ships()\position\x, ships()\destination\y - ships()\position\y)
  Next i
EndProcedure

Procedure DrawSprites() : With sprite_store
  \ship = CreateSprite(#PB_Any, 10, 10, #PB_Sprite_AlphaBlending)
  StartDrawing(SpriteOutput(\ship))
  DrawingMode(#PB_2DDrawing_Outlined | #PB_2DDrawing_AlphaBlend)
  Box(0, 0, OutputWidth(), OutputHeight())
  StopDrawing()
  
  \heading_line = CreateSprite(#PB_Any, #_HEADING_LINE_WIDTH, #_HEADING_LINE_HEIGHT, #PB_Sprite_AlphaBlending)
  StartDrawing(SpriteOutput(\heading_line))
  DrawingMode(#PB_2DDrawing_AlphaBlend)
  Box(0, 0, OutputWidth(), OutputHeight())
  StopDrawing()
EndWith : EndProcedure

;- CAMERA

Procedure InitCamera()
  camera\zoom = 1.0
EndProcedure

Procedure.i GetWorldToScreenX(x)
  ProcedureReturn x - camera\position\x + camera\zoom * (x - camera\position\x - ScreenWidth() / 2)
EndProcedure

Procedure.i GetWorldToScreenY(y)
  ProcedureReturn y - camera\position\y + camera\zoom * (y - camera\position\y - ScreenHeight() / 2)
EndProcedure

Procedure SetCameraPosition(x, y)
  camera\position\x = x
  camera\position\y = y
EndProcedure

Procedure MoveCameraPosition(x, y)
  camera\position\x + x
  camera\position\y + y
EndProcedure

Procedure SetCameraZoom(zoom.d)
  camera\zoom = zoom
EndProcedure

Procedure ZoomCamera(zoom.d)
  camera\zoom + zoom
EndProcedure

;- CORE

Procedure Init()
  InitSprite()
  OpenWindow(0, 0, 0, 0, 0, "", #PB_Window_BorderLess | #PB_Window_Maximize)
  OpenWindowedScreen(WindowID(0), 0, 0, WindowWidth(0), WindowHeight(0), #False, 0, 0, #PB_Screen_SmartSynchronization)
  InitKeyboard() : KeyboardMode(#PB_Keyboard_International)
EndProcedure

Procedure UpdateInput() ; Delta time?
  ExamineKeyboard()
  If KeyboardPushed(#PB_Key_A)
    MoveCameraPosition(-10, 0)
  EndIf
  If KeyboardPushed(#PB_Key_D)
    MoveCameraPosition(10, 0)
  EndIf
  If KeyboardPushed(#PB_Key_W)
    MoveCameraPosition(0, -10)
  EndIf
  If KeyboardPushed(#PB_Key_S)
    MoveCameraPosition(0, 10)
  EndIf
  If KeyboardPushed(#PB_Key_Add)
    ZoomCamera(0.1)
  EndIf
  If KeyboardPushed(#PB_Key_Subtract)
    ZoomCamera(-0.1)
  EndIf
  If KeyboardPushed(#PB_Key_Escape)
    End
  EndIf
EndProcedure

Procedure Update(delta.d) : With ships()
  UpdateInput()
  
  ForEach ships()
    If \position\x = \destination\x And \position\y = \destination\y : Continue : EndIf
    If Pow(\destination\x - \position\x, 2) + Pow(\destination\y - \position\y, 2) < 1.0
      \position\x = \destination\x
      \position\y = \destination\y
    Else
      \position\x + \speed * Cos(\angle) * delta
      \position\y + \speed * Sin(\angle) * delta
    EndIf
  Next
EndWith : EndProcedure

Procedure Render(delta.d)
  Define cx, cy, vx, vy, px, py
  
  ForEach ships()
    ZoomSprite(sprite_store\ship, #_SHIP_WIDTH * camera\zoom, #_SHIP_HEIGHT * camera\zoom)
    DisplayTransparentSprite(sprite_store\ship, GetWorldToScreenX(ships()\position\x), GetWorldToScreenY(ships()\position\y), 255, #_BGR_OBJECTS)
    
    ; Heading line (ship course).
    cx = ships()\position\x + SpriteWidth(sprite_store\ship) / 2
    cy = ships()\position\y + SpriteHeight(sprite_store\ship) / 2
    vx = SpriteWidth(sprite_store\heading_line) / 2
    vy = SpriteHeight(sprite_store\heading_line) / 2
    px = cx - vx + (Cos(ships()\angle) * vx)
    py = cy - vy + (Sin(ships()\angle) * vx)
    ZoomSprite(sprite_store\heading_line, #_HEADING_LINE_WIDTH * camera\zoom, #_HEADING_LINE_HEIGHT * camera\zoom)
    RotateSprite(sprite_store\heading_line, Degree(ships()\angle), #PB_Absolute)
    DisplayTransparentSprite(sprite_store\heading_line, GetWorldToScreenX(px), GetWorldToScreenY(py), 255, #_BGR_OBJECTS)
  Next
EndProcedure

Procedure.d GetDeltaTime()
  Static frame_time
  
  Define delta_time.d = ElapsedMilliseconds() - frame_time
  frame_time = ElapsedMilliseconds()
  
  ProcedureReturn delta_time / 1000 ; Number of seconds since the last frame.
EndProcedure

Procedure MainLoop()
  Define event
  Define delta_time.d
  
  Repeat
    Repeat
      event = WindowEvent()
      If event = #PB_Event_CloseWindow : End : EndIf
    Until event = #Null
    
    FlipBuffers()
    ClearScreen(#_BGR_BACKGROUND)
    
    delta_time = GetDeltaTime()
    
    Update(delta_time)
    Render(delta_time)
    
    Delay(1)
  ForEver
  
EndProcedure

Init()
InitObjects()
DrawSprites()
InitCamera()

MainLoop()
Use WASD to move, and +- to zoom. Be gentle on the zoom, there's no limit and it's very sensitive! :)

What am I doing wrong?

Re: Camera basic

Posted: Wed Feb 26, 2025 9:55 pm
by miso
Nice. If you want camerazoom and rotation with sprites, you might consider transformsprite instead of zoomsprite+rotatesprite.

Re: Maths problem with basic camera

Posted: Sat Mar 01, 2025 8:01 am
by Joubarbe
Yeah, I never understood how TransformSprite() works :D How would you do in my case? In order to merge Rotate and Zoom in Render()?

Re: Maths problem with basic camera

Posted: Sun Mar 02, 2025 12:58 pm
by miso
I made a prototype following your footsteps. It's not a showcase, but a prototype, so the code is crowdy and might be dumb.
I stopped fiddling with it, so I put here the current result.

Code: Select all

;2D ZOOM PROTOTYPE, NO MATRICES
;MIGHT CONTAIN DUMB SOLUTIONS BY MISO
;OPTIMIZED TO 16:9 60 FPS VSYNC REFRESH RATE
;MADE WITH PB 620 WINDOWS7 64 BIT WITH NO OS SPEC CODE
EnableExplicit
;-MODULES FILES 
DeclareModule petskii
  Declare init()
  Declare textout(x,y,text.s,color.i)
  Declare textoutlined(x,y,text.s,color.i,outlinecolor.i)
  Declare destroy()
EndDeclareModule

Module petskii
;-HIDDEN VARIABLES/CONSTANTS  
  #USED_CHARACTERS="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()-_=+[{]};:',<.>/?"+Chr(34)
  Global Dim petskiifont(370):Global Dim fontimport.i(370)
;-SUB PROCEDURES
  Procedure sub_loadfont()
    Protected x.i,i.i,j.i,sprline.a
    For i = 1 To Len(#USED_CHARACTERS):fontImport(Asc(Mid(#USED_CHARACTERS,i,1)))=1 : Next i 
    Restore petskii_font
      For x= 1 To 370
        If fontimport(x)=1
          petskiifont(x)=CreateSprite(-1,8,12,#PB_Sprite_AlphaBlending)
          StartDrawing(SpriteOutput(petskiifont(x)))
          DrawingMode(#PB_2DDrawing_AllChannels)
          For j=0 To 11  
            Read.a sprline 
            For i=0 To 7
              If sprline&%1 :Plot(i,j,RGBA(255,255,255,255)): Else : Plot(i,j,RGBA(0,0,0,0)) : EndIf
              sprline>>1 
            Next i
          Next j
          StopDrawing()
          ZoomSprite(petskiifont(x),16,24)
        EndIf
      Next x
  EndProcedure
  
  ;-PUBLIC PROCEDURES  
  Procedure init()
    sub_loadfont()
  EndProcedure
  
  Procedure textout(x,y,text.s,color.i) : Protected.i textlength,i,character
    textlength.i = Len(text.s)
    For i = 1 To textlength.i
      character.i = Asc(Mid(text.s,i,1))
      If IsSprite(petskiifont(character))
        DisplayTransparentSprite(petskiifont(character),(x+((i-1) * 16)),(y),255,color.i)
      EndIf
    Next i
  EndProcedure
  
  Procedure textoutlined(x,y,text.s,color.i,outlinecolor.i)
    textout(x-2,y,text.s,outlinecolor)
    textout(x+2,y,text.s,outlinecolor)
    textout(x,y-2,text.s,outlinecolor)
    textout(x,y+2,text.s,outlinecolor)
    textout(x,y,text.s,color)
  EndProcedure
  
  
  Procedure destroy()
    Protected i.i
    For i = 1 To Len(#USED_CHARACTERS)
      If IsSprite(petskiifont(i)) : FreeSprite(petskiifont(i)) : EndIf
    Next i
  EndProcedure
  
  ;-MODULE DATA
  DataSection
  petskii_font:
  Data.a $00,$00,$38,$38,$38,$38,$38,$38,$00,$38,$00,$00,$00,$00,$EE,$EE,$EE,$00,$00,$00,$00,$00,$00,$00,$00,$00,$EE,$EE,$EE,$FF,$EE,$FF,$EE,$EE,$00,$00,$00,$00,$38,$38,$FC,$0E,$7C,$E0,$7E,$38,$00,$00
  Data.a $00,$00,$CE,$CE,$EE,$70,$38,$1C,$EE,$E6,$00,$00,$00,$00,$7C,$7C,$EE,$7C,$3C,$EE,$EE,$FC,$00,$00,$00,$00,$E0,$E0,$70,$38,$00,$00,$00,$00,$00,$00,$00,$00,$70,$70,$38,$1C,$1C,$1C,$38,$70,$00,$00
  Data.a $00,$00,$1C,$1C,$38,$70,$70,$70,$38,$1C,$00,$00,$00,$00,$00,$00,$EE,$7C,$FF,$7C,$EE,$00,$00,$00,$00,$00,$00,$00,$38,$38,$FE,$38,$38,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$38,$38,$1C,$00
  Data.a $00,$00,$00,$00,$00,$00,$FE,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$38,$38,$00,$00,$00,$00,$00,$00,$C0,$E0,$70,$38,$1C,$0E,$00,$00,$00,$00,$7C,$7C,$EE,$FE,$FE,$EE,$EE,$7C,$00,$00
  Data.a $00,$00,$38,$38,$38,$3C,$38,$38,$38,$FE,$00,$00,$00,$00,$7C,$7C,$EE,$E0,$70,$1C,$0E,$FE,$00,$00,$00,$00,$7C,$7C,$EE,$E0,$78,$E0,$EE,$7C,$00,$00,$00,$00,$E0,$E0,$F0,$F8,$EE,$FE,$E0,$E0,$00,$00
  Data.a $00,$00,$FE,$FE,$0E,$7E,$E0,$E0,$EE,$7C,$00,$00,$00,$00,$7C,$7C,$EE,$0E,$7E,$EE,$EE,$7C,$00,$00,$00,$00,$FE,$FE,$EE,$70,$38,$38,$38,$38,$00,$00,$00,$00,$7C,$7C,$EE,$EE,$7C,$EE,$EE,$7C,$00,$00
  Data.a $00,$00,$7C,$7C,$EE,$EE,$FC,$E0,$EE,$7C,$00,$00,$00,$00,$38,$38,$38,$00,$00,$00,$38,$38,$00,$00,$00,$00,$38,$38,$38,$00,$00,$00,$38,$38,$1C,$00,$00,$00,$F0,$F0,$38,$1C,$0E,$1C,$38,$F0,$00,$00
  Data.a $00,$00,$00,$00,$00,$FE,$00,$FE,$00,$00,$00,$00,$00,$00,$1E,$1E,$38,$70,$E0,$70,$38,$1E,$00,$00,$00,$00,$7C,$7C,$EE,$E0,$70,$38,$00,$38,$00,$00,$00,$00,$7C,$7C,$EE,$FE,$FE,$0E,$CE,$7C,$00,$00
  Data.a $00,$00,$38,$38,$7C,$EE,$FE,$EE,$EE,$EE,$00,$00,$00,$00,$7E,$7E,$EE,$EE,$7E,$EE,$EE,$7E,$00,$00,$00,$00,$7C,$7C,$EE,$0E,$0E,$0E,$EE,$7C,$00,$00,$00,$00,$3E,$3E,$7E,$EE,$EE,$EE,$7E,$3E,$00,$00
  Data.a $00,$00,$FE,$FE,$0E,$0E,$3E,$0E,$0E,$FE,$00,$00,$00,$00,$FE,$FE,$0E,$0E,$3E,$0E,$0E,$0E,$00,$00,$00,$00,$7C,$7C,$EE,$0E,$FE,$EE,$EE,$7C,$00,$00,$00,$00,$EE,$EE,$EE,$EE,$FE,$EE,$EE,$EE,$00,$00
  Data.a $00,$00,$7C,$7C,$38,$38,$38,$38,$38,$7C,$00,$00,$00,$00,$F8,$F8,$70,$70,$70,$70,$7E,$3C,$00,$00,$00,$00,$EE,$EE,$7E,$3E,$1E,$3E,$7E,$EE,$00,$00,$00,$00,$0E,$0E,$0E,$0E,$0E,$0E,$0E,$FE,$00,$00
  Data.a $00,$00,$CE,$CE,$FE,$FE,$FE,$CE,$CE,$CE,$00,$00,$00,$00,$EE,$EE,$FE,$FE,$FE,$FE,$EE,$EE,$00,$00,$00,$00,$7C,$7C,$EE,$EE,$EE,$EE,$EE,$7C,$00,$00,$00,$00,$7E,$7E,$EE,$EE,$7E,$0E,$0E,$0E,$00,$00
  Data.a $00,$00,$7C,$7C,$EE,$EE,$EE,$EE,$7C,$F0,$00,$00,$00,$00,$7E,$7E,$EE,$EE,$7E,$3E,$7E,$EE,$00,$00,$00,$00,$7C,$7C,$EE,$0E,$7C,$E0,$EE,$7C,$00,$00,$00,$00,$FE,$FE,$38,$38,$38,$38,$38,$38,$00,$00
  Data.a $00,$00,$EE,$EE,$EE,$EE,$EE,$EE,$EE,$7C,$00,$00,$00,$00,$EE,$EE,$EE,$EE,$EE,$EE,$7C,$38,$00,$00,$00,$00,$CE,$CE,$CE,$CE,$FE,$FE,$FE,$CE,$00,$00,$00,$00,$EE,$EE,$EE,$7C,$38,$7C,$EE,$EE,$00,$00
  Data.a $00,$00,$EE,$EE,$EE,$EE,$7C,$38,$38,$38,$00,$00,$00,$00,$FE,$FE,$E0,$70,$38,$1C,$0E,$FE,$00,$00,$00,$00,$7C,$7C,$1C,$1C,$1C,$1C,$1C,$7C,$00,$00,$00,$00,$7C,$7C,$70,$70,$70,$70,$70,$7C,$00,$00
  Data.a $00,$00,$38,$38,$7C,$FE,$38,$38,$38,$38,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$00,$00,$00,$00,$00,$00,$00,$7C,$E0,$FC,$EE,$FC,$00,$00,$00,$00,$00,$00,$0E,$0E,$7E,$EE,$EE,$7E,$00,$00
  Data.a $00,$00,$00,$00,$00,$7C,$0E,$0E,$0E,$7C,$00,$00,$00,$00,$00,$00,$E0,$E0,$FC,$EE,$EE,$FC,$00,$00,$00,$00,$00,$00,$00,$7C,$EE,$FE,$0E,$7C,$00,$00,$00,$00,$00,$00,$F0,$38,$FC,$38,$38,$38,$00,$00
  Data.a $00,$00,$00,$00,$00,$FC,$EE,$EE,$FC,$E0,$7E,$00,$00,$00,$0E,$0E,$0E,$7E,$EE,$EE,$EE,$EE,$00,$00,$00,$00,$38,$38,$00,$3C,$38,$38,$38,$7C,$00,$00,$00,$00,$00,$00,$70,$00,$70,$70,$70,$70,$3C,$00
  Data.a $00,$00,$0E,$0E,$0E,$0E,$7E,$3E,$7E,$EE,$00,$00,$00,$00,$3C,$3C,$38,$38,$38,$38,$38,$7C,$00,$00,$00,$00,$00,$00,$00,$EE,$FE,$FE,$FE,$CE,$00,$00,$00,$00,$00,$00,$00,$7E,$EE,$EE,$EE,$EE,$00,$00
  Data.a $00,$00,$00,$00,$00,$7C,$EE,$EE,$EE,$7C,$00,$00,$00,$00,$00,$00,$00,$7E,$EE,$EE,$7E,$0E,$0E,$00,$00,$00,$00,$00,$00,$FC,$EE,$EE,$FC,$E0,$E0,$00,$00,$00,$00,$00,$00,$7E,$EE,$0E,$0E,$0E,$00,$00
  Data.a $00,$00,$00,$00,$00,$FC,$0E,$7C,$E0,$7E,$00,$00,$00,$00,$00,$00,$38,$FE,$38,$38,$38,$F0,$00,$00,$00,$00,$00,$00,$00,$EE,$EE,$EE,$EE,$FC,$00,$00,$00,$00,$00,$00,$00,$EE,$EE,$EE,$7C,$38,$00,$00
  Data.a $00,$00,$00,$00,$00,$CE,$FE,$FE,$FC,$FC,$00,$00,$00,$00,$00,$00,$00,$EE,$7C,$38,$7C,$EE,$00,$00,$00,$00,$00,$00,$00,$EE,$EE,$EE,$FC,$70,$3E,$00,$00,$00,$00,$00,$00,$FE,$70,$38,$1C,$FE,$00,$00
  Data.a $00,$00,$F0,$F0,$38,$38,$1E,$38,$38,$F0,$00,$00,$00,$00,$1E,$1E,$38,$38,$F0,$38,$38,$1E,$00,$00
  EndDataSection
EndModule

DeclareModule stripes
  Global spr_id.i
  Global columns.i
  Declare create(size.i)
  Declare draw(animationsteps.f)  
EndDeclareModule

Module stripes
  Procedure.i Create(size.i)
    Protected img_stripe.i
    img_stripe=CreateImage(#PB_Any,size,size,24,RGBA(1,1,1,255))
    StartVectorDrawing(ImageVectorOutput(img_stripe))
      MovePathCursor(0,size) : AddPathLine(size/2,0) : AddPathLine(size,0) : AddPathLine(size/2,size) : ClosePath()
      VectorSourceColor(RGBA(255,128,0,255)) : FillPath()
    StopVectorDrawing()
    stripes::spr_id=CreateSprite(#PB_Any,size,size)
    StartDrawing(SpriteOutput(stripes::spr_id)) : DrawImage(ImageID(img_stripe),0,0) : StopDrawing()
    FreeImage(img_stripe)
    columns.i = ScreenWidth()/SpriteWidth(stripes::spr_id)
    If IsSprite(stripes::spr_id) :ProcedureReturn #True : EndIf
    ProcedureReturn #False  
  EndProcedure
  
  Procedure.i draw(animationstep.f)
    Protected i.i
    Static offset.f =0
    For i=-1 To columns+1
      DisplaySprite(stripes::spr_id,i*SpriteWidth(stripes::spr_id)+offset,0)
      DisplaySprite(stripes::spr_id,i*SpriteWidth(stripes::spr_id)-offset,ScreenHeight()-SpriteHeight(stripes::spr_id))
    Next i
    offset.f + animationstep.f
    If offset>SpriteWidth(stripes::spr_id) : offset -SpriteWidth(stripes::spr_id) : EndIf
  EndProcedure  
EndModule

;-MAINPROGRAM FILE START HERE

;-CONSTANTS
#MAINDESKTOP_H = 0
#WINDOW_H = 0
#WINDOW_WIDTH = 1366
#WINDOW_HEIGHT = 768
#WINDOW_FLAGS  = #PB_Window_Invisible|#PB_Window_BorderLess|#PB_Window_ScreenCentered

#MAINLOOP_DELAY = 1
#COMPILER_MINIMUM_VERSION = 620

#ship_count = 250
#SPRSIZE = 10

#STRIPESIZE = 32
#STRIPESPEED = 2

#LEFTBORDER = -500
#RIGHTBORDER = 1600
#BOTTOMBORDER =-500
#TOPBORDER = 800

#off = -45
#off2 = -225
#ROTATION_SPEED = 0.5
#MOUSEWHEEL_SENSITIVY = 0.05

#MINZOOM = 0.25
#MAXZOOM = 10
#MAX_INTENSITY = 255

;-TYPES
Structure cameratype
  x.f
  y.f
  tx.f
  ty.f
  angle.f
  zoom.f
  tzoom.f
EndStructure

Structure spritetype
  spid.i
  basesize.f
  hb.f
  x.f
  y.f
  destx.f
  desty.f
  angle.f
  tangle.f
  color.i
EndStructure

;-GLOBALS
Global.i airship_sprite_id , arrowsprite_ID
Global camera.cameratype
Global Dim sprs.spritetype(#ship_count)

;-AUXILIARY PROCEDURES
Procedure sub_checks()
  If Int(#PB_Compiler_Version) < #COMPILER_MINIMUM_VERSION
    Debug "Please compile with the currently newest beta 6.20."
    Debug "Earlier versions will display things incorrectly"
    Debug "because of missing fixes that occoured in 6.20"
    ;End
  EndIf
  
  If Not #PB_Compiler_DPIAware
    Debug "DPI aware must be enabled for compile"
    ;End
  EndIf
EndProcedure

Procedure sub_createsprite()
  airship_sprite_id.i=CreateSprite(#PB_Any,#SPRSIZE,#SPRSIZE,#PB_Sprite_AlphaBlending)
  StartDrawing(SpriteOutput(airship_sprite_id.i))
  DrawingMode(#PB_2DDrawing_Outlined|#PB_2DDrawing_AllChannels)
  Box(0,0,OutputWidth(),OutputHeight())
  StopDrawing()
  
  arrowsprite_ID.i=CreateSprite(#PB_Any,#SPRSIZE,#SPRSIZE,#PB_Sprite_AlphaBlending)
  StartDrawing(SpriteOutput(arrowsprite_ID.i))
  DrawingMode(#PB_2DDrawing_Outlined|#PB_2DDrawing_AllChannels)
  Box(#SPRSIZE/2,0,1,#SPRSIZE)
  Plot(#SPRSIZE/2-1,1):Plot(#SPRSIZE/2+1,1)
  StopDrawing()
EndProcedure

Procedure sub_camerasetup()
  With camera
    \x=ScreenWidth()/4
    \y=ScreenHeight()/4
    \tx=ScreenWidth()/4
    \ty=ScreenHeight()/4
    \angle = 0
    \zoom = 1.0
    \tzoom = 2.0
  EndWith
EndProcedure

Procedure sub_airship_setup()
  Protected x.i
  For x = 0 To #ship_count
    With sprs(x)
      \spid = airship_sprite_id
      \x = Random(100)*15
      \y = Random(50)*15
      \destx = \x
      \desty = \y
      ;\tangle = Degree(ATan2(\destx-\x,\desty-\y))
      \tangle = Random(359)
      \angle = \tangle
      \basesize = 10.0
      \hb = \basesize/2.0
      \color.i = RGBA(128+Random(127),Random(255),Random(255),255)
    EndWith
  Next x
EndProcedure

Procedure sub_draw_UI()
    stripes::draw(#STRIPESPEED)
    petskii::textoutlined(0,2,"mouse = Scroll",RGBA(255,0,0,255),RGBA(5,5,5,5))
    petskii::textoutlined(350,2,"mwheel = zoom",RGBA(0,255,0,255),RGBA(5,5,5,255))
    petskii::textoutlined(700,2,"mousebutton left+right = rotate direction",RGBA(255,255,55,255),RGBA(5,5,5,255))
    petskii::textoutlined(450,741,"mousebutton middle = move",RGBA(255,255,255,255),RGBA(5,5,5,255))
    petskii::textoutlined(1150,741,"Escape = Quit",RGBA(255,55,55,255),RGBA(5,5,5,255))
    petskii::textoutlined(0,38,"Zoom level = ",RGBA(5,5,5,255),RGBA(255,5,5,255))
    petskii::textoutlined(210,38,StrF(camera\zoom,0),RGBA(5,5,5,255),RGBA(255,255,125,255))
    petskii::textoutlined(0,60,"Camera     = ",RGBA(5,5,5,255),RGBA(50,50,255,255))
    petskii::textoutlined(210,60,"("+StrF(camera\x,0)+" , "+ StrF(camera\y,0)+")",RGBA(55,55,200,255),RGBA(150,150,255,255))
    petskii::textoutlined(0,741,FormatDate("%hh:%ii:%ss",Date()),RGBA(255,255,55,255),RGBA(5,5,5,255))
EndProcedure

;-PROCEDURES
Procedure app_start()
  sub_checks()
  ExamineDesktops()
  InitMouse()
  InitSprite()
  InitKeyboard()
  OpenWindow(#WINDOW_H,0,0,#WINDOW_WIDTH,#WINDOW_HEIGHT,"Login screen",#WINDOW_FLAGS)
  OpenWindowedScreen(WindowID(#WINDOW_H),0,0,#WINDOW_WIDTH,#WINDOW_HEIGHT,1,0,0,#PB_Screen_WaitSynchronization)
  ResizeWindow(#WINDOW_H,0,0,DesktopUnscaledX(DesktopWidth(#MAINDESKTOP_H)),DesktopUnscaledY(DesktopHeight(#MAINDESKTOP_H)))
  HideWindow(#WINDOW_H,#False)
  petskii::init()
  sub_createsprite()
  stripes::Create(#STRIPESIZE)
  sub_camerasetup()
  sub_airship_setup()
EndProcedure

Procedure app_update()
  Protected x.i, multiplier.i
  Protected ddist.f = camera\zoom*8
  Protected dx.f, dy.f, trx.f,try.f, tmod.f
  Delay(#MAINLOOP_DELAY)
  Repeat : Until Not WindowEvent()
  ClearScreen(0)
  ExamineKeyboard()
  ExamineMouse()
  
  If MouseButton(#PB_MouseButton_Left)
    For x = 0 To #ship_count
      sprs(x)\tangle - #ROTATION_SPEED
    Next x
  EndIf
  
  If MouseButton(#PB_MouseButton_Right)
    For x = 0 To #ship_count
      sprs(x)\tangle + #ROTATION_SPEED
    Next x
  EndIf
  
  multiplier.i = (2*camera\zoom)
  If multiplier<1 : multiplier = 1 : EndIf  :  If multiplier>20 : multiplier = 20 : EndIf
  
  camera\tx + (MouseDeltaX()/(multiplier*2))
  camera\ty + (MouseDeltaY()/(multiplier*2))
  
  If camera\tx<#LEFTBORDER : camera\tx=#LEFTBORDER : EndIf
  If camera\tx>#RIGHTBORDER : camera\tx=#RIGHTBORDER : EndIf
  If camera\ty<#BOTTOMBORDER : camera\ty=#BOTTOMBORDER : EndIf
  If camera\ty>#TOPBORDER : camera\ty=#TOPBORDER : EndIf
  
  camera\x = camera\x*0.9+camera\tx*0.1
  camera\y = camera\y*0.9+camera\ty*0.1
  camera\zoom = camera\zoom*0.95+camera\tzoom*0.05
  
  For x = 0 To #ship_count
    sprs(x)\angle = sprs(x)\angle*0.9+sprs(x)\tangle*01
  Next x
    
  If MouseButton(#PB_MouseButton_Middle)
    For x = 0 To #ship_count
      sprs(x)\destx = sprs(x)\x- Sin(Radian(#off2+sprs(x)\angle))*10-Cos(Radian(#off2+sprs(x)\angle))*10
      sprs(x)\desty = sprs(x)\y-(-Cos(Radian(#off2+sprs(x)\angle)))*10-Sin(Radian(#off2+sprs(x)\angle))*10
    Next x
  EndIf
  
  If MouseWheel()<>0
    camera\tzoom=camera\tzoom+MouseWheel() * #MOUSEWHEEL_SENSITIVY * multiplier
    If camera\tzoom<#MINZOOM : camera\tzoom = #MINZOOM : EndIf
    If camera\tzoom>#MAXZOOM : camera\tzoom = #MAXZOOM : EndIf
  EndIf
  
  For x = 0 To #ship_count
    dx = camera\zoom*sprs(x)\x-camera\zoom*camera\x+SpriteWidth(sprs(x)\spid)/2
    dy = camera\zoom*sprs(x)\y-camera\zoom*camera\y+SpriteHeight(sprs(x)\spid)/2
    trx = dx+camera\zoom*(sprs(x)\x-SpriteWidth(sprs(x)\spid)/2-camera\x-ScreenWidth()/2)
    try = dy+camera\zoom*(sprs(x)\y-SpriteHeight(sprs(x)\spid)/2-camera\y-ScreenHeight()/2)
    trx =trx-camera\x*camera\zoom+ScreenWidth()/2
    try =try-camera\y*camera\zoom+ScreenHeight()/2
     With sprs(x)
      \x=\destx*0.05+\x*0.95
      \y=\desty*0.05+\y*0.95
      ZoomSprite(airship_sprite_id,sprs(x)\basesize*camera\zoom,sprs(x)\basesize*camera\zoom)
      ZoomSprite(arrowsprite_ID,8*camera\zoom,8*camera\zoom)
      tmod = SpriteWidth(airship_sprite_id)/-2+SpriteWidth(arrowsprite_ID)*0.75
      RotateSprite(arrowsprite_ID,\angle,#PB_Absolute)
      DisplayTransparentSprite(\spid,trx,try,#MAX_INTENSITY,\color)
      DisplayTransparentSprite(arrowsprite_ID,tmod+trx+((Sin(Radian(#off+\angle)))*ddist.f+Cos(Radian(#off+\angle))*ddist.f),tmod+try+(-Cos(Radian(#off+\angle)))*ddist.f+Sin(Radian(#off+\angle))*ddist.f)
    EndWith
  Next x
  
  sub_Draw_UI()
  FlipBuffers()
EndProcedure
;-MAIN PROGRAM PROCEDURE
Procedure main()
  app_start()
  Repeat
    app_update()
  Until KeyboardPushed(#PB_Key_Escape)
  petskii::destroy()
  End
EndProcedure

;-MAIN PROGRAM
main()

Re: Maths problem with basic camera

Posted: Sun Mar 02, 2025 1:41 pm
by Caronte3D
Very nice! :D

Re: Maths problem with basic camera

Posted: Sun Mar 02, 2025 1:44 pm
by BarryG
Wow! :shock:

Re: Maths problem with basic camera

Posted: Sun Mar 02, 2025 2:12 pm
by Joubarbe
Super nice, thanks a lot miso!

Re: Maths problem with basic camera

Posted: Mon Mar 03, 2025 10:09 am
by miso
I could not let this one slide, so made some improvements:

Code: Select all

EnableExplicit
;-MODULES FILES 

DeclareModule petskii
  Declare init()
  Declare textout(x,y,text.s,color.i)
  Declare textoutlined(x,y,text.s,color.i,outlinecolor.i)
  Declare destroy()
EndDeclareModule

Module petskii
;-HIDDEN VARIABLES/CONSTANTS  
  #USED_CHARACTERS="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()-_=+[{]};:',<.>/?"+Chr(34)
  Global Dim petskiifont(370):Global Dim fontimport.i(370)
;-SUB PROCEDURES
  Procedure sub_loadfont()
    Protected x.i,i.i,j.i,sprline.a
    For i = 1 To Len(#USED_CHARACTERS):fontImport(Asc(Mid(#USED_CHARACTERS,i,1)))=1 : Next i 
    Restore petskii_font
      For x= 1 To 370
        If fontimport(x)=1
          petskiifont(x)=CreateSprite(-1,8,12,#PB_Sprite_AlphaBlending)
          StartDrawing(SpriteOutput(petskiifont(x)))
          DrawingMode(#PB_2DDrawing_AllChannels)
          For j=0 To 11  
            Read.a sprline 
            For i=0 To 7
              If sprline&%1 :Plot(i,j,RGBA(255,255,255,255)): Else : Plot(i,j,RGBA(0,0,0,0)) : EndIf
              sprline>>1 
            Next i
          Next j
          StopDrawing()
          ZoomSprite(petskiifont(x),16,24)
        EndIf
      Next x
  EndProcedure
  
  ;-PUBLIC PROCEDURES  
  Procedure init()
    sub_loadfont()
  EndProcedure
  
  Procedure textout(x,y,text.s,color.i) : Protected.i textlength,i,character
    textlength.i = Len(text.s)
    For i = 1 To textlength.i
      character.i = Asc(Mid(text.s,i,1))
      If IsSprite(petskiifont(character))
        DisplayTransparentSprite(petskiifont(character),(x+((i-1) * 16)),(y),255,color.i)
      EndIf
    Next i
  EndProcedure
  
  Procedure textoutlined(x,y,text.s,color.i,outlinecolor.i)
    textout(x-2,y,text.s,outlinecolor)
    textout(x+2,y,text.s,outlinecolor)
    textout(x,y-2,text.s,outlinecolor)
    textout(x,y+2,text.s,outlinecolor)
    textout(x,y,text.s,color)
  EndProcedure
  
  
  Procedure destroy()
    Protected i.i
    For i = 1 To Len(#USED_CHARACTERS)
      If IsSprite(petskiifont(i)) : FreeSprite(petskiifont(i)) : EndIf
    Next i
  EndProcedure
  
  ;-MODULE DATA
  DataSection
  petskii_font:
  Data.a $00,$00,$38,$38,$38,$38,$38,$38,$00,$38,$00,$00,$00,$00,$EE,$EE,$EE,$00,$00,$00,$00,$00,$00,$00,$00,$00,$EE,$EE,$EE,$FF,$EE,$FF,$EE,$EE,$00,$00,$00,$00,$38,$38,$FC,$0E,$7C,$E0,$7E,$38,$00,$00
  Data.a $00,$00,$CE,$CE,$EE,$70,$38,$1C,$EE,$E6,$00,$00,$00,$00,$7C,$7C,$EE,$7C,$3C,$EE,$EE,$FC,$00,$00,$00,$00,$E0,$E0,$70,$38,$00,$00,$00,$00,$00,$00,$00,$00,$70,$70,$38,$1C,$1C,$1C,$38,$70,$00,$00
  Data.a $00,$00,$1C,$1C,$38,$70,$70,$70,$38,$1C,$00,$00,$00,$00,$00,$00,$EE,$7C,$FF,$7C,$EE,$00,$00,$00,$00,$00,$00,$00,$38,$38,$FE,$38,$38,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$38,$38,$1C,$00
  Data.a $00,$00,$00,$00,$00,$00,$FE,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$38,$38,$00,$00,$00,$00,$00,$00,$C0,$E0,$70,$38,$1C,$0E,$00,$00,$00,$00,$7C,$7C,$EE,$FE,$FE,$EE,$EE,$7C,$00,$00
  Data.a $00,$00,$38,$38,$38,$3C,$38,$38,$38,$FE,$00,$00,$00,$00,$7C,$7C,$EE,$E0,$70,$1C,$0E,$FE,$00,$00,$00,$00,$7C,$7C,$EE,$E0,$78,$E0,$EE,$7C,$00,$00,$00,$00,$E0,$E0,$F0,$F8,$EE,$FE,$E0,$E0,$00,$00
  Data.a $00,$00,$FE,$FE,$0E,$7E,$E0,$E0,$EE,$7C,$00,$00,$00,$00,$7C,$7C,$EE,$0E,$7E,$EE,$EE,$7C,$00,$00,$00,$00,$FE,$FE,$EE,$70,$38,$38,$38,$38,$00,$00,$00,$00,$7C,$7C,$EE,$EE,$7C,$EE,$EE,$7C,$00,$00
  Data.a $00,$00,$7C,$7C,$EE,$EE,$FC,$E0,$EE,$7C,$00,$00,$00,$00,$38,$38,$38,$00,$00,$00,$38,$38,$00,$00,$00,$00,$38,$38,$38,$00,$00,$00,$38,$38,$1C,$00,$00,$00,$F0,$F0,$38,$1C,$0E,$1C,$38,$F0,$00,$00
  Data.a $00,$00,$00,$00,$00,$FE,$00,$FE,$00,$00,$00,$00,$00,$00,$1E,$1E,$38,$70,$E0,$70,$38,$1E,$00,$00,$00,$00,$7C,$7C,$EE,$E0,$70,$38,$00,$38,$00,$00,$00,$00,$7C,$7C,$EE,$FE,$FE,$0E,$CE,$7C,$00,$00
  Data.a $00,$00,$38,$38,$7C,$EE,$FE,$EE,$EE,$EE,$00,$00,$00,$00,$7E,$7E,$EE,$EE,$7E,$EE,$EE,$7E,$00,$00,$00,$00,$7C,$7C,$EE,$0E,$0E,$0E,$EE,$7C,$00,$00,$00,$00,$3E,$3E,$7E,$EE,$EE,$EE,$7E,$3E,$00,$00
  Data.a $00,$00,$FE,$FE,$0E,$0E,$3E,$0E,$0E,$FE,$00,$00,$00,$00,$FE,$FE,$0E,$0E,$3E,$0E,$0E,$0E,$00,$00,$00,$00,$7C,$7C,$EE,$0E,$FE,$EE,$EE,$7C,$00,$00,$00,$00,$EE,$EE,$EE,$EE,$FE,$EE,$EE,$EE,$00,$00
  Data.a $00,$00,$7C,$7C,$38,$38,$38,$38,$38,$7C,$00,$00,$00,$00,$F8,$F8,$70,$70,$70,$70,$7E,$3C,$00,$00,$00,$00,$EE,$EE,$7E,$3E,$1E,$3E,$7E,$EE,$00,$00,$00,$00,$0E,$0E,$0E,$0E,$0E,$0E,$0E,$FE,$00,$00
  Data.a $00,$00,$CE,$CE,$FE,$FE,$FE,$CE,$CE,$CE,$00,$00,$00,$00,$EE,$EE,$FE,$FE,$FE,$FE,$EE,$EE,$00,$00,$00,$00,$7C,$7C,$EE,$EE,$EE,$EE,$EE,$7C,$00,$00,$00,$00,$7E,$7E,$EE,$EE,$7E,$0E,$0E,$0E,$00,$00
  Data.a $00,$00,$7C,$7C,$EE,$EE,$EE,$EE,$7C,$F0,$00,$00,$00,$00,$7E,$7E,$EE,$EE,$7E,$3E,$7E,$EE,$00,$00,$00,$00,$7C,$7C,$EE,$0E,$7C,$E0,$EE,$7C,$00,$00,$00,$00,$FE,$FE,$38,$38,$38,$38,$38,$38,$00,$00
  Data.a $00,$00,$EE,$EE,$EE,$EE,$EE,$EE,$EE,$7C,$00,$00,$00,$00,$EE,$EE,$EE,$EE,$EE,$EE,$7C,$38,$00,$00,$00,$00,$CE,$CE,$CE,$CE,$FE,$FE,$FE,$CE,$00,$00,$00,$00,$EE,$EE,$EE,$7C,$38,$7C,$EE,$EE,$00,$00
  Data.a $00,$00,$EE,$EE,$EE,$EE,$7C,$38,$38,$38,$00,$00,$00,$00,$FE,$FE,$E0,$70,$38,$1C,$0E,$FE,$00,$00,$00,$00,$7C,$7C,$1C,$1C,$1C,$1C,$1C,$7C,$00,$00,$00,$00,$7C,$7C,$70,$70,$70,$70,$70,$7C,$00,$00
  Data.a $00,$00,$38,$38,$7C,$FE,$38,$38,$38,$38,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$00,$00,$00,$00,$00,$00,$00,$7C,$E0,$FC,$EE,$FC,$00,$00,$00,$00,$00,$00,$0E,$0E,$7E,$EE,$EE,$7E,$00,$00
  Data.a $00,$00,$00,$00,$00,$7C,$0E,$0E,$0E,$7C,$00,$00,$00,$00,$00,$00,$E0,$E0,$FC,$EE,$EE,$FC,$00,$00,$00,$00,$00,$00,$00,$7C,$EE,$FE,$0E,$7C,$00,$00,$00,$00,$00,$00,$F0,$38,$FC,$38,$38,$38,$00,$00
  Data.a $00,$00,$00,$00,$00,$FC,$EE,$EE,$FC,$E0,$7E,$00,$00,$00,$0E,$0E,$0E,$7E,$EE,$EE,$EE,$EE,$00,$00,$00,$00,$38,$38,$00,$3C,$38,$38,$38,$7C,$00,$00,$00,$00,$00,$00,$70,$00,$70,$70,$70,$70,$3C,$00
  Data.a $00,$00,$0E,$0E,$0E,$0E,$7E,$3E,$7E,$EE,$00,$00,$00,$00,$3C,$3C,$38,$38,$38,$38,$38,$7C,$00,$00,$00,$00,$00,$00,$00,$EE,$FE,$FE,$FE,$CE,$00,$00,$00,$00,$00,$00,$00,$7E,$EE,$EE,$EE,$EE,$00,$00
  Data.a $00,$00,$00,$00,$00,$7C,$EE,$EE,$EE,$7C,$00,$00,$00,$00,$00,$00,$00,$7E,$EE,$EE,$7E,$0E,$0E,$00,$00,$00,$00,$00,$00,$FC,$EE,$EE,$FC,$E0,$E0,$00,$00,$00,$00,$00,$00,$7E,$EE,$0E,$0E,$0E,$00,$00
  Data.a $00,$00,$00,$00,$00,$FC,$0E,$7C,$E0,$7E,$00,$00,$00,$00,$00,$00,$38,$FE,$38,$38,$38,$F0,$00,$00,$00,$00,$00,$00,$00,$EE,$EE,$EE,$EE,$FC,$00,$00,$00,$00,$00,$00,$00,$EE,$EE,$EE,$7C,$38,$00,$00
  Data.a $00,$00,$00,$00,$00,$CE,$FE,$FE,$FC,$FC,$00,$00,$00,$00,$00,$00,$00,$EE,$7C,$38,$7C,$EE,$00,$00,$00,$00,$00,$00,$00,$EE,$EE,$EE,$FC,$70,$3E,$00,$00,$00,$00,$00,$00,$FE,$70,$38,$1C,$FE,$00,$00
  Data.a $00,$00,$F0,$F0,$38,$38,$1E,$38,$38,$F0,$00,$00,$00,$00,$1E,$1E,$38,$38,$F0,$38,$38,$1E,$00,$00
  EndDataSection
EndModule

DeclareModule stripes
  Global spr_id.i
  Global columns.i
  Declare create(size.i)
  Declare draw(animationsteps.f)  
EndDeclareModule

Module stripes
  Procedure.i Create(size.i)
    Protected img_stripe.i
    img_stripe=CreateImage(#PB_Any,size,size,24,RGBA(1,1,1,255))
    StartVectorDrawing(ImageVectorOutput(img_stripe))
      MovePathCursor(0,size) : AddPathLine(size/2,0) : AddPathLine(size,0) : AddPathLine(size/2,size) : ClosePath()
      VectorSourceColor(RGBA(255,128,0,255)) : FillPath()
    StopVectorDrawing()
    stripes::spr_id=CreateSprite(#PB_Any,size,size)
    StartDrawing(SpriteOutput(stripes::spr_id)) : DrawImage(ImageID(img_stripe),0,0) : StopDrawing()
    FreeImage(img_stripe)
    columns.i = ScreenWidth()/SpriteWidth(stripes::spr_id)
    If IsSprite(stripes::spr_id) :ProcedureReturn #True : EndIf
    ProcedureReturn #False  
  EndProcedure
  
  Procedure.i draw(animationstep.f)
    Protected i.i
    Static offset.f =0
    For i=-1 To columns+1
      DisplaySprite(stripes::spr_id,i*SpriteWidth(stripes::spr_id)+offset,0)
      DisplaySprite(stripes::spr_id,i*SpriteWidth(stripes::spr_id)-offset,ScreenHeight()-SpriteHeight(stripes::spr_id))
    Next i
    offset.f + animationstep.f
    If offset>SpriteWidth(stripes::spr_id) : offset -SpriteWidth(stripes::spr_id) : EndIf
  EndProcedure  
EndModule

;-MAINPROGRAM FILE START HERE

;-CONSTANTS
#MAINDESKTOP_H = 0
#WINDOW_H = 0
#WINDOW_WIDTH = 1366
#WINDOW_HEIGHT = 768
#WINDOW_FLAGS  = #PB_Window_Invisible|#PB_Window_BorderLess|#PB_Window_ScreenCentered

#MAINLOOP_DELAY = 1
#COMPILER_MINIMUM_VERSION = 620

#ship_count = 250
#SPRSIZE = 5
#ARROWDIST = 5
#GRID_COUNT = 50
#GRIDSIZE = 100

#STRIPESIZE = 32
#STRIPESPEED = 2

#LEFTBORDER = -15000
#RIGHTBORDER = 16200
#BOTTOMBORDER =-15000
#TOPBORDER = 18000

#off = -45
#off2 = -225
#ROTATION_SPEED = 0.5
#MOUSEWHEEL_SENSITIVY = 0.05

#MINZOOM = 0.25
#MAXZOOM = 10
#MAX_INTENSITY = 255

;-TYPES
Structure cameratype
  x.f
  y.f
  tx.f
  ty.f
  angle.f
  zoom.f
  tzoom.f
  scrollspeed.f
EndStructure

Structure spritetype
  spid.i
  basesize.f
  hb.f
  x.f
  y.f
  destx.f
  desty.f
  angle.f
  tangle.f
  color.i
  speed.f
EndStructure

;-GLOBALS
Global.i airship_sprite_id , arrowsprite_ID, gridsprite_ID
Global camera.cameratype
Global Dim sprs.spritetype(#ship_count)
Global Dim grid.spritetype(#GRID_COUNT,#GRID_COUNT)
Global sincounter.f
;-AUXILIARY PROCEDURES

Procedure.i floor(f.f)
  ProcedureReturn Round(f.f,#PB_Round_Down)
EndProcedure

Procedure.i ceil(f.f)
  ProcedureReturn Round(f.f,#PB_Round_Up)
EndProcedure

Procedure sub_checks()
  If Int(#PB_Compiler_Version) < #COMPILER_MINIMUM_VERSION
    Debug "Please compile with the currently newest beta 6.20."
    Debug "Earlier versions will display things incorrectly"
    Debug "because of missing fixes that occoured in 6.20"
    ;End
  EndIf
  
  If Not #PB_Compiler_DPIAware
    Debug "DPI aware must be enabled for compile"
    ;End
  EndIf
EndProcedure

Procedure sub_createsprite()
  airship_sprite_id.i=CreateSprite(#PB_Any,#SPRSIZE,#SPRSIZE,#PB_Sprite_AlphaBlending)
  StartDrawing(SpriteOutput(airship_sprite_id.i))
  DrawingMode(#PB_2DDrawing_Outlined|#PB_2DDrawing_AllChannels)
  Box(0,0,OutputWidth(),OutputHeight())
  StopDrawing()
  
  arrowsprite_ID.i=CreateSprite(#PB_Any,#SPRSIZE,#SPRSIZE,#PB_Sprite_AlphaBlending)
  StartDrawing(SpriteOutput(arrowsprite_ID.i))
  DrawingMode(#PB_2DDrawing_Outlined|#PB_2DDrawing_AllChannels)
  Box(#SPRSIZE/2,0,1,#SPRSIZE)
  Plot(#SPRSIZE/2-1,1):Plot(#SPRSIZE/2+1,1)
  StopDrawing()
  
  gridsprite_ID.i=CreateSprite(#PB_Any,#GRIDSIZE,#GRIDSIZE,#PB_Sprite_AlphaBlending)
  StartDrawing(SpriteOutput(gridsprite_ID.i))
  DrawingMode(#PB_2DDrawing_Default|#PB_2DDrawing_AllChannels)
  Box(0,0,OutputWidth(),OutputHeight())
  StopDrawing()
EndProcedure

Procedure sub_camerasetup()
  With camera
    \x=ScreenWidth()/4
    \y=ScreenHeight()/4
    \tx=ScreenWidth()/4
    \ty=ScreenHeight()/4
    \angle = 0
    \zoom = 1.0
    \tzoom = 2.0
    \scrollspeed = 2.0
  EndWith
EndProcedure

Procedure sub_airship_setup()
  Protected x.i
  For x = 0 To #ship_count
    With sprs(x)
      \spid = airship_sprite_id
      \x = Random(#GRID_COUNT*#GRIDSIZE)/20
      \y = Random(#GRID_COUNT*#GRIDSIZE)/20
      \destx = \x
      \desty = \y
      ;\tangle = Degree(ATan2(\destx-\x,\desty-\y))
      \tangle = Random(359)
      \angle = \tangle
      \basesize = 20.0
      \hb = \basesize/2.0
      \speed = (5+Random(25,1))/5
      \color.i = RGBA(128+Random(127),Random(255),Random(255),255)
    EndWith
  Next x
EndProcedure

Procedure sub_grid_setup()
  Protected i.i,j.i
  For i = 0 To #grid_count
    For j = 0 To #grid_count
      With grid(i,j)
        \spid = gridsprite_ID
        \x = i*#GRIDSIZE
        \y = j*#GRIDSIZE
        \destx = i*#GRIDSIZE
        \desty = j*#GRIDSIZE
        ;\tangle = Degree(ATan2(\destx-\x,\desty-\y))
        \tangle = 0
        \angle = 0
        \basesize = #GRIDSIZE
        \hb = \basesize/2.0
        \color.i = RGBA(0+Random(10),Random(Random(55)+25),0+Random(10),255)
     EndWith
    Next j
  Next i
EndProcedure

Procedure sub_draw_UI()
    stripes::draw(#STRIPESPEED)
    petskii::textoutlined(0,2,"mouse = Scroll",RGBA(255,0,0,255),RGBA(5,5,5,5))
    petskii::textoutlined(350,2,"mwheel = zoom",RGBA(0,255,0,255),RGBA(5,5,5,255))
    petskii::textoutlined(700,2,"mousebutton left+right = rotate direction",RGBA(255,255,55,255),RGBA(5,5,5,255))
    petskii::textoutlined(450,741,"mousebutton middle = move",RGBA(255,255,255,255),RGBA(5,5,5,255))
    petskii::textoutlined(1150,741,"Escape = Quit",RGBA(255,55,55,255),RGBA(5,5,5,255))
    petskii::textoutlined(0,38,"Zoom level = ",RGBA(5,5,5,255),RGBA(255,5,5,255))
    petskii::textoutlined(210,38,StrF(camera\zoom,0),RGBA(5,5,5,255),RGBA(255,255,125,255))
    petskii::textoutlined(0,60,"Camera     = ",RGBA(5,5,5,255),RGBA(50,50,255,255))
    petskii::textoutlined(210,60,"("+StrF(camera\x,0)+" , "+ StrF(camera\y,0)+")",RGBA(55,55,200,255),RGBA(150,150,255,255))
    petskii::textoutlined(0,741,FormatDate("%hh:%ii:%ss",Date()),RGBA(255,255,55,255),RGBA(5,5,5,255))
EndProcedure

;-PROCEDURES
Procedure app_start()
  sub_checks()
  ExamineDesktops()
  InitMouse()
  InitSprite()
  InitKeyboard()
  OpenWindow(#WINDOW_H,0,0,#WINDOW_WIDTH,#WINDOW_HEIGHT,"Login screen",#WINDOW_FLAGS)
  OpenWindowedScreen(WindowID(#WINDOW_H),0,0,#WINDOW_WIDTH,#WINDOW_HEIGHT,1,0,0,#PB_Screen_WaitSynchronization)
  ResizeWindow(#WINDOW_H,0,0,DesktopUnscaledX(DesktopWidth(#MAINDESKTOP_H)),DesktopUnscaledY(DesktopHeight(#MAINDESKTOP_H)))
  HideWindow(#WINDOW_H,#False)
  petskii::init()
  sub_createsprite()
  stripes::Create(#STRIPESIZE)
  sub_camerasetup()
  sub_airship_setup()
  sub_grid_setup()
EndProcedure

Procedure app_update()
  Protected x.i,i.i,j.i, multiplier.i
  Protected ddist.f = camera\zoom*8
  Protected dx.f, dy.f, trx.f,try.f, tmod.f
  Delay(#MAINLOOP_DELAY)
  Repeat : Until Not WindowEvent()
  ClearScreen(0)
  ExamineKeyboard()
  ExamineMouse()
  
  If MouseButton(#PB_MouseButton_Left)
    For x = 0 To #ship_count
      sprs(x)\tangle - #ROTATION_SPEED
    Next x
  EndIf
  
  If MouseButton(#PB_MouseButton_Right)
    For x = 0 To #ship_count
      sprs(x)\tangle + #ROTATION_SPEED
    Next x
  EndIf
  
  multiplier.i = (2*camera\zoom)
  If multiplier<1 : multiplier = 1 : EndIf  :  If multiplier>20 : multiplier = 20 : EndIf
  
  camera\tx + camera\scrollspeed*((MouseDeltaX()/(multiplier*2)))
  camera\ty + camera\scrollspeed*((MouseDeltaY()/(multiplier*2)))
  
  If camera\tx<#LEFTBORDER : camera\tx=#LEFTBORDER : EndIf
  If camera\tx>#RIGHTBORDER : camera\tx=#RIGHTBORDER : EndIf
  If camera\ty<#BOTTOMBORDER : camera\ty=#BOTTOMBORDER : EndIf
  If camera\ty>#TOPBORDER : camera\ty=#TOPBORDER : EndIf
  
  camera\x = camera\x*0.9+camera\tx*0.1
  camera\y = camera\y*0.9+camera\ty*0.1
  camera\zoom = camera\zoom*0.95+camera\tzoom*0.05
  
  For x = 0 To #ship_count
    sprs(x)\angle = sprs(x)\angle*0.9+sprs(x)\tangle*01
  Next x
    
  If MouseButton(#PB_MouseButton_Middle)
    For x = 0 To #ship_count
      sprs(x)\destx = sprs(x)\x- Sin(Radian(#off2+sprs(x)\angle))*sprs(x)\speed-Cos(Radian(#off2+sprs(x)\angle))*sprs(x)\speed
      sprs(x)\desty = sprs(x)\y-(-Cos(Radian(#off2+sprs(x)\angle)))*sprs(x)\speed-Sin(Radian(#off2+sprs(x)\angle))*sprs(x)\speed
    Next x
  EndIf
  
  If MouseWheel()<>0
    camera\tzoom=camera\tzoom+MouseWheel() * #MOUSEWHEEL_SENSITIVY * multiplier
    If camera\tzoom<#MINZOOM : camera\tzoom = #MINZOOM : EndIf
    If camera\tzoom>#MAXZOOM : camera\tzoom = #MAXZOOM : EndIf
  EndIf
  
  For i = 0 To #GRID_COUNT
    For j = 0 To #GRID_COUNT
      With grid(i,j)
        trx = floor(i*(#gridsize*camera\zoom)-(camera\x*camera\zoom)+ScreenWidth()/2)
        try = floor(j*(#gridsize*camera\zoom)-(camera\y*camera\zoom)+ScreenHeight()/2)
        ZoomSprite(gridsprite_ID,ceil(grid(i,j)\basesize*camera\zoom),ceil(grid(i,j)\basesize*camera\zoom))
        ;If trx>0-SpriteWidth(gridsprite_ID) And trx<ScreenWidth()
        ;  If try>0-SpriteHeight(gridsprite_ID) And try<ScreenHeight()
            DisplayTransparentSprite(\spid,trx,try,#MAX_INTENSITY,\color)
        ;  EndIf
        ;EndIf
      EndWith
    Next j
  Next i

  sincounter = sincounter+0.15 : If sincounter>360 : sincounter-360 : EndIf
  For x = 0 To #ship_count
    With sprs(x)
      trx = \x*(\basesize*camera\zoom)-(camera\x*camera\zoom)+ScreenWidth()/2
      try = \y*(\basesize*camera\zoom)-(camera\y*camera\zoom)+ScreenHeight()/2
      \x=\destx*0.05+\x*0.95
      \y=\desty*0.05+\y*0.95
      ZoomSprite(airship_sprite_id,2*sprs(x)\hb*camera\zoom,2*sprs(x)\hb*camera\zoom)
      ZoomSprite(arrowsprite_ID,2*sprs(x)\hb*camera\zoom,2*sprs(x)\hb*camera\zoom)
      tmod = SpriteWidth(airship_sprite_id)/-2+SpriteWidth(arrowsprite_ID)*0.5
      RotateSprite(arrowsprite_ID,\angle,#PB_Absolute)
      DisplayTransparentSprite(\spid,trx+\hb*camera\zoom,try+\hb*camera\zoom,#MAX_INTENSITY,\color)
      ddist.f = SpriteWidth(airship_sprite_id)/2+(Sin(sincounter)*#arrowdist)*camera\zoom
      DisplayTransparentSprite(arrowsprite_ID,tmod+trx+SpriteWidth(airship_sprite_id)/2+((Sin(Radian(#off+\angle)))*ddist.f+Cos(Radian(#off+\angle))*ddist.f),tmod+try+SpriteWidth(airship_sprite_id)/2+(-Cos(Radian(#off+\angle)))*ddist.f+Sin(Radian(#off+\angle))*ddist.f)
    EndWith
  Next x
  sub_Draw_UI()
  FlipBuffers()
EndProcedure
;-MAIN PROGRAM PROCEDURE
Procedure main()
  app_start()
  Repeat
    app_update()
  Until KeyboardPushed(#PB_Key_Escape)
  petskii::destroy()
  End
EndProcedure

;-MAIN PROGRAM
main()

Re: Maths problem with basic camera

Posted: Mon Mar 03, 2025 1:10 pm
by Caronte3D
You almost have a game! :lol:

Re: Maths problem with basic camera

Posted: Mon Mar 03, 2025 1:56 pm
by miso
Oh, no. I'm not planning anything. Just got distracted with the zoom idea.

Re: Maths problem with basic camera

Posted: Mon Mar 03, 2025 3:43 pm
by Caronte3D
Just joking :D

Re: Maths problem with basic camera

Posted: Mon Mar 03, 2025 4:00 pm
by miso
And the last addition can work with huge tilemaps. I'm finished with this.

Code: Select all

EnableExplicit
;-MODULES FILES 

DeclareModule petskii
  Declare init()
  Declare textout(x,y,text.s,color.i)
  Declare textoutlined(x,y,text.s,color.i,outlinecolor.i)
  Declare destroy()
EndDeclareModule

Module petskii
;-HIDDEN VARIABLES/CONSTANTS  
  #USED_CHARACTERS="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()-_=+[{]};:',<.>/?"+Chr(34)
  Global Dim petskiifont(370):Global Dim fontimport.i(370)
;-SUB PROCEDURES
  Procedure sub_loadfont()
    Protected x.i,i.i,j.i,sprline.a
    For i = 1 To Len(#USED_CHARACTERS):fontImport(Asc(Mid(#USED_CHARACTERS,i,1)))=1 : Next i 
    Restore petskii_font
      For x= 1 To 370
        If fontimport(x)=1
          petskiifont(x)=CreateSprite(-1,8,12,#PB_Sprite_AlphaBlending)
          StartDrawing(SpriteOutput(petskiifont(x)))
          DrawingMode(#PB_2DDrawing_AllChannels)
          For j=0 To 11  
            Read.a sprline 
            For i=0 To 7
              If sprline&%1 :Plot(i,j,RGBA(255,255,255,255)): Else : Plot(i,j,RGBA(0,0,0,0)) : EndIf
              sprline>>1 
            Next i
          Next j
          StopDrawing()
          ZoomSprite(petskiifont(x),16,24)
        EndIf
      Next x
  EndProcedure
  
  ;-PUBLIC PROCEDURES  
  Procedure init()
    sub_loadfont()
  EndProcedure
  
  Procedure textout(x,y,text.s,color.i) : Protected.i textlength,i,character
    textlength.i = Len(text.s)
    For i = 1 To textlength.i
      character.i = Asc(Mid(text.s,i,1))
      If IsSprite(petskiifont(character))
        DisplayTransparentSprite(petskiifont(character),(x+((i-1) * 16)),(y),255,color.i)
      EndIf
    Next i
  EndProcedure
  
  Procedure textoutlined(x,y,text.s,color.i,outlinecolor.i)
    textout(x-2,y,text.s,outlinecolor)
    textout(x+2,y,text.s,outlinecolor)
    textout(x,y-2,text.s,outlinecolor)
    textout(x,y+2,text.s,outlinecolor)
    textout(x,y,text.s,color)
  EndProcedure
  
  
  Procedure destroy()
    Protected i.i
    For i = 1 To Len(#USED_CHARACTERS)
      If IsSprite(petskiifont(i)) : FreeSprite(petskiifont(i)) : EndIf
    Next i
  EndProcedure
  
  ;-MODULE DATA
  DataSection
  petskii_font:
  Data.a $00,$00,$38,$38,$38,$38,$38,$38,$00,$38,$00,$00,$00,$00,$EE,$EE,$EE,$00,$00,$00,$00,$00,$00,$00,$00,$00,$EE,$EE,$EE,$FF,$EE,$FF,$EE,$EE,$00,$00,$00,$00,$38,$38,$FC,$0E,$7C,$E0,$7E,$38,$00,$00
  Data.a $00,$00,$CE,$CE,$EE,$70,$38,$1C,$EE,$E6,$00,$00,$00,$00,$7C,$7C,$EE,$7C,$3C,$EE,$EE,$FC,$00,$00,$00,$00,$E0,$E0,$70,$38,$00,$00,$00,$00,$00,$00,$00,$00,$70,$70,$38,$1C,$1C,$1C,$38,$70,$00,$00
  Data.a $00,$00,$1C,$1C,$38,$70,$70,$70,$38,$1C,$00,$00,$00,$00,$00,$00,$EE,$7C,$FF,$7C,$EE,$00,$00,$00,$00,$00,$00,$00,$38,$38,$FE,$38,$38,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$38,$38,$1C,$00
  Data.a $00,$00,$00,$00,$00,$00,$FE,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$38,$38,$00,$00,$00,$00,$00,$00,$C0,$E0,$70,$38,$1C,$0E,$00,$00,$00,$00,$7C,$7C,$EE,$FE,$FE,$EE,$EE,$7C,$00,$00
  Data.a $00,$00,$38,$38,$38,$3C,$38,$38,$38,$FE,$00,$00,$00,$00,$7C,$7C,$EE,$E0,$70,$1C,$0E,$FE,$00,$00,$00,$00,$7C,$7C,$EE,$E0,$78,$E0,$EE,$7C,$00,$00,$00,$00,$E0,$E0,$F0,$F8,$EE,$FE,$E0,$E0,$00,$00
  Data.a $00,$00,$FE,$FE,$0E,$7E,$E0,$E0,$EE,$7C,$00,$00,$00,$00,$7C,$7C,$EE,$0E,$7E,$EE,$EE,$7C,$00,$00,$00,$00,$FE,$FE,$EE,$70,$38,$38,$38,$38,$00,$00,$00,$00,$7C,$7C,$EE,$EE,$7C,$EE,$EE,$7C,$00,$00
  Data.a $00,$00,$7C,$7C,$EE,$EE,$FC,$E0,$EE,$7C,$00,$00,$00,$00,$38,$38,$38,$00,$00,$00,$38,$38,$00,$00,$00,$00,$38,$38,$38,$00,$00,$00,$38,$38,$1C,$00,$00,$00,$F0,$F0,$38,$1C,$0E,$1C,$38,$F0,$00,$00
  Data.a $00,$00,$00,$00,$00,$FE,$00,$FE,$00,$00,$00,$00,$00,$00,$1E,$1E,$38,$70,$E0,$70,$38,$1E,$00,$00,$00,$00,$7C,$7C,$EE,$E0,$70,$38,$00,$38,$00,$00,$00,$00,$7C,$7C,$EE,$FE,$FE,$0E,$CE,$7C,$00,$00
  Data.a $00,$00,$38,$38,$7C,$EE,$FE,$EE,$EE,$EE,$00,$00,$00,$00,$7E,$7E,$EE,$EE,$7E,$EE,$EE,$7E,$00,$00,$00,$00,$7C,$7C,$EE,$0E,$0E,$0E,$EE,$7C,$00,$00,$00,$00,$3E,$3E,$7E,$EE,$EE,$EE,$7E,$3E,$00,$00
  Data.a $00,$00,$FE,$FE,$0E,$0E,$3E,$0E,$0E,$FE,$00,$00,$00,$00,$FE,$FE,$0E,$0E,$3E,$0E,$0E,$0E,$00,$00,$00,$00,$7C,$7C,$EE,$0E,$FE,$EE,$EE,$7C,$00,$00,$00,$00,$EE,$EE,$EE,$EE,$FE,$EE,$EE,$EE,$00,$00
  Data.a $00,$00,$7C,$7C,$38,$38,$38,$38,$38,$7C,$00,$00,$00,$00,$F8,$F8,$70,$70,$70,$70,$7E,$3C,$00,$00,$00,$00,$EE,$EE,$7E,$3E,$1E,$3E,$7E,$EE,$00,$00,$00,$00,$0E,$0E,$0E,$0E,$0E,$0E,$0E,$FE,$00,$00
  Data.a $00,$00,$CE,$CE,$FE,$FE,$FE,$CE,$CE,$CE,$00,$00,$00,$00,$EE,$EE,$FE,$FE,$FE,$FE,$EE,$EE,$00,$00,$00,$00,$7C,$7C,$EE,$EE,$EE,$EE,$EE,$7C,$00,$00,$00,$00,$7E,$7E,$EE,$EE,$7E,$0E,$0E,$0E,$00,$00
  Data.a $00,$00,$7C,$7C,$EE,$EE,$EE,$EE,$7C,$F0,$00,$00,$00,$00,$7E,$7E,$EE,$EE,$7E,$3E,$7E,$EE,$00,$00,$00,$00,$7C,$7C,$EE,$0E,$7C,$E0,$EE,$7C,$00,$00,$00,$00,$FE,$FE,$38,$38,$38,$38,$38,$38,$00,$00
  Data.a $00,$00,$EE,$EE,$EE,$EE,$EE,$EE,$EE,$7C,$00,$00,$00,$00,$EE,$EE,$EE,$EE,$EE,$EE,$7C,$38,$00,$00,$00,$00,$CE,$CE,$CE,$CE,$FE,$FE,$FE,$CE,$00,$00,$00,$00,$EE,$EE,$EE,$7C,$38,$7C,$EE,$EE,$00,$00
  Data.a $00,$00,$EE,$EE,$EE,$EE,$7C,$38,$38,$38,$00,$00,$00,$00,$FE,$FE,$E0,$70,$38,$1C,$0E,$FE,$00,$00,$00,$00,$7C,$7C,$1C,$1C,$1C,$1C,$1C,$7C,$00,$00,$00,$00,$7C,$7C,$70,$70,$70,$70,$70,$7C,$00,$00
  Data.a $00,$00,$38,$38,$7C,$FE,$38,$38,$38,$38,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$00,$00,$00,$00,$00,$00,$00,$7C,$E0,$FC,$EE,$FC,$00,$00,$00,$00,$00,$00,$0E,$0E,$7E,$EE,$EE,$7E,$00,$00
  Data.a $00,$00,$00,$00,$00,$7C,$0E,$0E,$0E,$7C,$00,$00,$00,$00,$00,$00,$E0,$E0,$FC,$EE,$EE,$FC,$00,$00,$00,$00,$00,$00,$00,$7C,$EE,$FE,$0E,$7C,$00,$00,$00,$00,$00,$00,$F0,$38,$FC,$38,$38,$38,$00,$00
  Data.a $00,$00,$00,$00,$00,$FC,$EE,$EE,$FC,$E0,$7E,$00,$00,$00,$0E,$0E,$0E,$7E,$EE,$EE,$EE,$EE,$00,$00,$00,$00,$38,$38,$00,$3C,$38,$38,$38,$7C,$00,$00,$00,$00,$00,$00,$70,$00,$70,$70,$70,$70,$3C,$00
  Data.a $00,$00,$0E,$0E,$0E,$0E,$7E,$3E,$7E,$EE,$00,$00,$00,$00,$3C,$3C,$38,$38,$38,$38,$38,$7C,$00,$00,$00,$00,$00,$00,$00,$EE,$FE,$FE,$FE,$CE,$00,$00,$00,$00,$00,$00,$00,$7E,$EE,$EE,$EE,$EE,$00,$00
  Data.a $00,$00,$00,$00,$00,$7C,$EE,$EE,$EE,$7C,$00,$00,$00,$00,$00,$00,$00,$7E,$EE,$EE,$7E,$0E,$0E,$00,$00,$00,$00,$00,$00,$FC,$EE,$EE,$FC,$E0,$E0,$00,$00,$00,$00,$00,$00,$7E,$EE,$0E,$0E,$0E,$00,$00
  Data.a $00,$00,$00,$00,$00,$FC,$0E,$7C,$E0,$7E,$00,$00,$00,$00,$00,$00,$38,$FE,$38,$38,$38,$F0,$00,$00,$00,$00,$00,$00,$00,$EE,$EE,$EE,$EE,$FC,$00,$00,$00,$00,$00,$00,$00,$EE,$EE,$EE,$7C,$38,$00,$00
  Data.a $00,$00,$00,$00,$00,$CE,$FE,$FE,$FC,$FC,$00,$00,$00,$00,$00,$00,$00,$EE,$7C,$38,$7C,$EE,$00,$00,$00,$00,$00,$00,$00,$EE,$EE,$EE,$FC,$70,$3E,$00,$00,$00,$00,$00,$00,$FE,$70,$38,$1C,$FE,$00,$00
  Data.a $00,$00,$F0,$F0,$38,$38,$1E,$38,$38,$F0,$00,$00,$00,$00,$1E,$1E,$38,$38,$F0,$38,$38,$1E,$00,$00
  EndDataSection
EndModule

DeclareModule stripes
  Global spr_id.i
  Global columns.i
  Declare create(size.i)
  Declare draw(animationsteps.f)  
EndDeclareModule

Module stripes
  Procedure.i Create(size.i)
    Protected img_stripe.i
    img_stripe=CreateImage(#PB_Any,size,size,24,RGBA(1,1,1,255))
    StartVectorDrawing(ImageVectorOutput(img_stripe))
      MovePathCursor(0,size) : AddPathLine(size/2,0) : AddPathLine(size,0) : AddPathLine(size/2,size) : ClosePath()
      VectorSourceColor(RGBA(255,128,0,255)) : FillPath()
    StopVectorDrawing()
    stripes::spr_id=CreateSprite(#PB_Any,size,size)
    StartDrawing(SpriteOutput(stripes::spr_id)) : DrawImage(ImageID(img_stripe),0,0) : StopDrawing()
    FreeImage(img_stripe)
    columns.i = ScreenWidth()/SpriteWidth(stripes::spr_id)
    If IsSprite(stripes::spr_id) :ProcedureReturn #True : EndIf
    ProcedureReturn #False  
  EndProcedure
  
  Procedure.i draw(animationstep.f)
    Protected i.i
    Static offset.f =0
    For i=-1 To columns+1
      DisplaySprite(stripes::spr_id,i*SpriteWidth(stripes::spr_id)+offset,0)
      DisplaySprite(stripes::spr_id,i*SpriteWidth(stripes::spr_id)-offset,ScreenHeight()-SpriteHeight(stripes::spr_id))
    Next i
    offset.f + animationstep.f
    If offset>SpriteWidth(stripes::spr_id) : offset -SpriteWidth(stripes::spr_id) : EndIf
  EndProcedure  
EndModule

;-MAINPROGRAM FILE START HERE

;-CONSTANTS
#MAINDESKTOP_H = 0
#WINDOW_H = 0
#WINDOW_WIDTH = 1366
#WINDOW_HEIGHT = 768
#WINDOW_FLAGS  = #PB_Window_Invisible|#PB_Window_BorderLess|#PB_Window_ScreenCentered

#MAINLOOP_DELAY = 1
#COMPILER_MINIMUM_VERSION = 620

#ship_count = 500
#SPRSIZE = 5
#ARROWDIST = 1
#GRID_COUNT = 500
#GRIDSIZE = 100

#STRIPESIZE = 32
#STRIPESPEED = 2

#LEFTBORDER = -15000
#RIGHTBORDER = 160200
#BOTTOMBORDER =-15000
#TOPBORDER = 180000

#off = -45
#off2 = -225
#ROTATION_SPEED = 0.5
#MOUSEWHEEL_SENSITIVY = 0.05

#MINZOOM = 0.25
#MAXZOOM = 5
#MAX_INTENSITY = 255

;-TYPES
Structure cameratype
  x.f
  y.f
  tx.f
  ty.f
  angle.f
  zoom.f
  tzoom.f
  scrollspeed.f
EndStructure

Structure spritetype
  spid.i
  basesize.f
  hb.f
  x.f
  y.f
  destx.f
  desty.f
  angle.f
  tangle.f
  color.i
  speed.f
EndStructure

;-GLOBALS
Global.i airship_sprite_id , arrowsprite_ID, gridsprite_ID
Global camera.cameratype
Global Dim sprs.spritetype(#ship_count)
Global Dim grid.spritetype(#GRID_COUNT,#GRID_COUNT)
Global sincounter.f
;-AUXILIARY PROCEDURES

Procedure.i floor(f.f)
  ProcedureReturn Round(f.f,#PB_Round_Down)
EndProcedure

Procedure.i ceil(f.f)
  ProcedureReturn Round(f.f,#PB_Round_Up)
EndProcedure

Procedure sub_checks()
  If Int(#PB_Compiler_Version) < #COMPILER_MINIMUM_VERSION
    Debug "Please compile with the currently newest beta 6.20."
    Debug "Earlier versions will display things incorrectly"
    Debug "because of missing fixes that occoured in 6.20"
    ;End
  EndIf
  
  If Not #PB_Compiler_DPIAware
    Debug "DPI aware must be enabled for compile"
    ;End
  EndIf
EndProcedure

Procedure sub_createsprite()
  airship_sprite_id.i=CreateSprite(#PB_Any,#SPRSIZE,#SPRSIZE,#PB_Sprite_AlphaBlending)
  StartDrawing(SpriteOutput(airship_sprite_id.i))
  DrawingMode(#PB_2DDrawing_Outlined|#PB_2DDrawing_AllChannels)
  Box(0,0,OutputWidth(),OutputHeight())
  StopDrawing()
  
  arrowsprite_ID.i=CreateSprite(#PB_Any,#SPRSIZE,#SPRSIZE,#PB_Sprite_AlphaBlending)
  StartDrawing(SpriteOutput(arrowsprite_ID.i))
  DrawingMode(#PB_2DDrawing_Outlined|#PB_2DDrawing_AllChannels)
  Box(#SPRSIZE/2,0,1,#SPRSIZE)
  Plot(#SPRSIZE/2-1,1):Plot(#SPRSIZE/2+1,1)
  StopDrawing()
  
  gridsprite_ID.i=CreateSprite(#PB_Any,#GRIDSIZE,#GRIDSIZE,#PB_Sprite_AlphaBlending)
  StartDrawing(SpriteOutput(gridsprite_ID.i))
  DrawingMode(#PB_2DDrawing_Default|#PB_2DDrawing_AllChannels)
  Box(0,0,OutputWidth(),OutputHeight())
  StopDrawing()
EndProcedure

Procedure sub_camerasetup()
  With camera
    \x=ScreenWidth()/4
    \y=ScreenHeight()/4
    \tx=ScreenWidth()/4
    \ty=ScreenHeight()/4
    \angle = 0
    \zoom = 1.0
    \tzoom = 2.0
    \scrollspeed = 2.0
  EndWith
EndProcedure

Procedure sub_airship_setup()
  Protected x.i
  For x = 0 To #ship_count
    With sprs(x)
      \spid = airship_sprite_id
      \x = Random(#GRID_COUNT*#GRIDSIZE)/20
      \y = Random(#GRID_COUNT*#GRIDSIZE)/20
      \destx = \x
      \desty = \y
      ;\tangle = Degree(ATan2(\destx-\x,\desty-\y))
      \tangle = Random(359)
      \angle = \tangle
      \basesize = 20.0
      \hb = \basesize/2.0
      \speed = (5+Random(25,1))/5
      \color.i = RGBA(128+Random(127),Random(255),Random(255),255)
    EndWith
  Next x
EndProcedure

Procedure sub_grid_setup()
  Protected i.i,j.i
  For i = 0 To #grid_count
    For j = 0 To #grid_count
      With grid(i,j)
        \spid = gridsprite_ID
        \x = i*#GRIDSIZE
        \y = j*#GRIDSIZE
        \destx = i*#GRIDSIZE
        \desty = j*#GRIDSIZE
        ;\tangle = Degree(ATan2(\destx-\x,\desty-\y))
        \tangle = 0
        \angle = 0
        \basesize = #GRIDSIZE
        \hb = \basesize/2.0
        \color.i = RGBA(0+Random(10),Random(Random(55)+25),0+Random(10),255)
     EndWith
    Next j
  Next i
EndProcedure

Procedure sub_draw_UI()
    stripes::draw(#STRIPESPEED)
    petskii::textoutlined(0,2,"mouse = Scroll",RGBA(255,0,0,255),RGBA(5,5,5,5))
    petskii::textoutlined(350,2,"mwheel = zoom",RGBA(0,255,0,255),RGBA(5,5,5,255))
    petskii::textoutlined(700,2,"mousebutton left+right = rotate direction",RGBA(255,255,55,255),RGBA(5,5,5,255))
    petskii::textoutlined(450,741,"mousebutton middle = move",RGBA(255,255,255,255),RGBA(5,5,5,255))
    petskii::textoutlined(1150,741,"Escape = Quit",RGBA(255,55,55,255),RGBA(5,5,5,255))
    petskii::textoutlined(0,38,"Zoom level = ",RGBA(5,5,5,255),RGBA(255,5,5,255))
    petskii::textoutlined(210,38,StrF(camera\zoom,0),RGBA(5,5,5,255),RGBA(255,255,125,255))
    petskii::textoutlined(0,60,"Camera     = ",RGBA(5,5,5,255),RGBA(50,50,255,255))
    petskii::textoutlined(210,60,"("+StrF(camera\x,0)+" , "+ StrF(camera\y,0)+")",RGBA(55,55,200,255),RGBA(150,150,255,255))
    petskii::textoutlined(0,741,FormatDate("%hh:%ii:%ss",Date()),RGBA(255,255,55,255),RGBA(5,5,5,255))
EndProcedure

;-PROCEDURES
Procedure app_start()
  sub_checks()
  ExamineDesktops()
  InitMouse()
  InitSprite()
  InitKeyboard()
  OpenWindow(#WINDOW_H,0,0,#WINDOW_WIDTH,#WINDOW_HEIGHT,"Login screen",#WINDOW_FLAGS)
  OpenWindowedScreen(WindowID(#WINDOW_H),0,0,#WINDOW_WIDTH,#WINDOW_HEIGHT,1,0,0,#PB_Screen_WaitSynchronization)
  ResizeWindow(#WINDOW_H,0,0,DesktopUnscaledX(DesktopWidth(#MAINDESKTOP_H)),DesktopUnscaledY(DesktopHeight(#MAINDESKTOP_H)))
  HideWindow(#WINDOW_H,#False)
  petskii::init()
  sub_createsprite()
  stripes::Create(#STRIPESIZE)
  sub_camerasetup()
  sub_airship_setup()
  sub_grid_setup()
EndProcedure

Procedure app_update()
  Protected x.i,i.i,j.i, multiplier.i
  Protected ddist.f = camera\zoom*8
  Protected dx.f, dy.f, trx.f,try.f, tmod.f
  Delay(#MAINLOOP_DELAY)
  Repeat : Until Not WindowEvent()
  ClearScreen(0)
  ExamineKeyboard()
  ExamineMouse()
  
  If MouseButton(#PB_MouseButton_Left)
    For x = 0 To #ship_count
      sprs(x)\tangle - #ROTATION_SPEED
    Next x
  EndIf
  
  If MouseButton(#PB_MouseButton_Right)
    For x = 0 To #ship_count
      sprs(x)\tangle + #ROTATION_SPEED
    Next x
  EndIf
  
  multiplier.i = (2*camera\zoom)
  If multiplier<1 : multiplier = 1 : EndIf  :  If multiplier>20 : multiplier = 20 : EndIf
  
  camera\tx + camera\scrollspeed*((MouseDeltaX()/(multiplier*2)))
  camera\ty + camera\scrollspeed*((MouseDeltaY()/(multiplier*2)))
  
  If camera\tx<#LEFTBORDER : camera\tx=#LEFTBORDER : EndIf
  If camera\tx>#RIGHTBORDER : camera\tx=#RIGHTBORDER : EndIf
  If camera\ty<#BOTTOMBORDER : camera\ty=#BOTTOMBORDER : EndIf
  If camera\ty>#TOPBORDER : camera\ty=#TOPBORDER : EndIf
  
  camera\x = camera\x*0.9+camera\tx*0.1
  camera\y = camera\y*0.9+camera\ty*0.1
  camera\zoom = camera\zoom*0.95+camera\tzoom*0.05
  
  For x = 0 To #ship_count
    sprs(x)\angle = sprs(x)\angle*0.9+sprs(x)\tangle*01
  Next x
    
  If MouseButton(#PB_MouseButton_Middle)
    For x = 0 To #ship_count
      sprs(x)\destx = sprs(x)\x- Sin(Radian(#off2+sprs(x)\angle))*sprs(x)\speed-Cos(Radian(#off2+sprs(x)\angle))*sprs(x)\speed
      sprs(x)\desty = sprs(x)\y-(-Cos(Radian(#off2+sprs(x)\angle)))*sprs(x)\speed-Sin(Radian(#off2+sprs(x)\angle))*sprs(x)\speed
    Next x
  EndIf
  
  If MouseWheel()<>0
    camera\tzoom=camera\tzoom+MouseWheel() * #MOUSEWHEEL_SENSITIVY * multiplier
    If camera\tzoom<#MINZOOM : camera\tzoom = #MINZOOM : EndIf
    If camera\tzoom>#MAXZOOM : camera\tzoom = #MAXZOOM : EndIf
  EndIf
  
  
    
  
  
  Protected.i startgridx,endgridx,startgridy,endgridy
  For i = 0 To #grid_count
    trx = floor(i*(#gridsize)-(camera\x)+ScreenWidth())
    If trx>-ScreenWidth()-4*SpriteWidth(gridsprite_ID)
      startgridx = i 
      endgridx = startgridx+55 :
      ;endgridx = startgridx+ceil(ScreenWidth()/(#gridsize*camera\zoom))
      If endgridx > #GRID_COUNT : endgridx = #GRID_COUNT : EndIf
      i = #grid_count
    EndIf
  Next i
  
  For i = 0 To #grid_count
    try = floor(i*(#gridsize)-(camera\y)+ScreenHeight())
    If try>-ScreenHeight()-SpriteHeight(gridsprite_ID)
      startgridy = i 
      endgridy = startgridy+29 
      ;endgridy = startgridy+ceil(ScreenHeight()/(#gridsize*camera\zoom))
      If endgridy > #GRID_COUNT : endgridy = #GRID_COUNT : EndIf
      i = #grid_count
    EndIf
  Next i
  
  
  
  
  
  For i = startgridx To endgridx
    For j = startgridy To endgridy
      With grid(i,j)
        trx = floor(i*(#gridsize*camera\zoom)-(camera\x*camera\zoom)+ScreenWidth()/2)
        try = floor(j*(#gridsize*camera\zoom)-(camera\y*camera\zoom)+ScreenHeight()/2)
        ZoomSprite(gridsprite_ID,ceil(grid(i,j)\basesize*camera\zoom),ceil(grid(i,j)\basesize*camera\zoom))
        DisplayTransparentSprite(\spid,trx,try,#MAX_INTENSITY,\color)
      EndWith
    Next j
  Next i

  sincounter = sincounter+0.12 : If sincounter>=360 : sincounter-360 : EndIf
  For x = 0 To #ship_count
    With sprs(x)
      trx = \x*(\basesize*camera\zoom)-(camera\x*camera\zoom)+ScreenWidth()/2
      try = \y*(\basesize*camera\zoom)-(camera\y*camera\zoom)+ScreenHeight()/2
      \x=\destx*0.05+\x*0.95
      \y=\desty*0.05+\y*0.95
      ZoomSprite(airship_sprite_id,2*sprs(x)\hb*camera\zoom,2*sprs(x)\hb*camera\zoom)
      ZoomSprite(arrowsprite_ID,2*sprs(x)\hb*camera\zoom,2*sprs(x)\hb*camera\zoom)
      tmod = SpriteWidth(airship_sprite_id)/-2+SpriteWidth(arrowsprite_ID)*0.5
      RotateSprite(arrowsprite_ID,\angle,#PB_Absolute)
      DisplayTransparentSprite(\spid,trx+\hb*camera\zoom,try+\hb*camera\zoom,#MAX_INTENSITY,\color)
      ddist.f = #arrowdist + SpriteWidth(airship_sprite_id)/2+(Sin(sincounter)*2)*camera\zoom
      ddist.f = ddist*5
      DisplayTransparentSprite(arrowsprite_ID,tmod+trx+SpriteWidth(airship_sprite_id)/2+((Sin(Radian(#off+\angle)))*ddist.f+Cos(Radian(#off+\angle))*ddist.f),tmod+try+SpriteWidth(airship_sprite_id)/2+(-Cos(Radian(#off+\angle)))*ddist.f+Sin(Radian(#off+\angle))*ddist.f)
    EndWith
  Next x
  sub_Draw_UI()
  FlipBuffers()
EndProcedure
;-MAIN PROGRAM PROCEDURE
Procedure main()
  app_start()
  Repeat
    app_update()
  Until KeyboardPushed(#PB_Key_Escape)
  petskii::destroy()
  End
EndProcedure

;-MAIN PROGRAM
main()

Re: Maths problem with basic camera

Posted: Tue Mar 04, 2025 1:26 pm
by miso
Bold stress test with a huge map, 9 million tiles+overlay + 10k ships.

Code: Select all

EnableExplicit
#PSEUDORANDOM_SEED = 5000
RandomSeed(#PSEUDORANDOM_SEED)
UsePNGImageDecoder()
;-MODULES FILES 

DeclareModule petskii
  Declare init()
  Declare textout(x,y,text.s,color.i)
  Declare textoutlined(x,y,text.s,color.i,outlinecolor.i)
  Declare destroy()
EndDeclareModule

Module petskii
;-HIDDEN VARIABLES/CONSTANTS  
  #USED_CHARACTERS="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()-_=+[{]};:',<.>/?"+Chr(34)
  Global Dim petskiifont(370):Global Dim fontimport.i(370)
;-SUB PROCEDURES
  Procedure sub_loadfont()
    Protected x.i,i.i,j.i,sprline.a
    For i = 1 To Len(#USED_CHARACTERS):fontImport(Asc(Mid(#USED_CHARACTERS,i,1)))=1 : Next i 
    Restore petskii_font
      For x= 1 To 370
        If fontimport(x)=1
          petskiifont(x)=CreateSprite(-1,8,12,#PB_Sprite_AlphaBlending)
          StartDrawing(SpriteOutput(petskiifont(x)))
          DrawingMode(#PB_2DDrawing_AllChannels)
          For j=0 To 11  
            Read.a sprline 
            For i=0 To 7
              If sprline&%1 :Plot(i,j,RGBA(255,255,255,255)): Else : Plot(i,j,RGBA(0,0,0,0)) : EndIf
              sprline>>1 
            Next i
          Next j
          StopDrawing()
          ZoomSprite(petskiifont(x),16,24)
        EndIf
      Next x
  EndProcedure
  
  ;-PUBLIC PROCEDURES  
  Procedure init()
    sub_loadfont()
  EndProcedure
  
  Procedure textout(x,y,text.s,color.i) : Protected.i textlength,i,character
    textlength.i = Len(text.s)
    For i = 1 To textlength.i
      character.i = Asc(Mid(text.s,i,1))
      If IsSprite(petskiifont(character))
        DisplayTransparentSprite(petskiifont(character),(x+((i-1) * 16)),(y),255,color.i)
      EndIf
    Next i
  EndProcedure
  
  Procedure textoutlined(x,y,text.s,color.i,outlinecolor.i)
    textout(x-2,y,text.s,outlinecolor)
    textout(x+2,y,text.s,outlinecolor)
    textout(x,y-2,text.s,outlinecolor)
    textout(x,y+2,text.s,outlinecolor)
    textout(x,y,text.s,color)
  EndProcedure
  
  
  Procedure destroy()
    Protected i.i
    For i = 1 To Len(#USED_CHARACTERS)
      If IsSprite(petskiifont(i)) : FreeSprite(petskiifont(i)) : EndIf
    Next i
  EndProcedure
  
  ;-MODULE DATA
  DataSection
  petskii_font:
  Data.a $00,$00,$38,$38,$38,$38,$38,$38,$00,$38,$00,$00,$00,$00,$EE,$EE,$EE,$00,$00,$00,$00,$00,$00,$00,$00,$00,$EE,$EE,$EE,$FF,$EE,$FF,$EE,$EE,$00,$00,$00,$00,$38,$38,$FC,$0E,$7C,$E0,$7E,$38,$00,$00
  Data.a $00,$00,$CE,$CE,$EE,$70,$38,$1C,$EE,$E6,$00,$00,$00,$00,$7C,$7C,$EE,$7C,$3C,$EE,$EE,$FC,$00,$00,$00,$00,$E0,$E0,$70,$38,$00,$00,$00,$00,$00,$00,$00,$00,$70,$70,$38,$1C,$1C,$1C,$38,$70,$00,$00
  Data.a $00,$00,$1C,$1C,$38,$70,$70,$70,$38,$1C,$00,$00,$00,$00,$00,$00,$EE,$7C,$FF,$7C,$EE,$00,$00,$00,$00,$00,$00,$00,$38,$38,$FE,$38,$38,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$38,$38,$1C,$00
  Data.a $00,$00,$00,$00,$00,$00,$FE,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$38,$38,$00,$00,$00,$00,$00,$00,$C0,$E0,$70,$38,$1C,$0E,$00,$00,$00,$00,$7C,$7C,$EE,$FE,$FE,$EE,$EE,$7C,$00,$00
  Data.a $00,$00,$38,$38,$38,$3C,$38,$38,$38,$FE,$00,$00,$00,$00,$7C,$7C,$EE,$E0,$70,$1C,$0E,$FE,$00,$00,$00,$00,$7C,$7C,$EE,$E0,$78,$E0,$EE,$7C,$00,$00,$00,$00,$E0,$E0,$F0,$F8,$EE,$FE,$E0,$E0,$00,$00
  Data.a $00,$00,$FE,$FE,$0E,$7E,$E0,$E0,$EE,$7C,$00,$00,$00,$00,$7C,$7C,$EE,$0E,$7E,$EE,$EE,$7C,$00,$00,$00,$00,$FE,$FE,$EE,$70,$38,$38,$38,$38,$00,$00,$00,$00,$7C,$7C,$EE,$EE,$7C,$EE,$EE,$7C,$00,$00
  Data.a $00,$00,$7C,$7C,$EE,$EE,$FC,$E0,$EE,$7C,$00,$00,$00,$00,$38,$38,$38,$00,$00,$00,$38,$38,$00,$00,$00,$00,$38,$38,$38,$00,$00,$00,$38,$38,$1C,$00,$00,$00,$F0,$F0,$38,$1C,$0E,$1C,$38,$F0,$00,$00
  Data.a $00,$00,$00,$00,$00,$FE,$00,$FE,$00,$00,$00,$00,$00,$00,$1E,$1E,$38,$70,$E0,$70,$38,$1E,$00,$00,$00,$00,$7C,$7C,$EE,$E0,$70,$38,$00,$38,$00,$00,$00,$00,$7C,$7C,$EE,$FE,$FE,$0E,$CE,$7C,$00,$00
  Data.a $00,$00,$38,$38,$7C,$EE,$FE,$EE,$EE,$EE,$00,$00,$00,$00,$7E,$7E,$EE,$EE,$7E,$EE,$EE,$7E,$00,$00,$00,$00,$7C,$7C,$EE,$0E,$0E,$0E,$EE,$7C,$00,$00,$00,$00,$3E,$3E,$7E,$EE,$EE,$EE,$7E,$3E,$00,$00
  Data.a $00,$00,$FE,$FE,$0E,$0E,$3E,$0E,$0E,$FE,$00,$00,$00,$00,$FE,$FE,$0E,$0E,$3E,$0E,$0E,$0E,$00,$00,$00,$00,$7C,$7C,$EE,$0E,$FE,$EE,$EE,$7C,$00,$00,$00,$00,$EE,$EE,$EE,$EE,$FE,$EE,$EE,$EE,$00,$00
  Data.a $00,$00,$7C,$7C,$38,$38,$38,$38,$38,$7C,$00,$00,$00,$00,$F8,$F8,$70,$70,$70,$70,$7E,$3C,$00,$00,$00,$00,$EE,$EE,$7E,$3E,$1E,$3E,$7E,$EE,$00,$00,$00,$00,$0E,$0E,$0E,$0E,$0E,$0E,$0E,$FE,$00,$00
  Data.a $00,$00,$CE,$CE,$FE,$FE,$FE,$CE,$CE,$CE,$00,$00,$00,$00,$EE,$EE,$FE,$FE,$FE,$FE,$EE,$EE,$00,$00,$00,$00,$7C,$7C,$EE,$EE,$EE,$EE,$EE,$7C,$00,$00,$00,$00,$7E,$7E,$EE,$EE,$7E,$0E,$0E,$0E,$00,$00
  Data.a $00,$00,$7C,$7C,$EE,$EE,$EE,$EE,$7C,$F0,$00,$00,$00,$00,$7E,$7E,$EE,$EE,$7E,$3E,$7E,$EE,$00,$00,$00,$00,$7C,$7C,$EE,$0E,$7C,$E0,$EE,$7C,$00,$00,$00,$00,$FE,$FE,$38,$38,$38,$38,$38,$38,$00,$00
  Data.a $00,$00,$EE,$EE,$EE,$EE,$EE,$EE,$EE,$7C,$00,$00,$00,$00,$EE,$EE,$EE,$EE,$EE,$EE,$7C,$38,$00,$00,$00,$00,$CE,$CE,$CE,$CE,$FE,$FE,$FE,$CE,$00,$00,$00,$00,$EE,$EE,$EE,$7C,$38,$7C,$EE,$EE,$00,$00
  Data.a $00,$00,$EE,$EE,$EE,$EE,$7C,$38,$38,$38,$00,$00,$00,$00,$FE,$FE,$E0,$70,$38,$1C,$0E,$FE,$00,$00,$00,$00,$7C,$7C,$1C,$1C,$1C,$1C,$1C,$7C,$00,$00,$00,$00,$7C,$7C,$70,$70,$70,$70,$70,$7C,$00,$00
  Data.a $00,$00,$38,$38,$7C,$FE,$38,$38,$38,$38,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$00,$00,$00,$00,$00,$00,$00,$7C,$E0,$FC,$EE,$FC,$00,$00,$00,$00,$00,$00,$0E,$0E,$7E,$EE,$EE,$7E,$00,$00
  Data.a $00,$00,$00,$00,$00,$7C,$0E,$0E,$0E,$7C,$00,$00,$00,$00,$00,$00,$E0,$E0,$FC,$EE,$EE,$FC,$00,$00,$00,$00,$00,$00,$00,$7C,$EE,$FE,$0E,$7C,$00,$00,$00,$00,$00,$00,$F0,$38,$FC,$38,$38,$38,$00,$00
  Data.a $00,$00,$00,$00,$00,$FC,$EE,$EE,$FC,$E0,$7E,$00,$00,$00,$0E,$0E,$0E,$7E,$EE,$EE,$EE,$EE,$00,$00,$00,$00,$38,$38,$00,$3C,$38,$38,$38,$7C,$00,$00,$00,$00,$00,$00,$70,$00,$70,$70,$70,$70,$3C,$00
  Data.a $00,$00,$0E,$0E,$0E,$0E,$7E,$3E,$7E,$EE,$00,$00,$00,$00,$3C,$3C,$38,$38,$38,$38,$38,$7C,$00,$00,$00,$00,$00,$00,$00,$EE,$FE,$FE,$FE,$CE,$00,$00,$00,$00,$00,$00,$00,$7E,$EE,$EE,$EE,$EE,$00,$00
  Data.a $00,$00,$00,$00,$00,$7C,$EE,$EE,$EE,$7C,$00,$00,$00,$00,$00,$00,$00,$7E,$EE,$EE,$7E,$0E,$0E,$00,$00,$00,$00,$00,$00,$FC,$EE,$EE,$FC,$E0,$E0,$00,$00,$00,$00,$00,$00,$7E,$EE,$0E,$0E,$0E,$00,$00
  Data.a $00,$00,$00,$00,$00,$FC,$0E,$7C,$E0,$7E,$00,$00,$00,$00,$00,$00,$38,$FE,$38,$38,$38,$F0,$00,$00,$00,$00,$00,$00,$00,$EE,$EE,$EE,$EE,$FC,$00,$00,$00,$00,$00,$00,$00,$EE,$EE,$EE,$7C,$38,$00,$00
  Data.a $00,$00,$00,$00,$00,$CE,$FE,$FE,$FC,$FC,$00,$00,$00,$00,$00,$00,$00,$EE,$7C,$38,$7C,$EE,$00,$00,$00,$00,$00,$00,$00,$EE,$EE,$EE,$FC,$70,$3E,$00,$00,$00,$00,$00,$00,$FE,$70,$38,$1C,$FE,$00,$00
  Data.a $00,$00,$F0,$F0,$38,$38,$1E,$38,$38,$F0,$00,$00,$00,$00,$1E,$1E,$38,$38,$F0,$38,$38,$1E,$00,$00
  EndDataSection
EndModule

DeclareModule stripes
  Global spr_id.i
  Global columns.i
  Declare create(size.i)
  Declare draw(animationsteps.f)  
EndDeclareModule

Module stripes
  Procedure.i Create(size.i)
    Protected img_stripe.i
    img_stripe=CreateImage(#PB_Any,size,size,24,RGBA(1,1,1,255))
    StartVectorDrawing(ImageVectorOutput(img_stripe))
      MovePathCursor(0,size) : AddPathLine(size/2,0) : AddPathLine(size,0) : AddPathLine(size/2,size) : ClosePath()
      VectorSourceColor(RGBA(255,128,0,255)) : FillPath()
    StopVectorDrawing()
    stripes::spr_id=CreateSprite(#PB_Any,size,size)
    StartDrawing(SpriteOutput(stripes::spr_id)) : DrawImage(ImageID(img_stripe),0,0) : StopDrawing()
    FreeImage(img_stripe)
    columns.i = ScreenWidth()/SpriteWidth(stripes::spr_id)
    If IsSprite(stripes::spr_id) :ProcedureReturn #True : EndIf
    ProcedureReturn #False  
  EndProcedure
  
  Procedure.i draw(animationstep.f)
    Protected i.i
    Static offset.f =0
    For i=-1 To columns+1
      DisplaySprite(stripes::spr_id,i*SpriteWidth(stripes::spr_id)+offset,0)
      DisplaySprite(stripes::spr_id,i*SpriteWidth(stripes::spr_id)-offset,ScreenHeight()-SpriteHeight(stripes::spr_id))
    Next i
    offset.f + animationstep.f
    If offset>SpriteWidth(stripes::spr_id) : offset -SpriteWidth(stripes::spr_id) : EndIf
  EndProcedure  
EndModule

;-MAINPROGRAM FILE START HERE

;-CONSTANTS
#MAINDESKTOP_H = 0
#WINDOW_H = 0

#WINDOW_WIDTH = 1366
#WINDOW_HEIGHT = 768

#WINDOW_FLAGS  = #PB_Window_Invisible|#PB_Window_BorderLess|#PB_Window_ScreenCentered
#MAINLOOP_DELAY = 1
#COMPILER_MINIMUM_VERSION = 620

#ship_count = 10000
#SPRSIZE = 5
#ARROWDIST = 20
#GRID_COUNT = 3000
#GRIDSIZE = 100

#STRIPESIZE = 32
#STRIPESPEED = 2

#LEFTBORDER = 0
#RIGHTBORDER = #GRID_COUNT*#GRIDSIZE
#TOPBORDER =0
#BOTTOMBORDER = #GRID_COUNT*#GRIDSIZE

#off = -45
#off2 = -225
#ROTATION_SPEED = 0.5
#MOUSEWHEEL_SENSITIVY = 0.05

#MINZOOM = 0.25
#MAXZOOM = 5
#MAX_INTENSITY = 255

;-TYPES
Structure cameratype
  x.f
  y.f
  tx.f
  ty.f
  angle.f
  zoom.f
  tzoom.f
  scrollspeed.f
EndStructure

Structure spritetype
  spid.i
  ospid.i
  basesize.f
  hb.f
  x.f
  y.f
  destx.f
  desty.f
  angle.f
  tangle.f
  color.i
  speed.f
EndStructure

;-GLOBALS
Global.i airship_sprite_id , arrowsprite_ID, gridsprite_ID, gridsprite2_ID
Global camera.cameratype
Global Dim sprs.spritetype(#ship_count)
Global Dim grid.spritetype(#GRID_COUNT,#GRID_COUNT)
Global sincounter.f

Global Dim tiles.i(50)

;-AUXILIARY PROCEDURES

Procedure loadtiles()
  Protected imageid.i
  imageid = CatchImage(#PB_Any,?grasspng)

  tiles(0) = CreateSprite(#PB_Any,16,16)
  StartDrawing(SpriteOutput(tiles(0)))
  DrawingMode(#PB_2DDrawing_Default|#PB_2DDrawing_AllChannels)
    DrawAlphaImage(ImageID(imageid),0,0)
  StopDrawing()
  
  tiles(1) = CreateSprite(#PB_Any,16,16)
  StartDrawing(SpriteOutput(tiles(1)))
  DrawingMode(#PB_2DDrawing_Default|#PB_2DDrawing_AllChannels)
    DrawImage(ImageID(imageid),-16,0)
  StopDrawing()
  
  tiles(2) = CreateSprite(#PB_Any,16,16)
  StartDrawing(SpriteOutput(tiles(2)))
  DrawingMode(#PB_2DDrawing_Default|#PB_2DDrawing_AllChannels)
    DrawImage(ImageID(imageid),-32,0)
  StopDrawing()
    
  tiles(3) = CreateSprite(#PB_Any,16,16)
  StartDrawing(SpriteOutput(tiles(3)))
  DrawingMode(#PB_2DDrawing_Default|#PB_2DDrawing_AllChannels)
    DrawImage(ImageID(imageid),-48,0)
  StopDrawing()
    
  tiles(4) = CreateSprite(#PB_Any,16,16)
  StartDrawing(SpriteOutput(tiles(4)))
  DrawingMode(#PB_2DDrawing_Default|#PB_2DDrawing_AllChannels)
    DrawImage(ImageID(imageid),-64,0)
  StopDrawing()
  FreeImage(imageid)
  
  imageid = CatchImage(#PB_Any,?deadgrasspng)
  tiles(5) = CreateSprite(#PB_Any,16,16)
  StartDrawing(SpriteOutput(tiles(5)))
  DrawingMode(#PB_2DDrawing_Default|#PB_2DDrawing_AllChannels)
    DrawAlphaImage(ImageID(imageid),0,0)
  StopDrawing()
  
  tiles(6) = CreateSprite(#PB_Any,16,16)
  StartDrawing(SpriteOutput(tiles(6)))
  DrawingMode(#PB_2DDrawing_Default|#PB_2DDrawing_AllChannels)
    DrawImage(ImageID(imageid),-16,0)
  StopDrawing()
  
  tiles(7) = CreateSprite(#PB_Any,16,16)
  StartDrawing(SpriteOutput(tiles(7)))
  DrawingMode(#PB_2DDrawing_Default|#PB_2DDrawing_AllChannels)
    DrawImage(ImageID(imageid),-16,-16)
  StopDrawing()
    
  tiles(8) = CreateSprite(#PB_Any,16,16)
  StartDrawing(SpriteOutput(tiles(8)))
  DrawingMode(#PB_2DDrawing_Default|#PB_2DDrawing_AllChannels)
    DrawImage(ImageID(imageid),0,-16)
  StopDrawing()
  FreeImage(imageid)
  
  imageid = CatchImage(#PB_Any,?treespng)
  tiles(9) = CreateSprite(#PB_Any,16,16,#PB_Sprite_AlphaBlending)
  StartDrawing(SpriteOutput(tiles(9)))
  DrawingMode(#PB_2DDrawing_Default|#PB_2DDrawing_AllChannels)
    DrawAlphaImage(ImageID(imageid),0,0)
  StopDrawing()
    
  tiles(10) = CreateSprite(#PB_Any,16,16,#PB_Sprite_AlphaBlending)
  StartDrawing(SpriteOutput(tiles(10)))
  DrawingMode(#PB_2DDrawing_Default|#PB_2DDrawing_AllChannels)
    DrawAlphaImage(ImageID(imageid),-16,0)
  StopDrawing()
    
  tiles(11) = CreateSprite(#PB_Any,16,16,#PB_Sprite_AlphaBlending)
  StartDrawing(SpriteOutput(tiles(11)))
  DrawingMode(#PB_2DDrawing_Default|#PB_2DDrawing_AllChannels)
    DrawAlphaImage(ImageID(imageid),-32,0)
  StopDrawing()
    
  tiles(12) = CreateSprite(#PB_Any,16,16,#PB_Sprite_AlphaBlending)
  StartDrawing(SpriteOutput(tiles(12)))
  DrawingMode(#PB_2DDrawing_Default)
    DrawAlphaImage(ImageID(imageid),-48,0)
  StopDrawing()
FreeImage(imageid)
  
EndProcedure

Procedure.i floor(f.f)
  ProcedureReturn Round(f.f,#PB_Round_Down)
EndProcedure

Procedure.i ceil(f.f)
  ProcedureReturn Round(f.f,#PB_Round_Up)
EndProcedure

Procedure sub_checks()
  If #PB_Compiler_Debugger
    Debug "Please run without debugger"
    End
  EndIf
  
EndProcedure

Procedure sub_createsprite()
  loadtiles()
  
  airship_sprite_id.i=CreateSprite(#PB_Any,#SPRSIZE,#SPRSIZE,#PB_Sprite_AlphaBlending)
  StartDrawing(SpriteOutput(airship_sprite_id.i))
  DrawingMode(#PB_2DDrawing_Outlined|#PB_2DDrawing_AllChannels)
  Box(0,0,OutputWidth(),OutputHeight())
  StopDrawing()
  
  arrowsprite_ID.i=CreateSprite(#PB_Any,#SPRSIZE,#SPRSIZE,#PB_Sprite_AlphaBlending)
  StartDrawing(SpriteOutput(arrowsprite_ID.i))
  DrawingMode(#PB_2DDrawing_Outlined|#PB_2DDrawing_AllChannels)
  Box(#SPRSIZE/2,0,1,#SPRSIZE)
  Plot(#SPRSIZE/2-1,1):Plot(#SPRSIZE/2+1,1)
  StopDrawing()
  
  gridsprite_ID.i=CreateSprite(#PB_Any,#GRIDSIZE,#GRIDSIZE,#PB_Sprite_AlphaBlending)
  StartDrawing(SpriteOutput(gridsprite_ID.i))
  DrawingMode(#PB_2DDrawing_Default|#PB_2DDrawing_AllChannels)
  Box(0,0,OutputWidth(),OutputHeight(),RGBA(0,50,0,255))
  Protected x.i
  For x = 1 To 1000
    Plot(Random(OutputWidth()-1),Random(OutputHeight()-1),RGBA(Random(10),20+Random(50),Random(10),255))
  Next x
  StopDrawing()
  
  gridsprite2_ID.i=CreateSprite(#PB_Any,#GRIDSIZE,#GRIDSIZE,#PB_Sprite_AlphaBlending)
  StartDrawing(SpriteOutput(gridsprite2_ID.i))
  DrawingMode(#PB_2DDrawing_Default|#PB_2DDrawing_AllChannels)
  Box(0,0,OutputWidth(),OutputHeight(),RGBA(0,0,50,255))
  
  For x = 1 To 1000
    Plot(Random(OutputWidth()-1),Random(OutputHeight()-1),RGBA(Random(40),Random(40),40+Random(80),255))
  Next x

  
  StopDrawing()
EndProcedure

Procedure sub_camerasetup()
  With camera
    \x=ScreenWidth()/4
    \y=ScreenHeight()/4
    \tx=ScreenWidth()/4
    \ty=ScreenHeight()/4
    \angle = 0
    \zoom = 1.0
    \tzoom = 2.0
    \scrollspeed = 2.0
  EndWith
EndProcedure

Procedure sub_airship_setup()
  Protected x.i
  For x = 0 To #ship_count
    With sprs(x)
      \spid = airship_sprite_id
      \x = Random(#GRID_COUNT*#GRIDSIZE)/20
      \y = Random(#GRID_COUNT*#GRIDSIZE)/20
      \destx = \x
      \desty = \y
      ;\tangle = Degree(ATan2(\destx-\x,\desty-\y))
      \tangle = Random(359)
      \angle = \tangle
      \basesize = 40.0
      \hb = \basesize/2.0
      \speed = (5+Random(5,1))/2
      \color.i = RGBA(255,5,5,255)
    EndWith
  Next x
EndProcedure

Procedure sub_grid_setup()
  Protected i.i,j.i
  For i = 0 To #grid_count
    For j = 0 To #grid_count
      With grid(i,j)
        ;If Random(1)  
        ;  \spid = gridsprite_ID
        ;Else
        ;  \spid = gridsprite2_ID
        ;EndIf
        \spid = tiles(Random(8,0))
        If \spid =tiles(1) Or \spid =tiles(2) 
          If Random(4)<1
            \ospid = tiles(10+Random(2))
          EndIf
        EndIf
       
        If \spid =tiles(5) Or \spid =tiles(8) 
          If Random(4)<1
            \ospid = tiles(9)
          EndIf
        EndIf

        
        
        \x = i*#GRIDSIZE
        \y = j*#GRIDSIZE
        \destx = i*#GRIDSIZE
        \desty = j*#GRIDSIZE
        ;\tangle = Degree(ATan2(\destx-\x,\desty-\y))
        \tangle = 0
        \angle = 0
        \basesize = #GRIDSIZE
        \hb = \basesize/2.0
        \color.i = RGBA(0+Random(10),Random(Random(55)+25),0+Random(10),255)
     EndWith
    Next j
  Next i
EndProcedure

Procedure sub_draw_UI()
    stripes::draw(#STRIPESPEED)
    petskii::textoutlined(0,2,"mouse = Scroll",RGBA(255,0,0,255),RGBA(5,5,5,5))
    petskii::textoutlined(350,2,"mwheel = zoom",RGBA(0,255,0,255),RGBA(5,5,5,255))
    
    
    petskii::textoutlined(700,2,"mousebutton left+right = rotate direction",RGBA(255,255,55,255),RGBA(5,5,5,255))
    petskii::textoutlined(450,741,"mousebutton middle = move",RGBA(255,255,255,255),RGBA(5,5,5,255))
    petskii::textoutlined(1150,741,"Escape = Quit",RGBA(255,55,55,255),RGBA(5,5,5,255))
    petskii::textoutlined(0,38,"Zoom level = ",RGBA(5,5,5,255),RGBA(255,5,5,255))
    petskii::textoutlined(210,38,StrF(camera\zoom,0),RGBA(5,5,5,255),RGBA(255,255,125,255))
    petskii::textoutlined(0,60,"Camera     = ",RGBA(5,5,5,255),RGBA(155,155,250,255))
    petskii::textoutlined(210,60,"("+StrF(camera\x,0)+" , "+ StrF(camera\y,0)+")",RGBA(155,155,250,255),RGBA(5,5,5,255))
    
    petskii::textoutlined(0,82,"Number of Tiles = "+Str(#GRID_COUNT*#GRID_COUNT),RGBA(255,200,0,255),RGBA(5,5,5,5))
    petskii::textoutlined(0,104,"Number of Ships = "+Str(#ship_count),RGBA(255,200,0,255),RGBA(5,5,5,5))
    
    Protected mem.i = MemoryStatus(#PB_System_FreePhysical)/(1024*1024)
    If mem>2024
      petskii::textoutlined(0,126,"Free Memory = "+Str(mem)+" Mb",RGBA(55,255,0,255),RGBA(5,5,5,5))
    ElseIf mem<1000
      petskii::textoutlined(0,126,"Free Memory = "+Str(mem)+" Mb",RGBA(255,20,0,255),RGBA(5,5,5,5))
    Else
      petskii::textoutlined(0,126,"Free Memory = "+Str(mem)+" Mb",RGBA(255,200,0,255),RGBA(5,5,5,5))
    EndIf
    
    petskii::textoutlined(0,741,FormatDate("%hh:%ii:%ss",Date()),RGBA(255,255,55,255),RGBA(5,5,5,255))
EndProcedure

;-PROCEDURES
Procedure app_start()
  sub_checks()
  ExamineDesktops()
  InitMouse()
  InitSprite()
  InitKeyboard()
  OpenWindow(#WINDOW_H,0,0,#WINDOW_WIDTH,#WINDOW_HEIGHT,"Login screen",#WINDOW_FLAGS)
  OpenWindowedScreen(WindowID(#WINDOW_H),0,0,#WINDOW_WIDTH,#WINDOW_HEIGHT,1,0,0,#PB_Screen_WaitSynchronization)
  ResizeWindow(#WINDOW_H,0,0,DesktopUnscaledX(DesktopWidth(#MAINDESKTOP_H)),DesktopUnscaledY(DesktopHeight(#MAINDESKTOP_H)))
  HideWindow(#WINDOW_H,#False)
  petskii::init()
  sub_createsprite()
  stripes::Create(#STRIPESIZE)
  sub_camerasetup()
  sub_airship_setup()
  sub_grid_setup()
EndProcedure

Procedure app_update()
  Protected x.i,i.i,j.i, multiplier.i
  Protected ddist.f = camera\zoom*8
  Protected dx.f, dy.f, trx.f,try.f, tmod.f
  Delay(#MAINLOOP_DELAY)
  Repeat : Until Not WindowEvent()
  ClearScreen(0)
  ExamineKeyboard()
  ExamineMouse()
  
  If MouseButton(#PB_MouseButton_Left)
    For x = 0 To #ship_count
      sprs(x)\tangle - #ROTATION_SPEED
    Next x
  EndIf
  
  If MouseButton(#PB_MouseButton_Right)
    For x = 0 To #ship_count
      sprs(x)\tangle + #ROTATION_SPEED
    Next x
  EndIf
  
  multiplier.i = (2*camera\zoom)
  If multiplier<1 : multiplier = 1 : EndIf  :  If multiplier>20 : multiplier = 20 : EndIf
  
  camera\tx + camera\scrollspeed*((MouseDeltaX()/(multiplier*2)))
  camera\ty + camera\scrollspeed*((MouseDeltaY()/(multiplier*2)))
  
  If camera\tx<#LEFTBORDER : camera\tx=#LEFTBORDER : EndIf
  If camera\tx>#RIGHTBORDER : camera\tx=#RIGHTBORDER : EndIf
  If camera\ty<#TOPBORDER : camera\ty=#TOPBORDER : EndIf
  If camera\ty>#BOTTOMBORDER : camera\ty=#BOTTOMBORDER : EndIf
  
  camera\x = camera\x*0.9+camera\tx*0.1
  camera\y = camera\y*0.9+camera\ty*0.1
  camera\zoom = camera\zoom*0.95+camera\tzoom*0.05
  
  For x = 0 To #ship_count
    sprs(x)\angle = sprs(x)\angle*0.9+sprs(x)\tangle*01
  Next x
    
  If MouseButton(#PB_MouseButton_Middle)
    For x = 0 To #ship_count
      sprs(x)\destx = sprs(x)\x- Sin(Radian(#off2+sprs(x)\angle))*sprs(x)\speed-Cos(Radian(#off2+sprs(x)\angle))*sprs(x)\speed
      sprs(x)\desty = sprs(x)\y-(-Cos(Radian(#off2+sprs(x)\angle)))*sprs(x)\speed-Sin(Radian(#off2+sprs(x)\angle))*sprs(x)\speed
    Next x
  EndIf
  
  If MouseWheel()<>0
    camera\tzoom=camera\tzoom+MouseWheel() * #MOUSEWHEEL_SENSITIVY * multiplier
    If camera\tzoom<#MINZOOM : camera\tzoom = #MINZOOM : EndIf
    If camera\tzoom>#MAXZOOM : camera\tzoom = #MAXZOOM : EndIf
  EndIf
  
  
    
  
  
  Protected.i startgridx,endgridx,startgridy,endgridy
  
  For i = 0 To 15
    If IsSprite(tiles(i))
      ZoomSprite(tiles(i),ceil(grid(1,1)\basesize*camera\zoom),ceil(grid(1,1)\basesize*camera\zoom))
    EndIf
  Next i
  
  
  
  For i = 0 To #grid_count
    trx = floor(i*(#gridsize)-(camera\x)+ScreenWidth())
    If trx>-ScreenWidth()-4*SpriteWidth(grid(i,0)\spid)
      startgridx = i 
      endgridx = startgridx+55 :
      ;endgridx = startgridx+ceil(ScreenWidth()/(#gridsize*camera\zoom))
      If endgridx > #GRID_COUNT : endgridx = #GRID_COUNT : EndIf
      i = #grid_count
    EndIf
  Next i
  
  For i = 0 To #grid_count
    try = floor(i*(#gridsize)-(camera\y)+ScreenHeight())
    If try>-ScreenHeight()-SpriteHeight(grid(i,0)\spid)
      startgridy = i 
      endgridy = startgridy+29 
      ;endgridy = startgridy+ceil(ScreenHeight()/(#gridsize*camera\zoom))
      If endgridy > #GRID_COUNT : endgridy = #GRID_COUNT : EndIf
      i = #grid_count
    EndIf
  Next i
  
  
  
  
  
  For i = startgridx To endgridx
    For j = startgridy To endgridy
      With grid(i,j)
        trx = floor(i*(#gridsize*camera\zoom)-(camera\x*camera\zoom)+ScreenWidth()/2)
        try = floor(j*(#gridsize*camera\zoom)-(camera\y*camera\zoom)+ScreenHeight()/2)
        ;ZoomSprite(grid(i,j)\spid,ceil(grid(i,j)\basesize*camera\zoom),ceil(grid(i,j)\basesize*camera\zoom))
        ;DisplayTransparentSprite(\spid,trx,try,#MAX_INTENSITY,\color)
        DisplayTransparentSprite(\spid,trx,try)
        If \ospid<>0 : DisplayTransparentSprite(\ospid,trx,try) : EndIf
      EndWith
    Next j
  Next i

  ZoomSprite(airship_sprite_id,2*sprs(0)\hb*camera\zoom,2*sprs(0)\hb*camera\zoom)
  ZoomSprite(arrowsprite_ID,2*sprs(0)\hb*camera\zoom,2*sprs(0)\hb*camera\zoom)
  
  For x = 0 To #ship_count
    With sprs(x)
      trx = \x*(\basesize*camera\zoom)-(camera\x*camera\zoom)+ScreenWidth()/2
      try = \y*(\basesize*camera\zoom)-(camera\y*camera\zoom)+ScreenHeight()/2
      \x=\destx*0.05+\x*0.95
      \y=\desty*0.05+\y*0.95
      tmod = SpriteWidth(airship_sprite_id)/-2+SpriteWidth(arrowsprite_ID)*0.5
      RotateSprite(arrowsprite_ID,floor(\angle),#PB_Absolute)
      

        DisplayTransparentSprite(\spid,floor(trx+\hb*camera\zoom),floor(try+\hb*camera\zoom),#MAX_INTENSITY,\color)
        ;ddist.f = #arrowdist + SpriteWidth(airship_sprite_id)/2+(Sin(sincounter)*2)*camera\zoom
        
        
        DisplayTransparentSprite(arrowsprite_ID,floor(tmod+trx+SpriteWidth(airship_sprite_id)/2+((Sin(Radian(#off+\angle)))*#ARROWDIST*camera\zoom+Cos(Radian(#off+\angle))*#ARROWDIST*camera\zoom)),floor(tmod+try+SpriteWidth(airship_sprite_id)/2+(-Cos(Radian(#off+\angle)))*#ARROWDIST*camera\zoom+Sin(Radian(#off+\angle))*#ARROWDIST*camera\zoom))

    
    EndWith
  Next x
  sub_Draw_UI()
  FlipBuffers()
EndProcedure
;-MAIN PROGRAM PROCEDURE
Procedure main()
  app_start()
  Repeat
    app_update()
  Until KeyboardPushed(#PB_Key_Escape)
  petskii::destroy()
  End
EndProcedure

;-MAIN PROGRAM
main()


DataSection
grasspng:
Data.a $89,$50,$4E,$47,$0D,$0A,$1A,$0A,$00,$00,$00,$0D,$49,$48,$44,$52,$00,$00,$00,$50,$00,$00,$00,$10,$08,$06,$00,$00,$00,$81,$49,$F8,$C1,$00,$00,$01
Data.a $85,$69,$43,$43,$50,$49,$43,$43,$20,$70,$72,$6F,$66,$69,$6C,$65,$00,$00,$28,$91,$7D,$91,$3D,$48,$C3,$40,$1C,$C5,$5F,$53,$4B,$45,$2A,$0E,$ED,$20
Data.a $22,$18,$B0,$3A,$59,$10,$15,$71,$94,$2A,$16,$C1,$42,$69,$2B,$B4,$EA,$60,$72,$E9,$87,$D0,$A4,$21,$49,$71,$71,$14,$5C,$0B,$0E,$7E,$2C,$56,$1D,$5C
Data.a $9C,$75,$75,$70,$15,$04,$C1,$0F,$10,$27,$47,$27,$45,$17,$29,$F1,$7F,$49,$A1,$45,$8C,$07,$C7,$FD,$78,$77,$EF,$71,$F7,$0E,$10,$1A,$15,$A6,$9A,$5D
Data.a $E3,$80,$AA,$59,$46,$3A,$11,$17,$73,$F9,$15,$31,$F8,$8A,$20,$C2,$08,$60,$08,$C3,$12,$33,$F5,$64,$66,$21,$0B,$CF,$F1,$75,$0F,$1F,$5F,$EF,$62,$3C
Data.a $CB,$FB,$DC,$9F,$A3,$57,$29,$98,$0C,$F0,$89,$C4,$B3,$4C,$37,$2C,$E2,$75,$E2,$E9,$4D,$4B,$E7,$BC,$4F,$1C,$61,$65,$49,$21,$3E,$27,$1E,$33,$E8,$82
Data.a $C4,$8F,$5C,$97,$5D,$7E,$E3,$5C,$72,$58,$E0,$99,$11,$23,$9B,$9E,$23,$8E,$10,$8B,$A5,$0E,$96,$3B,$98,$95,$0D,$95,$78,$8A,$38,$AA,$A8,$1A,$E5,$0B
Data.a $39,$97,$15,$CE,$5B,$9C,$D5,$4A,$8D,$B5,$EE,$C9,$5F,$18,$2A,$68,$CB,$19,$AE,$D3,$1C,$44,$02,$8B,$48,$22,$05,$11,$32,$6A,$D8,$40,$05,$16,$62,$B4
Data.a $6A,$A4,$98,$48,$D3,$7E,$DC,$C3,$3F,$E0,$F8,$53,$E4,$92,$C9,$B5,$01,$46,$8E,$79,$54,$A1,$42,$72,$FC,$E0,$7F,$F0,$BB,$5B,$B3,$38,$39,$E1,$26,$85
Data.a $E2,$40,$E0,$C5,$B6,$3F,$46,$80,$E0,$2E,$D0,$AC,$DB,$F6,$F7,$B1,$6D,$37,$4F,$00,$FF,$33,$70,$A5,$B5,$FD,$D5,$06,$30,$F3,$49,$7A,$BD,$AD,$45,$8F
Data.a $80,$BE,$6D,$E0,$E2,$BA,$AD,$C9,$7B,$C0,$E5,$0E,$D0,$FF,$A4,$4B,$86,$E4,$48,$7E,$9A,$42,$B1,$08,$BC,$9F,$D1,$37,$E5,$81,$F0,$2D,$D0,$B3,$EA,$F6
Data.a $D6,$DA,$C7,$E9,$03,$90,$A5,$AE,$96,$6E,$80,$83,$43,$60,$B4,$44,$D9,$6B,$1E,$EF,$EE,$EE,$EC,$ED,$DF,$33,$AD,$FE,$7E,$00,$7C,$89,$72,$AB,$1A,$50
Data.a $E7,$4E,$00,$00,$00,$06,$62,$4B,$47,$44,$00,$93,$00,$67,$00,$4D,$2A,$10,$06,$37,$00,$00,$00,$09,$70,$48,$59,$73,$00,$00,$0B,$13,$00,$00,$0B,$13
Data.a $01,$00,$9A,$9C,$18,$00,$00,$00,$07,$74,$49,$4D,$45,$07,$E4,$07,$13,$06,$02,$1A,$7A,$54,$30,$1F,$00,$00,$00,$19,$74,$45,$58,$74,$43,$6F,$6D,$6D
Data.a $65,$6E,$74,$00,$43,$72,$65,$61,$74,$65,$64,$20,$77,$69,$74,$68,$20,$47,$49,$4D,$50,$57,$81,$0E,$17,$00,$00,$00,$BB,$49,$44,$41,$54,$58,$C3,$63
Data.a $F4,$DB,$B3,$F3,$3F,$03,$05,$A0,$54,$6A,$1E,$25,$DA,$19,$DE,$FD,$FD,$4B,$91,$7E,$33,$26,$7B,$86,$AF,$EF,$5F,$C3,$F9,$DC,$82,$A2,$0C,$0C,$0C,$0C
Data.a $28,$62,$C8,$E2,$C8,$72,$DC,$82,$A2,$58,$F5,$92,$02,$98,$18,$86,$01,$E0,$16,$14,$85,$63,$6C,$72,$E4,$8A,$11,$02,$5F,$DF,$BF,$1E,$1E,$01,$88,$2B
Data.a $50,$89,$0D,$30,$72,$02,$6F,$58,$A5,$40,$62,$02,$91,$56,$60,$58,$07,$20,$AD,$03,$99,$5B,$50,$74,$34,$00,$29,$05,$2C,$A3,$41,$40,$1E,$80,$D5,$DE
Data.a $4C,$A3,$01,$F1,$1A,$A3,$C9,$43,$6C,$E0,$8D,$A6,$40,$32,$CB,$40,$E4,$B6,$E6,$68,$19,$48,$61,$16,$1E,$2D,$03,$29,$4C,$B9,$A3,$29,$70,$B4,$1D,$38
Data.a $1A,$80,$54,$29,$8B,$06,$42,$FF,$B0,$A9,$44,$70,$05,$02,$BE,$C0,$41,$96,$23,$27,$10,$87,$5D,$25,$82,$3C,$44,$45,$AC,$5A,$52,$F4,$E0,$AA,$44,$00
Data.a $0C,$38,$49,$A7,$A3,$33,$11,$6F,$00,$00,$00,$00,$49,$45,$4E,$44,$AE,$42,$60,$82
EndDataSection

DataSection
deadgrasspng:
Data.a $89,$50,$4E,$47,$0D,$0A,$1A,$0A,$00,$00,$00,$0D,$49,$48,$44,$52,$00,$00,$00,$30,$00,$00,$00,$20,$08,$06,$00,$00,$00,$54,$D4,$FB,$1C,$00,$00,$01
Data.a $85,$69,$43,$43,$50,$49,$43,$43,$20,$70,$72,$6F,$66,$69,$6C,$65,$00,$00,$28,$91,$7D,$91,$3D,$48,$C3,$40,$18,$86,$DF,$A6,$4A,$45,$2A,$0E,$16,$14
Data.a $71,$08,$58,$5D,$B4,$20,$2A,$E2,$28,$55,$2C,$82,$85,$D2,$56,$68,$D5,$C1,$E4,$D2,$3F,$68,$D2,$90,$A4,$B8,$38,$0A,$AE,$05,$07,$7F,$16,$AB,$0E,$2E
Data.a $CE,$BA,$3A,$B8,$0A,$82,$E0,$0F,$88,$93,$A3,$93,$A2,$8B,$94,$F8,$5D,$52,$68,$11,$E3,$1D,$C7,$3D,$BC,$F7,$BD,$2F,$77,$DF,$01,$42,$BD,$CC,$54,$B3
Data.a $63,$02,$50,$35,$CB,$48,$C6,$A2,$62,$26,$BB,$2A,$06,$5E,$11,$44,$3F,$CD,$31,$0C,$4B,$CC,$D4,$E3,$A9,$C5,$34,$3C,$C7,$D7,$3D,$7C,$7C,$BF,$8B,$F0
Data.a $2C,$EF,$BA,$3F,$47,$8F,$92,$33,$19,$E0,$13,$89,$E7,$98,$6E,$58,$C4,$1B,$C4,$33,$9B,$96,$CE,$79,$9F,$38,$C4,$8A,$92,$42,$7C,$4E,$3C,$6E,$D0,$05
Data.a $89,$1F,$B9,$2E,$BB,$FC,$C6,$B9,$E0,$B0,$C0,$33,$43,$46,$3A,$39,$4F,$1C,$22,$16,$0B,$6D,$2C,$B7,$31,$2B,$1A,$2A,$F1,$34,$71,$58,$51,$35,$CA,$17
Data.a $32,$2E,$2B,$9C,$B7,$38,$AB,$E5,$2A,$6B,$DE,$93,$BF,$30,$98,$D3,$56,$52,$5C,$A7,$35,$84,$18,$96,$10,$47,$02,$22,$64,$54,$51,$42,$19,$16,$22,$B4
Data.a $6B,$A4,$98,$48,$D2,$79,$D4,$C3,$3F,$E8,$F8,$13,$E4,$92,$C9,$55,$02,$23,$C7,$02,$2A,$50,$21,$39,$7E,$F0,$3F,$F8,$DD,$5B,$33,$3F,$35,$E9,$26,$05
Data.a $A3,$40,$E7,$8B,$6D,$7F,$8C,$00,$81,$5D,$A0,$51,$B3,$ED,$EF,$63,$DB,$6E,$9C,$00,$FE,$67,$E0,$4A,$6B,$F9,$2B,$75,$60,$F6,$93,$F4,$5A,$4B,$0B,$1F
Data.a $01,$BD,$DB,$C0,$C5,$75,$4B,$93,$F7,$80,$CB,$1D,$60,$E0,$49,$97,$0C,$C9,$91,$FC,$B4,$84,$7C,$1E,$78,$3F,$A3,$6F,$CA,$02,$7D,$B7,$40,$F7,$9A,$DB
Data.a $B7,$E6,$39,$4E,$1F,$80,$34,$F5,$6A,$F9,$06,$38,$38,$04,$46,$0B,$94,$BD,$EE,$F1,$EE,$AE,$F6,$BE,$FD,$5B,$D3,$EC,$DF,$0F,$DE,$34,$72,$D2,$94,$1E
Data.a $82,$6D,$00,$00,$00,$06,$62,$4B,$47,$44,$00,$E7,$00,$D5,$00,$93,$81,$F3,$95,$95,$00,$00,$00,$09,$70,$48,$59,$73,$00,$00,$0B,$13,$00,$00,$0B,$13
Data.a $01,$00,$9A,$9C,$18,$00,$00,$00,$07,$74,$49,$4D,$45,$07,$E4,$0C,$18,$01,$31,$37,$6E,$7E,$A9,$CF,$00,$00,$00,$19,$74,$45,$58,$74,$43,$6F,$6D,$6D
Data.a $65,$6E,$74,$00,$43,$72,$65,$61,$74,$65,$64,$20,$77,$69,$74,$68,$20,$47,$49,$4D,$50,$57,$81,$0E,$17,$00,$00,$01,$6C,$49,$44,$41,$54,$58,$C3,$ED
Data.a $97,$CD,$6A,$83,$40,$14,$85,$BF,$16,$91,$41,$74,$61,$98,$6C,$5C,$84,$AC,$F2,$92,$79,$AC,$42,$9F,$A4,$AB,$AC,$D2,$D2,$66,$53,$69,$16,$11,$11,$11
Data.a $DA,$8D,$77,$08,$1A,$FF,$D0,$29,$A4,$9D,$BB,$12,$9D,$39,$73,$CE,$9C,$C3,$8C,$F7,$E1,$F9,$69,$FF,$CD,$1D,$D7,$23,$77,$5E,$4E,$C0,$9F,$14,$B0,$59
Data.a $EF,$D8,$AC,$77,$00,$14,$79,$49,$91,$97,$AD,$F7,$4B,$CD,$B3,$22,$E0,$ED,$F3,$60,$16,$56,$81,$6F,$9E,$AF,$BF,$0D,$CD,$03,$50,$81,$3F,$38,$CF,$5B
Data.a $9A,$BC,$EC,$5A,$5E,$65,$00,$E8,$38,$21,$E5,$44,$5E,$65,$A4,$E7,$D3,$28,$F1,$3A,$4E,$50,$81,$8F,$8E,$13,$83,$23,$B8,$B2,$21,$D6,$1C,$90,$05,$DE
Data.a $3F,$8E,$00,$86,$F4,$18,$F2,$52,$CD,$39,$82,$D5,$24,$6F,$C5,$81,$6B,$CB,$A7,$90,$EE,$13,$D3,$17,$A5,$C5,$1D,$38,$BC,$BE,$98,$E8,$2C,$55,$82,$25
Data.a $D8,$D6,$23,$34,$36,$EF,$53,$5C,$C8,$AB,$EC,$66,$84,$AC,$9C,$42,$4B,$92,$1F,$C2,$74,$17,$99,$13,$F0,$DF,$05,$78,$A1,$E7,$3B,$07,$9C,$00,$27,$C0
Data.a $09,$68,$D7,$2A,$DE,$B2,$8A,$B7,$00,$64,$55,$49,$56,$95,$AD,$F7,$73,$C6,$5B,$17,$F0,$75,$3E,$1A,$02,$72,$D2,$09,$11,$F9,$D6,$35,$1E,$20,$F4,$FC
Data.a $DE,$F1,$D6,$7E,$A7,$65,$07,$01,$54,$DD,$8C,$A8,$48,$C3,$25,$25,$AF,$32,$8A,$4B,$DA,$2B,$5A,$45,$9A,$D0,$F3,$51,$91,$36,$CD,$8C,$E0,$DD,$3A,$F2
Data.a $AD,$38,$20,$0B,$C9,$0F,$98,$90,$EE,$23,$6F,$3A,$BA,$C6,$58,$C1,$E8,$BA,$AF,$3C,$6B,$F9,$AF,$77,$74,$0C,$E9,$3E,$31,$43,$51,$B2,$DA,$D4,$AB,$48
Data.a $CF,$EF,$2F,$6A,$8C,$5F,$6B,$EA,$C5,$EE,$A1,$BC,$4F,$71,$81,$A8,$3B,$42,$D6,$4E,$A1,$25,$C8,$8F,$C1,$72,$17,$99,$13,$30,$B3,$7E,$00,$3E,$54,$C7
Data.a $DB,$58,$06,$50,$88,$00,$00,$00,$00,$49,$45,$4E,$44,$AE,$42,$60,$82
EndDataSection

DataSection
treespng:
Data.a $89,$50,$4E,$47,$0D,$0A,$1A,$0A,$00,$00,$00,$0D,$49,$48,$44,$52,$00,$00,$00,$40,$00,$00,$00,$10,$08,$06,$00,$00,$00,$A6,$E7,$79,$29,$00,$00,$01
Data.a $85,$69,$43,$43,$50,$49,$43,$43,$20,$70,$72,$6F,$66,$69,$6C,$65,$00,$00,$28,$91,$7D,$91,$3D,$48,$C3,$40,$1C,$C5,$5F,$53,$4B,$45,$2A,$0E,$ED,$20
Data.a $22,$18,$B0,$3A,$59,$10,$15,$71,$94,$2A,$16,$C1,$42,$69,$2B,$B4,$EA,$60,$72,$E9,$87,$D0,$A4,$21,$49,$71,$71,$14,$5C,$0B,$0E,$7E,$2C,$56,$1D,$5C
Data.a $9C,$75,$75,$70,$15,$04,$C1,$0F,$10,$27,$47,$27,$45,$17,$29,$F1,$7F,$49,$A1,$45,$8C,$07,$C7,$FD,$78,$77,$EF,$71,$F7,$0E,$10,$1A,$15,$A6,$9A,$5D
Data.a $E3,$80,$AA,$59,$46,$3A,$11,$17,$73,$F9,$15,$31,$F8,$8A,$20,$C2,$08,$60,$08,$C3,$12,$33,$F5,$64,$66,$21,$0B,$CF,$F1,$75,$0F,$1F,$5F,$EF,$62,$3C
Data.a $CB,$FB,$DC,$9F,$A3,$57,$29,$98,$0C,$F0,$89,$C4,$B3,$4C,$37,$2C,$E2,$75,$E2,$E9,$4D,$4B,$E7,$BC,$4F,$1C,$61,$65,$49,$21,$3E,$27,$1E,$33,$E8,$82
Data.a $C4,$8F,$5C,$97,$5D,$7E,$E3,$5C,$72,$58,$E0,$99,$11,$23,$9B,$9E,$23,$8E,$10,$8B,$A5,$0E,$96,$3B,$98,$95,$0D,$95,$78,$8A,$38,$AA,$A8,$1A,$E5,$0B
Data.a $39,$97,$15,$CE,$5B,$9C,$D5,$4A,$8D,$B5,$EE,$C9,$5F,$18,$2A,$68,$CB,$19,$AE,$D3,$1C,$44,$02,$8B,$48,$22,$05,$11,$32,$6A,$D8,$40,$05,$16,$62,$B4
Data.a $6A,$A4,$98,$48,$D3,$7E,$DC,$C3,$3F,$E0,$F8,$53,$E4,$92,$C9,$B5,$01,$46,$8E,$79,$54,$A1,$42,$72,$FC,$E0,$7F,$F0,$BB,$5B,$B3,$38,$39,$E1,$26,$85
Data.a $E2,$40,$E0,$C5,$B6,$3F,$46,$80,$E0,$2E,$D0,$AC,$DB,$F6,$F7,$B1,$6D,$37,$4F,$00,$FF,$33,$70,$A5,$B5,$FD,$D5,$06,$30,$F3,$49,$7A,$BD,$AD,$45,$8F
Data.a $80,$BE,$6D,$E0,$E2,$BA,$AD,$C9,$7B,$C0,$E5,$0E,$D0,$FF,$A4,$4B,$86,$E4,$48,$7E,$9A,$42,$B1,$08,$BC,$9F,$D1,$37,$E5,$81,$F0,$2D,$D0,$B3,$EA,$F6
Data.a $D6,$DA,$C7,$E9,$03,$90,$A5,$AE,$96,$6E,$80,$83,$43,$60,$B4,$44,$D9,$6B,$1E,$EF,$EE,$EE,$EC,$ED,$DF,$33,$AD,$FE,$7E,$00,$7C,$89,$72,$AB,$1A,$50
Data.a $E7,$4E,$00,$00,$00,$06,$62,$4B,$47,$44,$00,$93,$00,$67,$00,$4D,$2A,$10,$06,$37,$00,$00,$00,$09,$70,$48,$59,$73,$00,$00,$0B,$13,$00,$00,$0B,$13
Data.a $01,$00,$9A,$9C,$18,$00,$00,$00,$07,$74,$49,$4D,$45,$07,$E4,$07,$13,$09,$14,$05,$E0,$98,$CF,$00,$00,$00,$00,$19,$74,$45,$58,$74,$43,$6F,$6D,$6D
Data.a $65,$6E,$74,$00,$43,$72,$65,$61,$74,$65,$64,$20,$77,$69,$74,$68,$20,$47,$49,$4D,$50,$57,$81,$0E,$17,$00,$00,$03,$72,$49,$44,$41,$54,$58,$C3,$D5
Data.a $56,$4B,$48,$1B,$51,$14,$3D,$E3,$67,$2F,$52,$9D,$C4,$45,$DB,$58,$6C,$17,$B5,$50,$1B,$63,$DA,$45,$C5,$85,$52,$1B,$14,$4B,$84,$A9,$A5,$69,$A4,$0A
Data.a $45,$C4,$A5,$88,$64,$13,$BA,$09,$22,$71,$55,$11,$37,$B1,$68,$53,$2A,$81,$16,$4A,$C4,$0A,$7E,$28,$B8,$8A,$51,$52,$DA,$A2,$A2,$A0,$B6,$A2,$E6,$83
Data.a $A2,$28,$6E,$34,$79,$5D,$24,$33,$9D,$97,$BC,$19,$93,$5A,$29,$3D,$30,$CC,$FB,$DC,$F3,$EE,$DC,$73,$EF,$7B,$F3,$38,$9C,$13,$01,$97,$E5,$5C,$FC,$B2
Data.a $56,$37,$73,$9C,$E7,$79,$02,$00,$A1,$50,$88,$4B,$C7,$FF,$DA,$49,$04,$00,$50,$9C,$5B,$C0,$6C,$B3,$E6,$00,$20,$07,$17,$80,$5A,$DB,$24,$91,$F7,$27
Data.a $1C,$35,$DC,$59,$1C,$97,$AB,$16,$00,$D0,$DA,$3A,$01,$9E,$E7,$C9,$D8,$7C,$13,$00,$A0,$AE,$7C,$94,$38,$1C,$65,$9C,$38,$27,$B7,$13,$B1,$76,$12,$81
Data.a $D9,$5A,$0A,$8D,$CE,$2D,$F9,$0D,$AE,$5B,$38,$79,$1F,$00,$06,$5E,$DE,$E6,$CC,$D6,$52,$00,$C0,$87,$91,$EF,$28,$CE,$2D,$F8,$7B,$02,$7C,$CE,$D9,$07
Data.a $00,$F4,$74,$F9,$A5,$8F,$97,$04,$29,$1F,$25,$DD,$BD,$06,$AE,$EA,$34,$4F,$B2,$AB,$3A,$CD,$A3,$82,$7F,$F0,$BC,$2C,$9E,$79,$5B,$80,$E2,$8F,$CD,$37
Data.a $A1,$AE,$7C,$94,$2C,$EC,$B4,$70,$2E,$40,$B2,$73,$25,$89,$A0,$D1,$B9,$25,$9E,$3F,$1A,$83,$46,$E7,$26,$76,$9F,$00,$43,$76,$96,$34,$D6,$6E,$F4,$10
Data.a $B3,$B5,$94,$4A,$86,$24,$80,$D3,$D6,$98,$51,$C0,$9D,$8E,$F7,$54,$F0,$95,$56,$23,$4C,$9A,$FE,$94,$E0,$E5,$41,$A0,$D7,$C0,$55,$5A,$8D,$71,$CE,$88
Data.a $8F,$12,$21,$1D,$18,$EF,$6A,$99,$E3,$ED,$F6,$2F,$C4,$EE,$13,$A4,$BE,$21,$3B,$0B,$F2,$E0,$E5,$63,$1A,$9D,$9B,$04,$D7,$2D,$1C,$25,$80,$D3,$D6,$88
Data.a $CA,$F2,$22,$14,$95,$E4,$63,$7B,$75,$0F,$45,$25,$F9,$00,$80,$ED,$D5,$3D,$00,$A0,$FA,$A2,$8D,$D3,$D6,$48,$89,$90,$0E,$EE,$DC,$2B,$52,$9D,$D7,$6B
Data.a $87,$14,$05,$D4,$6B,$87,$C8,$C2,$4E,$8B,$EA,$56,$F2,$47,$63,$19,$57,$AE,$24,$91,$18,$A4,$F8,$4E,$6E,$2B,$D9,$88,$30,$69,$FA,$A9,$2C,$24,$C3,$EE
Data.a $13,$20,$DC,$FF,$48,$70,$41,$D8,$08,$C7,$B3,$2C,$CF,$BA,$3F,$1A,$A3,$9E,$8D,$30,$A4,$2A,$48,$11,$40,$09,$AC,$60,$33,$CD,$42,$3A,$99,$D1,$6B,$87
Data.a $88,$DD,$27,$50,$B6,$62,$DB,$1F,$8D,$C1,$EE,$13,$A0,$D7,$0E,$11,$D6,$81,$6B,$F7,$09,$B8,$5A,$08,$AA,$DC,$C5,$B7,$5C,$14,$B9,$4D,$CA,$19,$70,$1E
Data.a $F4,$74,$F9,$49,$B3,$57,$38,$33,$E0,$66,$AF,$00,$93,$A6,$9F,$8C,$07,$3B,$D2,$2E,$E5,$4C,$CA,$FA,$4F,$B6,$00,$53,$00,$7D,$F5,$20,$A5,$F4,$C2,$54
Data.a $1B,$87,$0B,$84,$CD,$16,$A0,$04,$54,$42,$B3,$57,$60,$9E,$05,$1B,$61,$A4,$64,$78,$23,$0C,$A0,$30,$06,$96,$9D,$AA,$00,$FA,$EA,$41,$E2,$1F,$78,$0C
Data.a $4D,$61,$FC,$A2,$10,$0C,$47,$A0,$AF,$1E,$24,$0B,$53,$6D,$9C,$FC,$80,$54,$DA,$87,$AC,$32,$53,$72,$AE,$C4,$67,$AD,$A3,$C2,$E7,$86,$EB,$3D,$A4,$D9
Data.a $2B,$A4,$D8,$B0,$38,$C3,$F5,$1E,$00,$E0,$54,$CF,$00,$31,$F8,$E4,$76,$BA,$87,$11,$EB,$C9,$84,$CF,$5A,$47,$09,$13,$8E,$9A,$8C,$2B,$2E,$B8,$6E,$81
Data.a $AA,$00,$C1,$70,$84,$D9,$56,$01,$97,$50,$56,$15,$C9,$EA,$FF,$2B,$7E,$64,$79,$17,$5F,$97,$F7,$E8,$2D,$20,$2F,$EF,$83,$C3,$43,$1C,$1C,$1E,$2A,$2E
Data.a $24,$DE,$0F,$44,$74,$F7,$1A,$D0,$D3,$E5,$E7,$86,$EB,$3D,$04,$00,$DE,$76,$56,$50,$F3,$4F,$9D,$73,$D2,$87,$8E,$07,$3B,$52,$D6,$B3,$3C,$BB,$02,$F7
Data.a $9B,$1F,$69,$F1,$A7,$67,$4C,$D8,$5F,$0A,$62,$71,$E9,$F7,$37,$B4,$3D,$B9,$8C,$C1,$77,$3F,$D3,$E2,$7F,$FB,$F4,$90,$7D,$0F,$60,$05,$C6,$9A,$63,$D9
Data.a $AC,$2C,$EE,$C2,$33,$DB,$20,$65,$87,$2F,$B8,$44,$3D,$A2,$73,$CF,$6C,$03,$8E,$56,$37,$71,$B4,$BA,$89,$95,$C5,$5D,$6A,$8D,$E9,$19,$D3,$99,$FC,$84
Data.a $0D,$13,$89,$C0,$54,$F9,$C9,$C1,$4B,$15,$20,$BF,$D1,$F1,$3C,$CF,$74,$50,$61,$7E,$A5,$E8,$FC,$C5,$F5,$6B,$C0,$EC,$31,$26,$1C,$35,$A8,$B5,$4D,$2A
Data.a $EF,$D5,$D9,$63,$9A,$93,$40,$9F,$73,$0E,$7D,$89,$2C,$29,$F9,$0F,$85,$42,$28,$BD,$F9,$9A,$39,$F7,$E8,$D6,$0D,$6C,$05,$4E,$CF,$F4,$BF,$15,$38,$A5
Data.a $38,$4A,$BF,$C1,$F3,$FE,$F2,$FE,$2B,$FE,$2F,$86,$32,$BB,$EA,$DC,$7F,$AC,$90,$00,$00,$00,$00,$49,$45,$4E,$44,$AE,$42,$60,$82
EndDataSection

Re: Maths problem with basic camera

Posted: Tue Mar 04, 2025 3:09 pm
by Caronte3D
I don't see the ships :?

Re: Maths problem with basic camera

Posted: Tue Mar 04, 2025 3:11 pm
by miso
The map is too big ; ) They are there, but have to search for them carefully ;) They are still represented as small red squares with a white arrow.