I've made a demo of the physics engine ("fzxNGN") I've been working for the last few years. Its a port of the Impulse engine written by Randy Gaul. Its been 100% ported to QB64 and not a 3rd part wrapper. Some may recognize the demo from a few years back, I've simply updated it to the newer engine, and changed some of the graphics.
Inside the compressed file you will find two directories, "fzxNGN_BASE_v2" and "fzxDemo" The "fzxNGN_BASE" is the core of the engine. The actual demo is located in "fzxDemo/fzxDemo.bas". Hopefully, all you have to do is run the "fzxDemo.bas" to play with the demo. I develop in Linux, so there may be some changes needed for Windows and Mac. And the speed of your machine may vary from mine so adjusting the dt(delta time) and iterations may help. My machine is probably old enough to drive a car in my state.
Code: (Select All)
DIM AS LONG iterations: iterations = 2
DIM SHARED AS DOUBLE dt: dt = 1 / 60
The idea of this mini game is to cross the sketchy bridge and then make the loop-to-loop. Beware the sketchy bridge will break. The more red the bridge is, the more stress its under. This was in part a test of a game mechanic I was kicking around for a driving/platformer.
Current features:
Rigid body simulation
Circle and polygon primitives
Joint simulation
Camera library to help with large play fields
Input Library
Finite State machine helper functions
Perlin noise library
XML parsing library - (not 100% and not fully integrated)
LERP functions
FPS helper functions
Countless vector, matrix math functions
Caveats:
Not documented
Work in progress
Not fully optimized
Possibility of vestigial code, or code that has yet to be updated.
When time permits, I'll work on proper documentation.
As far as license goes:
Quote:This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely.
I will try to use this thread to post more updates for the engine.
'$DYNAMIC
OPTION _EXPLICIT
_TITLE "fzxNGN Bare Bones"
' Initialize FZXNGN types, globals and constants
'$include:'..\fzxNGN_BASE_v2\fzxNGN_ini.bas'
SCREEN _NEWIMAGE(1024, 768, 32)
DIM AS LONG iterations: iterations = 2
DIM SHARED AS DOUBLE dt: dt = 1 / 60
'**********************************************************************************************
' Build the playfield
'**********************************************************************************************
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
' Create a object on mouse click
IF __fzxInputDevice.mouse.b1.NegEdge THEN
' Drop a ball or a box, flip a coin
IF RND > .5 THEN
temp = fzxCreateCircleBodyEx("b" + _TRIM$(STR$(RND * 1000000000)), 10)
ELSE
temp = fzxCreateBoxBodyEx("b" + _TRIM$(STR$(RND * 1000000000)), 10, 10)
END IF
' 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, so you can throw it
fzxSetBody cFZX_PARAMETER_VELOCITY, temp, __fzxInputDevice.mouse.velocity.x, __fzxInputDevice.mouse.velocity.y
' Change its orientation or angle
fzxSetBody cFZX_PARAMETER_ORIENT, temp, _D2R(RND * 360), 0
' Set the bouncyness
fzxSetBody cFZX_PARAMETER_RESTITUTION, temp, .95, 0 ' Bounce
' Set the friction values of the body
fzxSetBody cFZX_PARAMETER_STATICFRICTION, temp, .1, 0
fzxSetBody cFZX_PARAMETER_DYNAMICFRICTION, temp, .85, 0
' Bodies wont live forever
fzxSetBody cFZX_PARAMETER_LIFETIME, temp, RND * 20 + 10, 0
END IF
END SUB
'********************************************************
' Build you world here
'********************************************************
SUB buildScene
DIM AS LONG temp
'Initialize camera
__fzxCamera.zoom = 1
fzxCalculateFOV
' Set camera position
fzxVector2DSet __fzxCamera.position, __fzxWorld.spawn.x, __fzxWorld.spawn.y - 300
'********************************************************
' Setup World
'********************************************************
' Some math used on the impulse side
' Todo: move this elsewhere
DIM o AS tFZX_VECTOR2d
fzxVector2DMultiplyScalarND o, __fzxWorld.gravity, dt
__fzxWorld.resting = fzxVector2DLengthSq(o) + cFZX_EPSILON
SUB renderBodies STATIC
DIM i AS LONG
DIM AS tFZX_VECTOR2d scSize, scMid, scUpperLeft, camUpperLeft, aabbUpperLeft, aabbSize, aabbHalfSize
DIM AS LONG ub: ub = UBOUND(__fzxBody)
' Todo : move this to camera functions
fzxVector2DSet aabbSize, 40000, 40000
fzxVector2DSet aabbHalfSize, aabbSize.x / 2, aabbSize.y / 2
'Draw all of the bodies that are visible
i = 0: DO WHILE i < ub
IF __fzxBody(i).enable THEN
'fzxAABB to cut down on rendering objects out of camera view
fzxVector2DSubVectorND aabbUpperLeft, __fzxBody(i).fzx.position, aabbHalfSize
IF fzxAABBOverlap(camUpperLeft.x, camUpperLeft.y, scSize.x, scSize.y, aabbUpperLeft.x, aabbUpperLeft.y, aabbSize.x, aabbSize.y) 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
END IF
i = i + 1
LOOP
END SUB
SUB renderWireFrameCircle (index AS LONG, c AS LONG)
DIM AS tFZX_VECTOR2d o1, o2
fzxWorldToCameraEx __fzxBody(index).fzx.position, o1
CIRCLE (o1.x, o1.y), __fzxBody(index).shape.radius * __fzxCamera.zoom, c
o2.x = o1.x + (__fzxBody(index).shape.radius * __fzxCamera.zoom) * COS(__fzxBody(index).fzx.orient)
o2.y = o1.y + (__fzxBody(index).shape.radius * __fzxCamera.zoom) * SIN(__fzxBody(index).fzx.orient)
LINE (o1.x, o1.y)-(o2.x, o2.y), c
END SUB
SUB renderWireFramePoly (index AS LONG)
DIM vert(3) AS tFZX_VECTOR2d
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
06-17-2023, 06:44 PM (This post was last modified: 06-17-2023, 06:46 PM by TerryRitchie.)
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?
'$DYNAMIC
OPTION _EXPLICIT
_TITLE "fzxNGN Bare Bones"
' Initialize FZXNGN types, globals and constants
'$include:'..\fzxNGN_BASE_v2\fzxNGN_ini.bas'
SCREEN _NEWIMAGE(1024, 768, 32)
DIM AS LONG iterations: iterations = 2
DIM SHARED AS DOUBLE dt: dt = 1 / 60
'**********************************************************************************************
' Build the playfield
'**********************************************************************************************
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
' Create a object on mouse click
IF __fzxInputDevice.mouse.b1.NegEdge THEN
' Drop a ball or a box, flip a coin
IF RND > .5 THEN
temp = fzxCreateCircleBodyEx("b" + _TRIM$(STR$(RND * 1000000000)), 20)
ELSE
temp = fzxCreateBoxBodyEx("b" + _TRIM$(STR$(RND * 1000000000)), 20, 20)
END IF
' 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, so you can throw it
fzxSetBody cFZX_PARAMETER_VELOCITY, temp, __fzxInputDevice.mouse.velocity.x, __fzxInputDevice.mouse.velocity.y
' Change its orientation or angle
fzxSetBody cFZX_PARAMETER_ORIENT, temp, _D2R(RND * 360), 0
' Set the bouncyness
fzxSetBody cFZX_PARAMETER_RESTITUTION, temp, .95, 0 ' Bounce
' Set the friction values of the body
fzxSetBody cFZX_PARAMETER_STATICFRICTION, temp, .1, 0
fzxSetBody cFZX_PARAMETER_DYNAMICFRICTION, temp, .85, 0
' Bodies wont live forever
fzxSetBody cFZX_PARAMETER_LIFETIME, temp, RND * 20 + 10, 0
END IF
END SUB
'********************************************************
' Build you world here
'********************************************************
SUB buildScene
DIM AS LONG temp
'Initialize camera
__fzxCamera.zoom = .5
fzxCalculateFOV
' Set camera position
fzxVector2DSet __fzxCamera.position, __fzxWorld.spawn.x, __fzxWorld.spawn.y - 300
'********************************************************
' Setup World
'********************************************************
' Some math used on the impulse side
' Todo: move this elsewhere
DIM o AS tFZX_VECTOR2d
fzxVector2DMultiplyScalarND o, __fzxWorld.gravity, dt
__fzxWorld.resting = fzxVector2DLengthSq(o) + cFZX_EPSILON
SUB renderBodies STATIC
DIM i AS LONG
DIM AS tFZX_VECTOR2d scSize, scMid, scUpperLeft, camUpperLeft, aabbUpperLeft, aabbSize, aabbHalfSize
DIM AS LONG ub: ub = UBOUND(__fzxBody)
' Todo : move this to camera functions
fzxVector2DSet aabbSize, 40000, 40000
fzxVector2DSet aabbHalfSize, aabbSize.x / 2, aabbSize.y / 2
'Draw all of the bodies that are visible
i = 0: DO WHILE i < ub
IF __fzxBody(i).enable THEN
'fzxAABB to cut down on rendering objects out of camera view
fzxVector2DSubVectorND aabbUpperLeft, __fzxBody(i).fzx.position, aabbHalfSize
IF fzxAABBOverlap(camUpperLeft.x, camUpperLeft.y, scSize.x, scSize.y, aabbUpperLeft.x, aabbUpperLeft.y, aabbSize.x, aabbSize.y) 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
END IF
i = i + 1
LOOP
END SUB
SUB renderWireFrameCircle (index AS LONG, c AS LONG)
DIM AS tFZX_VECTOR2d o1, o2
fzxWorldToCameraEx __fzxBody(index).fzx.position, o1
CIRCLE (o1.x, o1.y), __fzxBody(index).shape.radius * __fzxCamera.zoom, c
o2.x = o1.x + (__fzxBody(index).shape.radius * __fzxCamera.zoom) * COS(__fzxBody(index).fzx.orient)
o2.y = o1.y + (__fzxBody(index).shape.radius * __fzxCamera.zoom) * SIN(__fzxBody(index).fzx.orient)
LINE (o1.x, o1.y)-(o2.x, o2.y), c
END SUB
SUB renderWireFramePoly (index AS LONG)
DIM vert(3) AS tFZX_VECTOR2d
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
Software and cathedrals are much the same — first we build them, then we pray. QB64 Tutorial
(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.
TerryRitchie and justsomeguy I downloaded the Bare bones. Guess what?.....That right! I had file problems. Do I need to leave because I'm the bearer of bad news. Maybe not because you and justsomeguy are curious.
I had to adjust the path in '$include:'..\fzxNGN_BASE_v2\fzxNGN_ini.bas' to '$include:'\fzxNGN_BASE_v2\fzxNGN_ini.bas'. This second one runs great. The reason it runs like this is probably where I put it. That's better than the last time. I hope I did not caused too much trouble by the way I did that. I enjoyed the program.
To justsomeguy, This was aimed at TerryRitchie. I had some file problems in his banner program I could not figure out without help. He did great in helping. if I had not move the folder like said I would still have trouble getting the path right. Thank you for this program. I liked it.
(06-17-2023, 08:11 PM)GareBear Wrote: TerryRitchie and justsomeguy I downloaded the Bare bones. Guess what?.....That right! I had file problems. Do I need to leave because I'm the bearer of bad news. Maybe not because you and justsomeguy are curious.
I had to adjust the path in '$include:'..\fzxNGN_BASE_v2\fzxNGN_ini.bas' to '$include:'\fzxNGN_BASE_v2\fzxNGN_ini.bas'. This second one runs great. The reason it runs like this is probably where I put it. That's better than the last time. I hope I did not caused too much trouble by the way I did that. I enjoyed the program.
To justsomeguy, This was aimed at TerryRitchie. I had some file problems in his banner program I could not figure out without help. He did great in helping. if I had not move the folder like said I would still have trouble getting the path right. Thank you for this program. I liked it.
Copy the "assets" folder found in the example folder to your QB64PE folder. I had the same issue until I copied the folder.
Software and cathedrals are much the same — first we build them, then we pray. QB64 Tutorial
justsomeguy, I must have downloaded it after you tweaked it. I found the line you had on the forum and what I got is the same. It has a lot of bouncing. More came almost as fast as I clicked. That way it looked to me. Keep it up.