This topic:
http://forum.solarus-games.org/index.php/topic,297.msg1086.html#msg1086
I can't seem to get the jumping working for the side scroller, but everything else works. The 3 MB project can be downloaded at TinyUpload.
http://s000.tinyupload.com/index.php?file_id=02681457115274128283
game_manager.lua
-- Script that creates a game ready to be played.
-- Usage:
-- local game_manager = require("scripts/game_manager")
-- local game = game_manager:create("savegame_file_name")
-- game:start()
local dialog_box_manager = require("scripts/dialog_box")
local game_manager = {}
local map_metatable = sol.main.get_metatable("map")
local gravity = 1
local jump_height = 10
local jumping = true
local i = 0
--------------------------------------------------------------------------------
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())
end
game:start()
function game:on_command_pressed(command)
if command == "up" and not jumping then
-- override default behaviour and make the hero jump up!
jumping = true
i = 0
end
end
end
function map_metatable:on_update()
-- gravity: move entities down one pixel on every update if there's no collision
-- (like with the ground or a platform)
local x,y,l = self:get_game():get_hero():get_position()
if not jumping then
if not self:get_game():get_hero():test_obstacles(0,gravity) then
self:get_game():get_hero():set_position(x,y+gravity,l)
end
else
self:get_game():get_hero():set_animation("jumping")
for i=1, jump_height do
if not self:get_game():get_hero():test_obstacles(0,-1) then
self:get_game():get_hero():set_position(x,(y-1),l)
end
end
sol.timer.start(50*jump_height, function()
jumping = false
if self:get_game():is_command_pressed("right") or self:get_game():is_command_pressed("left") then
self:get_game():get_hero():set_animation("walking")
else
self:get_game():get_hero():set_animation("stopped")
end
end)
end
for entity in self:get_entities("g_") do
local gx,gy,gl = entity:get_position()
if not entity:test_obstacles(0,gravity) then
entity:set_position(gx,gy+gravity,gl)
end
end
end
-------------------------------------------------------------------------------
-- Sets initial values for a new savegame of this quest.
local function initialize_new_savegame(game)
game:set_starting_location("Test side")
game:set_max_money(100)
game:set_max_life(12)
game:set_life(game:get_max_life())
end
-- Creates a game ready to be played.
function game_manager:create(file)
-- Create the game (but do not start it).
local exists = sol.game.exists(file)
local game = sol.game.load(file)
if not exists then
-- This is a new savegame file.
initialize_new_savegame(game)
end
local dialog_box
-- Function called when the player runs this game.
function game:on_started()
dialog_box = dialog_box_manager:create(game)
end
-- Function called when the game stops.
function game:on_finished()
dialog_box:quit()
dialog_box = nil
end
function game:on_paused()
game:start_dialog("pause.save",function(answer)
if answer == 2 then
game:save()
end
game:set_paused(false)
end)
end
return game
end
return game_manager
Hi, just to say, you can use Lua syntax coloring when you post code. In the code tag, you can set Lua like this:
[code=lua]
I edited your post to set this option ;)
First thing I see is that
local jumping = true
at the top should be:
local jumping = false
That may be your only problem since the code is checking that you're not already jumping, which is indicated by jumping = true.
Other things to check in case that doesn't fix it - Do you get an error of any sort? Do you have an animation set "jumping" in your character?
An additional improvement I would recommend (unrelated to the problem) is:
if command == "up" and not jumping then
would be better as:
if command == "up" and not self:is_suspended() and not jumping then
To check that the game isn't paused or otherwise disabled, since on_command_pressed is applied to the whole game.
Quote from: wrightmat on October 09, 2015, 02:31:10 PM
First thing I see is that
local jumping = true
at the top should be:
local jumping = false
That may be your only problem since the code is checking that you're not already jumping, which is indicated by jumping = true.
Other things to check in case that doesn't fix it - Do you get an error of any sort? Do you have an animation set "jumping" in your character?
An additional improvement I would recommend (unrelated to the problem) is:
if command == "up" and not jumping then
would be better as:
if command == "up" and not self:is_suspended() and not jumping then
To check that the game isn't paused or otherwise disabled, since on_command_pressed is applied to the whole game.
It still doesn't work when setting it to false, but the player does jump once at the start without me pressing any keys if I set jumping to true. He doesn't jump after that.
There is an animation folder for jumping. It is named correctly.
There is no error output file.
when I set the gravity to zero.....I am able to walk on the enemies head to kill it. Although, the player still walks the way he would in an ARPG. That could be the reason the "up" key is being ignored. Maybe all the keys in the script are being ignored.....
Hi! I don't know exactly why it does not allow jumping, but it is clear that the code is not correctly done for the nice behaviour. Some advices to improve and restructure your code (although I could be wrong in some of them):
1) I think that the "i" variable is not being used, so you can remove the lines 16 and 36.
2) You could write "local hero = self:get_game():get_hero()" to use the hero variable, avoiding to repeat the code "self:get_game():get_hero()". The same for the game variable.
3) The on_update() event is called very quickly, almost every instant, so it is not a good idea to change the position of hero when it is called. You could use also some timer to change the position of the hero with the desired speed (use a falling speed variable for this timer). Be careful so that each time the event is called you create the timer only if there is not already some timer created before.
4) Changing the position of the hero with "hero:set_position(x,y+gravity,l)" is not a good idea. If the gravity is bigger than 1, say 8 for instance, then in the case that the hero has coordinate "y" 4 coordinates above the ground he would not fall because there is an obstacle 8 coordinates under him. (The hero should fall 1 pixel each time, and set the falling speed with a timer as I suggested above.)
I will try to help you more after you rewrite/improve your code.
I kinda don't understand why the key commands are not working. If anyone can get a side platform script working, them that would be great.
http://forum.solarus-games.org/index.php/topic,297.15.html
I updated the script on the original topic. Feel free to try it out and let me know if it works.
I confirm that the new script works. No bugs encountered yet for your script.
Using the Solarus sample quest:
His enemy script still works with the new script. The hero freezes because he has "no death animation" or transition after death (not a script bug), but the hero shows that damage flickering animation if hurt with life beyond 1.
game:set_max_life(3)
Freeze death and jump on enemy:
(https://media.giphy.com/media/26ybxf66ur6dqu6IM/source.gif)
Damage flicker:
(https://media.giphy.com/media/3otOKtBtX2JsiNJMOY/source.gif)
slime_green.lua
local enemy = ...
local state = "stopped" -- "stopped", "moving", "going_back" or "paused".
local initial_xy = {}
local activation_distance = 24
function enemy:on_created()
self:set_life(1)
self:set_damage(2)
self:create_sprite("enemies/slime_green")
self:set_size(32, 32)
self:set_origin(16, 29)
initial_xy.x, initial_xy.y = self:get_position()
end
function enemy:on_update()
local hero = self:get_map():get_entity("hero")
if state == "stopped" and self:get_distance(hero) <= 192 then
-- Check whether the hero is close.
local x, y = self:get_position()
local hero_x, hero_y = hero:get_position()
local dx, dy = hero_x - x, hero_y - y
if math.abs(dy) < activation_distance then
if dx > 0 then
self:go(0)
else
self:go(2)
end
end
if state == "stopped" and math.abs(dx) < activation_distance then
if dy > 0 then
self:go(3)
else
self:go(1)
end
end
end
end
function enemy:go(direction4)
local dxy = {
{ x = 8, y = 0},
{ x = 0, y = -8},
{ x = -8, y = 0},
{ x = 0, y = 8}
}
-- Check that we can make the move.
local index = direction4 + 1
if not self:test_obstacles(dxy[index].x * 2, dxy[index].y * 2) then
state = "moving"
self:get_sprite():set_animation("walking")
local x, y = self:get_position()
local angle = direction4 * math.pi / 2
local m = sol.movement.create("straight")
m:set_speed(40)
m:set_angle(angle)
m:set_max_distance(104)
m:set_smooth(false)
m:start(self)
end
end
function enemy:on_obstacle_reached()
self:go_back()
end
function enemy:on_movement_finished()
self:go_back()
end
function enemy:on_collision_enemy(other_enemy, other_sprite, my_sprite)
if other_enemy:get_breed() == self:get_breed() and state == "moving" then
self:go_back()
end
end
function enemy:on_attacking_hero(hero, enemy_sprite)
-- If hero is above the enemy (jumping on its head), kill it; otherwise, hurt the hero
if self:get_angle(hero) >= 0.8 and self:get_angle(hero) <= 2.2 then
self:remove_life(2)
else
hero:start_hurt(self, 1)
end
end
function enemy:go_back()
if state == "moving" then
state = "going_back"
self:get_sprite():set_animation("walking")
local m = sol.movement.create("target")
m:set_speed(32)
m:set_target(initial_xy.x, initial_xy.y)
m:set_smooth(false)
m:start(self)
elseif state == "going_back" then
state = "paused"
self:get_sprite():set_animation("prepare_jump")
sol.timer.start(self, 500, function() self:unpause() end)
end
end
function enemy:unpause()
self:get_sprite():set_animation("prepare_jump")
state = "stopped"
end
game_manager.lua
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(3)
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