Page 2 of 2

Re: Demo in PB?

Posted: Sat Jan 24, 2026 6:23 pm
by Mindphazer
Nice demos miso, thanks !!
And i'm glad and honoured to be included to your greetings :D

Re: Demo in PB?

Posted: Sun Jan 25, 2026 4:31 pm
by miso
Thanks Mindphaser. I already see some mistakes in the code. The sin lookup table is mathematically incorrect. (but so small difference at the overflowing part, that it isn't visible.)

Re: Demo in PB?

Posted: Sun Jan 25, 2026 9:42 pm
by moulder61
@miso,
Your suggestion worked for example 3. :D

@Mindphazer,
I didn't notice you did a demo first! Yours is very nice too. Thanks for sharing. 8)

Moulder.

Re: Demo in PB?

Posted: Tue Jan 27, 2026 11:19 pm
by miso
Made a reusable module with some demostyle movements. Of course it has a correct sintable.
This is standalone and organized.

Code: Select all

DeclareModule tool
  Structure s_pointF
    x.f
    y.f
  EndStructure
  
  Structure s_pointI
    x.i
    y.i
  EndStructure
  
  Global Blank.i
  Global Full.i

  
  Declare ministart2d(wTitle.s)
  Declare minicheckevents()
  Declare msRadomSeed_Set(seed.q)
  Declare.q RadomSeed_Get(seed.q)
  Declare msRandom(min.i, max.i)
  Declare msRandomize()
  Declare.f LERP(a.f, b.f, t.f)
  Declare.f INVLERP(a.f, b.f, v.f)
  Declare.f Remap(iMin.f, iMAX.f, oMin.f, oMax.f, v.f)  
  Declare.f smoothmotion(x.f, targetx.f)
  Declare.f smoothstep256(a.a)
  Declare.f Sin256(a.a)
  Declare.f Cos256(a.a)
  Declare CirclePosF(cx.i, cy.i, r.i, phase.a, *result.s_pointF)
  Declare CirclePosI(cx.i, cy.i, r.i, phase.a, *result.s_pointI)
  Declare EllipsePosF(cx.i, cy.i, r1.i, r2, phase.a, *result.s_pointF)
  Declare EllipsePosI(cx.i, cy.i, r1.i, r2.i, phase.a, *result.s_pointI)
  Declare PingPongVF(x.i, y.i, r.i, phase.a, *result.s_pointF)
  Declare PingPongVI(x.i, y.i, r.i, phase.a, *result.s_pointI)
  Declare PingPongHF(x.i, y.i, r.i, phase.a, *result.s_pointF)
  Declare PingPongHI(x.i, y.i, r.i, phase.a, *result.s_pointI)
  Declare spiralPosF(cx.i, cy.i, r0.i, r1.i, phase.a, *result.s_pointF)
  Declare spiralPosI(cx.i, cy.i, r0.i, r1.i, phase.a, *result.s_pointI)
  Declare.i CircleReveal(SpriteId.i, Phase.a)
  Declare.i CircleHide(SpriteId.i, Phase.a)

  
EndDeclareModule

Module tool
  EnableExplicit
  ;===========================================
  ;Windowed fullscreen quickstart
  ;===========================================
  Procedure ministart2d(wTitle.s)
    InitSprite():InitKeyboard():InitMouse():UsePNGImageDecoder():UsePNGImageEncoder():UseJPEGImageDecoder():UseJPEGImageEncoder()
    ExamineDesktops()
    OpenWindow(0, 0, 0, DesktopUnscaledX(DesktopWidth(0)), DesktopUnscaledY(DesktopHeight(0)), wTitle, #PB_Window_ScreenCentered|#PB_Window_BorderLess)
    OpenWindowedScreen(WindowID(0), 0, 0, WindowWidth(0) * DesktopResolutionX() , WindowHeight(0) * DesktopResolutionY(), 0, 0, 0, #PB_Screen_WaitSynchronization)
  EndProcedure
  
  ;===========================================
  ;Quickly handles flipbuffers, window events, 
  ;keyboard and mouse, esc And mouse middle 
  ;quits For short programs/tests
  ;===========================================
  Procedure minicheckevents()
    FlipBuffers()
    While WindowEvent() : Wend
    ClearScreen(RGBA(0,0,0,255)) ;Linux Fix at the moment
	  ExamineKeyboard()
	  ExamineMouse()
	  MouseDeltaX()                ;Linux Fix at the moment
	  If KeyboardPushed(#PB_Key_Escape) Or MouseButton(#PB_MouseButton_Middle) : End : EndIf
  EndProcedure

  
  
  ;==============================================
  ;Random 
  ;This is 4 times slower than PB builtin one!
  ;Randomize is second based, that is a Warn!
  ;Not for cryptography!
  ;Still has its uses, designed to be able
  ;to know the seed without computation
  ;Can get the random value from seed+n or
  ;seed-n, can accept negative numbers,
  ;min - max is swappable.
  ;msRandom(1,100) is the same as msRandom(100,1)
  ;==============================================
  #MAJORSEED = $a7129B0134C2D728
  #MINORSEED = $1DC8FA4510E6C352
  
  Global msrandomSeed.q
  msrandomSeed = Date()
  
  ;==============================================
  ;Sets the seed (Quad)
  ;==============================================
  Procedure msRadomSeed_Set(seed.q)
    msrandomSeed = seed
  EndProcedure
  
  ;==============================================
  ;Get the seed (Quad)
  ;==============================================
  Procedure.q RadomSeed_Get(seed.q)
    ProcedureReturn msrandomSeed
  EndProcedure
  
  ;==============================================
  ;Generates a random number (Int)
  ;min and max can be swapped
  ;==============================================
  Procedure msRandom(min.i, max.i)
    Protected temp.q
    If max < min   :   Swap min,max   :   EndIf
    temp = msrandomSeed
    temp = temp ! (temp << 13)
    temp = temp ! (temp >> 17)
    temp = temp ! (temp << 5)
    temp & $7FFFFFFFFFFFFFFF
    msrandomSeed + 1
    ProcedureReturn min + (temp  %  (max - min + 1))
  EndProcedure
  
  ;FIXME
  ;=====================================================
  ;Randomize the seed. This is not really works randomly
  ;as seeds steps one at a time, date() steps 1 at 
  ;a second.
  ;=====================================================
  Procedure msRandomize()
    msrandomseed ! ElapsedMilliseconds() << 7
    msrandomseed ! Date() >> 7
    msrandomSeed ! (msRandomSeed >> 30)
    msrandomSeed * #MINORSEED
    msrandomseed ! ((msRandomSeed >> 27))
    msrandomSeed * #MAJORSEED
    msrandomseed ! ((msRandomSeed >> 31))
  EndProcedure
  
  ;==============================================
  ;Precreating sin256 Lookup Table
  ;This one is correct mathematically
  ;Automatically created if module is included
  ;==============================================
  Define i.i
  Global Dim sin256LUT.f(255)
  For i = 0 To 255
    sin256LUT(i) = Sin(2 * #PI * i / 256)
  Next i
  
  ;==============================================
  ;Precreating smoothstep256 Lookup Table
  ;Automatically created if module is included
  ;==============================================
  Define t.f
  Global Dim smoothstep256LUT.f(255)
  For i = 0 To 255
    t = i / 255
    SmoothStep256LUT(i)=  t  *  t  *  (3 - 2 * t)
  Next i
  
  ;==============================================
  ;Presets for alpha channel modifications
  ;Automatically sets if module is included
  ;==============================================
  Global Blank.i = RGBA(0,0,0,0)
  Global Full.i  = RGBA(0,0,0,255)
  
  ;==============================================
  ;Linear interpolation
  ;==============================================
  Procedure.f LERP(a.f, b.f, t.f)
    ProcedureReturn(((1.0 - t.f) * a) + (b * t))
  EndProcedure
  
  ;==============================================
  ;Inverted Linear interpolation
  ;==============================================
  Procedure.f INVLERP(a.f, b.f, v.f)
    If a = b : ProcedureReturn(1) : EndIf
    ProcedureReturn((v - a)  /  (b - a))
  EndProcedure
  
  ;==============================================
  ;Remap
  ;==============================================
  Procedure.f Remap(iMin.f, iMAX.f, oMin.f, oMax.f, v.f)  
    Define t.f
    t.f = INVLERP(iMin, iMAX, v)
    ProcedureReturn(LERP(oMin, oMax, t))
  EndProcedure
  
  ;==============================================
  ;Smooth motion, distance based, not time based
  ;==============================================
  Procedure.f smoothmotion(x.f, targetx.f)
    ProcedureReturn((0.9 * x.f) + (0.1 * targetx.f))
  EndProcedure
  
  ;==============================================
  ;Smoothstep, time/phase based, resolution 0-255
  ;==============================================
  Procedure.f smoothstep256(a.a)
    ProcedureReturn smoothstep256LUT(a)
  EndProcedure
  
  ;===============================================
  ;Sinus, angle/time/phase based, resolution 0-255
  ;===============================================
  Procedure.f Sin256(a.a)
    ProcedureReturn sin256LUT(a)
  EndProcedure
  
  ;=================================================
  ;CoSinus, angle/time/phase based, resolution 0-255
  ;sintable+64
  ;=================================================
  Procedure.f Cos256(a.a)
    a + 64
    ProcedureReturn sin256LUT(a)
  EndProcedure
  
  ;==================================================
  ;Position x,y (Float) in a circle center x,y radius
  ;based on angle/time/phase. Resolution 0-255
  ;==================================================
  Procedure CirclePosF(cx.i, cy.i, r.i, phase.a, *result.s_pointF)
    *result\x = sin256(phase) * r + cx
    *result\y = cos256(phase) * r + cy
  EndProcedure
  
  ;==================================================
  ;Position x,y (Int) in a circle center x,y radius
  ;based on angle/time/phase. Resolution 0-255
  ;==================================================
  Procedure CirclePosI(cx.i, cy.i, r.i, phase.a, *result.s_pointI)
    *result\x = sin256(phase) * r + cx
    *result\y = cos256(phase) * r + cy
  EndProcedure
  
  ;======================================================
  ;Position x,y (Float) in an ellipse center x,y, radius1
  ;radius 2, based on angle/time/phase. Resolution 0-255
  ;======================================================
  Procedure EllipsePosF(cx.i, cy.i, r1.i, r2, phase.a, *result.s_pointF)
    *result\x = sin256(phase) * r1 + cx
    *result\y = cos256(phase) * r2 + cy
  EndProcedure
  
  ;======================================================
  ;Position x,y (Int) in an ellipse center x,y, radius1
  ;radius 2, based on angle/time/phase. Resolution 0-255
  ;======================================================
  Procedure EllipsePosI(cx.i, cy.i, r1.i, r2.i, phase.a, *result.s_pointI)
    *result\x = sin256(phase) * r1 + cx
    *result\y = cos256(phase) * r2 + cy
  EndProcedure
  
  ;======================================================
  ;Position x,y (Float) of a vertical pingpong movement
  ;based on angle/time/phase. Resolution 0-255
  ;parameters: center x,y,radius, phase
  ;======================================================
  Procedure PingPongVF(x.i, y.i, r.i, phase.a, *result.s_pointF)
    *result\x = sin256(phase) * r + x
    *result\y = y
  EndProcedure
  
  ;======================================================
  ;Position x,y (Int) of a vertical pingpong movement
  ;based on angle/time/phase. Resolution 0-255
  ;parameters: center x,y,radius, phase
  ;======================================================
  Procedure PingPongVI(x.i, y.i, r.i, phase.a, *result.s_pointI)
    *result\x = sin256(phase) * r + x
    *result\y = y
  EndProcedure
  
  ;======================================================
  ;Position x,y (Float) of a horizontal pingpong movement
  ;based on angle/time/phase. Resolution 0-255
  ;parameters: center x,y,radius, phase
  ;======================================================
  Procedure PingPongHF(x.i, y.i, r.i, phase.a, *result.s_pointF)
    *result\x = x
    *result\y = cos256(phase) * r + y
  EndProcedure
  
  ;======================================================
  ;Position x,y (Int) of a horizontal pingpong movement
  ;based on angle/time/phase. Resolution 0-255
  ;parameters: center x,y,radius, phase
  ;======================================================
  Procedure PingPongHI(x.i, y.i, r.i, phase.a, *result.s_pointI)
    *result\x = x
    *result\y = cos256(phase) * r + y
  EndProcedure
  
  Procedure spiralPosF(cx.i, cy.i, r0.i, r1.i, phase.a, *result.s_pointF)
    Protected a.f, c.f, r.f, s.f
    s = sin256( phase )
    c = Cos256( phase )
    r = r0 + (r1 - r0) * (phase / 255)
    *result\x = cx + c * r
    *result\y = cy + s * r
  EndProcedure
  
  Procedure spiralPosI(cx.i, cy.i, r0.i, r1.i, phase.a, *result.s_pointI)
    Protected a.f, c.f, r.f, s.f
    s = sin256( phase )
    c = Cos256( phase )
    r = r0 + (r1 - r0) * (phase / 255)
    *result\x = cx + c * r
    *result\y = cy + s * r
  EndProcedure
  
  ;========================================================
  ;Reveals a sprite with a circle
  ;based on angle/time/phase. Resolution 0-255
  ;Modifies alpha channel, so works with background sprites
  ;========================================================
  Procedure.i CircleReveal(SpriteId.i, Phase.a)
    Protected dist.i, x, y
    If Not IsSprite( SpriteID ) : ProcedureReturn #False : EndIf 
  
    StartDrawing( SpriteOutput(Spriteid) )
    x=OutputWidth() / 2
    y=OutputHeight() / 2
    dist = Sqr( (x * x) + (y * y) ) + 5
    dist * smoothstep256(phase)
    
    DrawingMode(#PB_2DDrawing_AlphaChannel)
    Box(0, 0, OutputWidth(), OutputHeight(), Blank)
    Circle(x, y, dist, Full)
    StopDrawing()
  EndProcedure
  
  ;========================================================
  ;Hides a sprite with a circle
  ;based on angle/time/phase. Resolution 0-255
  ;Modifies alpha channel, so works with background sprites
  ;========================================================
  Procedure.i CircleHide(SpriteId.i, Phase.a)
    If Not IsSprite(SpriteID) : ProcedureReturn #False : EndIf
    Phase = 255 - Phase
    Circlereveal(SpriteID, Phase)
  EndProcedure

EndModule
A couple of usage example, mouse leftclick switches between them:

https://nextcloud.cloudns.ph/index.php/ ... 89L6EEykty

Re: Demo in PB?

Posted: Wed Jan 28, 2026 2:40 am
by Joubarbe
Thank you miso, that's really great! 🎉