Solarus-Games English Forum

Solarus => Development => Topic started by: froggy77 on May 07, 2017, 08:06:50 PM

Title: [Solved]How to add an "opening" animation for chests?
Post by: froggy77 on May 07, 2017, 08:06:50 PM
Hello,

I would like to add an intermediate animation for chests. "closed" and "open" are the basic animations. I added, in the .dat files, an "opening" animation which it could be in 1 or 2 frames according the size of the chests.

How woud you proceed in lua scripts?


Sorry, I have lost a lot of skills in lua and even about Solarus in general, because I have not worked on it for several months.
Moreover, there are now in the last versions, scripts "features" and "multi_events" which is all the more new and difficult for me.
But instead, I improved my pixel art skills a bit  ;) . I will soon update my topic on the project.
Title: Re: How to add an "opening" animation for chests?
Post by: Zefk on May 07, 2017, 08:20:25 PM
If you mean opening as in lifting the lid of the chest, then try changing the number of frames for the "open" animation.

(http://forum.solarus-games.org/index.php?action=dlattach;topic=971.0;attach=530)
Title: Re: How to add an "opening" animation for chests?
Post by: MetalZelda on May 07, 2017, 09:23:01 PM
you have to go through custom entity

Or, maybe this could help ?
http://www.solarus-games.org/doc/latest/lua_api_chest.html#lua_api_chest_on_opened
Title: Re: How to add an "opening" animation for chests?
Post by: Zefk on May 07, 2017, 10:00:54 PM
@froggy77

MetalZelda is correct. I made a super quick chest opening animation and apparently the chest sprite vanishes with more than one frame.
Title: Re: How to add an "opening" animation for chests?
Post by: froggy77 on May 07, 2017, 11:09:37 PM
@Zefk > I had already tried to change the number of frames for the "open" animation. Yes, " the chest sprite vanishes with more than one frame."  :(

@MetalZelda >  OK, I also think I have to go through custom entity :'(
http://www.solarus-games.org/doc/latest/lua_api_chest.html#lua_api_chest_on_opened (http://www.solarus-games.org/doc/latest/lua_api_chest.html#lua_api_chest_on_opened) is when the chest is already opened. It is above all to choose the treasure.

Thanks for your help!
Title: Re: How to add an "opening" animation for chests?
Post by: Zefk on May 10, 2017, 09:16:20 AM
@froggy77

If you do not mind, I'd like to discuss features for a custom chest with you.

So far my thought process led me to the following. I will be coding this sometime for my Lib. What more features would it need?

Code ( lua) Select
entity:custom_chest(treasure, treasure_variant, save_variable, sprite_directory, traversable, closed_animation, open_animation, opening_animation, key)

With default settings it could be called inside a custom entity like this.

Code ( lua) Select
entity:custom_chest()

With custom settings it would be more readable like this:

Code ( lua) Select
entity:custom_chest(
treasure, --treasure
treasure_variant, --treasure_variant
save_variable, --save_variable
sprite_directory, --sprite_directory
traversable, --traversable
closed_animation, --closed_animation
open_animation, --open_animation
opening_animation, --opening_animation
key) --key


Maybe something like....

Opening mode:

-By hero
-By hero with save variable
-By hero with item required
-increment/decrement item

and maybe these...
http://forum.solarus-games.org/index.php/topic,971.msg5646.html#msg5646

-By entity
-By entity with save variable
-By entity with dummy item required
-increment/decrement dummy item
-By entity overlap

Dialog:

-fail dialog
Title: Re: How to add an "opening" animation for chests?
Post by: Diarandor on May 10, 2017, 12:31:01 PM
For your purposes with chests, I recommend to use normal chests in the map editor, just to have compatibility with the map editor. There are several ways to do this:
-Use a script that replaces chests with custom entities when a map is created, or when chests are created. This can be done directly by defining chest_metatable:on_created().
-Another way is to define chest_metatable:on_created() in order to define some events on the sprite of the chest, which would allow that animation to appear.
Title: Re: How to add an "opening" animation for chests?
Post by: Diarandor on May 10, 2017, 12:45:11 PM
Remark: using custom entities takes a bit more of work than using the chest metatable, since you would need to define the functions and events of the chest Lua API. On the other hand that solution allows much more customization on chests: for instance, you can make chests that can only be opened by one of the heroes and not by the others, or make chests that can be opened by throwing a pot.
Title: Re: How to add an "opening" animation for chests?
Post by: Zefk on May 10, 2017, 07:14:17 PM
By entity overlap is a good idea Diarandor. I am guessing a specific entity would be best because not one wants any entity to open a chest.

Aha! I did it. I made an on_interaction function. Of course, it will need some tweaking to actually work for the chest, but it allows me to interact with many entities.

Code ( lua) Select
function metatable_entity:on_entity_interaction()
  local map = self:get_map()
  local hero = map:get_hero()
  local game = map:get_game()
  local dialog_activation_distance = 20

    sol.timer.start(2000, function()
      local distance_check = hero:get_distance(self)
      if distance_check <= dialog_activation_distance then -- dialog_activation_distance
       function map:on_key_pressed(key)
         if key == "y" then
           print("pressed")
         end
       end
     end
    return true  -- To call the timer again (with the same delay).
  end)
end


It can be called in an entity like this:

Code ( lua) Select
entity:on_entity_interaction()
Title: Re: How to add an "opening" animation for chests?
Post by: Diarandor on May 10, 2017, 09:07:50 PM
I think you are complicating things too much. You should just define custom_entity:on_interaction() for your custom chest. There is no need of checking distances and timers, or using the event on_key_pressed().
Title: Re: How to add an "opening" animation for chests?
Post by: MetalZelda on May 10, 2017, 09:11:25 PM
I like Diarandor's solution, overwriting a chest to replace it with a custom entity.

For the custom entity script, simple trick is to use add_collision_test to do HUD stuffs and simply add an animation in on_interaction. Thn call hero:start_treasure from there
Title: Re: How to add an "opening" animation for chests?
Post by: MetalZelda on May 10, 2017, 10:28:50 PM
You need 3 things.

1) the metatable modification
2) a chest entity
3) a chest on a map, where you need to define
    - it's spriteset
    - it's treasure
    - it's variant
    - the savegame variable

1) * Keep note that it is from my project so you might need to modify things to fit your needs
And, with this script you can only set a treasure that you can open if you press Action, other chest action cannot be done without more complex modifications
Also to set a direction for your chest (if needed), put the desired direction as the chest name.

Code (lua) Select
local chest_meta = sol.main.get_metatable("chest")

function chest_meta:on_created()
  local treasure, variant, savegame = self:get_treasure()
  local x, y, layer = self:get_position()
  local graphic = self:get_sprite():get_animation_set()
 
  local setup = {
    x = x,
y = y,
layer = layer,
model = "chest/chest",
width = 16,
height = 16,
direction = 3,
sprite = graphic
  }
 
  local entity = self:get_map():create_custom_entity(setup)
  entity:set_treasure(treasure, variant, savegame)
  entity:create()

  -- You might need to customize this chest.
  function self:get_chest()
    return entity
  end
  self:remove()
end


2)

Code (lua) Select

local entity = ...
entity.data = {}

function entity:set_treasure(treasure, variant, savegame)
  self.data.treasure = treasure
  self.data.variant  = variant
  self.data.savegame = savegame
end

local game = entity:get_game()
local hero = game:get_hero()

function entity:is_open()
  return game:get_value(self.data.savegame)
end

function entity:create()
  self:set_drawn_in_y_order(true)
  self:set_can_traverse("hero", false)
  self:set_traversable_by("hero", false)
  self:set_traversable_by("custom_entity", false)

  if self:is_open() then
    self:get_sprite():set_animation("open")
    return
  end
 
  -- Hud notification
  self:add_collision_test("facing", function(_, other)
    if other:get_type() == "hero" then
      if not self:is_open() then
    self.action_effect = other:get_direction() == self:get_direction() and "open" or "look"
  else
    self:clear_collision_tests()
  end
    end
  end)
end

function entity:on_interaction()
  -- This is where you will play your animation, set the savegame value to true and give the hero the treasure
  -- savegame value is stored in entity.data.savegame

  if self:is_open() then
    return
  end

  hero:freeze()
  game:set_pause_allowed(false)
  self:get_sprite():set_animation("opening", function()
    self:get_sprite():set_animation("open")
    hero:start_treasure(self.data.treasure, self.data.variant, self.data.savegame, function()
      -- After the treasure has been obtained
      hero:unfreeze()
      game:set_pause_allowed(true)
    end)
  end)

  self.action_effect = nil
end
Title: Re: How to add an "opening" animation for chests?
Post by: Zefk on May 11, 2017, 05:31:15 AM
Quote from: Diarandor on May 10, 2017, 09:07:50 PM
I think you are complicating things too much. You should just define custom_entity:on_interaction() for your custom chest. There is no need of checking distances and timers, or using the event on_key_pressed().

I think only custom_entity:on_interaction() works for a hero. It would not work for a player 2 custom entity as far as I know, but I guess I could just make that a second custom chest function.
Title: Re: How to add an "opening" animation for chests?
Post by: Diarandor on May 11, 2017, 07:40:20 AM
Ok, if you allow to do that then you are right, I did not think on that case.
Title: Re: How to add an "opening" animation for chests?
Post by: Zefk on May 11, 2017, 08:16:23 AM
I am still debating on it though because first my main goal is to just get a fully function ally AI system working. A custom entity chest for the hero is far easier.
Title: Re: How to add an "opening" animation for chests?
Post by: Diarandor on May 11, 2017, 10:19:14 AM
You will need to do something similar for NPCs, and many other types of interactions with other entities (switches, carried entities, etc). That is a lot of work.
Title: Re: How to add an "opening" animation for chests?
Post by: Zefk on May 11, 2017, 05:52:14 PM
The switch I have already basically done, but only for stepping on. I do not plan to make all the entities except for when it is simple or when I need it for animation purposes. I probably will not have a second player feature because it is not something I want with my games, but in some cases simple second player features can be useful.  For example, when you want an entity to step on a switch or to move a block that can only be pushed from their side.
Title: Re: How to add an "opening" animation for chests?
Post by: froggy77 on May 12, 2017, 11:30:56 AM
Thanks for the time spent. I just needed advice, not a brainstorming.  ;)
I would like to use the editor to create the chest normally; maybe it could be disabled and replaced by an entity during the opening and at the end enabled to appear when completely opened. I will try to write a script even I lost my poor level in lua.
Title: Re: How to add an "opening" animation for chests?
Post by: MetalZelda on May 12, 2017, 05:48:03 PM
I did posted the solution on page 1, it does replace the default chest by a custom entity, you might do some tweaks to make it properly work to your needs though
Title: Re: How to add an "opening" animation for chests?
Post by: froggy77 on June 18, 2017, 01:10:07 PM
Thank you MetalZelda, I did not understand where to put those scripts and I did not realize that there was no need to create an entity from the editor.
Even if I managed to make it work, I found some problems.

Error: In on_created: [string "entities/chest/chest.lua"]:23: bad argument #1 to is_open (string expected, got nil))
Error: In on_interaction: [string "entities/chest/chest.lua"]:44: bad argument #1 to is_open (string expected, got nil))

Error: In sprite callback: [string "entities/chest/chest.lua"]:52: bad argument #1 to start_treasure (string expected, got nil))
This one is not a problem.

In order to correct this, I added a value for "delay between frames", for example: 200 ms.

Title: Re: How to add an "opening" animation for chests?
Post by: MetalZelda on June 18, 2017, 03:31:18 PM
To make this work you need to create a chest entity, not a custom entity, the script do the rest (delete the chest and create the custom entity).

You need to define the sprite, treasure and savegame variable from there, like this

(http://i.imgur.com/IFrH8Y6.png)

But, it is very basic atm, the entity name could be used to store frame delays or other stuffs