Panda3D Arena FPS Sample Program Submission

Based on the recent discussion here Contribution ideas - more GAME samples! I have created a compact FPS sample program using Bullet Physics, .gltf exports, blend2bam Actor animation exports, Hardware Skinning with panda3d-complexpbr, a first-person camera handler, a movement timing system, an animated handgun model, and more.

06/25/23 PBR IBL update:

I have updated the Arena FPS Sample Program to utilize complexpbr for PBR IBL rendering of the scene and for actor hardware skinning support (skeletal animations). I believe that this update increases the quality of the program significantly, and demonstrates how to use complexpbr in a practical program. As always, if you run into any issues using this new setup procedure, post a comment below and I will get back to you. PBR IBL screenshots below.

Comparison between last major update and the 06/25/23 update:

Please discuss enhancements and changes to this sample program here. I am willing to take it further based on suggestions, or if you feel capable go ahead and start hacking on it. The amount of detail and logic in this sample program may be deceptive. Itā€™s not exactly simple.

Full code and assets here:

Features:

  • First person shooter basic environment
  • First person camera handling system
  • Interactive target dot reticule system
  • Gamepad support
  • Armature with ā€œwalkingā€ and ā€œdeathā€ animations
  • PBR IBL rendering via panda3d-complexpbr GitHub - rayanalysis/panda3d-complexpbr: Functional node level shader application for Panda3D.
  • Working gltf2bam Actor exporting script
  • Hardware Skinning support via complexpbr.skin(your_actor)
  • Bullet Physics integration of environment, characters, and collision spheres
  • Advanced timing logic in Panda3D
  • Basic weapon loading and animation
  • State machine based onscreen text updating
  • Toggle based flashlight with shadow casting
  • Modern .gltf and .bam based modeling
  • Very basic NPC movement system
  • Jumping and slope physics support

Included Full Assets:

  • Handgun model with Blender file
  • Adult male model with Blender file and .bam animation exports
  • Arena model with Blender file
  • Sphere models for PBR IBL physics spheres
  • Daytime skybox model

Game Goal:

  • Neutralize the NPC by shooting the head hitbox
  • Receive success message

Requirements:

  • panda3d
  • panda3d-complexpbr

06/25/23 PBR IBL update screenshots:

7 Likes

Very cool Simulan! I went ahead and pulled the repo, and tested things out as Iā€™ve been looking to hack on some very similar types of things for Panda. Until now Iā€™ve been tweaking ā€˜Roaming Ralphā€™ to work out bugs.

First off, thanks for doing this. Being new to Panda myself, just reading your code really helped me get ideas on some ways to do things that would have probably taken me hours/days/weeks of trial and error to try to figure out on my own. This is a great example of how sample code like this can really help other folks new to Panda really get up to speed quickly.

I also like how youā€™ve already gone above/beyond, and decided to add support for things I didnā€™t even know existed till I saw your code (simplepbr, gltf support). Maybe experienced Panda3d folks know about these things but I had no clue! Another great reason to have such nice (up to date) samples, the cumulative experience of experienced Panda3d usersā€™ knowledge gets condensed into some working code that others can learn from.

Anyhow, thanks for all your efforts here. Iā€™d definitely like to read through this code much more deeply and see if I can help flesh things out more.

Iā€™ve been play-testing this a bit, and lots of ideas came to mind on things Iā€™d like to try my hand at.

  • It only took a few seconds of google-ing, but for total newbies like myself a blurb in the README on what to ā€˜pip installā€™ might help others. Once I did that, ran perfectly

  • Definitely would like to take a bunch of free media assets I have lying around and see if I can get it to work with your foundation, I have a lot of animated character, textures, meshes for the level and the like. Also the physics library you started with (bullet) I know is super capable - so some objects to collide with might help to show itā€™s capability.

  • I few bugs that popped up for me: - the NPC seems to dart around super quickly, then dash to a far wall and fall through the floor and disappear. I couldnā€™t really catch it. Iā€™m sure super easy to tweak, but just to mention. Also colliding with the walls seems to teleport my camera on top of the wall immediately, collision definitely works but my guess is collision response just needs a little configuration. Other minor little things, like movement was hard to perceive without a floor texture or some obstacles, but this is likely by design - for a first version this is a really great foundation.

Thanks again for this. Iā€™ll drop a blurb if/when I can get any useful results building off of what youā€™ve started!!

Thanks,

-Sal

2 Likes

Very neat! And thank you for contributing this! :slight_smile:

I do have a question: Why are you creating multiple DirectObjects? Why not just implement the various events in the ā€œappā€ class?

Great, but you forgot to mention the dependency gltf

Traceback (most recent call last):
  File "main.py", line 54, in <module>
    import gltf
ModuleNotFoundError: No module named 'gltf'

In view of the fact that Iā€™m a bore, I think itā€™s worth noting that this example is related to python. It is impossible to repeat this in C++.

I have another message .

:display:gsg:glgsg(warning): Shader created-shader produced the following warnings:
WARNING: Too many temp register is used in Fragment shader, it may cause slow execution.

As for the example, itā€™s a good idea to sort the rendering of the character and weapons so that you donā€™t visually pass through walls.

Great work :slight_smile: !

As a minor nitpick, one thing Iā€™d like to suggest is to only use the snake_case variant of the Panda method names, since there was talk of deprecating the use of the camelCase names at some point.

1 Like

You can change the NPC movement speed by changing the increments which are applied to the position, making the NPC slow or fast. I made it fast by default to give some challenge to the player in shooting the head. The NPC movement implementation is bad, but this is because I didnā€™t want to go way above an entry level userā€™s head with AI techniques. I have written code that avoids all above floor collision meshes but it is rather more sophisticated than Iā€™d want an entry level user to deal with.

Yep, there are some bugs and suboptimal choices in this sample program. All fixable I believe.

Thanks for the supportive comment and feel free to share your demos with the community. Itā€™s nice to have another seasoned dev here, even if your specialty is the big name engines. I have used Unreal 4 to some extent for VR development so Iā€™m about as familiar with it as you are Panda3D.

Ah, I didnā€™t even think about that. Youā€™re right, that should be updated.

1 Like

Thanks, I added that to the post.

The multiple DirectObjects are now just under one called ā€œbeepā€ in arena.py .

I made a quick ā€œfixā€ for this, which is to make the npc_1 movements more normalized. It should at least take longer to escape the arena this way.

The real solution is to add some ray testing logic to the character, or do something like apply Bullet forces to the character node. Either of these is getting into complexity I donā€™t think is appropriate, but Iā€™m open to solutions other people may suggest. I think the existing NPC timer could be used to apply Bullet forces equally as well, which may prevent most cases of the NPC passing through the arena wall. After all Iā€™m manually applying a graph transformation on the character with the Task system even though itā€™s being actively collision modeled, which may not be the best (general) solution.

One fairly simple way to implement future collision detection is to have, I believe, a Bullet Ghost node Box some multiple the size of the NPC character, and check wall intersections on that. This would require some more logic to implement, but might be fairly compact code-wise.

The updated NPC timer cycle:

        # npc movement timer
        def npc_1_move_gen():
            while not self.npc_1_is_dead:
                m_incs = []
                for x in range(0, 2):
                    m_incs.append(random.uniform(0.03, 0.08))
                
                print('NPC_1 movement increments this cycle: ' + str(m_incs))
                self.npc_1_move_increment[0] = m_incs[0]
                self.npc_1_move_increment[1] = m_incs[1]
                time.sleep(3)
                self.npc_1_move_increment[0] = m_incs[0]
                self.npc_1_move_increment[1] = m_incs[1]
                time.sleep(3)
                self.npc_1_move_increment[0] = (-1 * m_incs[0]) * 2
                self.npc_1_move_increment[1] = (-1 * m_incs[1]) * 2
                time.sleep(3)
                self.npc_1_move_increment[0] = 0
                self.npc_1_move_increment[1] = 0

Added

hardware-animated-vertices #t

to load_prc_file_data.

Fair enough!

For the record, you donā€™t need a separate DirectObject at all: ā€œShowBaseā€ inherits from ā€œDirectObjectā€, and thus you can register your events with your ā€œappā€ class. Something like this:

class Game(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        self.accept("space", self.someMethod)

I would suggest, in place of ā€œsleepā€-timers, that you apply a delta-time value to your movements. That should normalise for potentially-variable frame-rates, at the least!

If the NPCs still move too fastā€“or if the frame-rate drops too lowā€“then you can perhaps implement either sub-division of physics updates or ā€œcontinuous collision detectionā€.

The variable frame rate issue is limited to some extent with calling clock-frame-rate 60 in the prc file. But yes, enhancing the NPC handler is important.

CCD was already enabled upon the first posting, at least on some objects.

Fair enough, on all points. Iā€™ll confess that I didnā€™t read the sample closely!

(In part perhaps because it uses a style that I personally donā€™t find intuitive, but thatā€™s me.)

I hope we can somehow combine these different styles in a productive way, but I do not yet see a truly idiomatic way of writing Panda3D. I similarly have a difficult time reading your examples, and I apologize for a lack of communication in that regard.

No no, thereā€™s no lack of communication! Different people have different styles, and thatā€™s okay!

(And I apologise if I made it seem that there was a problem with your communication! ^^; )

Rather, I would like to have samples of both our styles (and perhaps others besides). Let users pick whichever suits them best!

1 Like

Hereā€™s what happens without syncing the video.

1 Like

260+ frames per second, nice. The flashlight seems to be horribly slow with the shadow casting enabled, unfortunately.

This is if you do not turn on the flashlight :slightly_smiling_face: