In the hello world tutorial, I read “You do not need to extend the Node class to include variables!”. However, I can come up with lots of reasons why I would want to extend it. So I wondered, is there a reason not to do it?
May I ask what the reasons are, that you want to do that? In an inheritance hierarchy I generally only have Leaf Nodes as concrete instantiateable classes (something I learned painfully from C++). If you just want to add some data, add it as UserData or add a control
I will repreat Phoenix’s comment “mostly only happens if you mix logic and grafic”
@Empire Phoenix said:
The main reason is, this mostly only happens if you mix logic and grafic.
You might want to keep your game objects seperate.
A very simple solution would be HashMap<Node,MyLogicObject>
Pro if you ever want to add entowrk ect. you can just send the logicobjects, since sending scene graphs is not a good idea.
Now I will answer the question by asking another questions:
“How many Java way you know to put additional piece of infomation into an object”. Extends mean put it into “class definition”, another way is to add in a object instance internal bag of properties, userdata, controls… as JME spatial can, which called instance expanding. 3rd way is to associated that object instance or class with a link to another object, which called reference or Mapping… So through levels of search, from 0 to a fews you have the new addtional information of an object.
“How your Node extended class gonna be used instead of being rendered - how much the new data gonna be useful if it still stick to the scenegraph” - That’s call the split object dilemma, if a “class of object” are mixture and cause confusion, let split them into more than one, make each of them useful in the new data structure or enviroment.
“How many levels of abstract you gonna put into your class?” if you extend an existed class, Node for example… it can not “extends” another! Remember to implements behaviour via interface in java
“How many levels of references you gonna link your new class with associated Node data?” Zero mean extends, one mean property, more than one mean Map. In additional, proxy mean your new class can acted like the real Node, you can do it via scripting…
After anwser questions about the trade off between “Usefulness vs complexity” - “Convenient in coding vs reusable” - “Clearance vs performance” , you can decide you should “extends” Node or not.
Scondly, yes, I am very aware that you don’t want to mix logic and graphics. For almost all of my projects I employ a Model-View-Controller architecture. I was just wondering about that, because of how it was formulated in the tutorial.
Concluding your answers: there are only design reasons not to do it, no technical reasons (except for the multiple inheritance, which I am not wanting to do as I want to keep my stuff separated).
I dislike using maps to add data, because they are slower than a direct link and less obvious (design, again), and you can’t add operations related to the added data. What I most likely want to do in terms of extra data is put a link back to the logic object.
One final thing: if it is generally a bad idea to use the map, why is it in? Only takes memory if it isn’t being used. And where additional data is needed, this can be solved with a subclass.
@alestrooisma said:
First of all, thanks for your answers.
Scondly, yes, I am very aware that you don’t want to mix logic and graphics. For almost all of my projects I employ a Model-View-Controller architecture. I was just wondering about that, because of how it was formulated in the tutorial.
Concluding your answers: there are only design reasons not to do it, no technical reasons (except for the multiple inheritance, which I am not wanting to do as I want to keep my stuff separated).
I dislike using maps to add data, because they are slower than a direct link and less obvious (design, again), and you can’t add operations related to the added data. What I most likely want to do in terms of extra data is put a link back to the logic object.
One final thing: if it is generally a bad idea to use the map, why is it in? Only takes memory if it isn’t being used. And where additional data is needed, this can be solved with a subclass.
Though every down side you’ve described is then better handled with a control instead of user data. And controls and user data have the added benefit that they can be added to any spatial… or even different spatials than you originally intended. This means you could add them directly to a loaded model, for example.
As you’ve guessed, the user data is only allocated if used. Since a scene with more than 2000 nodes is already horribly inefficient for other reasons, it is likely that you will still only have a handful of user data in comparison to all of the other things allocated in the VM. Even 2000 tiny hashmaps is not many.
In general, the MVC pattern in JME tends to look like Node->Control->Model where the Control is responsible for updating the spatial based on the model.
if youre writing a game, avoid extending stuff. (in case of Node, you would add a Control to it that holds your game’s content)
if youre writing a game engine, extend classes as needed to add new features.
of course this is just general “best practices”, even jmonkey itself violates this in some ways. (for instance SimpleApplication is abstract ). Its ultimately your code and you can do whatever you want. You’ll likely discover as you work on things in jmonkey what practices work best for you.
@icamefromspace said:
how i usually respond to this situation is
“are you writing a game, or a game engine?”
if youre writing a game, avoid extending stuff. (in case of Node, you would add a Control to it that holds your game’s content)
if youre writing a game engine, extend classes as needed to add new features.
of course this is just general “best practices”, even jmonkey itself violates this in some ways. (for instance SimpleApplication is abstract ). Its ultimately your code and you can do whatever you want. You’ll likely discover as you work on things in jmonkey what practices work best for you.
This is good advice.
I have found myself extending Node in the past for various reasons but I couldn’t solidify clearly what heuristic I used to decide to do that. Universally, it’s when I’m making an API for someone else. (See Lemur) Sometimes doing it leaves the API less flexible but it’s a trade off.
For my game code it’s nearly always a control or an app state. The only other case I’ve found to extend a Spatial class is to stub out collidesWith().
I have found myself extending Node in the past for various reasons but I couldn’t solidify clearly what heuristic I used to decide to do that. Universally, it’s when I’m making an API for someone else. (See Lemur) Sometimes doing it leaves the API less flexible but it’s a trade off.
For my game code it’s nearly always a control or an app state. The only other case I’ve found to extend a Spatial class is to stub out collidesWith().
it’s nearly always a “Control” or an “App state”.
This is also one of my “best practices” so far - favourite one in JME3 learning path.
I DID come from web background which “M-V-C” means the solid design pattern which i and my colleagues have to use over time. Where the View and the Model should not contain any logics but behaviours, and Control do all the activitives underlying. We also usually have ViewController to update control and ModelController mostly do data access and stuffs … acordingly. But my M-V-C experiences also DID lead me the wrong way at first - JME3 don’t have a clear M-V-C as thought!
In JME3, the hidden Render “AppState” do the ViewController job. And other Control and AppState do ModelController job mostly. If we just concentrade to graphics side, we can also see the Spatial as a solid “view only” Model. If we put UserData into Spatial, it also become a “data container” Model.
So to write up a “common game”, not extend the engine with new API. We only put more logic into “AppState” and “Control”. To extend the engine, mostly graphics side, we should extends the Spatial - which is the real hidden “View+Model”. Better look carefully in SceneProcessor-Geometry-Material-Shader-Filter … and trace down that path.
To the topic owner @alestrooisma: if you don’t need to extend graphics side, just put data into UserData_Clearance is good, performance is not that bad, dynamic should also be good until you can also handle memory usage with Control or AppState to make it acceptable. That’s JME3 has a “good” design for a real-time application, but it’s NOT “pure” M-V-C!
my logic is completly independent of jme, in fact I could plug any other grafic engine into it, as I only have one mapping class wich does the binding to jme.
But there are many ways to write something, for one university project I just extend node and put all stuff in there, works also and saves any kind of additional sutff at the cost of flexibility.
So make up you mind about how long you expect to work with the code, if it is just to finsih a small project then go for whatever. if it is a largescale project you plan on spending a few years with, better make sure it stays flexible.
@Empire Phoenix said:
Depends, for me complete jme3 is the view,
my logic is completly independent of jme, in fact I could plug any other grafic engine into it, as I only have one mapping class wich does the binding to jme.
But there are many ways to write something, for one university project I just extend node and put all stuff in there, works also and saves any kind of additional sutff at the cost of flexibility.
So make up you mind about how long you expect to work with the code, if it is just to finsih a small project then go for whatever. if it is a largescale project you plan on spending a few years with, better make sure it stays flexible.
Agree with you most of the points but the first sentence, its depens on how you look at the situation, from what point of view and the scope. I explain how “JME3 system” alone works under the lens of M-V-C inspector.
If envolve something else, for ex: a repository of data else where (any kind), then you can look at the repository as model and the JME3 scene graph is view. There is also no contract that you have to use AppState as the Control, as it’s just a hook to the main cycle but we should recommend to do so.
Others can properly come up with somekind of Cycle imposition instead of just init-render-update paradigm. In my framework I comeup with 5 steps paradigm init-config-load-update-finish interface called ICycle … render is not even in there. So eventually an “Control” can be an AppState and also envolve ICycle or whatever it likes .
…but in JME3 system, there is already one solid AppState did act as ViewControl is the RenderAppState and the main update cycle act like a View callback to Control!
I find the whole MVC model to be deeply flawed, as it fails to properly seperate the layers for all but the simplest applications.
Thinking in a cycle logic is also flawed, as it cannot properly reflect a multiprocessor enviroment (for single Thread applications it works mostly).
When I develop I never think about patterns, but about the problem. If my resulting solution is a pattern then so be it, but thinking the other way around limits artifically.
I, for one, think you should extend Node always… even if there is no good reason. Just to buck the system.
Power to the people.
You gotta fight for your right to party.
I should buy a boat.
Seriously though, there are times when it is appropriate and times when there is no good reason (which is probably 99% of the time).
1 thing to keep in mind, if you do decide to go this route is: Devs won’t be able to support your implementation of Node, so if you hit issues, the first thing they will point at (and 99.9% of time, rightly so) is your code.
The one time I think it is appropriate would be if you are actually extending the functionality of Node… not storing extra data… but really extending the functionality.