wobble movement, slowly shaking sprite

Advanced game related topics
User avatar
TheAutomator
Enthusiast
Enthusiast
Posts: 112
Joined: Tue Dec 01, 2020 8:33 pm

wobble movement, slowly shaking sprite

Post by TheAutomator »

i'm coding movement for an element in my game,
the item has to move smoothly in a slightly rotating way but on average keep straight.

to simplify things, i would like to make a sprite move like a firefly.
here is the perfect example:
https://gifer.com/en/Rx73

does someone know how to do this? i googled it a lot but can only find aftereffects stuff or predefined effects in software..

Code: Select all

If InitSprite() = 0 Or InitKeyboard() = 0
	MessageRequester("Error", "Sprite system can't be initialized", 0)
	End
EndIf

If OpenScreen(800, 600, 32, "Sprite")
	
	LoadSprite(0, #PB_Compiler_Home + "examples/sources/Data/PureBasic.bmp")
	
	Repeat
		
		FlipBuffers()
		ClearScreen(RGB(0,0,0))
		
		ExamineKeyboard()
		
		x + Random(2)-1
     		y + Random(2)-1
      		r.f = Random(2)-1
     		RotateSprite(0, r, #PB_Relative)
		
		DisplaySprite(0, 50+ x, 50+ y)

	Until KeyboardPushed(#PB_Key_Escape)
	
Else
	MessageRequester("Error", "Can't open a 800*600 - 32 bit screen !", 0)
EndIf
User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: wobble movement, slowly shaking sprite

Post by Mijikai »

PB only:

Code: Select all

EnableExplicit

Procedure.i Main()
  Protected px.f
  Protected py.f
  Protected fmod.f
  Protected fx1.f
  Protected fx2.f
  If InitSprite()
    If OpenWindow(0,0,0,640,400,#Null$,#PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_MinimizeGadget)
      If OpenWindowedScreen(WindowID(0),0,0,640,400,#False,0,0,#PB_Screen_NoSynchronization)
        SetFrameRate(60)
        LoadSprite(0,#PB_Compiler_Home + "examples/sources/Data/PureBasic.bmp")
        px = 320 - (SpriteWidth(0) / 2)
        py = 200 - (SpriteHeight(0) / 2)
        Repeat
          Repeat
            Select WindowEvent()
              Case #PB_Event_CloseWindow
                Break 2
              Case #Null
                Break
            EndSelect
          ForEver
          fmod + 1.4
          fx1 = Sin(fmod / 50) * 10
          fx2 = Sin(fmod / 80) * 2
          ClearScreen(0)
          RotateSprite(0,fx2,#PB_Absolute)
          DisplaySprite(0,px,py + fx1)
          FlipBuffers()  
        ForEver
      EndIf
      CloseWindow(0)  
    EndIf  
  EndIf
  ProcedureReturn #Null
EndProcedure

Main()

End
PB + Nautilus:

Code: Select all

EnableExplicit

XIncludeFile "nautilus.pbi"

Procedure.i Main()
  Protected *ne.NAUTILUS_ENGINE
  Protected *sp.NAUTILUS_TEXTURE
  Protected fmod.f
  Protected fx1.f
  Protected fx2.f
  If nautilusVersion() = #NAUTILUS_VERSION
    If OpenWindow(0,0,0,800,600,#Null$,#PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_MinimizeGadget)
      *ne = nautilusEngine(WindowID(0),800,600)
      If *ne
        *ne\RenderFilter(#True);<- enable bilinear filtering
        *ne\RenderVSyncMode(#False);<- disable vsync
        *sp = *ne\CreateTexture(#Null,#PB_Compiler_Home + "examples/sources/Data/PureBasic.bmp")
        Repeat
          Select WaitWindowEvent(16)
            Case #PB_Event_CloseWindow
              Break
          EndSelect
          fmod + 1.4
          fx1 = Sin(fmod / 30) * 10
          fx2 = Sin(fmod / 80) * 2
          *ne\RenderBegin()
          *sp\DrawMod(400,300 + fx1,500,150,#True,$FF,$FFFFFF,fx2)
          *ne\RenderEnd()
        ForEver
        *ne\Release()
      EndIf
      CloseWindow(0)  
    EndIf  
  EndIf
  ProcedureReturn #Null
EndProcedure

Main()

End
User avatar
TheAutomator
Enthusiast
Enthusiast
Posts: 112
Joined: Tue Dec 01, 2020 8:33 pm

Re: wobble movement, slowly shaking sprite

Post by TheAutomator »

did you test "PB only", it just crashes after the image moves very fast and then slows down very hard in framerate..
the second one does the job but needs a whole engine for it?

this is what i came up with in the mean time, there must be a more easy way, like the Sin() function you showed but i need a little randomness in it :)

Code: Select all

InitSprite()

#w = 480
#h = 360

OpenWindow(0, 0, 0, #w, #h, "A screen in a window...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, #w, #h)

LoadSprite(0, "sb-129.bmp")

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

xpos.f = #w / 2
xvel.f = 0
xgo = 0
time = 0
timerandom = 0
ypos.f = #h / 2
yvel.f = 0
ygo = 0
speed.f = 0.025
maxspeed.f = 1

rot.f = 0
rgo.f = 0
rvel.f = 0
rspeed.f = 0.001
rmaxspeed.f = 0.5
rmax.f = 1

Xmid = SpriteWidth(0)/2
ymid = SpriteHeight(0)/2

Wmid = #w/2
Hmid = #h/2
WHmax = 2

Repeat
	Repeat
		If WindowEvent() = #PB_Event_CloseWindow : End : EndIf
	Until Event = 0
	
	FlipBuffers() 
	ClearScreen(0)
	
	DisplaySprite(0, xpos - Xmid, ypos - ymid)
	RotateSprite(0, rot, #PB_Absolute)
	
	If ElapsedMilliseconds() - time > timerandom
		xgo = Random(Wmid + WHmax, Wmid - WHmax)
		ygo = Random(Hmid + WHmax, Hmid - WHmax)
		rgo = Random(rmax)-rmax
		time = ElapsedMilliseconds()
		timerandom = Random(1000)
		;xpos = #w / 2
		;ypos = #h / 2
	EndIf
	
	If rot < rgo : rvel + rspeed : EndIf
	If rot > rgo : rvel - rspeed : EndIf
	
	If rvel > rmaxspeed : rvel = rmaxspeed : EndIf
	If rvel < -rmaxspeed : rvel = -rmaxspeed : EndIf
	
	rot + rvel
	
	If xpos < xgo : xvel + speed : EndIf
	If xpos > xgo : xvel - speed : EndIf
	
	If xvel > maxspeed : xvel = maxspeed : EndIf
	If xvel < -maxspeed : xvel = -maxspeed : EndIf
	
	xpos + xvel
	
	If ypos < ygo : yvel + speed : EndIf
	If ypos > ygo : yvel - speed : EndIf
	
	If yvel > maxspeed : yvel = maxspeed : EndIf
	If yvel < -maxspeed : yvel = -maxspeed : EndIf
		
	ypos + yvel
			
ForEver

User avatar
Demivec
Addict
Addict
Posts: 4086
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: wobble movement, slowly shaking sprite

Post by Demivec »

You can use easing functions with random input.

I apologize for not having the time to give you an example at the moment.
User avatar
DK_PETER
Addict
Addict
Posts: 898
Joined: Sat Feb 19, 2011 10:06 am
Location: Denmark
Contact:

Re: wobble movement, slowly shaking sprite

Post by DK_PETER »

Eddy did some great easing procedures here:
viewtopic.php?f=12&t=63770&hilit=easing
Current configurations:
Ubuntu 20.04/64 bit - Window 10 64 bit
Intel 6800K, GeForce Gtx 1060, 32 gb ram.
Amd Ryzen 9 5950X, GeForce 3070, 128 gb ram.
User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: wobble movement, slowly shaking sprite

Post by Mijikai »

TheAutomator wrote:did you test "PB only", it just crashes after the image moves very fast and then slows down very hard in framerate..
...
I had no issue with the PB code, so i cant tell why it is not working / crashing for you.
Sounds like some internal issue (VSync or timing).
Can you test it with OpenGL as subsystem?
User avatar
TheAutomator
Enthusiast
Enthusiast
Posts: 112
Joined: Tue Dec 01, 2020 8:33 pm

Re: wobble movement, slowly shaking sprite

Post by TheAutomator »

Demivec wrote:You can use easing functions with random input.
I apologize for not having the time to give you an example at the moment.
Hey man, no problem!
we all have our lives and now with the upcoming holydays i'm not super active here myself.
no need to apologize :)
User avatar
TheAutomator
Enthusiast
Enthusiast
Posts: 112
Joined: Tue Dec 01, 2020 8:33 pm

Re: wobble movement, slowly shaking sprite

Post by TheAutomator »

DK_PETER wrote:Eddy did some great easing procedures here:
viewtopic.php?f=12&t=63770&hilit=easing
Well after some research i seemed to need a Perlin noise algorithm.
Writing that for pb was not really an option for a beginner like me so
i ended up with randomized sin calls actually.

to show you an example i made this screensaver that mimics the SpongeBob titlecard gif
https://www.youtube.com/watch?v=A-WZOA6Fwng
as close as possible, it does the job:

Code: Select all

InitSprite()
InitSound()
InitKeyboard()

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

#w = 800
#h = 600

OpenScreen(#w, #h, 32, "SB-129")

LoadSound(0, "loop.wav")
PlaySound(0, #PB_Sound_Loop)

LoadSprite(0, "Titlecard.bmp")
LoadSprite(1, "sb-129.bmp")

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

; ProgramParameter()
; /s = normal start
; /c = configure window
; /p = little preview window

; they can be followed by the windo ID:
; /c:1024
; use WinAPI to display a graphic in the preview window when the 'P' parameter is passed to the program

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

xmid = #w / 2 - SpriteWidth(1) / 2
ymid = #h / 2 - SpriteHeight(1) / 2

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

XmaxSpd = 300 ; / 100
XminSpd = 100	; / 100

XmaxDis = 500 ; / 100
XminDis = 300	; / 100

YmaxSpd = 300 ; / 100
YminSpd = 200 ; / 100

YmaxDis = 1500 ; / 100
YminDis = 1000	; / 100

RmaxSpd = 400 ; / 100
RminSpd = 100	; / 100

RmaxDis = 200 ; / 100
RminDis = 50 ; / 100

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

x.f = 0
y.f = 0
r.f = 0

Xdis = XmaxDis ; how far from middle / 100
Ydis = YmaxDis	; how far from middle / 100
Rdis = RmaxDis	; how far from middle / 100

XnewDis = Xdis ; walk to random distance point
YnewDis = Ydis ; walk to random distance point
RnewDis = Rdis ; walk to random distance point

Xdeg.f = 0 ; 1 - 360
Ydeg.f = 0 ; 1 - 360
Rdeg.f = 0 ; 1 - 360

Xspd = XmaxSpd ; how much pixels per frame / 100
Yspd = YmaxSpd ; how much pixels per frame / 100
Rspd = RmaxSpd ; how much pixels per frame / 100

XnewSpd = Xspd ; walk to random speed point
YnewSpd = Yspd	; walk to random speed point
RnewSpd = Rspd ; walk to random speed point

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

snip = ElapsedMilliseconds()
time = 1000
duration = SoundLength(0)

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

Repeat
	
	ExamineKeyboard()
	FlipBuffers()
	
	;--------------------------------
	
	r = Sin(Radian(Rdeg)) * (Rdis / 100)
	
	If Rdis = Rnewdis
		Rnewdis = Random(RmaxDis, RminDis)
	ElseIf Rdis < Rnewdis
		Rdis + 1
	Else
		Rdis - 1
	EndIf
		
	Rdeg + Rspd / 100
	
	If Rdeg > 360 : Rdeg = 0 : EndIf
	
	If Rspd = Rnewspd
		Rnewspd = Random(RmaxSpd, RminSpd)
	ElseIf Rspd < Rnewspd
		Rspd + 1
	Else
		Rspd - 1
	EndIf
	
	;--------------------------------
	
	x = Sin(Radian(Xdeg)) * (Xdis / 100)
	
	If Xdis = Xnewdis
		Xnewdis = Random(XmaxDis, XminDis)
	ElseIf Xdis < Xnewdis
		Xdis + 1
	Else
		Xdis - 1
	EndIf
	
	Xdeg + Xspd / 100
	
	If Xdeg > 360 : Xdeg = 0 : EndIf
	
	If Xspd = Xnewspd
		Xnewspd = Random(XmaxSpd, XminSpd)
	ElseIf Xspd < Xnewspd
		Xspd + 1
	Else
		Xspd - 1
	EndIf
	
	;--------------------------------
	
	Y = Sin(Radian(Ydeg)) * (Ydis / 100)
	
	If Ydis = Ynewdis
		Ynewdis = Random(YmaxDis, YminDis)
	ElseIf Ydis < Ynewdis
		Ydis + 1
	Else
		Ydis - 1
	EndIf
	
	Ydeg + Yspd / 100
	
	If Ydeg > 360 : Ydeg = 0 : EndIf
	
	If Yspd = Ynewspd
		Ynewspd = Random(YmaxSpd, YminSpd)
	ElseIf Yspd < Ynewspd
		Yspd + 1
	Else
		Yspd - 1
	EndIf
	
	;--------------------------------
	
	If ElapsedMilliseconds() - snip > time
		snip = ElapsedMilliseconds()
		SetSoundPosition(0, duration - Random(duration))
		SetSoundFrequency(0, Random(54100, 34100))
	EndIf
	
	;--------------------------------
	
	DisplaySprite(0,0,0)
	RotateSprite(1, r, #PB_Absolute)
	DisplayTransparentSprite(1, xmid + x, ymid + y)
	
Until KeyboardInkey()
Post Reply