woke up in the middle of the night with a solution similar to blink's tho not as pretty
// Project: 2D Wrap
// Created: 2023-05-04
// show all errors
SetErrorMode(2)
// set window properties
SetWindowTitle( "2D Wrap" )
SetWindowSize( 640,360, 0 )
SetWindowAllowResize( 1 ) // allow the user to resize the window
// set display properties
SetVirtualResolution( 640,360 ) // doesn't have to match the window
SetOrientationAllowed( 1, 1, 1, 1 ) // allow both portrait and landscape on mobile devices
SetSyncRate( 30, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts
CenterWindow()
Type Object
ID, OriginX#, OriginY#, Velocity#
EndType
GLOBAL BufferX#, WorldWidth#
WorldWidth# = 2000.0
GLOBAL Objects as Object []
GLOBAL Player as Object
MakeWorld()
Player.ID = CreateSprite(0) : SetSpriteSize(Player.ID, 32,16)
SetSpritePositionByOffset(Player.ID, 1000,180)
GLOBAL OffX#, DIR#
do
Move()
Check()
Sync()
loop
Function Check()
PlayerX# = GetSpriteXByOffset(Player.ID)
Low# = WrapX(GetSpriteXByOffset(Player.ID)-BufferX#)
High# = WrapX(GetSpriteXByOffset(Player.ID)+BufferX#)
Print(STR(Low#,0) + "["+STR(PlayerX#,0) + "]" + STR(High#,0))
For x = 0 to Objects.Length //Move Enemies
If Objects[x].Velocity# <> 0.0
Objects[x].OriginX# = WrapX(Objects[x].OriginX# + Objects[x].Velocity#)
EndIf
ThisEnemy = Objects[x].ID
ThisX# = GetSpriteXByOffset(ThisEnemy)
If Objects[x].OriginX# <> ThisX# then SetSpritePositionByOffset(ThisEnemy, Objects[x].OriginX#, GetSpriteYByOffset(Objects[x].ID))
Next x
If Low# => High# //Wrap
For x = 0 to Objects.Length
ThisX# = Objects[x].OriginX#
If GetViewOffsetX() <= BufferX# //Left
If ThisX# >= Low# then SetSpritePositionByOffset(Objects[x].ID, ThisX#-WorldWidth# , GetSpriteYByOffset(Objects[x].ID) )
Else //Right
If ThisX# <= High# then SetSpritePositionByOffset(Objects[x].ID, ThisX# + WorldWidth#, GetSpriteYByOffset(Objects[x].ID) )
EndIf
Next x
EndIf
EndFunction
Function Move()
If GetRawKeyPressed(32) then SetSpritePositionByOffset(Player.ID, 320,GetSpriteYByOffset(Player.ID))
DIR# = 0
If GetJoystickX() < 0.0 then DIR# = -1.0
If GetJoystickX() > 0.0 then DIR# = 1.0
ThisX# = WrapX(GetSpriteXByOffset(Player.ID) + DIR#*30.0)
ThisY# = WrapY(GetSpriteYByOffset(Player.ID) + GetJoystickY()*5.0 )
SetSpritePositionByOffset(Player.ID, ThisX#, ThisY# )
OffX# = ThisX# - 320.0
SetViewOffset(OffX#, 0)
EndFunction
Function WrapX(Num#)
Result# = FMOD(NUM#, WorldWidth#)
if Result# < 0.0
Result# = Result# + WorldWidth#
endif
EndFunction Result#
Function Wrap(Num#, High#)
Result# = FMOD(NUM#, High#)
if Result# < 0.0
Result# = Result# + High#
endif
EndFunction Result#
Function WrapY(Num#)
Result# = FMOD(NUM#, 360.0)
if Result# < 0.0
Result# = Result# + 360.0
endif
EndFunction Result#
Function MakeWorld()
ThisObj as Object
For x = 0 to 9 //Static
ThisObj.ID = CreateSprite(0) : SetSpriteColor(ThisObj.ID, Random(128,255), Random(128,255), Random(128,255), 255)
SetSpriteSize(ThisObj.ID, Random(50,100), Random(50,100))
SetSpritePositionByOffset(ThisObj.ID, x*200, 360-(GetSpriteHeight(ThisObj.ID)/2.0) )
ThisObj.OriginX# = GetSpriteXByOffset(ThisObj.ID)
Objects.Insert(ThisObj)
If GetSpriteWidth(ThisObj.ID)/2.0 > BufferX# then BufferX# = GetSpriteWidth(ThisObj.ID)/2.0
Next x
For x = 0 to 9 //Dynamic
ThisObj.ID = CreateSprite(0) : SetSpriteColor(ThisObj.ID, Random(128,255), Random(128,255), Random(128,255), 255)
SetSpriteSize(ThisObj.ID, Random(20,50), 10)
SetSpritePositionByOffset(ThisObj.ID, x*200, Random(100,220) )
ThisObj.OriginX# = GetSpriteXByOffset(ThisObj.ID)
ThisObj.Velocity# = 20.0 : If Random(1,2) = 1 then ThisObj.Velocity# = -ThisObj.Velocity#
Objects.Insert(ThisObj)
If GetSpriteWidth(ThisObj.ID)/2.0 > BufferX# then BufferX# = GetSpriteWidth(ThisObj.ID)/2.0
Next x
BufferX# = BufferX# + 320.0
EndFunction
Function CenterWindow()
X = GetMaxDeviceWidth()/2.0 - GetWindowWidth()/2.0
Y = GetMaxDeviceHeight()/2.0 - GetWindowHeight()/2.0
SetWindowPosition( X,Y)
EndFunction
WASD + [Space] to Reset
this moves some sprites unnecessarily which is what i was trying to avoid in early rounds (and it also uses SetViewOffset() which i forgot i was using all along).
anyway, it might be nice to add this functionality to
THIS
re-reading your posts, BitManip, and i feel blink and i have only caught up to what you already have (this is why we should include code that shows the current start of the project so that we all start on the same page when looking for a solution)?
if i'm right, i've no time to implement now but when you're spawning groups, i'd mark 1 as the leader and the rest of the group spawns at a given offset (wrapped) from the leader's origin with those offsets recorded for future reference.
then, as the leader moves, the rest move at the same/similar rate based on their recorded offset from the leader. the wrapping (in my example) should still bring them into view when appropriate.
i'll implement groups and offsets when i get home from work this afternoon if nobody beats me to it and if this is what you're looking for. let us know?