• 2D
  • Hints on good way to structure weapon attack animations?

Basically, I have a character node, which could have different attacks (thrust, swing, punch, kick, etc.), and possibly different weapons. So I'm thinking that an attack could be a node, which would contain an animator, and eventually a weapon to pass, which will get thrust, swung, etc. everything initiated from the character node. Eventually, I'm thinking the hit detection, damage attack speed will be computed by the 'attack' node, which will take the weapon in effect.

Is this a good way to architecture that sort of logic?

Quick mockup works with a hardcoded sprite as weapon, but I'm having a bit of trouble with scales; character vs weapons vs animations, and since ex; the SlashAttackNode that contains the animator is the root node, I can't seem to get a 'reference' node; like a static sprite that would just sit in the middle so I could see if the animation is in scale to the character...

Typing this, maybe the root attack node could just be a holder, and contain a node to be animated, which might contain the weapon and character, which could both be animated (with 1 animator each?), would this make more sense? Seems much better; as this node would point to the same direction as the player and the animation would then likely point in the right direction...

So, different attack nodes would animate the player and weapon... (maybe eventually, 'scale' param could be passed for size of character; so it could animate smaller/larger characters also... (end goal is procedural characters via script)

Thanks!

6 days later

I am making a game with walk, run and idle animations along with a hide state and I feel a state machine might be what you're looking for. Even better, if you make your "weapon" node a child of your "actor" node, you can even use the methods of the state machine on the actor node to control the weapon. Or just make the state machine a class/extension.

Just spitballing but:

extends Node


enum StateMachine {IDLE, KICK, PUNCH, THRUST}
var attackState = StateMachine.IDLE

var weapons = ['BARE', 'SWORD', 'SPEAR', 'AXE']
var w_byte = 0
var myWeapon = weapons[w_byte]

func _input(event):
	if Input.is_action_just_pressed("kick"):
		attackState = 1
		print('Kick attack!')
		### do a kick function
		weapon_animate()
	if Input.is_action_just_pressed("punch"):
		attackState = 2
		print('Punch attack!')
		### punch function
		weapon_animate()
	if Input.is_action_just_pressed("thrust"):
		attackState = 3
		print('Thrust attack!')
		### thrust attack
		weapon_animate()
	else:
		attackState = 0
	
	if Input.is_action_just_pressed("change_weapon"):
		var w_max = int(weapons.size()-1)
		if w_byte <= 3:
			var w_shift = w_byte+1
			w_byte = w_shift
			if w_byte <= w_max:
				myWeapon = weapons[w_byte]
			else:
				w_shift = 0
				w_byte = w_shift
				myWeapon = weapons[w_byte]
				
		print('Switched to :' + str(myWeapon + "!"))





func weapon_animate():
	match myWeapon:
		'BARE':
			### change sprite here
			print("Striking bare handed.")
		'SWORD':
			### change sprite here
			print('Sword in hand.')
		'SPEAR':
			### change sprite here
			print('Spear in hand.')
		'AXE':
			### change sprite here
			print('Axe in hand.')

As for the animation, that's just a part of art. May want to chat with some pixel artists or look around the free assets on a site like ITCH.IO to see what they do. You can also just try making sprite for all the weapons as they are idle, as they attack and then tie an AnimatedSprite node to a separate Area2D node coming from the player where the animations move to when attacking. Also, I would keep your attack functions separate so it's easier to clean up when you hit transition territory.

This is where creative programming comes in. What I would do I have a set number of attacks and then change those as with match depending on the weapon. I've done something like that in the "weapon_animate" above.

Worth a note: I used an enumerator for the State Machine (actions) but an Array for the weapons. This allows you to change how many and what weapons you have over time. You could, if you wanted, also use an Array for the States to change when attacks are available. Be aware that match works differently, implementation-wise, if you do (you can call arrays by number or string, but enums are called by their constants or numbers only).

That should be a starting point.