Side scrolling functionality

Started by wizard_wizzle (aka ZeldaHistorian), June 25, 2015, 04:24:13 AM

Previous topic - Next topic
So it will work as long as there's no shadow? But no shadow while moving or no shadow altogether?

The shadow is made with a custom entity, created when you throw the entity and removed after the item has fallen. If you don't create it there are no crashes. Maybe it's a problem of my script...
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

In that case, don't use the shadow created with the custom entity. Shadows already appear correctly when destructible items are thrown. Is there any way to work around that?

But I am not using a destructible entity. With my scripts, what you lift is a custom entity. The lifting, carrying and throwing states of the hero and the entity are fully scripted. So there is no shadow if you do not create it. (And probably the crash is due to something that I did wrong. But I don't have much time this summer to work in my game...)

You should do your own scripts for your purposes, or wait until the day that custom entities can be carried. There is no other workaround. You have to be patient and don't underestimate the programming, since it takes a lot of effort and months (or years) of work.
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

July 27, 2015, 02:31:25 AM #19 Last Edit: July 27, 2015, 04:24:59 AM by DementedKirby
Lol, trust me, I know how much time programming can take (studied Computer Sciences in college) that's why I'm dedicating myself more to the graphical aspect and story and map design aspect of my game while I'm able to then get my bearings to make my own menu system. Also, I plan on scripting other items as well besides the ones available thanks to Christopho and his Solarus DX. So I got the patience as well (since I also don't have the time  :P).

What I meant by the shadow created by the destructible object is to see if you can mimic that particularity of the code for a destructible object. But I understand that you're trying to take this route from scratch - which is damn near amazing. I'm fully aware of the effort needed to code something so complex. When I can, I can help look over the section of the code pertaining to the shadow. I'm still a fledgling in lua but I know my C++ so I can at least get a feel of what I'm reading.

I really think you got something going here. This would be useful to make cuccos that you can hold to help you glide or even the rooster from Koholint (as you also suggested). This could also be used to carry around a helpless NPC like a young Princess Ruto from Ocarina of Time. The possibilities really are endless and I give you some well deserved kudos.  I'm merely rooting for you to be able to fully achieve this to your own expectations ;).

July 27, 2015, 03:28:02 AM #20 Last Edit: July 27, 2015, 04:30:48 AM by Diarandor
Thanks for the compliments! :D
With your knowledge of programming you won't have problems, since Lua is much easier and flexible than C++ (actually, I forgot C++ many years ago :P).

As a workaround for the generic_portable.lua script, you can comment/delete the lines of the script where shadow:remove() appears (there are two of them), which would avoid the crash, but the shadow will not be deleted, so each time you throw the entity a shadow will appear and stay where the entity has fallen. To test the script, you can try to use my script key.lua, which uses the code of the script generic_portable.lua.

I think the cause of the crash was already solved here:
https://github.com/christopho/solarus/issues/690
so I am still waiting for the next bugfix 1.4.3 to see if it works. There was another bug fixed in
https://github.com/christopho/solarus/issues/691
that did not allow to recover the information of any entity when the player leaves the map (since the entities were removed before the event map:on_finished() was called). This could also give some problems, maybe, to save the position of generic_portable entities when changing maps, so I am also waiting for the next bugfix 1.4.3 because of this, before repairing/improving my script.

EDIT: I think it would be better to open a new topic to talk about this, since it has nothing to do with the side scrolling.
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

Well, the good thing is that you found a bug which allows Cristopho to fix for later releases of Solarus. So I guess you're in the right to wait for the update to check your code again. If it looks good and does what it's supposed to do I guess time will determine whether you have to change some things in your lua code or it's resolved with the latest changes.

One thing you can try in the mean time is to change the direction of the entity carried in the same direction as the hero (if you were carrying an "npc", for example) in the case of carrying a cucco or a Princess Ruto type situation. Does your script already do this?

July 27, 2015, 04:55:54 AM #22 Last Edit: July 27, 2015, 04:58:32 AM by Diarandor
Of course, you can change the direction of the carried entity while it is carried. It should be very easy to simulate carrying the princess or the cucco (but unfortunately this is not so easy to make the flying rooster).

I can put some examples (including graphics) in my repository, so you can understand better how to make it. But before I want to put my graphics in opengameart.org or other website like that (I will do it someday soon, today I am a bit lazy, and before I need to separate my graphics from the ones of "A Link to the past"). I made a ball of yarn entity that can be carried and changes direction when the hero does, and cats that can interact (playing) with it and follow it (even when you carry it). I will put this example in my repository when I add more things.

Both bugs were solved by Christopho (thanks!!! ;D), so we just need to wait. (If you know how to compile Solarus from the development version on github, you could check if it works.)
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

Nah, I'll just wait for it to be released in the next release :P. That'll build the anticipation of being able to look forward to it when it's released :D. It's great that he was able to solve the problem, though! Entities you can carry that can be thrown around without exploding or breaking is a Zelda staple. It's also great to design puzzles around the concept. I'll do some map designs in the mean time! Sweet!

Do you know if Christopho is going to release a 1.4.3 version with those bugs fixed or is he going to wait to have 1.5 ready to release it altogether?

I don't know for sure (he should answer this), but probably in 1.4.3. You can check how much work remains to be done in his github repositories.

I have opened another post to talk about the generic_portable entities of my script, since this post is not the good place to talk about it. It's here: http://forum.solarus-games.org/index.php/topic,332.0.html
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

October 08, 2015, 05:27:33 AM #25 Last Edit: October 08, 2015, 05:29:27 AM by zutokaza
I can't seem to get the jumping working. (3MB)
http://s000.tinyupload.com/index.php?file_id=02681457115274128283
Solarus Works on ReactOS Opensource Windows OS

https://www.reactos.org/forum/viewtopic.php?f=2&t=14759&p=120616#p120616

In Link's Awakening and Zelda 1 side-view caves, there are ladders.
The hero should not fall when on a ladder. There is already a "ladder" ground type in the engine it should be easy to take it into account in the script (if I understand correctly, this is not the case yet).
I think we just need to check the ground below the hero:

Code (lua) Select

if entity:get_type() == "hero" and map:get_ground(hero:get_position()) ~= "ladder" then
  -- Gravity
end

Very true, christopho! Thanks for the addition!

I realize this is kind of grave digging, and I apologize, but I decided to do some work and this script and wanted to post it in the original topic.

I generalized the script a bit and built it around a state engine for the hero. The animations used for the hero sprite are the same as the state names.

The gravity updating is not done via a timer rather than the map's on_update routine, as Diarandor had suggested in another topic. I also added a "multi jump" option to allow the player to press the jump key several times. It doesn't work the way I would like yet, but the basics are there. Finally, I added a ladder option that Christopho had suggested on another topic.

Code (lua) Select

local game_manager = {}
local game_over_menu = {}
local map_metatable = sol.main.get_metatable("map")

local gravity = 5       -- How often to update gravity in milliseconds (move the hero down one pixel this often). Default is every 10 ms.
local jump_height = 40  -- How high to make the hero go when he jumps (in pixels). Default is 40.
local multi_jump = 2    -- How many times to allow the character to jump. Default is 1, or enter 0 to disable jumping entirely.
local state             -- "stopped", "walking", "jumping", "ladder", "dying", "action", "attack"
local last_anim

function game_manager:start_game()
  local exists = sol.game.exists("save1.dat")
  local game = sol.game.load("save1.dat")
  if not exists then
    -- Initialize a new savegame.
    game:set_max_life(1)
    game:set_life(game:get_max_life())
    game:set_starting_location("2")
  end
  game:start()
 
  function game:on_started()
    sol.timer.start(gravity, function()
      if self:get_map() ~= nil then
        -- Gravity: move entities down one pixel on every update if there's no collision.
        --   (like with the ground or a platform) and hero not jumping or on a ladder.
        local hero = self:get_hero()
        local x, y, l = hero:get_position()
        if state ~= "jumping" and self:get_map():get_ground(hero:get_position()) ~= "ladder" then
          if not hero:test_obstacles(0, 1) then hero:set_position(x, (y + 1), l) end
        elseif state == "jumping" then
          for i = 1, jump_height do
            if not hero:test_obstacles(0, -1) then hero:set_position(x, (y - 1), l) end
          end
          sol.timer.start(gravity * jump_height, function()
            if self:is_command_pressed("right") or self:is_command_pressed("left") then
              state = "walking"
            else
              state = "stopped"
            end
          end)
          hero:set_animation(state)
        end
       
        for entity in self:get_map():get_entities("g_") do
          local gx, gy, gl = entity:get_position()
          if not entity:test_obstacles(0, 1) then
            entity:set_position(gx, (gy + 1), gl)
          end
        end
      end
      return true
    end)
  end
 
  function game:on_command_pressed(command)
    local hero = game:get_map():get_hero()
    local multi_jump_temp = multi_jump
    if command == "up" then
      if not self:is_suspended() and not jumping and multi_jump_temp > 0 then
        if game:get_map():get_ground(hero:get_position()) ~= "ladder" then
          -- Override default behavior and make the hero jump up!
          state = "jumping"
          multi_jump_temp = multi_jump_temp - 1
        else
          state = "ladder"
        end
      else
        state = "stopped"
      end
    elseif command == "action" and not self:is_suspended() then
      state = "action"
    elseif command == "attack" and not self:is_suspended() then
      state = "attack"
    else
      state = "stopped"
    end
    last_anim = hero:get_animation()
    hero:set_animation(state)
  end
 
  function game:on_command_released(command)
    state = last_anim
    if state == nil then state = "stopped" end
    game:get_map():get_hero():set_animation(state)
  end
 
  function game:on_game_over_started()
    sol.menu.start(game:get_map(), game_over_menu)
  end
 
  function game_over_menu:on_started()
    local hero = game:get_hero()
    local map = game:get_map()
    local camera_x, camera_y = map:get_camera():get_position()
    local hero_x, hero_y = hero:get_position()
    hero_dead_x = hero_x - camera_x
    hero_dead_y = hero_y - camera_y

    hero_dead_sprite = sol.sprite.create("hero/tunic1")
    hero_dead_sprite:set_animation("hurt")
    state = "dying"

    sol.audio.stop_music()
    hero:set_visible(false)
    hero_dead_sprite:set_animation("dying")
    hero_dead_sprite.on_animation_finished = function()
      sol.timer.start(self, 500, function()
        game:stop_game_over()
        game:start()
      end)
    end
  end
 
  function game_over_menu:on_finished()
    local hero = game:get_hero()
    if hero ~= nil then hero:set_visible(hero_was_visible) end
    music = nil
    hero_dead_sprite = nil
    fade_sprite = nil
    sol.timer.stop_all(self)
  end
 
  function game_over_menu:on_draw(dst_surface)
    hero_dead_sprite:draw(dst_surface, hero_dead_x, hero_dead_y)
  end
end

return game_manager


Please post any improvements or critiques!

October 11, 2016, 03:16:54 AM #29 Last Edit: May 13, 2020, 06:01:59 PM by Zefk
Everything is looking good now. I am just wondering....what broke the old jump function?