Solarus Forum

Solarus => Development => Topic started by: Diarandor on August 04, 2015, 02:22:07 pm

Title: Creating a custom jump
Post by: Diarandor on August 04, 2015, 02:22:07 pm
Greetings! I always wanted to script a jump like in Zelda games (the one given by the engine is too limited), where you can control the hero during the jump. I had an idea of how we could program this (although there may be other better ways).

The idea is, when using the item to jump, we first create a custom entity with transparent sprite and solid ground that follows the hero under him, and we start the jumping animation on the hero. (The custom entity would allow to move over holes, water and lava while we are jumping, because it has solid ground. It should have smaller size than the hero to avoid traversing walls.) When the jump animation finishes, we destroy the custom entity. It would be necessary to use the save solid ground function before the jump, just in case the hero ends in bad ground, and reset the solid ground function when the jump ends.

One of the advantages (or disadvantages) of doing it this way is that it allows the hero to jump over lower layers (in case that the current layer ends) without falling to the lower ones until the end of the jump. In other words, this would allow to jump between solid grounds on the same layer that have "empty" grounds (not holes!) between them without falling to lower layers. (I was planning to use this to make puzzles where you move boxes of the low layer to make a way on the middle layer where you can jump over the boxes without falling to the lower layer.)

I have not programmed this yet (someday I wil try it) so I am not sure if this will work as I expect. Anyway, I have hope in this trick to program the jump, so I wanted to share the idea.
Title: Re: Creating a custom jump
Post by: Christopho on August 04, 2015, 03:07:53 pm
I think it should work. I did not think of using a custom entity to change the ground along the way.

Another solution (also a hack) is to call hero:start_jumping(), but right after that, stop the jump movement created by the engine. The hero will stay in jumping state, which allows to fly over lava, holes, etc and avoids to fall on lower layers. I used this trick for the scripted hookshot and it works. Maybe this is simpler.
Title: Re: Creating a custom jump
Post by: Zeror on August 04, 2015, 03:25:10 pm
I was wondering for this as well. The way jumping works in Solarus was odd compared to how Roc's feather worked, for example, in Link's Awakening.
Title: Re: Creating a custom jump
Post by: Diarandor on August 04, 2015, 03:34:23 pm
I have tested my solution and works fine (the only problem is to choose the duration of the jump).

Anyway, your solution seems better, so I will change my script again. Thanks!
Title: Re: Creating a custom jump
Post by: Diarandor on August 04, 2015, 03:53:17 pm
How do you stop the movement while keeping the jumping state?

I have tried with hero:stop_movement(), but the hero stays frozen. If I add hero:unfreeze(), I recover the control of the hero, but this also seems to stop the jumping state... :o Am I doing something wrong? The code I am using is:
Code: [Select]
function item:on_using()
  local hero = self:get_map():get_entity("hero")
  local direction4 = hero:get_direction()
  hero:start_jumping(direction4 * 2, 32, false)
  hero:stop_movement()
  --hero:unfreeze()
  hero:set_animation("black")
  --self:set_finished()
end

EDIT: I forgot to add the methods, hero:get_solid_ground_position() and hero:reset_solid_ground().
Title: Re: Creating a custom jump
Post by: Christopho on August 04, 2015, 03:56:24 pm
With hero:stop_movement(), yes. Then you can start a new movement of your own on the hero. The engine will still consider that the hero is jumping, and is okay with the fact that you are customizing the movement.
You are right, hero:unfreeze() gets back to the free state.
Title: Re: Creating a custom jump
Post by: Zeror on August 04, 2015, 03:58:46 pm
I just played Link's Awakening to watch the jump closely.

What i think what happens is this:

The hero jump into a direction (let say starting direction) any other direction's movement speed is reduced. Starting direction keeps normal speed. So when the starting direction is left, then the speed to up, down and right direction is reduced, i think by 50% or something. And i think you can only change the direction once per jump.
Then you have the jumping animation. When the animation starts the hero is considered off the ground (meaning holes, empty tiles can be bypassed) until the animation ends (reaches it last frame). The hero is considered on the ground again. Then the tile type decides what happens next. If hero is on a hole, he falls down. If he is on the edge of a hole he get a change to save himself or if he is on safe ground he will just stand.

Maybe this helps in building the new jump. :)
Title: Re: Creating a custom jump
Post by: Diarandor on August 04, 2015, 04:01:19 pm
Just in case someone is interested, my trick (already tested and works fine) is:
Code: [Select]
function item:on_using()
  local hero = self:get_map():get_entity("hero")
  local jump_duration = 500 -- Change this for duration of the jump.
  sol.audio.play_sound("jump")
  hero:set_animation("black")
  hero:unfreeze()
  local x,y,layer = hero:get_position()
  local tile = self:get_map():create_custom_entity({x=x,y=y,layer=layer,direction=0,width=8,height=8})
  tile:set_origin(4, 4)
  tile:set_modified_ground("traversable")
  function tile:on_update()
    -- Follow the hero.
    tile:set_position(hero:get_position())
  end
  sol.timer.start(self, jump_duration, function()
    hero:set_animation("stopped")
    tile:remove()
    item:set_finished() 
  end)
end

EDIT: I forgot to add the methods, hero:get_solid_ground_position() and hero:reset_solid_ground().
Title: Re: Creating a custom jump
Post by: Diarandor on August 04, 2015, 04:05:29 pm
I assume that for your solution I need to modify the event on_command_pressed() to create movements that control the hero? Because I think that is only way to control the hero in that freezing state.
Title: Re: Creating a custom jump
Post by: Diarandor on August 04, 2015, 04:25:48 pm
@Zeror, I think that you are right, probably, that the movement during the jump in Link's awakening has some restrictions (I have tested it now with the gb emulator, although I am not completely sure of these restrictions). The only way to impose these restrictions would probably be using Christopho's solution and programming all the behaviour, which could be hard. I think I will keep my solution anyway, at least for some time.
Title: Re: Creating a custom jump
Post by: Christopho on August 04, 2015, 04:29:11 pm
I assume that for your solution I need to modify the event on_command_pressed() to create movements that control the hero? Because I think that is only way to control the hero in that freezing state.
Yes. I understand now that you are avoiding that extra work with your solution, so your solution is better :)
Title: Re: Creating a custom jump
Post by: Diarandor on August 04, 2015, 04:35:27 pm
I realized that with my solution the animation is not changed to "jumping", so you would need to define a new tunic sprite for the jumping, where the stopped and walking animations show the hero jumping (other animations could be needed too in this new tunic sprite, for instance, if you allow the hero to be hurt during the jump, etc). In the end of the jump, you have to restore the previous tunic sprite.