Modifying Config File vs Nesting Objects in Structs - Time to execute

edited October 2020 in Help request

I'm currently tying some things to an Animation. A player can pick something up and they bend down and are set as uncontrollable, when the animation ends I figured I could use an animation event handler to set and unset the "controllable" property that I'd place inside the config file. What I'm wondering is whether it would be too much overhead to constantly pull config file information to see whether someone can actually move or not, or whether I'm better off creating a struct with the "controllable" bool and placing the orxObject inside the struct.

As a side thought I was also hoping to make a server/client architecture in the future, and was wondering whether its a terrible idea tying things to animations in this case, and how much having the server not actually display the animations on the screen will affect its animation routine.

Tagged:

Comments

  • There is definitely a cost to fetching config data, but it's very likely to be negligible in your use case.
    To give you an idea, on my 5-6 years old CPU, fetching a config value takes around 0.1 microseconds.

    I don't know much about the details of your game, but having a server doesn't mean you can't have the animation running on it, even if you do not display anything in the end.

    As for setting your controllable status, you can also do it by using a command that would be executed directly by the animation (you can tie to to specific frames), which would help reducing the amount of code handling events.

    For example, let's say you want to set your controllable status to false at the first frame of your pick anim, you can simply do something like:

    [Pick1] ; First frame of Pick anim
    KeyEvent = Set ^ Controllable false ; <= this would use the current object's GUID as section
    

    or

    [Pick1] ; First frame of Pick anim
    KeyEvent = > Object.GetName ^, Set < Controllable false ; <= this would use the current object's name as section
    

    Those are just example, but it should give you an idea of how easy it is to tie logic to animations in a data-driven way.

  • edited October 2020

    Oh beautiful, I should have checked the creationTemplate better before posting, its like theres already something for everything.

    Again I appreciate the help.

    I'll post a video of my game once I get some more art done for it.

  • My pleasure, don't hesitate if you have any other questions!

  • https://wiki.orx-project.org/en/tutorials/objects/using_orxobjects_in_classes_with_an_eventhandler

    I found the useful eventhandler guide which allows you to tie an OrxObject to its parent Struct, which seems to work well and is an easy way to do things. In case anyone wants to do something similar in the future and manages to find this.

    Object creation

     orxConfig_Load("playerObject.ini");
     player1.object = orxObject_CreateFromConfig("Player1");
     orxObject_SetUserData(player1.object, &player1);
     player1.controllable = true;
    

    Then I think its easy enough to watch those animation events as in the other guide:

    orxSTATUS orxFASTCALL EventHandler(const orxEVENT *_pstEvent) {
        orxANIM_EVENT_PAYLOAD *pstPayload;
        
        pstPayload = (orxANIM_EVENT_PAYLOAD *)_pstEvent->pstPayload;
        struct Player* playholder;
    
        switch(_pstEvent->eID) {
            case orxANIM_EVENT_STOP:
                //Set controllable to false
                playholder = orxObject_GetUserData(orxOBJECT(_pstEvent->hRecipient));
                playholder->controllable = true;
                orxLOG("stop");
                break;
        }
        
        return orxSTATUS_SUCCESS;
    }
    

    Then the animation config file of course needs this
    PickupAnim-> = IdleAnim

  • Yes, that's the intent for the UserData parameter.
    That's also what Scroll does (in C++) as well, though the binding is semi-automated and follows inheritance: https://wiki.orx-project.org/en/tutorials/orxscroll/binding-orxscroll

  • Thanks. I've been trying to learn C. Its been pretty difficult but rewarding so far, function pointers are a hard thing to wrap my head around.

    Think I've got Orx Timers working well enough:

    > // Timer Event
    
    void orxFASTCALL SetControllableHandler(const orxCLOCK_INFO *clockInfo, void *_object) {
        struct Player* playerObj = (struct Player*)_object;
        playerObj->controllable = true;
    }
    
    > // Add 2 second timer with player object struct.
    
    orxClock_AddGlobalTimer(SetControllableHandler, 2.0, 1, &player1); 
    

    The one thing I'm wracking my brain with is passing the time, I'd need to read the config file for the animation, and then multiply it by the number of frames of the animation. Yet I'm having a hard time reading specific configs; is there a way to target this specific player config in a generic way so that this works for multiple configs, or does every animationSet and animationTemplate need to be named differently?

  • Hi @sacked, I'm afraid I don't understand your current question.

    Do you think you could give me a detailed example of what you want to achieve and the hurdles you're facing, to help me understand?

  • edited November 2020

    Sure, I apologize, I realize I'm all over the place. I got it working with the animation just fine, however I thought it may be better to perhaps use timers, since not every animation ending should allow an object to be controllable, and not every object will have a controllable variable attached.

    So when I push a button an animation starts and the player becomes uncontrollable, I figured I could use a timer event to initiate when the player becomes controllable again, the timer event being set to the animation time being frametime * number of frames.

    So my script above was what I was doing with there. However I was hoping to read the config file to pull the animation time, and I was hoping to make it generic. So I've got a Player1 object which inherits the playerobject, is there a way to possibly drill down from the Player1->PlayerObject->PlayerAnimationSet->PickupAnime?

    >! [Player1@PlayerObject]
    
    ;###################################
    ; Player
    [PlayerObject]
    Graphic = PlayerGraphic
    Position = (100,-100,0)
    AnimationSet = PlayerAnimationSet
    Smoothing = true
    Body         = PlayerBody
    
    [PlayerGraphic]
    Texture = RunGuide.png
    Pivot          = center
    
    [PlayerBody]
    Dynamic  = true
    ;PartList = HeroBodyPart
    LinearDamping     = 5
    
    ; Animation
    [PlayerAnimationSet]
    Texture          = RunGuide.png
    FrameSize    = (55, 55, 0)
    Pivot        = center
    KeyDuration  = 0.1
    IdleAnim = 4
    RunAnim = 8
    PickupAnim = 3
    StartAnim   = IdleAnim
    IdleAnim-> = IdleAnim # .RunAnim # PickupAnim
    PickupAnim-> = IdleAnim 
    RunAnim-> = RunAnim # .IdleAnim
    
    [IdleAnim]
    TextureOrigin = (0,110)
    KeyDuration  = 0.1
    
    [PickupAnim]
    TextureOrigin = (0,0)
    KeyDuration  = 1.0
    
    [ThrowAnim]
    TextureOrigin = (0,55)
    
    [RunAnim]
    TextureOrigin = (0,0)
    
    
    
    ;###################################
    
  • No worries, and thanks for the details, I can now understand the situation much better.

    I can think of three alternatives, from the top of my head:

    • You could simply retrieve the length from the animation structure itself, instead of trying to compute it from the config data, with orxAnim_GetLength.
    • Another option would be to use key event to trigger this behavior from a command instead, and keep the whole system data driven.
    • A last option would be to listen to the animation end event instead, you can register your event handler when starting the animation, then in the handler, you can execute your code and unregister the handler.

    I tend to prefer data-driven approaches, but beside personal preferences here, I think they're all valid paths.

  • Ah nice, I clearly didnt fully understand key events. I see now that its available in the event handler as orxANIM_EVENT_CUSTOM_EVENT. I figured it was localized entirely to the config files. This looks like it will work great, thanks again!

  • My pleasure! You can use commands directly in the KeyEvent properties, or have your own data that you'll use in your event handler. Both should work correctly.
    If you haven't seen it already, this video might help, especially the last part:

  • edited November 2020

    Holy cow thats very powerful. Are there any simpler resource to learn all these things, such as what the ^ is doing, and where the name Object is coming from? Whats the best way to learn these key events?

  • Yep, everything should be available from the wiki.
    Regarding commands, I'd suggest reading the top links found with: https://wiki.orx-project.org/doku.php?do=search&id=commands

  • If you look at the tutorial 04_Anim that ships with orx, you'll see a simple example of key events, though it's not executing any commands there.

  • Ah perfect, thanks.

Sign In or Register to comment.