application framework / design

How long have you been writing code?

  • <= 9 months
  • 9 months, <= 3 years

  • 3 years, <= 6 years

  • 6 years, <= 12 years

  • 12 years

0 voters

Hi,

I love how panda provides a really quick prototyping environment via python and the architecture used in the example apps. Yet, the design there isn’t one of a modular and organized application.

In short my question is this… Is there a more advanced way to utilize panda that doesn’t force me into the paradigm used in the example code? Stated otherwise, globals and a monolithic main file are not my style.

I prefer to generate many of my own classes. Also, for the sake of opacity I like to wrap API specific access with classes, i.e. no co-mingling of panda-specific stuff in my high-level concepts, so that I can open it to unsupported platforms or change API’s with less hassle.

I’ve managed to do this to some extent, but I feel like I’m working against the software a bit… I’ve been advised recently to just avoid using the “direct” library, and that is good advice. I am willing to look at the direct library and see how it uses panda core then engineer to my own needs. That does not really answer the true problem, though, which is bridging Panda’s quick setup and rapid prototyping with developing a strong, lasting application. I wanted to bring this up here in case someone has already got a great application design using panda.

Thanks for your time!

Hi, you’re not the only one who dislikes those global variables used in the examples :slight_smile:

The way I get around those globals, and direct.directbase.DirectStart, is similar to the following:

import panda3d.core

window = panda3d.core.ShowBase() # Replaces the "base" global variable
window.render # Replaces the "render" global variable
window.loader # Replaces the "loader" global variable
# And so on...

# Replaces the global "run" function
window.run()

To separate my code from Panda’s even more, I’ve hidden all (and I mean all: graphics, physics, audio, hardware, and DirectGUI) the Panda code from all the other, non-Panda-related code into a group of plugins (that all use custom datatypes I created) my Panda project loads at runtime. Not only does it make my code easier to change (since I never directly access Panda, and I use my own datatypes), but if I want to port my project to another game engine, I just write another set of plugins.

To see the code I wrote, see http://openblox.hg.sourceforge.net/hgweb/openblox/openblox/file/d7c3142f7edb/src/obengine/plugin for the plugin framework, http://openblox.hg.sourceforge.net/hgweb/openblox/openblox/file/d7c3142f7edb/src/obengine/math for the majority of the custom datatypes, and http://openblox.hg.sourceforge.net/hgweb/openblox/openblox/file/d7c3142f7edb/src/plugins/panda-backend for the actual Panda plugins my project uses.

Wow, dude, fantastic. I will have to look at your plugin framework more deeply before I can really comment, but thank you for the leads!

I’m glad someone else has thought about this deeply.

The code snippet is also helpful as a stepping stone to get away from the globals. I was looking for the straight answer on that. Thanks for this!

No problem :slight_smile: Actually, that snippet I posted is (hopefully) common practice here - I don’t know of any full-fledged Panda projects that use direct.directbase.DirectStart.

Also, here’s a quick example snippet that shows how to use my plugin system (so you can see how it works, from a developer’s perspective):

import obengine.plugin # The plugin framework


def found_plugin(root_dir):

    # The root directory of a plugin is the directory that
    # contains the plugin's plugin.ini file, which contains
    # info on the plugin's name, what virtual plugins it implements,
    # what other plugins it depends on, and other stuff
    print 'found plugin %s' % root_dir


def initialized_plugin(plugin):

    # As you can see, plugins are full-fledged Python modules
    print 'initialized plugin from file %s' % plugin.__module__.__name__


# Initialize all the parts of my framework that have been imported
obengine.init()

# Create a plugin manager - actually, all plugin managers
# are really the same object, so we're just creating one
# so we can bind our event handlers to it
manager = obengine.plugin.PluginManager()
manager.on_plugin_found += found_plugin
manager.on_plugin_initialized += initialized_plugin

# Find and load an implementation of core.scripting (for
# the curious, a Lua scripting engine under-the-hood).
# This line should fire both our event handlers
obengine.plugin.require('core.scripting')

# To import the newly-loaded plugin, we simply do the following:
import obplugin.core.scripting

# Now, our plugin is loaded, imported, and ready to be used,
# just like a normal Python module!

When run, this snippet prints something like the following, due to our event handlers firing:

found plugin <some path>/plugins/lupa-scripting
initialized plugin from file <some path>/plugins/lupa-scripting/lupa_backend.pyc

ShowBase is a simple Python file. You can grab it and divide it into your own classes.
Same goes for Loader.

To be honest I work in a computer science research lab at the university I work attend and the program we develop uses one file as a main and everything else is called and ran through other classes. Maybe I misread your post but for me I have a main that controls and calls other classes.

I think the OP author meant something more along the lines of the design of your entire application; i.e, how you partition behavior across your classes, if you use them.

Thats a cogent correction, DangerOnTheRanger.

Nemesis, I’d rather not taint my mind with LGPL code. :wink: No, but that is really probably a good way to see how Panda is used at the metal and also how much the direct lib has to do to accomplish all that it does. I wouldn’t go so far as to take it and piece it into my own classes, regardless, jokes aside.

I actually do not mind at this stage of development continuing to use direct to some extent, but in order to maintain the app’s sanity with the way I code I had to remove the use of globals.

Later, when I know better what the app is and I’m not prototyping stuff, I definitely want to use obengine to isolate my app. Its better for now not to get tied up into something that isn’t the game.

Thanks everyone! I’m back on my project again after a small break.

Nice to know someone else might be using code I wrote in the future :slight_smile: For future reference, you can now download the very latest version of my plugin framework (and other code I’ve written, like my event, asynchronous, and VFS frameworks) here. Keep in mind though, since my code is GPL’ed - I really don’t like the idea of someone coming along, making money off my code, and keeping their modifications (if any) proprietary - if you use any of that code, your code must also be licensed under the GPL 3 or later. I just want to make sure this is OK with you, before you decide to use my code or not.

Like any other GPL library, I’d keep it separate, and I don’t plan to make changes to it. Profits are way ahead of where I’m at right now, heh, but I’d merely be a user of your plugin framework, and it might as well be in a dll for all I care because I dont want to see the source at all. I didnt’ even open the link to your openbox because i prefer to keep my mind clean of it, heh. But thats cool youve got a framework. I may look at it again in the future as a possible approach to my app design.

Unfortunately, whether you make changes to it or not, you’ll still need to license your game under the GPL 3 (or later) as well. Inconvenient in some cases, but not a show-stopper.

Still, if you choose to use it, I’ll be more than happy to answer/solve any questions/problems you have with it :slight_smile:

you collectivist commie… no, but I definitely wont be doing that. heh. thanks for helping me remove those globals though. no doubt a big help. Keep up your project, its really cool!