PlayNodes ready to kill the bricks

Hello World !

Ive spent a few hours on taking a look at the pynode api, creating some basic gameplay noodles for the blender game engine. Main motivation is from ue4’s allmighty kismet that any preschool child can use.

I created with some simple nodes for the sake of the proof of concept :

Events nodes

  • Event Tick (fired at each frame)
  • Event KeyDown (fired while your finger is holding the key)

Motion Nodes

  • Object Rotate (performs some awesome rotation on the selected object)

I just wanted to see how complicated it would be to get something working ASAP.
With these 3 nodes i did a good start.

I implemented the 3 nodes using the custom nodes template. And did some ninja research on ui layouts.
I made a simple scene with a floor plane, a spot lamp, and a cube (the most amazing scene i could imagine, but unforunately i forgot to add a monkey head, im sorry)


After creating an amazing graph featuring the rotational super powers of the Cube i wanted to read the nodes inside the bge.
Sadly i discovered that the bge couldnt access the nodes… :’(

I had to find a way to export the nodes so that the bge could use them damnit !

I first thought about a json solution but when i looked at my screen, my hands already had coded an xml exporter, so xml imposed itself by speed (see ya next time J-son)

Temp xml structure example for the sake of this demo


<?xml version="1.0"?>
<data>
    <nodetree name="NodeTree">
        <node type="NodeEvtTick" name="Event Tick.001">
            <output name="Exec">
                <link to_socket="Exec" to_node="Object Motion.001"/>
            </output>
        </node>
        <node type="NodeObjectRotate" name="Object Motion.001">
            <object name="Lamp"/>
            <rotation x="0.0" y="0.0" z="0.009999999776482582"/>
            <input name="Exec">
                <link from_socket="Exec" from_node="Event Tick.001"/>
            </input>
            <output name="Exec">
            </output>
        </node>
        <node type="NodeObjectRotate" name="Object Motion">
            <object name="Cube"/>
            <rotation x="0.0" y="0.0" z="0.009999999776482582"/>
            <input name="Exec">
                <link from_socket="Exec" from_node="Event KeyDown"/>
            </input>
            <output name="Exec">
            </output>
        </node>
        <node type="NodeEvtKeyDown" name="Event KeyDown">
            <key id="D"/>
            <input name="Key">
            </input>
            <output name="Exec">
                <link to_socket="Exec" to_node="Object Motion"/>
            </output>
        </node>
        <node type="NodeObjectRotate" name="Object Motion.002">
            <object name="Cube"/>
            <rotation x="0.0" y="0.0" z="-0.009999999776482582"/>
            <input name="Exec">
                <link from_socket="Exec" from_node="Event KeyDown.001"/>
            </input>
            <output name="Exec">
            </output>
        </node>
        <node type="NodeEvtKeyDown" name="Event KeyDown.001">
            <key id="Q"/>
            <input name="Key">
            </input>
            <output name="Exec">
                <link to_socket="Exec" to_node="Object Motion.002"/>
            </output>
        </node>
        <node type="NodeObjectRotate" name="Object Motion.003">
            <object name="Cube"/>
            <rotation x="0.009999999776482582" y="0.0" z="0.0"/>
            <input name="Exec">
                <link from_socket="Exec" from_node="Event KeyDown.002"/>
            </input>
            <output name="Exec">
            </output>
        </node>
        <node type="NodeEvtKeyDown" name="Event KeyDown.002">
            <key id="Z"/>
            <input name="Key">
            </input>
            <output name="Exec">
                <link to_socket="Exec" to_node="Object Motion.003"/>
            </output>
        </node>
        <node type="NodeObjectRotate" name="Object Motion.004">
            <object name="Cube"/>
            <rotation x="-0.009999999776482582" y="0.0" z="0.0"/>
            <input name="Exec">
                <link from_socket="Exec" from_node="Event KeyDown.003"/>
            </input>
            <output name="Exec">
            </output>
        </node>
        <node type="NodeEvtKeyDown" name="Event KeyDown.003">
            <key id="S"/>
            <input name="Key">
            </input>
            <output name="Exec">
                <link to_socket="Exec" to_node="Object Motion.004"/>
            </output>
        </node>
    </nodetree>
</data>

When i saw this xml i was afraid, because as it is the bge couldnt do anything with it and it meant i had to code some classes to replicate the nodes behaviors in the bge (damnit !)

So, i coded the base classes, socket, node, Event nodes, and the full featured ~Object rotation node~

Then i coded a simple runtime wich captures the different events that should occur in the game (tick, keydown) and executes the corresponding nodes.

After 600 lines of code in 3 python files :

  • Nodes.py (custom node tree and nodes for the node editor)
  • PlayNodesCompile.py (xml exporter)
  • bge runtime (PlayNodesRuntime.py)

I pressed Alt+P and BÂM ! It worked, the damn Cube was rotating at will in any axis !!!
Whatever you want to rotate in your scene will rotate !!!

Nodes.py allows you to create the gameplay nodes in the node editor.
PlayNodesCompile.py exports the xml representation of the nodes you created

You generate any number of gameplay graphs for any purpose, they will all be processed by the runtime.

****.xml
*****.xml

PlayNodesRuntime.py is the only file you would need in your project to play the game.

Dear bge users, can you tell me if you would be interested in this easy to use nodal logic system for the bge.
It is still compatible with the rest of the logic bricks.

Thx to pynodes, it is very easy to create the node gameplay system of our dreams in blender 2.6+, without the use of external libs or custom blender build.

I believe this could be an awesome way to create gameplay. There have been projects on nodal systems for the bge, the last one is the hive system, i find it a bit complicated to use and not user-friendly.
To unleash the full power of the bge there would be a trillion nodes to add in the PlayNodes system and it would take time.

Have you ever used unreal’s Kismet or cryengine’s flow graph or even threenodes.js ?!

http://udn.epicgames.com/Three/KismetReference.html#Actions
http://docs.cryengine.com/display/SDKDOC2/Flow+Graph+Editor
http://idflood.github.io/ThreeNodes.js/public/index.html

Blender Game Engine must have this feature now !

I believe this will be interesting, since the logic bricks are outdated and a better system is needed, more modern than the current one! Im sure that there are interested bge users for a node based logic system, that will replace the logic bricks, but lets see what will they say. Also to note a design doc should be made before the actual work begins. :slight_smile:

Being unable to see your implementation, I will make some points in the interest of friendly development. I’m managing the HIVE project for SjoerdDeVries whilst he is indefinitely occupied with his job.

Currently, the main limitation of the logic bricks isn’t the fact that the linking is limited, it’s the fact that data that sensors collect cannot be mapped easily to the actuator. Parameters are hard coded. It is also quite frustrating that you can only have single-stage operations, so if data needs multiple operations performed on it, you need to stage it over a number of logic ticks. Both of these issues are addressed in HIVE’s design.

Currently, you seem to have addressed the staging problem, but still avoid sharing data between nodes. Most of HIVE’s code base is dedicated to ensuring clean connections between nodes, and supporting multiple means of data exchange.

I admit that HIVE is currently user unfriendly. The project to give it a Blender UI will improve the existing workflow, and the standard library should further encourage logic-brick users to give it a try.

Maybe someone will help you in this endeavour.

@agoose77

If you connect multiple nodes together, they must get their data in the current frame. lol.

Im sure there will be some issues with the mechanisms of the current implementations of the python api, for example i have seen that collision callbacks were added only last year on KX_GameObject.

But i hope the api will evolve in a good way and enable us to replicate the same visual programming style as kismet.

The logic behind the implementation is simple :

The runtime initialisation reads the xml file, instantiates all nodes and links them together to replicate the graph as it exists in the node editor.

In its run method, when there is an event, it fires the nodes related to this event.
Event nodes are entry points to the graph, some nodes are never processed until an event occur.
The challenge is to optimize the way to detect events and fire the related nodes, to minimize the processing time of the run idle.

There is no multithreading, everything is linear and happens within the current frame.

The logic bricks are limited in 2D space, becoming a mess of lines rapidly.
And you still need to code in python some gameplay stuff.

With the node editor you have enough 2D space to organize your stuff without multiple overlap. And there will be nodes like if, switch, for loops, that will allow you to code without writing lines of python, that is why they call it “visual scripting”, it is still a full featured python scripting but in the form of nodes and graphs.

Whatever you can do with python in the bge, must be available in the form of nodes.

And there are other interesting things that can be done for games with the node editor like

  • behavior trees
  • state machines
  • animation blend trees (mecanim in unity, persona in ue4)
  • post processing

Allow me to rephrase. Your implementation does not currently expose parameters like rotation speed or object selectors to the nodes. So you will still need to write scripts to modify such values in-game. Have you plans to address this? And if so, have you given thought to the possibility of push / pull data transfer.

I am all for fixing hive, or implimenting logic nodes,

Hive hurts my brain crater it leaves.
Can you easily make constraint nodes? What about existing logic bricks, can you impliment all of them?

After you do, do you think you could take a look at finishing the collision callbacks?

Right now you can’t get collision.impulse

and then there is ray.poly_proxy right now I can only get materials on triangle meshes, and you cant compound parent them.

Btw Thank you!
I love logic and python, but could use something that was “halfway” between the two.

  1. HIVE isn’t “broken”. It just isn’t finished (though that’s only the BGE side, which any Python-user could develop)
  2. Constraints are not logical operations, and don’t belong in HIVE or PlayNodes
  3. Yes, all logic bricks can be implemented, except for the actuator sensors, and the near/radar sensors (though these can be implemented as game objects with collision sensors, so that doesn’t matter).
  4. I have finished them, but the data that Blender spits it out is either wrong, or useless (the impulses and forces are highly unreliable, I blame the BGE’s implementation of Bullet)

@agoose77

Your implementation does not currently expose parameters like rotation speed or object selectors to the nodes. So you will still need to write scripts to modify such values in-game

It has object selector.
Do you mean rotation speed of the object ?

In fact in the nodes you will be able to access that blender can.

And in the bge, once you know the name of an object, you can grab a reference of it and do anything you want with.

Yes, you have objects selectors, but there is not visible way that I can see for other nodes to provide that information. So if you wanted to add an object during the execution of the game and use that as an object for another node, there would be no means for doing this
For example, see the “view matrix” pin:

I never said hive was broken, it’s just much harder to work, and to get the same result,

Have the dev team been looking at blenders bullet wrapper?

@@BluePrintRandomm

The way actuators and sensors are designed they can be translated to nodes, in fact they are already nodes, but the logic editor has design restrictions.

If there is a problem with the python wrapper, some missing elements that are available in the original bullet sdk, it will need to be fixed in the cpp files.

My idea, is to have similar features as the new kismet for adding gameplay, hud, etc, to a game.

@agoose77

So if you wanted to add an object during the execution of the game and use that as an object for another node, there would be no means for doing this

Ill tell you how it works in ue4 kismet to manage dynamic instanced objects :

at runtime, you need to keep track of the objects you create and store them somewhere, maybe in an array variable, or just a variable, or you could just store their name.

Then to grab a reference of the instanced object at runtime you would use a node. The node would read the data in the array, or the variable, or find the object by name for you.

give me 5 minutes i will edit this post and put some screenshots to illustrate

Edit :


In this screenshot you can see how to deal with dynamic object instances.
You always know where they are stored and how to retrieve them, you can see that the node editor doesnt know anything about them, it just guess that they are here, then at runtime it knows exactly what is where.

in this case GameObjects are stored in an array, there are built in nodes to access the array property such as “length”, and functions like “GET element at index”
The result of the GET node is used as a reference for a node that performs a cast on it for use in the next node that we do not see on this screenshot.

You can see mechanisms like dynamic casting used in the node system, in fact the node system is just the same as writting scripts in a text editor, but instead of writing text, you just use some cool nodes to do the job.

For example, see the “view matrix” pin:
http://www.pasteall.org/pic/72577


On this image look at the pins, you can add as many as you want. in pynodes there must be a way to do something similar i think

I am sure there will be more than enough support for you to want to continue developing this, but I would recommend you work with agoose77 to complete HIVE. It already supports custom nodes so your framework should be compatible. I am sure it would be a lot less work fixing the minor GUI problems and adding nodes than starting from scratch. In any case, I wish your project well and hope you decide to help make HIVE better.

Its not minor ui problems, it is like it was written by aliens, but its been a few months since I checked it out. But at that point, it was not apparent how to do anything, it just did not feel intiuitive like the logic bricks.

Workers spyder, etc, the lingo was tricky even.

It needa to be named with conventions that are apparent.

Wow, another pynode implementation! I’m surprised to see this because I’m also working on a similar system. While my method isn’t exactly the same, it seems similar enough. I would look to see your code and how you got everything working :slight_smile:
As far as working on hive goes, I don’t have anything against it, but the system just seems so much more complex than we need. Also, is hive still being actively worked on, or ar you guys just waiting for someone e to try and pick up the project?

Anyway, great to see people interested in improving the bge, and I can’t wait to see what you come up with.
-sent from my Note 3

That is more of a limit with the available documentation than the actual system. Granted that the GUI could be a bit more friendly, but even then it would still be less work solving that than starting over. It is very difficult to use in its current state, but once it gets past those hurdles, it will be more widely used.

There would still be problems as “apparent” is highly subjective to the individual. What may seem like common sense to one person, may not be so common for another. Having documentation to browse through should reduce or even eliminate the uncertainties of proper use. In any case, this is starting to go off topic, lets discuss HIVE over at its thread.

While it’s nice that Pynode implementations can now be done for BGE logic, I believe the one that the majority of people will end up using will be HIVE (once the addon for it is complete).

HIVE is already designed for completeness, performance, flexibility, and widescale use of Python. It willl simply take a lot of work if you were to get a full Blender-based implementation to that level.

Whilst I am of course a HIVE advocate, there is merit in exploring other systems if you’re interested.

@Renaud
I feel like we’re slightly crossing wires, I know that these features already exist (HIVE has them after all :)) but I didn’t see any evidence for them in your screen shots, so I was curious if you were planning on implementing them at some stage.

A little note on HIVE:
HIVE’s apparent complexity is more of a misunderstanding of its capabilities. Issues that I consider of a higher priority than documentation at the moment are essentially user friendliness of the UI. This is from little things like catching all possible exceptions, moving the code to a more PEP8 friendly format, ensuring node names are sensible and docstrings display. Certain HIVE-terminology like “bound objects” need clarification (a bound object basically means that the logic system is bound to that object, rather than running independently).

After implementing the UI, I’ll create some demonstration files, and perhaps a converter from logic bricks to HIVE nodes.

And there are other interesting things that can be done for games with the node editor like

  • behavior trees
  • state machines
  • animation blend trees (mecanim in unity, persona in ue4)
  • post processing

This will be the BGE`s = The Doom BFG! Thats like a winner features! (Im thinking about dialogue trees with nodes.) It will be interesting to see a U4 blueprint made with pynodes.