Appstate or controls

hello,

I used to write controls , passing them their corresponding Node/Spatial and tons of other stuffs (rootNode,Bullet…)

reading the doc I figured out I should use appstate to do basicaly everything (AI, …) instead

“Needing access to application level objects is a sign that this class should be designed as an AppState”

  • I was doing AI in a control passing it the PlayerControl class, is it wrong ? should this be moved to an appsate ?

  • if an appstate manages AI, it will eventualy use classes to represents characters/props data for instance, witch in the end will look like control classes ??

  • what if a Control has to replace sub nodes of it’s spatial by new objects, it has to have an instance of assetmanager to load these new objects/materials

anyone could enlight me on these ?

thanks

Well, think of controls as something that adds a behavior on a single spatial. For example, you want to have a spatial rotate on itself, that’s a job for a control.

Now if you have something that should handle some things more general to the scene, or to the game, it’s more the work of an AppState. For example you can have an AppState for each game level, an appState for the “pause” menu and so on.
You can also have AppStates for more localized things (a cinematic is an Appstate for example).
I would make an appState for handling AI, and have it access data that represents characters (the data model) on one side, and have it access the scene’s objects (the view) on an other side. And of course the AppState would be the controller.

Now you’re gonna say,“yes but I can do that with a control attached to the rootNode”. yes you can. and that wouldn’t be wrong neither. But if you have to do this, that’s maybe a signal that you’d better use an AppState instead.
Remember that an AppState is not only a hook on the update and render loop, it also has an easy access to the app itself, so transitively to the assetManager, the inputManager, the renderManager, and so on.
A control is just a hook on the update and render loop.

There is no absolute rule though, It’s more for more of a matter of convenience and code readability.

but I’ll end up with an appstate doing everything
AI, path finding for npc’s, input handling for player, and so on, in a huge big update() loop …
going back to #1 where simpleapplication.update() did everything

controls seemed to deal with specilalised cases better

Well no, I’m not saying to use only ONE AppState. You can have many of them, one for each task…
AIAppState, InputHandlingAppState, CameraMovementAppState, WhatEverAppState.
You can have specialized AppState as well as specialized controls

I cleaned up my constructors, but now a lot of rootNode,assetmanager… are missing in my controls, so I end up passing them by parameter where needed, what a mess

also I used to maintain a state machine in each control, it means I gonna have to move that code in the appstate
it seems so ugly

also the update function of my controls needed the rootNode and assetmanager, now they’re gone, I dont get this…
I guess I’ll put the state machine in the appstate, but then what is the point of having a control class if all the logic is done somewhere else

You can get the assetManager from the app. (passed in initialize()). And the rootNode is the first scene of the app’s viewport.

Why is that ugly to have a state machine in an appState and not in a control?

I’m not saying either that you should use AppState over Controls every time. I can’t tell what’s the best choice in your case as I don’t know enough about your application.

Well that’s definitely a sign that this should be an AppState. But there again no absolute truth exists.
What is this control doing? On what spatial did you attach it?

Controls controls one spatial, AppState controls more broad things…
Logic can be done in a control, if the logic is relative to this spatial.

I removed rootnode and assetmanager , they were used only for debuging purpouses

but I end up having in the update loop of my appstate:

  • the code that was formerly in the simpleapplication.update
  • the code of the state machine that was formerly in my control (cos it needs game state data like navmesh and other list of controls)
@Override
    public void update(float tpf)
    {
        super.update(tpf); //To change body of generated methods, choose Tools | Templates.
        
        if(go && (playerControl!=null) )
        {
            Vector3f frontDirection = Tools.GetFrontDirection(playerControl.getOwnerNode()).normalize();
            Vector3f finalDir= new Vector3f(0,0,0);
            if (forward)
                finalDir=frontDirection;
            else if (backward) 
                finalDir=frontDirection.mult(-1);

            if (strafeRight)
            {
                Vector3f rightDirection = Tools.GetRightDirection(playerControl.getOwnerNode()).normalize();
                finalDir.addLocal(rightDirection.mult(-1));
            }
            else if (strafeLeft)
            {
                 Vector3f rightDirection = Tools.GetRightDirection(playerControl.getOwnerNode()).normalize();
                 finalDir.addLocal(rightDirection);
            }
            //-----------------------------
            if(finalDir.length()>0)
            {
                finalDir.normalizeLocal().multLocal(playerControl.getWalkSpeed() * tpf);
                playerControl.RequestMove(finalDir);
            }
            //------------------------------
            CheckObjectUnderMouse();
        }
        
        switch(playerControl.getState()) // <------------- state machine
        {
            case ROTATE_TO_TARGET:
            {
                if(playerControl.RotateToTarget(tpf))
                {
                     playerControl.setState(playerControl.getNextState());
                }
            }   
                break;
            case GOTO_TARGET:
            {
                if(playerControl.GotoTarget(tpf, sceneDataBundle))
                {
                    playerControl.StopMoving();
                    playerControl.setState(playerControl.getNextAction());
                }
            }
                break;
            case PICKUP_PROP:
            {
                playerControl.PickupProp();
                playerControl.setState(PlayerControl.States.IDDLE);
            }
                break;
        }
    }

I am not sure if i should leave the state machine there or put it back in the PlayerControl, passing it the navmesh and other things in the constructor

I gonna have to avoid appStates, this is crazy

as I try to update my AI code for ennemies, they need
-rootNode for ray collision detection
-navmesh
-PlayerControl for interraction,

and I dont want to put all my update() codes(machine states) for each type of character to an appstate
it does not make any sens

Probably it doesn’t make sense because your code isn’t very structured.

It was structured before I started digging into appstates

as I said my controls requires sometimes rootNode for ray collision detections, or assetmanager to create new stuffs, and others data

my controls are state machines, so putting the update() code from different controls into an appstate update() is illogical in a OO paradigm

I just dont understand what’s the point of having an appstate dealing a list of controls if the update() function of these controls is not used and if it is the appstate that does the AI stuffs

MyControl(bulletAppState,rootNode,Assetmanager) <------------------ doc says it is bad

so if you check the previous code, I put the state machine code in the appstate (with to me is crap and anti OO)

or I create a function dosomestuff(tpf,rootnode… ) that just replaces the MyControl update function

myappstate.update()
{
it=listofcontrols.iterator
while(..)
{
 it.next().dosomestuff(bulletAppState,rootNode,Assetmanager)

???

You know, you are free to use Appstates, but dont you have to.

I just want to code in a good practice manner
the issue is that phrase “passing… to constructor is sign I should use appstate” like bad implementation or something
come to think of it, there is no explanation why

to summarize, either I pass an appstate or a bundle or whatever to a Control
or I use Control only for simple pos/rot/sca of the spatial
and use another class for AI, like AIControl wich would be updated by the appstate

any better idea is welcome

I think the root of all of your problems is that you treat Spatials as game objects. In an MVC type of approach, the Spatials are just the view.

Normally you’d have your own game objects doing their game object things… perhaps with their own state machines or whatever. An app state could then manage the global stuff related to all of the game objects (making sure the AI that requires updating gets updated and the AI that is asleep doesn’t or using some kind of AI-LOD to control which AI gets updated). Then the only controls on spatials you have are to update visual stuff based on the game objects’ current state.

When controls need global stuff it’s a sign of design problems like this. Having a Spatial need to do navmesh checks is like having a Swing Button directly talking to a database to get it’s label text.

yep you pointed it right, I always saw Controls as AI stuffs :smile:
it’s becos they are called Control, I figured it was the C in MVC
my bad

Controls kind of are the “C” in MVC… but I wouldn’t put AI in the C in MVC either because it has nothing to do with coordinating between the view and the model. It’s “business logic” as they say… it’s part of the model. There is good reason that VC is often collapsed (as in Swing).

I think you will find your life gets simplified if you separate out your game objects as their own thing. You gain a ton of flexibility and in the long run your code will be much cleaner.

MVC is deeply flawed anyway, its kinda like the OSI network model, nice to explain stuff with, but not usable in reality.

Usually you have more MVC of MVC’s. Eg a button in a gui alone has full MVC logic alone (model how does a button behave ect, its controller and its view)
You have the same in the sense of a single ingame window, and the same again with the Database side.

Yes, but it’s still a useful metaphor to discuss why his design is causing him issues… and already we see he slightly misunderstands the ‘C’ in control, too.

MVC of MVCs is accurate, though. I even had an HMVC (hierarchical MVC) approach I implemented in one of my old open source libraries… it was still all at the presentation layer, though. Kind of a combination between MVC and PAC.