I made the following two functions. The bug happens with my entity:jump function. It seems not to want to change the facing direction.
entity:jump_create() -- default jump sprite Eldran is created for this one.
and
entity:jump() -- no sprite set to be created
The direction does not change even though I set:
function self:on_movement_changed()
self:set_direction(quick_movement:get_direction4())
end
The problem only occurs if I do not manually create the sprite with script. (If I do not pick the sprite from the custom entity.)
function self:on_created()
sprite = self:create_sprite(sprite_directory) -- sprite_directory
end
function self:on_movement_changed()
sprite:set_direction(quick_movement:get_direction4())
end
What makes no sense is I have other functions with identical code. For example, entity:wander() and entity:follow(). Both those functions use a sprite I picked from the custom entity and work perfectly.
I used "self:set_direction(quick_movement:get_direction4())" on both of those functions and they change direction correctly.
function self:on_movement_changed()
self:set_direction(quick_movement:get_direction4())
end
My only solution was to manually check.
if direction8 == 0 or direction8 == 1 then
if self:get_direction() == 1 then -- up
self:set_direction(0)
end
if self:get_direction() == 2 then -- left
self:set_direction(0)
end
if self:get_direction() == 3 then -- down
self:set_direction(0)
end
if self:get_direction() == 0 then-- right
self:set_direction(0)
end
end
if direction8 == 2 or direction8 == 3 then
if self:get_direction() == 1 then -- up
self:set_direction(1)
end
if self:get_direction() == 2 then -- left
self:set_direction(1)
end
if self:get_direction() == 3 then -- down
self:set_direction(1)
end
if self:get_direction() == 0 then-- right
self:set_direction(1)
end
end
if direction8 == 4 or direction8 == 6 then
if self:get_direction() == 1 then -- up
self:set_direction(2)
end
if self:get_direction() == 2 then -- left
self:set_direction(2)
end
if self:get_direction() == 3 then -- down
self:set_direction(2)
end
if self:get_direction() == 0 then-- right
self:set_direction(2)
end
end
if direction8 == 6 or direction8 == 7 then
if self:get_direction() == 1 then -- up
self:set_direction(3)
end
if self:get_direction() == 2 then -- left
self:set_direction(3)
end
if self:get_direction() == 3 then -- down
self:set_direction(3)
end
if self:get_direction() == 0 then-- right
self:set_direction(3)
end
end
This is a bit unclear to me, can you upload the whole code ?
entity:jump_create() works, but entity:jump() does not. The only main different is entity:jump_create() makes the sprite with script and entity:jump() needs a sprite and on_created():
-- Event called when the custom entity is initialized.
function entity:on_created()
entity:jump()
end
-------------------------------------------
--Entity Create Jump Method
-------------------------------------------
function metatable_entity:jump_create(sprite_directory, speed, traversable, set_can_traverse_hero, set_traversable_by_hero, ignore_obstacles, direction8, jump_distance, animation, finish_animation, finish_time, finish_jump_sound, jump_sound, sound_timer, dialog, dialog_activation_distance)
local map = self:get_map()
local hero = map:get_hero()
local game = map:get_game()
local sprite
local quick_movement
--speed default value
if speed == nil then
speed = 40
end
if traversable == nil then
traversable = false
end
--By default the entity cannot traverse the hero
if set_can_traverse_hero == nil then
set_can_traverse_hero = false
end
--By default the hero cannot traverse the entity.
if set_traversable_by_hero == nil then
set_traversable_by_hero = false
end
--By default the entity does not ignore obstacles
if ignore_obstacles == nil then
ignore_obstacles = false
end
if direction8 == nil then
direction8 = 0
end
if jump_distance == nil then
jump_distance = 100
end
--By default the sprite directory is the hero tunic1
if sprite_directory == nil then
sprite_directory = "main_heroes/Eldran"
end
if animation == nil then
animation = "jumping"
end
if finish_animation == nil then
finish_animation = "stopped"
end
if finish_time == nil then
finish_time = 3000
end
if jump_sound == nil then
jump_sound = "jump"
end
if finish_jump_sound == nil then
finish_jump_sound = "jump"
end
if sound_timer == nil then
sound_timer = 500
end
--By default the welcome sign dialog is used.
if dialog == nil then
dialog = "welcome_sign"
end
--dialog_activation_distance default value
if dialog_activation_distance == nil then
dialog_activation_distance = 20
end
function self:on_created()
sprite = self:create_sprite(sprite_directory) -- sprite_directory
self:set_can_traverse("hero", set_can_traverse_hero) -- set_can_traverse_hero
self:set_traversable_by("hero", set_traversable_by_hero) -- set_traversable_by_hero
self:set_drawn_in_y_order(true)
self:set_traversable_by(traversable)
quick_movement = sol.movement.create("jump")
self:get_sprite():set_animation(animation) -- animation
quick_movement:set_ignore_obstacles(ignore_obstacles) -- ignore obstacles
quick_movement:set_direction8(direction8) --direction8
quick_movement:set_distance(jump_distance) -- distance
quick_movement:set_speed(speed) -- speed
quick_movement:start(self)
sol.timer.start(sound_timer, function() --finish_time
sol.audio.play_sound(jump_sound) --finish_animation
end)
end
sol.timer.start(finish_time, function() --finish_time
sol.audio.play_sound(finish_jump_sound)
self:get_sprite():set_animation(finish_animation) --finish_animation
end)
function self:on_interaction()
local distance_check = hero:get_distance(self)
if distance_check <= dialog_activation_distance then -- dialog_activation_distance
if hero:get_direction() == 0 then
self:set_direction(2)
map:get_game():start_dialog(dialog) -- dialog
end
if hero:get_direction() == 1 then
self:set_direction(3)
map:get_game():start_dialog(dialog) -- dialog
end
if hero:get_direction() == 2 then
self:set_direction(0)
map:get_game():start_dialog(dialog) -- dialog
end
if hero:get_direction() == 3 then
self:set_direction(1)
map:get_game():start_dialog(dialog) -- dialog
end
end
end
function self:on_movement_changed()
sprite:set_direction(quick_movement:get_direction4())
end
end
-------------------------------------------
--Entity Jump Method
-------------------------------------------
function metatable_entity:jump(speed, traversable, ignore_obstacles, direction8, jump_distance, animation, finish_animation, finish_time, finish_jump_sound, jump_sound, sound_timer, dialog, dialog_activation_distance)
local map = self:get_map()
local hero = map:get_hero()
local game = map:get_game()
local quick_movement
--speed default value
if speed == nil then
speed = 40
end
if traversable == nil then
traversable = false
end
--By default the entity does not ignore obstacles
if ignore_obstacles == nil then
ignore_obstacles = false
end
if direction8 == nil then
direction8 = 0
end
if jump_distance == nil then
jump_distance = 100
end
if animation == nil then
animation = "jumping"
end
if finish_animation == nil then
finish_animation = "stopped"
end
if finish_time == nil then
finish_time = 3000
end
if jump_sound == nil then
jump_sound = "jump"
end
if finish_jump_sound == nil then
finish_jump_sound = "jump"
end
if sound_timer == nil then
sound_timer = 500
end
--By default the welcome sign dialog is used.
if dialog == nil then
dialog = "welcome_sign"
end
--dialog_activation_distance default value
if dialog_activation_distance == nil then
dialog_activation_distance = 20
end
self:set_drawn_in_y_order(true)
self:set_traversable_by(traversable)
quick_movement = sol.movement.create("jump")
self:get_sprite():set_animation(animation) -- animation
quick_movement:set_ignore_obstacles(ignore_obstacles) -- ignore obstacles
quick_movement:set_direction8(direction8) --direction8
quick_movement:set_distance(jump_distance) -- distance
quick_movement:set_speed(speed) -- speed
quick_movement:start(self)
sol.timer.start(sound_timer, function() --finish_time
sol.audio.play_sound(jump_sound) --finish_animation
end)
sol.timer.start(finish_time, function() --finish_time
sol.audio.play_sound(finish_jump_sound)
self:get_sprite():set_animation(finish_animation) --finish_animation
end)
function self:on_interaction()
local distance_check = hero:get_distance(self)
if distance_check <= dialog_activation_distance then -- dialog_activation_distance
if hero:get_direction() == 0 then
self:set_direction(2)
map:get_game():start_dialog(dialog) -- dialog
end
if hero:get_direction() == 1 then
self:set_direction(3)
map:get_game():start_dialog(dialog) -- dialog
end
if hero:get_direction() == 2 then
self:set_direction(0)
map:get_game():start_dialog(dialog) -- dialog
end
if hero:get_direction() == 3 then
self:set_direction(1)
map:get_game():start_dialog(dialog) -- dialog
end
end
end
function self:on_movement_changed()
self:set_direction(quick_movement:get_direction4())
end
end
The Fix:
--Manual jump direction check
if direction8 == 0 or direction8 == 1 then
if self:get_direction() == 1 then -- up
self:set_direction(0)
end
if self:get_direction() == 2 then -- left
self:set_direction(0)
end
if self:get_direction() == 3 then -- down
self:set_direction(0)
end
if self:get_direction() == 0 then-- right
self:set_direction(0)
end
end
if direction8 == 2 or direction8 == 3 then
if self:get_direction() == 1 then -- up
self:set_direction(1)
end
if self:get_direction() == 2 then -- left
self:set_direction(1)
end
if self:get_direction() == 3 then -- down
self:set_direction(1)
end
if self:get_direction() == 0 then-- right
self:set_direction(1)
end
end
if direction8 == 4 or direction8 == 6 then
if self:get_direction() == 1 then -- up
self:set_direction(2)
end
if self:get_direction() == 2 then -- left
self:set_direction(2)
end
if self:get_direction() == 3 then -- down
self:set_direction(2)
end
if self:get_direction() == 0 then-- right
self:set_direction(2)
end
end
if direction8 == 6 or direction8 == 7 then
if self:get_direction() == 1 then -- up
self:set_direction(3)
end
if self:get_direction() == 2 then -- left
self:set_direction(3)
end
if self:get_direction() == 3 then -- down
self:set_direction(3)
end
if self:get_direction() == 0 then-- right
self:set_direction(3)
end
end
http://www.solarus-games.org/doc/latest/lua_api_entity.html#lua_api_entity_on_movement_changed
Your approach is good but try with
function self:on_movement_changed(movement)
self:set_direction(movement:get_direction4())
end
If it doesn't work, try
http://www.solarus-games.org/doc/latest/lua_api_movement.html#lua_api_movement_on_changed
Also, you are overwriting the on_interaction function, all custom entities with undefined on_interaction will have this "default" code. This might be related to http://forum.solarus-games.org/index.php/topic,974.0.html
QuoteIf it doesn't work, try
http://www.solarus-games.org/doc/latest/lua_api_movement.html#lua_api_movement_on_changed
Does not work.
QuoteAlso, you are overwriting the on_interaction function, all custom entities with undefined on_interaction will have this "default" code. This might be related to http://forum.solarus-games.org/index.php/topic,974.0.html
No matter how I test it. If the custom entity is able to wander off after an on_interaction, then I can activate it as long as the hero does not move. If the hero moves 1 step, then it cancels. The fact that it cancels when the hero moves it super strange because my code has nothing to do with the hero movement.
Can you send your project here ? I'll investigate this, weird issues there
I attached the jump_lib.lua. Put it in the script directory.
From your main.lua put the following at the top.
require("scripts/jump_lib.lua")
Pick a sprite from the custom entity and paste the following into a custom entity script. The sprite will need a "jumping" and "stopped" animation. Also, a sound called "jump". Using the sample_quest and Eldran will work. Remember to change the direction of the custom entity. It jumps "right" by default.
-- Event called when the custom entity is initialized.
function entity:on_created()
entity:jump()
end
I have tested this outside of my project. I am pretty sure you will get the same result. That is why I reported it as a bug. This only happens with the jump movement.
https://github.com/solarus-games/solarus/issues/1057
For entity:jump_create() all you gotta do is paste it into a custom entity. This is the function that works. It uses Eldran as the default sprite. main_heroes/eldran
entity:jump_create()
You can change the directory.
entity:jump_create("main_heroes/eldran")
The jump_create function creates the sprite with script instead.
sprite = self:create_sprite(sprite_directory)
What I see is, you try to get the direction4, which doesn't exist in the jump movement
You can only get direction8 from a jump movement, which is understandable
http://www.solarus-games.org/doc/latest/lua_api_jump_movement.html#lua_api_jump_movement_get_direction8
So then, to get a 4 direction way, simply divide by 2
Also in on_interaction, you can save a lot of space by doing
self:set_direction((2 + hero:get_direction()) % 4) -- Make the entity face the hero
map:get_game():start_dialog(dialog) -- dialog
And i maintain, i don't get the on_interaction issue you're facing, so it comes from your code
If this doesn't solve the issue then it have something to do with your code, i'll investigate it tomorrow.
Quote from: MetalZelda on May 14, 2017, 02:36:25 AM
What I see is, you try to get the direction4, which doesn't exist in the jump movement
You can only get direction8 from a jump movement, which is understandable
http://www.solarus-games.org/doc/latest/lua_api_jump_movement.html#lua_api_jump_movement_get_direction8
So then, to get a 4 direction way, simply divide by 2
I do not understand what you mean. Doesn't the following script make the hero turn depending on the direction the movement is moving? The hero should still face the jumping direction.
function self:on_movement_changed()
self:set_direction(quick_movement:get_direction4())
end
Jump movements are particular movement objects. Therefore, they inherit all methods from the type movement.
http://www.solarus-games.org/doc/latest/lua_api_movement.html#lua_api_movement_get_direction4
0 will make the hero jump to the right with the direction8 movement. If I face the hero up from the custom entity and jump, then the hero jumps to the right while facing up. It does this for everything else. I understand that the direction8 is different from the direction4.
QuoteAlso in on_interaction, you can save a lot of space by doing
self:set_direction((2 + hero:get_direction()) % 4) -- Make the entity face the hero
map:get_game():start_dialog(dialog) -- dialog
Thanks for the tip. I will try it out sometime.
QuoteAnd i maintain, i don't get the on_interaction issue you're facing, so it comes from your code
If this doesn't solve the issue then it have something to do with your code, i'll investigate it tomorrow.
Did you try letting the custom entity move away from the hero after interacting with it? If you move the hero one step, then the bug cancels. If the custom entity is standing still, then you will never get the bug because you will move the hero. Also, this does not happen with an NPC entity. This is kinda off topic.
For example, If I set the direction8 to 2 for sprite to jump up and I face him down from the custom entity, then the following script should make him face up.
Maybe a visual explanation will help.
(https://media.giphy.com/media/3ohzdMVrALkd7meIkE/giphy.gif)
I use this script to change his direction, but it does not work.
function self:on_movement_changed()
self:set_direction(quick_movement:get_direction4())
end
1.I set direction8 to 0 for the hero to jump to the right. From the entity I face the entity up. He will jump right while facing up.
entity:jump(speed, traversable, ignore_obstacles, 0, jump_distance, start_animation, finish_animation, finish_jump_sound, start_jump_sound, sound_timer, dialog, dialog_activation_distance)
2.I set the direction8 to 2 for the hero to jump up. From the entity I face the entity right. He will jump up while facing right.
entity:jump(speed, traversable, ignore_obstacles, 2, jump_distance, start_animation, finish_animation, finish_jump_sound, start_jump_sound, sound_timer, dialog, dialog_activation_distance)
My entity:jump_create() function works. It is 95% identical to entity:jump(). The major difference with entity:jump_create() is that it creates the sprite by script. I believe that using a sprite from the custom entity with the jump movement causes a facing direction bug.
Could you post the full code of each script again? (The newest version.)
Also, indicate the filename of each script above its code. Then, if you want to comment something about the code, you only need to give the script name and the line number. (Copy-pasting isolated pieces of code does not help at all!!!)
I believe the problem is when picking the sprite from the custom entity. it seems to ignore directional change. The "Entity Create Jump Method" creates the sprite with script and it works. That is the only difference between the two functions.
1. Entity Create Jump Method = make sprite with script
2. Entity Jump Method = pick sprite from custom entity GUI
Entity Create Jump Method
-------------------------------------------
--Entity Create Jump Method
-------------------------------------------
function metatable_entity:jump_create(sprite_directory, speed, traversable, set_can_traverse_hero, set_traversable_by_hero, ignore_obstacles, direction8, jump_distance, start_animation, finish_animation, finish_jump_sound, start_jump_sound, sound_timer, dialog, dialog_activation_distance)
local map = self:get_map()
local hero = map:get_hero()
local game = map:get_game()
local sprite
local quick_movement
--speed default value
if speed == nil then
speed = 40
end
if traversable == nil then
traversable = false
end
--By default the entity cannot traverse the hero
if set_can_traverse_hero == nil then
set_can_traverse_hero = false
end
--By default the hero cannot traverse the entity.
if set_traversable_by_hero == nil then
set_traversable_by_hero = false
end
--By default the entity does not ignore obstacles
if ignore_obstacles == nil then
ignore_obstacles = false
end
if direction8 == nil then
direction8 = 0
end
if jump_distance == nil then
jump_distance = 100
end
--By default the sprite directory is the hero tunic1
if sprite_directory == nil then
sprite_directory = "main_heroes/Eldran"
end
if start_animation == nil then
start_animation = "jumping"
end
if finish_animation == nil then
finish_animation = "stopped"
end
if start_jump_sound == nil then
start_jump_sound = "jump"
end
if finish_jump_sound == nil then
finish_jump_sound = "jump"
end
if sound_timer == nil then
sound_timer = 500
end
--By default the welcome sign dialog is used.
if dialog == nil then
dialog = "welcome_sign"
end
--dialog_activation_distance default value
if dialog_activation_distance == nil then
dialog_activation_distance = 20
end
function self:on_created()
sprite = self:create_sprite(sprite_directory) -- sprite_directory
self:set_can_traverse("hero", set_can_traverse_hero) -- set_can_traverse_hero
self:set_traversable_by("hero", set_traversable_by_hero) -- set_traversable_by_hero
self:set_drawn_in_y_order(true)
self:set_traversable_by(traversable)
quick_movement = sol.movement.create("jump")
self:get_sprite():set_animation(start_animation) -- animation
quick_movement:set_ignore_obstacles(ignore_obstacles) -- ignore obstacles
quick_movement:set_direction8(direction8) --direction8
quick_movement:set_distance(jump_distance) -- distance
quick_movement:set_speed(speed) -- speed
quick_movement:start(self)
sol.timer.start(sound_timer, function() --finish_time
sol.audio.play_sound(start_jump_sound) --finish_animation
end)
end
local set_stop_aniamtion = false
sol.timer.start(450, function()
function quick_movement:on_finished()
set_stop_aniamtion = true
end
if set_stop_aniamtion == true then
sol.audio.play_sound(finish_jump_sound)
self:get_sprite():set_animation(finish_animation) --finish_animation
return false
end
return true
end)
function self:on_interaction()
local distance_check = hero:get_distance(self)
if distance_check <= dialog_activation_distance then -- dialog_activation_distance
if hero:get_direction() == 0 then
self:set_direction(2)
map:get_game():start_dialog(dialog) -- dialog
end
if hero:get_direction() == 1 then
self:set_direction(3)
map:get_game():start_dialog(dialog) -- dialog
end
if hero:get_direction() == 2 then
self:set_direction(0)
map:get_game():start_dialog(dialog) -- dialog
end
if hero:get_direction() == 3 then
self:set_direction(1)
map:get_game():start_dialog(dialog) -- dialog
end
end
end
function self:on_movement_changed()
sprite:set_direction(quick_movement:get_direction4())
end
end
The following function is what does not work correctly. The above function is almost identical. This function does not work without the code I commented out.
Entity Jump Method
-------------------------------------------
--Entity Jump Method
-------------------------------------------
function metatable_entity:jump(speed, traversable, ignore_obstacles, direction8, jump_distance, start_animation, finish_animation, finish_jump_sound, start_jump_sound, sound_timer, dialog, dialog_activation_distance)
local map = self:get_map()
local hero = map:get_hero()
local game = map:get_game()
local quick_movement
--speed default value
if speed == nil then
speed = 40
end
if traversable == nil then
traversable = false
end
--By default the entity does not ignore obstacles
if ignore_obstacles == nil then
ignore_obstacles = false
end
if direction8 == nil then
direction8 = 0
end
if jump_distance == nil then
jump_distance = 100
end
if start_animation == nil then
start_animation = "jumping"
end
if finish_animation == nil then
finish_animation = "stopped"
end
if start_jump_sound == nil then
start_jump_sound = "jump"
end
if finish_jump_sound == nil then
finish_jump_sound = "jump"
end
if sound_timer == nil then
sound_timer = 500
end
--By default the welcome sign dialog is used.
if dialog == nil then
dialog = "welcome_sign"
end
--dialog_activation_distance default value
if dialog_activation_distance == nil then
dialog_activation_distance = 20
end
--[[
--Manual jump direction check
if direction8 == 0 or direction8 == 1 then
if self:get_direction() == 1 then -- up
self:set_direction(0)
end
if self:get_direction() == 2 then -- left
self:set_direction(0)
end
if self:get_direction() == 3 then -- down
self:set_direction(0)
end
if self:get_direction() == 0 then-- right
self:set_direction(0)
end
end
if direction8 == 2 or direction8 == 3 then
if self:get_direction() == 1 then -- up
self:set_direction(1)
end
if self:get_direction() == 2 then -- left
self:set_direction(1)
end
if self:get_direction() == 3 then -- down
self:set_direction(1)
end
if self:get_direction() == 0 then-- right
self:set_direction(1)
end
end
if direction8 == 4 or direction8 == 6 then
if self:get_direction() == 1 then -- up
self:set_direction(2)
end
if self:get_direction() == 2 then -- left
self:set_direction(2)
end
if self:get_direction() == 3 then -- down
self:set_direction(2)
end
if self:get_direction() == 0 then-- right
self:set_direction(2)
end
end
if direction8 == 6 or direction8 == 7 then
if self:get_direction() == 1 then -- up
self:set_direction(3)
end
if self:get_direction() == 2 then -- left
self:set_direction(3)
end
if self:get_direction() == 3 then -- down
self:set_direction(3)
end
if self:get_direction() == 0 then-- right
self:set_direction(3)
end
end
--]]
self:set_drawn_in_y_order(true)
self:set_traversable_by(traversable)
quick_movement = sol.movement.create("jump")
self:get_sprite():set_animation(start_animation) -- animation
quick_movement:set_ignore_obstacles(ignore_obstacles) -- ignore obstacles
quick_movement:set_direction8(direction8) --direction8
quick_movement:set_distance(jump_distance) -- distance
quick_movement:set_speed(speed) -- speed
quick_movement:start(self)
sol.timer.start(sound_timer, function() --finish_time
sol.audio.play_sound(start_jump_sound) --finish_animation
end)
local set_stop_aniamtion = false
sol.timer.start(450, function()
function quick_movement:on_finished()
set_stop_aniamtion = true
end
if set_stop_aniamtion == true then
sol.audio.play_sound(finish_jump_sound)
self:get_sprite():set_animation(finish_animation) --finish_animation
return false
end
return true
end)
function self:on_interaction()
local distance_check = hero:get_distance(self)
if distance_check <= dialog_activation_distance then -- dialog_activation_distance
if hero:get_direction() == 0 then
self:set_direction(2)
map:get_game():start_dialog(dialog) -- dialog
end
if hero:get_direction() == 1 then
self:set_direction(3)
map:get_game():start_dialog(dialog) -- dialog
end
if hero:get_direction() == 2 then
self:set_direction(0)
map:get_game():start_dialog(dialog) -- dialog
end
if hero:get_direction() == 3 then
self:set_direction(1)
map:get_game():start_dialog(dialog) -- dialog
end
end
end
function self:on_movement_changed()
self:set_direction(quick_movement:get_direction4())
end
end
Usage directions:
http://forum.solarus-games.org/index.php/topic,976.msg5677.html#msg5677
P.S. I plan to use tables for easier usage in the future.
I will try to find out what is the problem.
Anyway, some advices that you should take seriously into account to write better code:
1) This was already pointed out by MetalZelda but you did not change it:
Lines 121-136 of your "Entity Create Jump Method" and lines 174-189 of your "Entity Jump Method" can be shortened in a clearer way with only 2 lines:
self:set_direction((hero:get_direction() + 2) % 4)
game:start_dialog(dialog)
(You were repeating too much code unnecessarily.) If you don't understand the math, just ask.
2) This is just a matter of taste(not so important), but lines like:
if speed == nil then
speed = 40
end
can be also written (in a shorter way) like
speed = speed or 40
(Check the "or" and "and" operators in the Lua maual for more info.)
I cannot understand anything. You did not explain properly what you are doing and what is the problem. And there is too much unnecessary information in the explanations.
-The image does not help at all. We cannot even know which entity is the hero, or what you are doing.
-In your explanations I cannot understand "what" is facing "what". All is unclear.
-You should learn to debug properly before we get crazy with your code.
Try this function instead:
function self:on_movement_changed()
print("Movement Direction: " .. quick_movement:get_direction4())
print("Entity Initial Direction: " .. self:get_direction())
self:set_direction(quick_movement:get_direction4())
print("Entity Final Direction: " .. self:get_direction())
end
Now, tell us the printed values that you get in the console, and what really happens in the game when you test it.
(We need more information. But only the useful one.)
I have tested the function custom_entity:set_direction() and it works perfectly for me, at least with the main sprite, so I cannot find functions that work in a wrong way as you say.
If you can write a new script with the MINIMAL and SIMPLEST code necessary to reproduce the bug, that would help a lot.
If you cannot figure it out by trying my script yourself, then I do not know what to tell you. The script is very simple in my opinion. It is just a bunch of defaults, self properties, and movement functions. That is if we ignore the stop/start jump sound and interaction part of the script.
The only thing that needs to be looked at is this:
(I would suggest making a custom entity and apply a jump movement to it.)
function entity:on_created()
self:set_drawn_in_y_order(true)
self:set_traversable_by(traversable)
quick_movement = sol.movement.create("jump")
self:get_sprite():set_animation(start_animation) -- animation
quick_movement:set_ignore_obstacles(ignore_obstacles) -- ignore obstacles
quick_movement:set_direction8(direction8) --direction8
quick_movement:set_distance(jump_distance) -- distance
quick_movement:set_speed(speed) -- speed
quick_movement:start(self)
function self:on_movement_changed()
self:set_direction(quick_movement:get_direction4())
end
end
The problem lies with picking the sprite from the custom entity. If this is done, then the custom entity will not face the proper direction when jumping.
(https://s8.postimg.org/t4fpkgmjp/Selection_001.png)
If the custom entity sprite is created with code, then the custom entity faces the proper direction. That is all I know.
sprite = self:create_sprite(sprite_directory) -- sprite_directory
Why would "only" making the custom entity sprite from script work for the jump movement? I do not understand why the sprite will not face the proper direction when it is picked from the custom entity. That is literally the only major difference between the two scripts I posted previously. I only get this facing direction problem with the "jump" movement. That is why I think it is a bug.
Note:
I did not make this post for the following. (I do however appreciate the tips and advice because I will change my code later.)
1. Report an issue for a debug lesson
2. Shorten my code
3. Shorten the temporary fix.
I confirm the bug. I got the same problem when I checked this with a custom entity.
Sorry for my arrogance before, but I am under too much stress these days.
I have now tried the script directly (I didn't before, I had only read the code).
After "cleaning" the code a bit, it works, so I confirm that there is no bug (unless someone can prove that I am wrong :P).
The problem is just that the script is not well coded, in the following parts:
I tested it with a custom_entity script. There is a line of code missing since "metatable_entity" is not defined, but I guess that it is metatable_entity = ...
and in that case "metatable_entity" is not really a metatable in the formal sense (I think).
1) Your events on_interaction() and on_movement_changed() are not called the first time you create a jump, because they are defined inside your function "metatable_entity:jump". These events should be defined outside that function. Although the variable quick_movement is not defined outside the function "jump", you can still access the movement with entity:get_movement().
2) This part is really confusing and gives problems:
sol.timer.start(450, function()
function quick_movement:on_finished()
set_stop_aniamtion = true
end
if set_stop_aniamtion == true then
sol.audio.play_sound(finish_jump_sound)
self:get_sprite():set_animation(finish_animation) --finish_animation
return false
end
return true
end)
If your jump ends in less than 450 ms, the event quick_movement:on_finished() would never be called since it would be defined after the movement has ended. Actually you do not need a timer, and should probably write something like this instead of the above code:
function quick_movement:on_finished()
sol.audio.play_sound(finish_jump_sound)
entity:get_sprite():set_animation(finish_animation)
end
I can paste a copy of the modified script if you want. It works and the sprite of the custom entity is always facing the direction of the jump, which I believe is what you wanted (otherwise I did not understand your final purpose).
And I insist that having a clean code is more important that it may appear, not only for finding bugs, but also to make the code understandable to others who want to help you.
Quote2) This part is really confusing and gives problems:
Ah, I think you are correct about the timer. I will do some tests later. That would not prevent a facing direction change though.
Quote1) Your events on_interaction() and on_movement_changed() are not called the first time you create a jump, because they are defined inside your function "metatable_entity:jump". These events should be defined outside that function. Although the variable quick_movement is not defined outside the function "jump", you can still access the movement with entity:get_movement().
Everything is defined in my "Entity Create Jump Method" and it works, so I am not sure that is the problem. The only difference is that function self:on_created() is inside the script and the sprite is created by the function instead of being picked from the custom entity.
-------------------------------------------
--Entity Create Jump Method
-------------------------------------------
function metatable_entity:jump_create(sprite_directory, speed, traversable, set_can_traverse_hero, set_traversable_by_hero, ignore_obstacles, direction8, jump_distance, start_animation, finish_animation, finish_jump_sound, start_jump_sound, sound_timer, dialog, dialog_activation_distance)
local map = self:get_map()
local hero = map:get_hero()
local game = map:get_game()
local sprite
local quick_movement
--speed default value
if speed == nil then
speed = 40
end
if traversable == nil then
traversable = false
end
--By default the entity cannot traverse the hero
if set_can_traverse_hero == nil then
set_can_traverse_hero = false
end
--By default the hero cannot traverse the entity.
if set_traversable_by_hero == nil then
set_traversable_by_hero = false
end
--By default the entity does not ignore obstacles
if ignore_obstacles == nil then
ignore_obstacles = false
end
if direction8 == nil then
direction8 = 0
end
if jump_distance == nil then
jump_distance = 100
end
--By default the sprite directory is the hero tunic1
if sprite_directory == nil then
sprite_directory = "main_heroes/Eldran"
end
if start_animation == nil then
start_animation = "jumping"
end
if finish_animation == nil then
finish_animation = "stopped"
end
if start_jump_sound == nil then
start_jump_sound = "jump"
end
if finish_jump_sound == nil then
finish_jump_sound = "jump"
end
if sound_timer == nil then
sound_timer = 500
end
--By default the welcome sign dialog is used.
if dialog == nil then
dialog = "welcome_sign"
end
--dialog_activation_distance default value
if dialog_activation_distance == nil then
dialog_activation_distance = 20
end
function self:on_created()
sprite = self:create_sprite(sprite_directory) -- sprite_directory
self:set_can_traverse("hero", set_can_traverse_hero) -- set_can_traverse_hero
self:set_traversable_by("hero", set_traversable_by_hero) -- set_traversable_by_hero
self:set_drawn_in_y_order(true)
self:set_traversable_by(traversable)
quick_movement = sol.movement.create("jump")
self:get_sprite():set_animation(start_animation) -- animation
quick_movement:set_ignore_obstacles(ignore_obstacles) -- ignore obstacles
quick_movement:set_direction8(direction8) --direction8
quick_movement:set_distance(jump_distance) -- distance
quick_movement:set_speed(speed) -- speed
quick_movement:start(self)
sol.timer.start(sound_timer, function() --finish_time
sol.audio.play_sound(start_jump_sound) --finish_animation
end)
end
local set_stop_aniamtion = false
sol.timer.start(450, function()
function quick_movement:on_finished()
set_stop_aniamtion = true
end
if set_stop_aniamtion == true then
sol.audio.play_sound(finish_jump_sound)
self:get_sprite():set_animation(finish_animation) --finish_animation
return false
end
return true
end)
function self:on_interaction()
local distance_check = hero:get_distance(self)
if distance_check <= dialog_activation_distance then -- dialog_activation_distance
if hero:get_direction() == 0 then
self:set_direction(2)
map:get_game():start_dialog(dialog) -- dialog
end
if hero:get_direction() == 1 then
self:set_direction(3)
map:get_game():start_dialog(dialog) -- dialog
end
if hero:get_direction() == 2 then
self:set_direction(0)
map:get_game():start_dialog(dialog) -- dialog
end
if hero:get_direction() == 3 then
self:set_direction(1)
map:get_game():start_dialog(dialog) -- dialog
end
end
end
function self:on_movement_changed()
sprite:set_direction(quick_movement:get_direction4())
end
end
QuoteI can paste a copy of the modified script if you want. It works and the sprite of the custom entity is always facing the direction of the jump, which I believe is what you wanted (otherwise I did not understand your final purpose).
I found the problem. The problem is that the facing direction will not change because function entity:on_movement_changed() is inside the function entity:on_created(). Taking it out results in correct direction change. That means it is not a bug I think. That is the only reason my script does not work for facing direction change.
I declared my function like this and that is why will not work.
function entity:on_created()
entity:jump()
end
Try it out if you do not believe me.
local entity = ...
local game = entity:get_game()
local map = entity:get_map()
function entity:on_created()
entity:set_drawn_in_y_order(true)
entity:set_traversable_by(true)
quick_movement = sol.movement.create("jump")
entity:get_sprite():set_animation("jumping") -- animation
quick_movement:set_ignore_obstacles(true) -- ignore obstacles
quick_movement:set_direction8(2) --direction8
quick_movement:set_distance(100) -- distance
quick_movement:set_speed(100) -- speed
quick_movement:start(entity)
function entity:on_movement_changed()
entity:set_direction(quick_movement:get_direction4())
end
end
I will go ahead and close the issue I reported.
Quote from: Zefk on June 24, 2017, 07:32:36 AM
I found the problem. The problem is that the facing direction will not change because function entity:on_movement_changed() is inside the function entity:on_created().
It is good to see that there is no engine bug this time and all is fixed. (The less bugs it has, the sooner we will have new features added by Chris. ;D) Yes, we should close the github issue.