2D Physics Engine
#11
(06-17-2023, 07:24 PM)justsomeguy Wrote:
(06-17-2023, 06:44 PM)TerryRitchie Wrote: I made some modifications to the scene to play around with the physics.

I'm wondering about something curious that happens, I'll call it the "popcorn effect". If you start filing the room I created with objects at some point the objects seem to get extra impulse from somewhere. It looks like popcorn and doesn't stop until the end of object lifetimes starts removing them, allowing the scene to settle down.

Any idea why this happens? Are there settings to control this kind of chaos from happening?

' Set the bouncyness
fzxSetBody cFZX_PARAMETER_RESTITUTION, temp, .95, 0 ' Bounce

Try lowering the restitution to something like .5. Using .95 is like a super ball on steroids. I did that to make it more bouncy.
Ah, gotcha. I'm going through to code to find all of these settings and get a feel for the flow of it. Once I get a better grasp on what's going on I'll cobble together a quick front end to make thing easier on myself.
Software and cathedrals are much the same — first we build them, then we pray.
QB64 Tutorial
Reply
#12
Your file structure should look like this.

[Image: File-Structure.png]

 I assume you are using windows? This could be also related to the differences in windows use of slashes. I thought QB64 compensated for those, but I may be mistaken. I will work on it to be more universal. Time to blow the dust off my windows machine.
Reply
#13
Another issue is may be how I set up my QB64 ide.  I use _CWD$ to locate my working directory.


[Image: QB64setting.png]

If you have "Output EXE to Source Folder" unselected it will put the executable in the QB64 directory and not in the source directory where the assets are located. This may be the issue.
Reply
#14
I'm starting to write some documentation for the engine. It's obviously a work in progress and there is still along way to go. However, I would like some feedback, to see if it clear enough and if it is informative enough for a person to make use of it. Any critique would be welcome as long as it is constructive.


.pdf   Documentation.pdf (Size: 101.73 KB / Downloads: 41)
Reply
#15
(06-19-2023, 12:25 PM)justsomeguy Wrote: I'm starting to write some documentation for the engine. It's obviously a work in progress and there is still along way to go. However, I would like some feedback, to see if it clear enough and if it is informative enough for a person to make use of it. Any critique would be welcome as long as it is constructive.
Yes, your documentation is off to an excellent start.

When I make documentation I've found the best feedback I receive from readers is from documentation that contains plenty of example code to explain the idea presented. When I was a teacher I found the best approach to teaching code was through example first then analysis of the code. By having many examples the students would play with the code then go back to read the synopsis of how the code worked. Many benefited from seeing it in action first.

Another benefit to documenting I found was showing where my code needed improved. If I found it difficult or confusing to explain a concept I often took a step back to see how I could modify my code to implement the concept much cleaner and straight forward. In other words if my documentation was difficult or confusing for me to follow, it would most definitely confuse the reader.

Thank you for creating documentation. I know first-hand this is often the most difficult and tedious task to complete, but for me was the most rewarding when finished. I'm looking forward to your progress. If there is anything I can assist with please don't hesitate to ask.
Software and cathedrals are much the same — first we build them, then we pray.
QB64 Tutorial
Reply
#16
Hello again,

I took a little break from writing documentation to add another little demo.

[Image: orbital-Mechanics-SS.png]


Its a simple orbital mechanics simulator. You basically shoot little planetoids around the larger planet and try to get them to orbit, or you can shoot the planet with the planetoids and it will absorb their mass and grow larger.

Cheers
justsomeguy
Code: (Select All)
'**********************************************************************************************
'   fzxOrbital Mechanics
'**********************************************************************************************

'$DYNAMIC
OPTION _EXPLICIT
_TITLE "fzxNGN Orbital Mechanics"

' Initialize FZXNGN types, globals and constants
'$include:'..\fzxNGN_BASE_v2\fzxNGN_ini.bas'

SCREEN _NEWIMAGE(1024, 768, 32)

DIM AS LONG iterations: iterations = 10
DIM SHARED AS DOUBLE dt: dt = 1 / 60

'**********************************************************************************************
' Build the playfield
'**********************************************************************************************

CONST cGRAVCONST = 1
' To little for our simulation
'CONST cGRAVCONST = 6.674E-11
buildScene

'**********************************************************************************************
' This is the main loop
'**********************************************************************************************

DO
  CLS
  fzxHandleInputDevice
  animatescene
  fzxImpulseStep dt, iterations
  renderBodies
  _DISPLAY
LOOP UNTIL INKEY$ = CHR$(27)

SYSTEM

' This provides access to all of the fzxNGN functionality
'$include:'..\fzxNGN_BASE_v2\fzxNGN_BASE.bas'

'**********************************************************************************************
'    This is where you interact with the world.
'**********************************************************************************************

SUB animatescene
  DIM AS LONG temp
  DIM AS DOUBLE vel, angle, sa, ca

  ' Use the mouse wheel to set Camera Zoom
  __fzxCamera.zoom = fzxImpulseClamp(.001, 2, __fzxCamera.zoom - (__fzxInputDevice.mouse.wCount * .001))
  __fzxInputDevice.mouse.wCount = 0
  fzxCalculateFOV

  ' Move the Camera to where you right clicked
  IF __fzxInputDevice.mouse.b2.PosEdge THEN
    fzxVector2DSet __fzxCamera.position, __fzxInputDevice.mouse.worldPosition.x, __fzxInputDevice.mouse.worldPosition.y
  END IF

  ' Give on screen visual, for how hard you are drawing back the velocity
  IF __fzxInputDevice.mouse.b1.drag THEN
    CIRCLE (__fzxInputDevice.mouse.b1.anchorPosition.x, __fzxInputDevice.mouse.b1.anchorPosition.y), 3, _RGB32(255, 255, 0)
    LINE (__fzxInputDevice.mouse.b1.anchorPosition.x, __fzxInputDevice.mouse.b1.anchorPosition.y)-(__fzxInputDevice.mouse.position.x, __fzxInputDevice.mouse.position.y), _RGB32(0, 0, 127), , &B1110110111011011
    CIRCLE (__fzxInputDevice.mouse.position.x, __fzxInputDevice.mouse.position.y), 3, _RGB32(255, 0, 0)
  END IF

  ' Release the orbital body
  IF __fzxInputDevice.mouse.b1.NegEdge THEN
    vel = fzxVector2DDistance(__fzxInputDevice.mouse.b1.anchorPosition, __fzxInputDevice.mouse.position) * __fzxCamera.invZoom

    angle = getangle(__fzxInputDevice.mouse.b1.anchorPosition.x, __fzxInputDevice.mouse.b1.anchorPosition.y, __fzxInputDevice.mouse.position.x, __fzxInputDevice.mouse.position.y)
    sa = -SIN(angle) * vel
    ca = COS(angle) * vel

    temp = fzxCreateCircleBodyEx("b" + _TRIM$(STR$(RND * 1000000000)), 100)
    ' Set the bodies parameters
    ' Put the body where the mouse is on the screen
    fzxSetBody cFZX_PARAMETER_POSITION, temp, __fzxInputDevice.mouse.worldPosition.x, __fzxInputDevice.mouse.worldPosition.y
    ' Give it the mouse's velocity
    fzxSetBody cFZX_PARAMETER_VELOCITY, temp, sa, ca
    fzxSetBody cFZX_PARAMETER_STATICFRICTION, temp, 0.9, 0
    fzxSetBody cFZX_PARAMETER_DYNAMICFRICTION, temp, 0.7, 0
    fzxSetBody cFZX_PARAMETER_RESTITUTION, temp, .10, 0

  END IF


  gravitizeEverthing

  LOCATE 1
  PRINT "Simple Gravity Mechanics Simulator"
  PRINT "Click and drag left mouse button to add a object and give it velocity."
  PRINT "Right click to move the camera. Use mouse wheel to zoom."

  IF fzxBodyManagerID("planetX") >= 0 THEN LOCATE 45: PRINT USING "PlanetX mass:#######.#"; __fzxBody(fzxBodyManagerID("planetX")).fzx.mass
END SUB

'********************************************************
'   Build you world here
'********************************************************

SUB buildScene
  DIM AS LONG temp

  'Initialize camera
  __fzxCamera.zoom = .0625
  fzxCalculateFOV

  '********************************************************
  '   Setup World
  '********************************************************

  fzxVector2DSet __fzxWorld.minusLimit, -200000, -200000
  fzxVector2DSet __fzxWorld.plusLimit, 200000, 200000
  fzxVector2DSet __fzxWorld.spawn, 0, 0
  fzxVector2DSet __fzxWorld.gravity, 0.0, 0.0

  ' Set camera position
  fzxVector2DSet __fzxCamera.position, __fzxWorld.spawn.x, __fzxWorld.spawn.y

  '********************************************************
  '   Build Level
  '********************************************************

  temp = fzxCreateCircleBodyEx("planetX", 800)
  fzxSetBody cFZX_PARAMETER_POSITION, temp, __fzxWorld.spawn.x, __fzxWorld.spawn.y
  fzxSetBody cFZX_PARAMETER_STATICFRICTION, temp, 0.9, 0
  fzxSetBody cFZX_PARAMETER_DYNAMICFRICTION, temp, 0.7, 0
  fzxSetBody cFZX_PARAMETER_RESTITUTION, temp, .10, 0

END SUB

SUB gravitizeEverthing
  DIM AS LONG i, j, touch
  DIM AS LONG ub: ub = UBOUND(__fzxBody)
  DIM AS DOUBLE gv, dist, newRAd
  DIM AS tFZX_VECTOR2d v1
  i = 0: DO WHILE i < ub
    j = 0: DO WHILE j < ub
      IF __fzxBody(i).enable AND __fzxBody(i).objectHash <> 0 AND __fzxBody(j).enable AND __fzxBody(j).objectHash <> 0 AND i <> j THEN

        dist = fzxVector2DDistance(__fzxBody(i).fzx.position, __fzxBody(j).fzx.position)
        gv = (cGRAVCONST * ((__fzxBody(i).fzx.mass * __fzxBody(j).fzx.mass) / (dist * dist)))

        ' Some math guru's can easily simplify this
        fzxVector2DSubVectorND v1, __fzxBody(i).fzx.position, __fzxBody(j).fzx.position '(o AS tFZX_VECTOR2d, v AS tFZX_VECTOR2d, m AS tFZX_VECTOR2d)
        fzxVector2DNormalize v1
        fzxVector2DMultiplyScalar v1, 100000000

        __fzxBody(i).fzx.force.x = __fzxBody(i).fzx.force.x - (gv * v1.x)
        __fzxBody(i).fzx.force.y = __fzxBody(i).fzx.force.y - (gv * v1.y)
      END IF
      j = j + 1
    LOOP

    ' Bodies can absorb each other
    touch = fzxIsBodyTouching(i) ' Who's touching me?
    IF touch > 0 THEN
      IF __fzxBody(i).fzx.mass > __fzxBody(touch).fzx.mass THEN ' Who's bigger?
        newRAd = addCircles(__fzxBody(i).shape.radius, __fzxBody(touch).shape.radius)
        __fzxBody(i).shape.radius = newRAd
        fzxCircleComputeMass i, cFZX_MASS_DENSITY
        fzxBodyDelete touch, 0
      ELSE
        newRAd = addCircles(__fzxBody(i).shape.radius, __fzxBody(touch).shape.radius)
        __fzxBody(touch).shape.radius = newRAd
        fzxCircleComputeMass touch, cFZX_MASS_DENSITY
        fzxBodyDelete i, 0
      END IF
    END IF
    i = i + 1
  LOOP

END SUB

FUNCTION addCircles# (r1 AS DOUBLE, r2 AS DOUBLE)
  DIM AS DOUBLE a1, a2
  a1 = _PI * r1 * r1
  a2 = _PI * r2 * r2
  addCircles = areaToRadius(a1 + a2)
END FUNCTION

FUNCTION areaToRadius# (area AS DOUBLE)
  areaToRadius = SQR(area / _PI)
END FUNCTION

SUB renderBodies STATIC
  DIM AS LONG i

  DIM AS LONG ub: ub = UBOUND(__fzxBody)

  'Draw all of the bodies that are visible
  i = 0: DO WHILE i < ub
    IF __fzxBody(i).enable AND __fzxBody(i).objectHash <> 0 THEN
      IF __fzxBody(i).shape.ty = cFZX_SHAPE_CIRCLE THEN
        renderWireFrameCircle i, _RGB32(0, 255, 0)
      ELSE IF __fzxBody(i).shape.ty = cFZX_SHAPE_POLYGON THEN
          renderWireFramePoly i
        END IF
      END IF
    END IF
    i = i + 1
  LOOP
END SUB

' Function written bu Galleon (modified for using radians)
FUNCTION getangle# (x1 AS DOUBLE, y1 AS DOUBLE, x2 AS DOUBLE, y2 AS DOUBLE) 'returns 0-359.99...
  IF y2 = y1 THEN
    IF x1 = x2 THEN EXIT FUNCTION
    IF x2 > x1 THEN getangle# = _PI * .5 ELSE getangle# = _PI * 1.5
    EXIT FUNCTION
  END IF
  IF x2 = x1 THEN
    IF y2 > y1 THEN getangle# = _PI
    EXIT FUNCTION
  END IF
  IF y2 < y1 THEN
    IF x2 > x1 THEN
      getangle# = -ATN((x2 - x1) / (y2 - y1))
    ELSE
      getangle# = -ATN((x2 - x1) / (y2 - y1)) + (2 * _PI)
    END IF
  ELSE
    getangle# = -ATN((x2 - x1) / (y2 - y1)) + _PI
  END IF
END FUNCTION


SUB renderWireFrameCircle (index AS LONG, c AS LONG)
  DIM AS tFZX_VECTOR2d o1
  fzxWorldToCameraEx __fzxBody(index).fzx.position, o1
  CIRCLE (o1.x, o1.y), __fzxBody(index).shape.radius * __fzxCamera.zoom, c
END SUB

SUB renderWireFramePoly (index AS LONG)
  DIM vert(3) AS tFZX_VECTOR2d

  fzxGetBodyVert index, 0, vert(0)
  fzxWorldToCamera index, vert(0)

  fzxGetBodyVert index, 1, vert(1)
  fzxWorldToCamera index, vert(1)

  fzxGetBodyVert index, 2, vert(2)
  fzxWorldToCamera index, vert(2)

  fzxGetBodyVert index, 3, vert(3)
  fzxWorldToCamera index, vert(3)

  LINE (vert(0).x, vert(0).y)-(vert(1).x, vert(1).y), _RGB(0, 255, 0)
  LINE (vert(1).x, vert(1).y)-(vert(2).x, vert(2).y), _RGB(0, 255, 0)
  LINE (vert(2).x, vert(2).y)-(vert(3).x, vert(3).y), _RGB(0, 255, 0)
  LINE (vert(3).x, vert(3).y)-(vert(0).x, vert(0).y), _RGB(0, 255, 0)
END SUB
Reply
#17
@justsomeguy - Something is missing:

Code: (Select All)
'$include:'..\fzxNGN_BASE_v2\fzxNGN_ini.bas'
Reply
#18
(06-23-2023, 04:09 PM)Kernelpanic Wrote: @justsomeguy - Something is missing:

Code: (Select All)
'$include:'..\fzxNGN_BASE_v2\fzxNGN_ini.bas'
Forgive me, Its a demo for the larger package. I assumed if you were following the thread you would already have it.

It is located in my github as well. https://github.com/mechatronic3000/fzxNGN


Attached Files
.7z   fzx_NGN_repo.7z (Size: 229.53 KB / Downloads: 15)
Reply
#19
Quote:Forgive me, . . .
Exceptionally! It is friday!  Big Grin  Thanks, now it works. However, I have a different folder structure and changed the links a bit.

[Image: Orbital-Ablauf2023-06-23.jpg]
Reply
#20
I've added another demo to my 2d physics engine. Its a soft-body simulation using mesh of joints and circles. Use the UP and Down arrow keys to adjust the bias on the joints. The bias is how stiff the joints are.

I have included everything in the zip, obviously no assets.

I'm still working on the documentation.

More demos (in various phases of functionality) are available on my github.

[Image: Screenshot.png]


Attached Files
.7z   fzxNGN.7z (Size: 133.11 KB / Downloads: 17)
Reply




Users browsing this thread: 3 Guest(s)