Currently, animations are not much flexible. I propose an Action definition for animations. This would make smoother transitions between actions and synchronization of logic with animations.
Actions define a single action in the animation, such as "walk", "jump", and "punch". Actions would be defined in the properties on registering entities.
This is similar to the simplemobs animation framework. But we need more properties for the actions in addition to frame_start, frame_end, and frame_speed. I'm not that good at explaining so I'll post some example code.
Code: Select all
minetest.register_entity("mymod:mymob", {
-- ...
actions = { -- An array of actions for this entity
{
name = "walk", -- Identifier
start = 0, -- Start frame
end = 16, -- End frame
rate = 30, -- Frame rate
-- Here's the additional properties of the action
next_action = "walk", -- The action to be set after this action ends. nil for the old behaviour
start_call = function, -- Function to call when this action starts
end_call = function, -- Function to call when this action ends
},
-- More action definitions
}
-- ...
})
-- To set an animation, instead of set_animation(...), use set_action(action_name)
entity:set_action("walk")
Code: Select all
...
-- Define actions for jumping
{ -- Jump action
name = "jump",
start = ...,
end = ...,
rate = ...,
next_action = "fall",
},
{ -- Fall action
name = "fall",
start = ...,
end = ...,
rate = ...,
},
...
-- Do the jump
self.object:setvelocity(...)
self.object:set_action("jump")
start_call and end_call is good for synchronizing logic to animations. For example, a throwing sequence:
Code: Select all
...
{ -- Pick up the rock/Charge the fireball/Whatever pre-throwing animation
name = "prethrow",
start = ..., end = ..., rate = ...,
next_action = "throw" -- After picking up/charging, throw
},
{ -- Throw/Fire
name = "throw",
start = ..., end = ..., rate = ...,
next_action = "stand", -- After throwing, go to idle animation
start_call = throw, -- Fire a projectile
}
...
-- Check enemies to throw at
if player_distance < range then
self.object:set_action("prethrow")
end
...
-- Throw callback
function throw(self)
...
end
...
Code: Select all
{ -- Define death animation
name = "die",
start = ..., end = ..., rate = ...,
end_call = remove -- Remove the entity after the death animation finishes
}
...
-- Somewhere, maybe in on_punch
if self.object:get_hp() <= 0 then
-- Start the die animation
self.object:set_action("die")
end
...
We can take things further, by making the engine automatically set an action for each entity (There could be client-side action prediction too, since the engine decides animations). For example, if an entity is on the ground, the "stand" action is set. When an entity is moving on the ground, "walk" is set. When the entity is off the ground, "fall" is set automatically. This is useful for mobs.
All these can be done in Lua (Yes, even the sequencing and callback part) but they are hacky/dirty.