Need help with multiple actions and inputs

Hi everybody, i’m working on a fight game and get stuck in some functions:

_Need to play some actions, like walk and guard, ONLY when the key input is pressed, something like flipper mode in logic bricks, but with python. I’ve tried many codes and aways plays the entire animation.

_Hold the animation (action “Guard”) on certain frame while key is pressed and continue the animation til the end when key is released.

My code so far:

import bge 

def charActions():

    cont = bge.logic.getCurrentController()
    own = cont.owner
    keyboard = bge.logic.keyboard

    guardOn = True
    backKey = bge.logic.KX_INPUT_ACTIVE == keyboard.events[bge.events.AKEY]
    frontKey = bge.logic.KX_INPUT_ACTIVE == keyboard.events[bge.events.DKEY]
    lkickKey = bge.logic.KX_INPUT_JUST_ACTIVATED == keyboard.events[bge.events.JKEY]
    mkickKey = bge.logic.KX_INPUT_JUST_ACTIVATED == keyboard.events[bge.events.KKEY]
    hkickKey = bge.logic.KX_INPUT_JUST_ACTIVATED == keyboard.events[bge.events.LKEY]
    lpunchKey = bge.logic.KX_INPUT_JUST_ACTIVATED == keyboard.events[bge.events.UKEY]
    mpunchKey = bge.logic.KX_INPUT_JUST_ACTIVATED == keyboard.events[bge.events.IKEY]
    hpunchKey = bge.logic.KX_INPUT_JUST_ACTIVATED == keyboard.events[bge.events.OKEY]
    
    if backKey and frontKey:
        backKey = bge.logic.KX_INPUT_NONE
        frontKey = bge.logic.KX_INPUT_NONE
    
    if backKey and guardOn:
        own.playAction('Guard',1,10,layer=0, priority=1, blendin=0, play_mode=bge.logic.KX_ACTION_MODE_PLAY)
    
    if backKey:
        own.playAction('WalkBack',1,18,layer=0, priority=5, blendin=0, play_mode=bge.logic.KX_ACTION_MODE_PLAY)
    
    elif frontKey:
        own.playAction('WalkFront',1,18,layer=0, priority=5, blendin=0, play_mode= bge.logic.KX_ACTION_MODE_PLAY)
        
    elif lkickKey:
        own.playAction('LKick',1,15,layer=0, priority=4, blendin=0, play_mode=bge.logic.KX_ACTION_MODE_PLAY)
       
    elif mkickKey:
        own.playAction('MKick',1,16,layer=0, priority=3, blendin=0, play_mode=bge.logic.KX_ACTION_MODE_PLAY)
            
    elif hkickKey:
        own.playAction('HKick',1,18,layer=0, priority=1, blendin=0, play_mode=bge.logic.KX_ACTION_MODE_PLAY)
            
    elif lpunchKey:
        own.playAction('LPunch',1,8,layer=0, priority=4, blendin=0, play_mode=bge.logic.KX_ACTION_MODE_PLAY)
            
    elif mpunchKey:
        own.playAction('MPunch',1,17,layer=0, priority=4, blendin=0, play_mode=bge.logic.KX_ACTION_MODE_PLAY) 
    
    elif hpunchKey:
        own.playAction('HPunch',1,17,layer=0, priority=2, blendin=0,  play_mode=bge.logic.KX_ACTION_MODE_PLAY) 
        
    else:
        own.playAction('Stand',1,44,layer=0, priority=6, blendin=0,  play_mode=bge.logic.KX_ACTION_MODE_PLAY) 
                      
charActions()

You have to stop playback explicitly.

if input1:
    #playAction
elif own.isPlayingAction() and own.getActionName() == "name_of_action":
    own.stopAction()

Here’s functions you can play around with to get different behaviours going.
https://upbge-docs.readthedocs.io/en/latest/api/bge.types.KX_GameObject.html#KX_GameObject.stopAction

Thanks for the answer. I tried stopAction but it did not work. What I need is:

While key is pressed, play the animation until certain frame and hold that frame until the key is release.

you can get the current frame with
action_layer = a_l = 1
f=armature.getActionFrame(a_l)
n=your frame limit
than you can check if f>=n
and set
own.playAction(‘your action’,n,n,layer=1, priority=1, blendin=0, play_mode=bge.logic.KX_ACTION_MODE_PLAY)
you can change play_mode if you need
didnt test it but should works

@giobbo I think your solution shoud work, but I solved using keyboard events activated/active/released. I just dont know if i can use this method for joystic inputs too…

if backKeyP and guardOn:
        own.playAction('Guard',1,5,layer=0, priority=2, blendin=0, play_mode=bge.logic.KX_ACTION_MODE_PLAY)
        
    if backKey and guardOn:
        own.playAction('Guard',5,5,layer=0, priority=3, blendin=0, play_mode=bge.logic.KX_ACTION_MODE_PLAY)
        
    if backKeyR and guardOn:
        own.playAction('Guard',5,10,layer=0, priority=2, blendin=0, play_mode=bge.logic.KX_ACTION_MODE_PLAY) 

sure, just add an check to set the keyboard or controller

example:

joystick = joystick detection

if joystick:
    backKeyP = joystickbutton
    forward = joystickbutton
    etc...
elif not joystick:
    backKeyP = keyboard button 
    etc....

if backKeyP:
    obj.playAction()

also:

elif own.isPlayingAction() and own.getActionName() == "name_of_action":
    own.stopAction()

need the layer where the action is played on, so if an action plays on layer 2 it should be:

elif own.isPlayingAction(2) and own.getActionName(2) == "name_of_action":
    own.stopAction(2)

and also

f=armature.getActionFrame(a_l)
n=your frame limit
than you can check if f>=n
and set

should be handled a little bit different, like:

action_layer = 2
current_action_frame =armature.getActionFrame(action_layer)
frame_to_do_something_at = 10
if current_action_frame > frame_to_do_something_at and current_action_frame < frame_to_do_something_at + 1)
    #do something here, like parenting a weapon or something

This will ensure that it will only execute when needed, doing >= will at least execute it twice or not at all, so you need to pick a frame between 2 checks, so in this case at frame10.5 frame it will execute the code to do something.


@Liebranca, @giobbo

Layer defaults to zero for all action methods AFAIK; he’s setting all actions on layer zero, so it should work anyhoo. But ayyy, me was a tad lazy and didn’t get into detail.

Thank you guys, problem solved. :grinning: