(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.
New to QB64pe? Visit the QB64 tutorial to get started. QB64 Tutorial
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.
Another issue is may be how I set up my QB64 ide. I use _CWD$ to locate my working directory.
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.
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.
06-19-2023, 01:55 PM (This post was last modified: 06-19-2023, 02:00 PM by TerryRitchie.)
(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.
New to QB64pe? Visit the QB64 tutorial to get started. QB64 Tutorial
06-23-2023, 09:24 AM (This post was last modified: 06-23-2023, 09:58 AM by justsomeguy.)
Hello again,
I took a little break from writing documentation to add another little demo.
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.
'$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
'********************************************************
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
' 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
' 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
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
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.