Contribution ideas - more GAME samples!

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.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.

        # Set the background color to black, 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()


        return task.cont

demo = RoamingRalphDemo()

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. :slight_smile:

(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!)

[edit] 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.

I don’t think that it’s inherently bad, just as I don’t think that the functional style is bad. Different paradigms will work for different people.

This is my style when I started programming, from the point of view of code reuse, it’s just a dead end.

Bear in mind that they did say that they’d “over refactored” as part of their process–let’s see what the code looks like when it’s done.

[edit] On this forum, we often have bears in mind. :stuck_out_tongue_winking_eye:

[edit 2] Ah, regarding my confusion above about a changelog that mentions CollisionHandlerPusher, I’ve just noticed that said changelog is not part of the new changes, and is in fact much older. I still find it curious that there’s indication that the collision-approach was changed while the code seems to indicate otherwise, but that’s not relevant to this new set of changes. My apologies!

@Thaumaturge is absolutely right here!!

Interesting side note - I could put the split-out classes back into the main module and there would be an equivalent sample to before, but still have code that is cleanly organized by function. I still feel even there it is infinitely easier to understand than the original, even though its still incomplete.

But I’m not doing that yet - why? There is still a lot of cleanup needed. Going back to coding principles from above -

Single-Use: Now that the logic is split into multiple components, most components are closer to single use. There is one grave violation here, in that the modules all rely on Ralph’s scene graph layout. This isn’t necessary - most only need a single node (like Ralph himself) as a reference, so next on my list is to remove this dependancy.

Open-closed: Every component violates this right now. I can’t for example configure the ‘input’ logic for a different set of keys. Or physics for a different scene layout. Changes are needed here to fix this clearly.

Loose coupling - we’re definitely not there. Ralph needs all these modules to function, if I removed any of them the sample would break, and I can’t swap any module out for another easily. Conversely all modules rely on the main application class to have a specific scene graph layout, this is also too tight of coupling.

Lots to clean up yet :slight_smile:

Don’t sound so surprised, I’m posting on a forum as I go specifically so that the thought process is a community effort, feel free to recommend other approaches, I promise that I’ll listen!! Note most of the things being done here were discussed in prior posts, I feel the work is in-line with what we had agreed to.

Panda samples should be representative of what the Panda community feels is right, please give any ideas you might have!!

One question I do have - is in how to handle N-number of nodes in a scene that have movement and collision. N could be several or several million - depending on the size of the scene. Does Panda have any mechanics for organizing the collision logic here? I normally always have to use octrees, quadtrees, or precomputed physics zones to optimize this for real time use. Has this been worked out in Panda yet? I’d like to add a sample that shows multiple moving bodies - so trying to think this ahead.



Hmm… In all fairness, I think that I recall one person agreeing with you, and others in whole or in part disagreeing. ^^;

I’m not sure of several million–having that many individual nodes would likely overtax the system if you don’t start doing some fairly fancy stuff, both on the collision side and the rendering side, I think.

Having several, however, is fairly feasible at the least.

I’m not sure of Panda’s internal handling, but I imagine that it has some degree of broad-phasing. In addition, it provides bitmask-based collision filtering, and an “active-object”/“static-object” dichotomy to reduce the number of collision-sources.

The outcome is that for most games, the dev needn’t worry too much about octrees and the like, I suspect. The main things tend to be to limit the number of “active” objects present at any given time, and to use bitmasks to limit what interacts with what.

For a simple implementation of this, let me suggest taking a look at the final game built up by my “Beginner’s Tutorial”–that should show one approach to handling collision using the internal collision system. You should find the full code here:

Regarding the “active object” vs. “static object” split, I recommend looking at this page, starting with the second paragraph:

For high-performance physics with a greater number of elements, it may be better to use Bullet.

Update, just pushed a fix, world collision works again, and strangely enough the sticking bug disappeared still. Something about not using the app-local cTrav fixed it.

There was a lot of debate for sure! But I think I responded to each point with a solution until consensus - if you find I missed any let me know! Definitely not my intention!!

This is awesome stuff, thank you =)

Heh, honestly, the thread is large enough that I doubt that I would find either consensus or dissent–indeed, I just looked back now to that effect. ^^;

I’m thinking mainly of the SOLID thing; as I recall, I agreed with the “L”, but not with the rest–but in all fairness didn’t pursue the matter much.

As to Ralph specifically, I’m standing by seeing how the code turns out in the end. As last I saw it, I wasn’t a fan of the style (as I mentioned), but there’s no point in commenting either way on something that is explicitly intended to be reworked!

It’s my pleasure. :slight_smile:

Right - we agreed to not follow it literally. It was only useful as some guidelines to help improve code ‘only’ where applicable. I haven’t deviated from that, I promise =) But if I appear to have violated this let me know for sure. I’ll reconsider.

For sure! Ends might justify means here. That being said, you’re really helping the end product be a much better one, thanks for all the support! (And being so open minded to new ideas!!)