Contribution ideas - more GAME samples!

Okay, I’m not sure if this will affect my work though. I’m sure it’s possible to build a bunch of Classes around my logic to make it more readable, but it’s not something I’m likely to do myself. I am probably in the minority of programmers in that I find most Class groupings beyond the framework unnecessary or difficult to read. That’s just me, I just wouldn’t want to throw great code examples in the dust bin because they’re not 100% matching somebody’s rubric of quality.

And that’s very fair.

Note that I said that good code is “readable”–not “readable to everyone” or even “readable to the majority”. As long as the code is readable to those who use it, then fair enough, I say.

Indeed, if changing your style would make the code less readable to you, then there’s a fair argument to be made there that doing so would make it, for you, worse code.

(Although that it is potentially worth being aware that one’s code might not be readable to others, of course. In some cases, comments might help in code that’s to be seen by other developers.)

All I was arguing, really, was that there’s at least that one more thing to code being “good”: readability.

The description I gave of the different acts might have given the impression that I wanted something that takes hours to complete, but that really wasn’t my intent. Each act could last for only a few minutes, with a minimal amount of assets needed to give the feeling of a single scene from a fully fleshed-out game.

As I’m not all that great myself at texturing and using special effects, I’m not in a position to judge what is “good enough” with regard to what others would want to contribute.
But generally speaking, while using all of these different kinds of maps could show what Panda can do with them, I think it depends on how much of a visual difference they make, per model. For example, a complex normal map can add lots of detail to a low-poly mesh, but if the model is high-resolution, then it won’t have the same impact and may even be redundant. Another example that comes to mind is the use of a gloss map for a wet stone wall. If the effect is too strong it can end up looking like plastic, while toning it down could make it barely noticeable. In that case it might be better to just not bother with it.
What I’d suggest then, is to start out with simple, low-poly models without any maps or effects and gradually enhance them and see what works and what doesn’t.

Indeed. And as such, it seems a bit early to me to already start worrying about details like what effects, maps, materials etc. to use for which models – I mean, have we already come to a consensus regarding the actual content of the tech-demo? It’s great if you want to use my ideas, of course, but maybe others would like to offer alternative ideas as well.

In terms of coding, one thing I would keep in mind is that to some extent, a tutorial or samples or anything that is meant to teach in some way, is responsible for potentially shaping the coding habits of new, inexperienced programmers. It happens often that someone new to programming starts a project by copying code from such instructional material and deems its style to be more-or-less authorative. Even if not, they will usually code around it in a way that adheres to that style, simple because “it works, so why not”. That would be one reason to have some kind of “standard”, I guess.

Apart from that, when I see things like a Panda method – e.g. attach_new_node – being used in some places written like that, while in other places it’s written like attachNewNode, then I worry a little bit that new Panda users are going to get confused – and might ultimately settle on a name that will get deprecated at some point (the camelCase version, to be precise). Yeah there I go again – I can be such a nag sometimes :stuck_out_tongue: .

One reasonably straightforward way would be to create the model as a collection of 3D primitives (spheres, cylinders, boxes, etc.), which can easily be built up procedurally. My proposed geometry sample pack already contains an example where you can see this happen (primitives_assembly.py). In fact, it’s while making that particular sample that I got the starship-in-hangar idea.

If a shape consisting purely of primitives is unacceptable, the alternative would be to create the model in a modelling program as usual and clear its GeomTriangles primitive. Then it would be a matter of deciding on the exact order in which to re-add the triangles to it over time.

That’s fair! I have no argument with that scale, I think!

My quoted reply was, I think, in response to a mention of Half Life and Prey (2006)–both full-scale games, not brief tech-demos.

While I hear you, my thought is that this is intended to be a demo that impresses, that shows to a potential new user what Panda can do. If the assets are generally low-poly and without fancy effects, it may appear that such is all that the engine supports.

Polishing assets as we go might work, but I do then fear that they might be left half-complete.

Further, it might help to have some idea of what we’re aiming for in the end.

For my part, I’m less concerned with what is applied to what specific models, than with a general idea of what we’re aiming for. I’m not going to advocate for glow-maps on simple rocks, but should we be looking to have them on, say, neon-bedecked robots or glowing-eyed monsters? Or would we look for other approaches to keep it simple? And so on.

So less a fine-grained “let’s list what textures we’ll apply to everything, right now”, than “what level of flashiness are we aiming for?”.

Totally agreed!

That’s a risk in general with such an ambitious project, I fear. It needs people who are truly motivated to continue their part, to be sufficiently dedicated to see it through.

If you mean how to achieve a specific effect technically in the most efficient way possible (e.g. the use of shaders, appropriate material settings and the like), then I have to admit that I’m not the most qualified to answer this, I’m afraid. So I’m hoping that others more knowledgeable in that department will chime in on this.

Obviously, the flashier the better I’d say. Because, as you rightly said, it’s all about impressing people. There is the consideration that Panda3D has always prided itself of being able to run on lower-spec hardware though, but having certain effects (and model resolution) user-configurable should take care of that, I think.

So in conclusion – and assuming that my idea for the intro of the tech-demo is accepted – I’d suggest to go all out in whatever way the contributors feel most comfortable realizing those fancy visuals. The hangar itself, for example, could be littered with small blinking lights, glowing circuitry, screens with animated content and perhaps an additional layer of bloom on top of all that. That’s the kind of thing I’d like to see, but if you ask me the best, most efficient way to realize all that, then I must confess I don’t really know.

Great info! I started to keep track of the samples we’ve built in this thread as well as the links that are coming up to useful resources for building samples. Here’s the latest update:


New samples created by the community here! (Updated as we build them):

Resources for helping folks create samples:


Great progress folks, let’s keep all the great ideas coming!

I’m less asking after the best or most efficient way to do it, but rather after what we want to show off. Do we want to show off that we can support glow-maps, and displacement maps, and other maps besides? Do we want to keep it simple, or show off as much as possible, or something in-between? That sort of thing.

Indeed. Hence it seems to me to be a good idea to reduce the likelihood of it. If a model is made once and is then done, then it may be more likely that it’ll be finished–or at least, that’s my intuition, which may well be mistaken.

A good update, and thank you for it! :slight_smile:

Well put! My thoughts here: Whether we design step 3 or step 9, We still need to perform steps 1 and 2. And in my experience with software development, once you have steps 1 and 2, all plans you had previously for anything beyond that changes!!! (And more ideas come to mind). I’m OK to tunnel-vision on the next couple steps, and worry about the complex stuff once we get there. My thoughts are we need a lot of boiler-plate basic stuff - I don’t think we have a sample that actually has fully working player & NPC collision/physics for example, it might be a good place to start. For most game engines things like this are considered basic features - that Panda doesn’t have this in a sample yet is a nice big gap we can fill.

However, thinking/designing that long-term vision can be extremely exciting and motivational. I wouldn’t want to kill the fun - if that’s what folks would like to focus on, by all means, I’d love to see more ideas there. (and long-term vision always does help to ground your design.)

One of my coworkers loves to say ‘perfect is the enemy of good’, which is a fun concept, since everyone’s definition of ‘perfect’ and ‘good’ varies, but point taken - most importantly results are what matter, for sure. Bias for action is a great rule to work by.

Well put, again!! I think you’re hitting the crux of the idea here.

Consider there are ‘samples’ for a game engine and ‘official samples’. ‘Samples’ just need ‘to work’ and it’s, after all sample code of how one could use the engine. ‘Official samples’ however typically need to go beyond, actually showing clean / elegant code structure and serve as models for best practices for many things like code re-use, modularity, clean code structure, understandability - overall, an official sample is what shows how the entire game engine’s design comes together to deliver a good user experience (for the developer) to build a game. If official samples are difficult to understand, or lacking features, it leaves little hope the engine can do much more / can scare away new folks that see things done easily elsewhere. (Not to spell doom and gloom here, but TLDR: sample quality is important)

Ideally we’d like to open the ‘official’ samples for Panda and say ‘wow this engine is so nice to use, is intuitive, etc.’ and it inspires one to tweak and start to build.

To expand on this a bit further (apologies if this sounds super pedantic but I’m a stickler for well written code). Consider this article for a moment. There are many ways to write the ‘same’ piece of code, some ways much more intuitive than others.

Let’s take for example an imperative style:


    #here is a sample 1st person app

    #this is all pseudocode, not Panda specific
    def main():
          node1 = makeNode(x,y,z, parent=root)
          node2 = makeNode(x2,y2,z2, parent=node1)
          myshader = '''
vec4 gl_Position;
  float gl_PointSize;
  float gl_ClipDistance[];
...
          '''
         scene.addShader(myshader)
         keypressmap= {"k":"jump", "k_down":"stopjump", "w":"forward" ...}
         node2.loadMesh("first_person_char.fbx")
         node1.loadMesh("first_person_scene.fbx")

         #insert here : lots of collision detection setup code
         #insert here : lots of lighting setup 

         def updatescene():
              if kepressmap["foo"].bar.blah.bam:
                  node1.moveSomplace(x,y,z)
              #insert here: lots of AI, frame processing, etc.
         scene.run (updatescene)

At first glance I think many wouldn’t see much issue with that style of code. But from the perspective of one who may have much more experience with other game engines / code styles they could think a few things:

  • Why do I need to setup super basic shaders in my game main setup code? Isn’t there some default or basic rendering supported by the engine that allows me to just load media? It’s definitely the case for other engines. I can just model some media and load, no need for writing shader code.

  • Likewise for input and camera handling for a 1st person game - does this really need to be written from scratch every time? It seems like this could have been abstracted already into a very basic input class

  • First person, third person, top-down camera management, pretty much encompasses the majority of game styles out there - one would expect not to have to write this from scratch for each game as well

  • On the style of the code written here - everything is in one / few methods, hard to re-use or split out logic. Hard to decipher which part of the code is for which task (scene setup vs, input setup, vs AI, etc.) Also the user could go down the wrong path by adding even ‘more’ code, and this method/file would become complete unmaintainable.

Anyhow - this is why I think it’s good to have some thought put into the sample code design. To flesh out more along the right path - consider the ‘declarative’ DSL style of writing code that is in this article that I referenced.

If things were more modular, and a declarative style was used, code could look like this:


    #3rd person game example
    import .... deps ....
    def main():
        MyApp(loadScene="myscene.blend", 
              controller=3rdPersonController(playerMesh="player.fbx"),
              sceneNodes=[
                 NPCNode(model="mynpc1.fbx", ai=HostileAI()),
                 Node(model="button.fbx", collisionLogic=OpenDoor(id="door1"))
              ]).run()

    

    #1st person game example
    import ... deps ...
    def main():
        MyApp(loadScene="myscene.blend", 
              controller=FirstPersonController(playerMesh="player.fbx"),
              sceneNodes=[
                 NPCNode(model="mynpc1.fbx", ai=HostileAI()),
                 Node(model="button.fbx", collisionLogic=OpenDoor(id="door1"))
              ]).run()

Note how to go from a ‘First person’ to a ‘Third person’ game style you only had to change one line of code. Likewise we could open the .py source (in the samples folders) for each of these classes and see how they work, change/customize, etc.

It’s also comforting to know, that at least in a simple sample, a game could be working in ~15 lines of code, with advanced functionality. These samples could have fully working collision, camera management, etc.

Happy to hear more thoughts here. I know this is probably a lot more code-engineering and architecture than most might have expected to put into game engine samples, but I think the little extra effort here goes a very long way to making Panda infinitely simpler to use.

Thanks!

Conversely, I suspect that with no solid idea of where one wants to go, it can become easier to get mired in earlier steps or spend one’s efforts on things that end up unused. (Of course, some of that is likely to happen anyway, in most projects for that matter. I just suspect that it’s more likely under such circumstances.)

It’s fine of the end-goal changes over time–but I don’t think that this means that the end-goal is of no value before its reached.

I would argue that if it’s intended to be a sample of how one could use the engine, then readability is still important.

Even if it’s not an “official” sample, it seems likely that people will want to learn from it. As a result, a sample that isn’t readable might confuse and frustrate new users, direct them to producing low-readability code, and potentially scare them away.

I think that the general philosophy with Panda has been that games vary so much that there’s a preference here for giving the developer the freedom to develop the elements that they want, even if that means that the developer has to do more themselves.

Even within camera controllers there are quite a few variations: Third-person in particular has over-the-shoulder, top-down, distant isometric, free-roaming separate from the character, and perhaps more. Then there are cases in which the game might require a switch between third- and first- person cameras. And likely so on besides!

In this way, providing an array of small, modular elements is arguably preferable, as it allows a developer to assemble more-granular parts, thus allowing something closer to their vision.

1 Like

This is specific enough as advice that I can actually understand it. I’ll make an effort to change my declarations to the_futuristic_underscore_way().

You can use the built-in shader system, my example is nonstandard in that regard. Just call self.render.setShaderAuto() and you will not need more shader code. I’m not an expert on this implementation but I believe it generally applies built in shaders on the entire scene. There are some cool ones, like Cartoon Ink. However this way does not yet support features such as metalicness and a few others that I believe are important.

These examples are not representative of the range of all possible games, which I hope I am not alone in thinking is the general idealistic goal of our framework.

I get what you’re saying, I want my code to be readable too. I will, at least, switch to using underscores instead of camelCase (I don’t care stylistically either way and I’ll probably get used to it).

However it seems that you want my code examples (or @Thaumaturge 's) to actually be part of the framework and called as built-ins. This is, simply, not the case today. Panda3D requires a little more work on the developer’s part and I don’t see an issue with that as of yet.

Not to downplay the shortcomings of our codebase, but this is really not the case. I have written several programs which solve the NPC state. It’s not a problem for me. It is a problem for me to present this quite convoluted code to the whole world as some kind of perfect, general solution. It’s just not natural for me to do this. There are many, many ways of solving the state. I suggested three or four different ways of approaching a more general solution in this regard in the Arena post.

I definitely wouldn’t want to take the steam out of the effort here. I may be able to think of a way to reduce my AI code to something more applicable to arbitrary NPC configurations. However I must warn yet again that we are quite close to that scary world of opinionated template games. There is, I believe, a strong case to be made for not overspecifying. And much more generally, I question the ability of a developer to write an entire game in native code if they cannot produce the most basic AI mechanics from scratch. “The Basics” are not well defined for the range of all possible games, I think.

The irony for me is that, if I recall correctly, I used to prefer snake-case, and switched over to camel-case… due to Panda3D. XD;

2 Likes

Agreed! So many balances and trade-offs exists with software dev. I’ve been in too many similar discussions in the vein of waterfall vs agile, iterative progress vs. design-first. All arguments for either are valid, based on scenario, for sure. Good judgement is key!

Agreed here as well! I’m just also trying to be sensitive, ie - if folks are ‘afraid’ to make samples for Panda due to fear of not being able to meet some impossible architecture standard, then we get less progress. I wouldn’t want folks to be afraid to contribute. Its best to keep the fire-hose on, let the flood of samples come through and we can always refactor later. But we should have some idea of what the ‘standard’ is we’re trying to hit, so folks have a goal to aim for. The more structure we’re agreed to apriori the less rework we have later.

Agreed, and this is one of the creative aspects of software design - when building a framework you’re always making some subjective decisions to handle a generic case, but also allowing users to work more granularly to handle any other case. (This topic near to my heart as its also my day-job, so I understand the pain one feel when trying to make these decisions for sure.)

A good rule of thumb here - is to try not to ‘generalize the exception’. For example, in 0.01% of games, we may want a very eccentric camera angle, but given this probability is low, we wouldn’t make fundamental design decisions in a game engine to target that 0.01%, rather we’d like to optimize for the 99% or majority use cases. With clarity in code, users can always customize to tweak things for that 0.01%. Again it’s a balance - I for one feel it’s very doable to have the best of both worlds - ie components that handle the majority use cases, but also the ability to customize those components to handle the minority cases. It does take some up-front thought though, just ignoring this aspect or sweeping it under the rug doesn’t get to a design solution there.

Agreed here as well - see the previous point here - I do think it’s possible to solve for both cases. I want to be careful not to create a false-dichotomy in our minds, that says a framework is either opinionated or flexible, but can’t be both, as I don’t feel that’s true.

Sorry if I gave that impression! I’d never expect / ask anyone to do something a certain way. My questions are mostly for myself to guide my own work - as I plan to write a significant amount of code for Panda, I like to work out some design first - and if there is a standard to meet so I can get my own samples in the official codebase I’m happy to comply - to maximize the benefit of my contributions. I have written much code that has fallen to the dust-bin of Github, over the years have learned that some understanding can help your code live on in a much more impact-ful way, if that’s the goal, anyway.

I tend to assume if I have these questions, others might too, so it’s good to try to get to answers. If others would like to collaborate on a common standard as well, that’s amazing!! But I’ve been a part of many opensource projects through the years, one can only control their own contributions (and choose to understand or match the standards of the project they contribute too) - the worst thing to happen is to discourage contributions altogether, as any volunteer effort / code written for Panda is good at the end of the day for the entire Panda ecosystem (imo.)

Don’t feel pressure to change your code! I wasn’t trying to suggest this, just asking questions to guide my own work. I don’t know we came to any consensus yet, but this discussion has definitely got us closer, and I appreciate everyone’s feedback!

By all means, if we have the desire to crank out some sample code let’s do it, not worry about over-design just yet.

I’m getting closer to the point where I can start to crank out some code myself - everyone here has posted such great example code, or ideas to work off of, we now have some free art/media we can use. I promise to have some samples of my own to review here very soon!

Thanks everyone for the great feedback!

-Sal

I have uploaded the initial case changes. There are a few examples that were not easy to switch over.

Oustanding issues switching from camelCase:

lerp_pos_hpr_interval is not defined
mouse_watcher_node is not defined
lerp_func is not defined
global_clock is not defined
cam_lens is not defined
bullet_character_controller_node is not defined

Partial list of changes to snake_case:

set_mouse_mode()
set_fov()
set_near_far()
set_focal_length()
set_pos()
attach_new_node()
set_light()
BulletWorld().set_gravity()
load_model()
reparent_to()
find_all_matches()
get_path()
add_geom()
add_shape()
set_mass()
set_friction()
set_scale()
set_collide_mask()
attach_rigid_body()
set_attrib()
set_x()
set_y()
set_z()
set_h()
set_p()
set_r()
set_text()
set_pixels_per_unit()
set_page_size()
load_font()
set_font()
set_small_caps()
set_align()
set_text_color()
set_color()
set_lens()
set_attenuation()
set_light()
set_light_off()
attach_character()
get_anim_control()
set_play_rate()
set_ccd_motion_threshold()
set_ccd_swept_sphere_radius()
get_pos()
get_hpr()
get_parent()
has_mouse()
get_mouse()
get_relative_point()
ray_test_closest()
get_node()
get_pointer()
get_x()
get_y()
get_z()
get_x_size()
get_y_size()
get_p()
globalClock.get_dt()
show_wireframe()
show_constraints()
show_bounding_boxes()
show_normals()
set_debug_node()
is_hidden()
do_physics()

Yes, I’m rather interested to see you actually write some code. Speaking to experience is worth something but code is better.

That’s a fair concern, I do think. That said, I don’t mean to argue for a serious standard, as such–just readability.

Panda has generally (at least to my knowledge) taken a different tack: to not generalise at all; to not constrain devs to one paradigm or another above a certain level of the engine.

It’s one of the reasons, as I recall, that there has been resistance to the idea of an official level-editor in the past.

Don’t get me wrong, I am 100% for more developers writing Panda3D games. It’s a great engine as it stands.

We already have a very capable set of tools which solve the general case and the specific case (the framework). This is not a shortcoming, it’s the primary feature of Panda3D, if I may say so. Look at the 50+ built in functions I used in a 600 line example program. That’s the flexibility of Panda3D. Examples of specific AI techniques are just examples in a sea of possibilities.

Please respond more specifically to my/our statements about generality, if you would, @svf . Do you not find it appropriate that a developer in an engine quite explicitly designed to be code-first, code-only even, which uses Blender at most as a GUI, could also write their own character controller? This is fairly basic comp sci.

Now you’re giving me some motivation =)

Which is great! I’m of the opinion that you can have both flexibility as well as ease-of-use & feature completeness - they aren’t opposite ends of a spectrum. For example, having physics support in an engine sample - one could argue that it ‘biases’ the game to have gravity and work in games that are on planet Earth (most physics libraries assume a -default- 9.8m/s gravity acceleration rate after all). Which is true, but the user could choose not to use that sample or its code - they still have the option. Not having the sample in the first place doesn’t make the engine more ‘flexible’, it just leaves the user with more work to do for some basics - that they might expect from a mature game engine, like physics. (Not to beat on physics support at all, and totally unrelated to my experiences with Roaming Ralph sample cough cough)

I don’t think we should be afraid to make Panda easier to use - but I think we all agree here =) My only reason to push the point is I’m seeing a lot of hesitation from folks to improve on Panda’s scripting interfaces due to a fear that the engine becomes less useful somehow. Improvements should be just that - improvements!! With some careful thought I’m sure we aren’t restricting users in any way, but giving them more help to make great games.

On a side note I was planning out some of my initial Panda sample code contribution ideas. Here is where I’m currently going. I’ve found some javascript/three.js code that does a lot of what I was looking to do, and being that I prefer Python over JS (and three.js isn’t there yet) I’d like to rewrite the code for Panda.

Check this video out, it’s a tutorial for building a full-out 3rd person multiplayer RPG (with combat, etc.) in JS. I highly recommend this channel for folks that are interested in game dev algorithms in general. This video is particularly amazing .

Code is here as well. And that sample has full Blender media, models, textures, etc - so this helps. One thing that might be missing is the procedural terrain capability, but I’m thinking to swap for a simpler Panda supported option.

I think my approach will be to just work on some basics now, controls and physics to start. Then start loading media and working over to some of the nicer features like networking. The other major dimension though is I’d like to work in small increments - each increment a standalone Panda sample that has code incorporated into the end-sample game. So the actual end-sample game should come in at less than a couple dozen lines of code if abstracted correctly.

Happy to hear thoughts on this approach!

Thanks!

-Sal

The thing is, as originally worded, it looked (to me at least) like you were advocating for the engine itself having things like “first-person camera controllers”.

Having an array of samples available is, indeed, something that I’m in favour of!

As I said:

I suppose the question then is whether a change to the engine’s interfaces is an improvement.

Again, external samples or modules I’m in favour of. Adding such controllers to the engine itself I’m rather more hesitant about.

That’s interesting, and ambitious! I’m interested to see how it turns out! :slight_smile:

For something of that size, I might suggest taking a look at the various things already offered by the community that might be useful for or as part of it–GUI designers, exporters, keymapping modules, and so on.

I guess its a matter of perspective, if there’s a ‘first person camera controller’ as part of a scripting example that one can import or re-use, users might consider that ‘part of the engine’. I don’t know most users really know/understand which pieces exactly are C++ vs Python, nor do they mind either way. From a user perspective, they either need to write all that code manually, or import it from someplace. I think the point here is, given that ‘first person cameras’ are so common in games, there’s no harm in having one available.

I don’t think it ‘opinionates’ the engine in any way. As it’s an optional component. If that component also is extensible (ie, you can inherit from the object, override methods) due to OO paradigms one can also completely customize the behavior of it - or, take the source and modify.

The intention for all changes to an engine is to improve it, correct? Not sure I follow.

For sure - there is less harm in modifying an engine sample to have some re-usable code. But it is very common for game engines to take very time-intensive or CPU hungry scripting logic and eventually nativize it. (Convert to C++ or otherwise). If a scripting component proves to have enough usage and needs the optimization, no harm done. Again if the component is optional - the user isn’t forced to use it. Its about giving the user more options overall, not constraining them at all - whether its a Python or C++ feature.

Again, I don’t think there’s an ‘either / or’ option here, of ‘opinionated’ or ‘flexible’, you can have both. I don’t know we should be so concerned. I do agree other game engines may have been designed poorly or have this wrong, but I don’t feel like we are doomed to follow there. (This discussion a perfect example of why we wouldn’t easily fall down the wrong path!)

Absolutely, and the fine work by yourself and @Simulan are incredibly useful as well, thank you for all your feedback / ideas. I’ll definitely post as things progress!!