Open Diarandor opened 8 years ago
More functions that will be useful:
hero_or_entity:get_carrying_entity() -- This should be nil if it is not carrying anything.
entity:get_carrier_entity() -- This will be nil if the entity is not being carried.
Also, a "thrown" animation could be started by default on the hero sprite whenever it is defined (I know Link does not have this sprite, but Eldran has one and we could use it).
More details: if the thrown entity falls on bad ground it will be destroyed by default with some animation/sound effects. To override/customize this we could allow to define an optional event:
entity:on_fallen_on_bad_ground(ground_type)
Some entities may not fall, for instance if they can fly or swim, etc.
(This event should be called on any of the possible bounces if it happens on bad ground.)
I think the throw trajectory should be given by a different function than for the bounces, because for the bounces the max height is reached in the middle point of the parabola, but that is not the case for the first falling trajectory when the hero throws it. For the bounces, the parabola can be given as function of the time by:
local function f(t)
return math.floor(4 * max_height * (t / duration - (t / duration) ^ 2))
end
but this has to be translated into C++. I will compute the first parabolic trajectory and test it in Lua other day.
More useful things: The function I use now in my Lua script to compute the heights (as shifts of the sprite) is the following:
-- Function to compute height for each fall (bounce).
local function current_height()
if current_bounce == 1 then return h * ((t / dur) ^ 2 - 1) end
return 4 * h * ((t / dur) ^ 2 - t / dur)
end
The first fall uses a different function because the initial height is from above the hero. The parameters are the max height of the current bounce "h", the current instant of the current bounce in milliseconds "t", the current bounce "current_bounce", the duration in milliseconds of the current bounce "dur".
The initial parameters for customization could be given in a list of properties (some parameters may be lists) similar to the following ones I use:
entity.sprite_shift = 0 -- To customize the shift of the sprite or position (for the height).
entity.num_bounces = 3 -- Number of bounces when falling (it can be 0).
entity.bounce_distances = {80, 16, 4} -- Distances for each bounce.
entity.bounce_heights = {"same", 4, 2} -- Heights for each bounce ("same" on first parameter means the initial height).
entity.bounce_durations = {400, 160, 70} -- Durations for each bounce.
The values above (or other ones chosen by you) could be used as default ones. I have tested the height function above in Lua and they work fine, so you can translate it into C++ to mimic the same.
We should have functions to shift the carried entity and center it correctly over the hero (or the corresponding carrier entity):
entity:set_carried_xy(x, y)
entity:get_carried_xy()
this can be used to code the custom "bouncing" effect when an entity is being carried and the carrier is walking, all directly from the scripts.
To allow to lift/carry/throw custom entities, or more in general any kind of entity, I propose the following Lua API events/functions.
It would also be nice to allow enemies and NPCs (and maybe any entity?) to lift other entities. The events should be built-in events that can be overriden if they are coded in Lua (in that case, we can decide if the next event of the sequence is called or not).
The most realistic option for the throw (and lifting?) is a parabolic trajectory, which can be given parametrized in time. I can help with these trajectories.
Parabolas are determined by three points (or three independent conditions that determine their parameters). The parabola will be applied to the y-coordinate only, to simulate the height, and this could be combined with a straight (linear) trajectory on both coordinates (x, y) to simulate the movement. The initial height (custom), final height (= 0) and the point where the max_height is reached can be used to determine an explicit expression for the parabola. (There are infinite choices for the point where the max_height happens, so I will use one that fits fine.) Maybe we should make the parabolic trajectory of the y-component as a shift of the sprites of the entity to separate it from the other movement?
The straight movement can be determined by two of the following parameters: "speed", "duration" and "max_distance". So tell me which of them you prefer to use so I can give you the parabolic trajectory given as function of them. The properties list for the thrown trajectory could be the following (some elements could be lists of properties inside the properties list):
There are more custom properties to add: -For instance, for the carrying state we can choose how the "bounces" are done with a boolean list that indicates in which frames of the carrier walking animation correspond to higher position and which ones to lower position. -When the entity is thrown, we should allow to choose if we hurt or not enemies with the thrown entity. -By default, after the last bounce, the on_fallen event is called, which by default will destroy the entity (as in destructibles), but it can be overriden to make other behaviors (if it is set to nil then the entity is not removed). -Maybe more things?