I think the existing is OK, with just working physics. But I don’t have any experience yet with ‘Panda’ physics, so not sure yet if it’s faster to swap the terrain out with something better (happy to whip it up in Blender) or, gen it procedurally, or other (there is a terrain engine, I’ve noticed! has collision been implemented there yet?)
The collision is the grid data. In the role of this is the usual geometry, which is usually easier than for rendering geometry.
And yes, collisions are not physics. A math intersection of geometry.
One thing the built-in collision system does is straightforward character welding, which is not necessarily the case with the current state of the Bullet methods.
Here’s an example of a more sophisticated Ralph variant:
Need to add to the examples
That’s fair–and a good argument for overhauling what we currently have, I believe.
Oh, of course! I’m not suggesting that I want the entire engine replicated in one file! XD;
Would you like some help there (whether advice or reference-code), or would you prefer to work on it yourself?
Let me note that we do have a few Blender exporters around–for two, we have “blend2bam” and “YABEE”, albeit that the latter only supports versions of Blender before 2.8, I believe.
That said, a better one, or an improvement to one that we have, could well be excellent!
Right, there’s no need to reinvent the wheel. I do think there is an elegance of the Blender plugin system ingesting a .zip file and having all of our modeling and animation needs met at the Blender export stage, without running a command line program for instance.
That was the nice thing about YABEE, indeed! It’s a pity that Blender changes combined with YABEE’s developer (I gather) dropping away from it resulted in it being incompatible with newer versions of Blender.
For sure! Happy to have help! Send anything at all you think might be useful, I’m starting from scratch here, understanding what the options are for fixing collision in Ralph. Reverse engineering the collision calls I see now in the current crop of samples.
I’m trying really hard to keep Roaming Ralph in one file, @Thaumaturge but I’m struggling… please promise not to be angry if I cave in to my weaknesses and organize this thing… =)
Not a problem!
The main thing that I’d suggest would be to rework Ralph’s collision to work something like this:
- Have a ray-and-CollisionHandlerQueue setup for the ground-height, similar to what’s there bit using Bitmasks to filter collisions rather than a name-check
- Remove the code that resets Ralph’s position on hitting an obstacle.
- Use a sphere-and-CollisionHandlerPusher setup for obstacle-collisions
With the position-reset removed and a pusher to more-smoothly prevent intersections, Ralph should no longer just stop dead when hitting an obstacle. Instead, Ralph should be able to “slide along” walls and the like.
You can see an example of the use of a CollisionHandlerPusher here:
Hah, to be honest, I’m curious as to how you might separate it out without the modules being of very limited utility–there’s barely anything in Roaming Ralph! XD;
Sounds great, thanks for the tips. I’ll give this a go!
I caved, very quickly. I’ll write a shell script to recombine the code into a single file though. Promise =)
Strange, added a single line of code after some refactoring, and the ‘stuck’ bug no longer happens. Ralph will stop when he hits things but can walk away now.
# Normally, we would have to call traverse() to check for collisions. # However, the class ShowBase that we inherit from has a task to do # this for us, if we assign a CollisionTraverser to self.cTrav. #self.cTrav.traverse(render) self.physics.update(render) # (this in turn calls cTrav.traverse())
Code is here:
Just to be clear, why use the word physics? Does it reflect the essence of what is happening?
Not yet, most of the symbols are nonsense until all the refactoring is done. I had to pick some temporary names for now to start to get code sorted out… my guess is most of these deps will get deleted / replaced after cleanup.
It is strange that I do not see the module code, for example:
Logically, it should be global. If you then add AI? Will you also create your own CollisionTraverser for them?
It might depend - my strategy here:
Separate code out by function for now. So when looking at a screen of code it’s doing one thing clearly (scene setup, physics, ui, input, etc). Temporarily I’m splitting logic out. Batched together it was insanely confusing, alternating between lines of code that were working with ui, physics, scene setup, input, camera manipulation, etc.
Once the code is split out - fix and refactor. Replace with things that do everything better, possibly use better looking, more stable or up to date panda features. Major cleanup in ie how the input and camera logic work, right now super hard to control and wonky. Here decide if we should swap out any media
After everything tests out / works well and is stable. Revisit the code structure. Ie - I’d think through about after adding another sample that might need AI, networking, etc - see how best to reuse all the existing pieces. Design how it should fit best without duplicating any logic already in Ralph
Finally move code into the right classes / modules / etc. once things work well we’ll know what deps are needed. Here code should land in all the right places (And be named appropriately by function)
All just ideas, happy to tweak the approach =)
Most of the code is grouped by function now. Although far from done. I’ve purposely ‘over refactored’ to get all the logic grouped so I can better clean it up tomorrow. But some structure is starting to come out of the noise.
Here’s the new main class:
from direct.showbase.ShowBase import ShowBase import random import os import math from ralph_helpers import ui, input, physics, scene, camera class RoamingRalphDemo(ShowBase): def __init__(self): # Set up the window, camera, etc. ShowBase.__init__(self) # Set the background color to black self.win.setClearColor((0, 0, 0, 1)) self.scene = scene.RalphScene(self) self.ui = ui.RalphUI() self.input = input.RalphInput(self) self.cameraMgr = camera.RalphCameraMgr(self) self.physics = physics.RalphPhysics(self) taskMgr.add(self.move, "moveTask") # Accepts arrow keys to move either the player or the menu cursor, # Also deals with grid checking and collision detection def move(self, task): # Get the time that elapsed since last frame. We multiply this with # the desired speed in order to find out with which distance to move # in order to achieve that desired speed. dt = globalClock.getDt() self.input.update(dt) self.physics.update(render) self.cameraMgr.update() return task.cont demo = RoamingRalphDemo() demo.run()
Sample runs as is written (although work not done):
It’s an interesting process that you have! I am curious to see how it turns out in the end.
(And won’t comment on it in its current state, since it’s work-in-progress; there’s little point in comment when I don’t know what’s temporary and what’s intended to stay!)
 Actually, one or two things, if I may: The commit-notes on one of the folders indicate that a CollisionSphere and CollisionHandlerPusher have been used, but I don’t seem to be finding them browsing the source. Now, I am tired right now, but I’ll confess that I’m also finding the structure a little counter to my personal intuition. So am I just looking in the wrong place/missing it, or has it not been added yet?
[edit 2] But see my second edit in a later post, below, which addresses that confusion.
I am a different person by nature, I will comment: this looks like an example of how not to do it.