I completed the War Battle Tutorial. I wanted to add some features to grow my confidence and understanding of Defold.
I added the 3 other directional animations for the player, and an ‘idle’ animation of just one frame (using the first image of the player-left group). I also implemented the code to check for player direction and adjust the animation according.
I get no error messages in the console
Now when I run the game and the player is stationary (i.e.: no input from the arrow keys) the rockets don’t move. They time out and explode as before, and will behave properly if a collision occurs with a tank.
The function update(self, dir) in the player.script now looks like this:
function update(self, dt)
if self.moving then
local pos = go.get_position()
pos = pos + self.dir * self.speed * dt
go.set_position(pos)
end
if self.firing then
local angle = math.atan2(self.dir.y, self.dir.x)
local rot = vmath.quat_rotation_z(angle)
local props = {dir = self.dir}
factory.create("#rocketfactory", nil, rot, props)
end
local anim = hash("player-idle")
if self.dir.x > 0 then
anim = hash("player-right")
elseif self.dir.x < 0 then
anim = hash("player-left")
elseif self.dir.y > 0 then
anim = hash("player-down")
elseif self.dir.y < 0 then
anim = hash("player-up")
end
if anim ~= self.current_anim then
--sprite.play_flipbook("#sprite", anim)
msg.post("#sprite", "play_animation", {id = anim})
self.current_anim = anim
end
self.input.x = 0
self.input.y = 0
self.moving = false
self.firing = false
self.dir = vmath.vector3()
end
I am pretty sure I haven’t touched any of the other scripts files. The only other changes made were to the atlas.
That’s because you pass the self.dir of the player to the dir of the rocket. So if player is not moving, self.dir is the zero vector, so the rocket got a zero vector too and dont move.
You should test : prop = self.is_moving and self.dir or vmath.vector3(1,0,0) – default rocket direction
Or your define a new self.shoot_dir with a default vector in init(), then you update this direction only if self.dir is changed to something not zero. So the shoot dir is always the last direction of player.
But maybe you should do this before computing the angle for rotation => i think the robust version is to have a shoot_dir state vector dedicated to that. So you can also change it in the futur independently of the player dir. Like autoaiming rockets
I added an else statement to the if self.moving in the update function
if self.moving then
local pos = go.get_position()
pos = pos + self.dir * self.speed * dt
go.set_position(pos)
props = {dir = self.dir}
else
props = last_props
end
finally at the end of the update function I added.
last_props = props
All of this should (in my mind) preserve the last used vector for the rockets that are fired from a non-moving position.
This almost works.
If no player movement has occurred at all, i.e.: the space bar is the first key pressed, then the rocket spawned has no movement, I obviously need to change the initial value assigned to last_props. Right?
Now after the player has moved, and when the space bar is used, the rockets do fire off in the right direction, only the direction that the rockets are pointing in is the right hand facing animation. I’m not quite sure where that is coming from. Unless its from some kind of clumsiness when I implemented the ‘player-idle‘ animation.
Sorry for the constant supply of what feels like really stupid questions.
Sorry for the formatting. I’m haven’t worked out the finer details of posting code here yet.
The current state of things is
the first rocket fired from the initial stationary position does not move. I’m obviously not putting the props = default vector in the right place.
rockets fired from a new stationary position (i.e.: after the character has moved) move in the right direction but use the ‘right’ pointing rocket animation.
I am returning to basics and doing the Side Scroller Construction Demo in the hopes of better understanding how to implement code.
player.script follows:
function init(self)
– Add initialization code here
– Learn more: https://defold.com/manuals/script/
– Remove this function if not needed
msg.post(“.”, “acquire_input_focus”)
self.moving = false
self.firing = false
self.input = vmath.vector3()
self.dir = vmath.vector3(0, 1, 0)
self.speed = 50
last_props = self.dir
end
function final(self)
– Add finalization code here
– Learn more: https://defold.com/manuals/script/
– Remove this function if not needed
msg.post(“.”, “release_input_focus”)
end
function update(self, dt)
– Add update code here
– Learn more: https://defold.com/manuals/script/
– Remove this function if not needed
props = {dir = self.dir}
if self.moving then
local pos = go.get_position()
pos = pos + self.dir * self.speed * dt
go.set_position(pos)
props = {dir = self.dir}
else
props = last_props
end
if self.firing then
local angle = math.atan2(self.dir.y, self.dir.x)
local rot = vmath.quat_rotation_z(angle)
--local props = {dir = self.dir}
-- local props = vmath.vector3(1,0,0) --self.is_moving
--local props = vmath.vector3(1,0,0)
--local props = self.dir
factory.create("#rocketfactory", nil, rot, props)
end
local anim = hash("player-idle")
if self.dir.x > 0 then
anim = hash("player-right")
elseif self.dir.x < 0 then
anim = hash("player-left")
elseif self.dir.y > 0 then
anim = hash("player-down")
elseif self.dir.y < 0 then
anim = hash("player-up")
end
if anim ~= self.current_anim then
--sprite.play_flipbook("#sprite", anim)
msg.post("#sprite", "play_animation", {id = anim})
self.current_anim = anim
end
self.input.x = 0
self.input.y = 0
self.moving = false
self.firing = false
self.dir = vmath.vector3()
last_props = props
end
function late_update(self, dt)
– This function is called at the end of update cycle but before render
– Learn more: https://defold.com/manuals/script/
– Remove this function if not needed
end
function fixed_update(self, dt)
– This function is called if ‘Fixed Update Frequency’ is enabled in the Engine section of game.project
– Can be coupled with fixed updates of the physics simulation if ‘Use Fixed Timestep’ is enabled in
– Physics section of game.project
– Add update code here
– Learn more: https://defold.com/manuals/script/
– Remove this function if not needed
end
function on_message(self, message_id, message, sender)
– Add message-handling code here
– Learn more: https://defold.com/manuals/message-passing/
– Remove this function if not needed
end
function on_input(self, action_id, action)
– Add input-handling code here. The game object this script is attached to
– must have acquired input focus:
–
– msg.post(“.”, “acquire_input_focus”)
–
– All mapped input bindings will be received. Mouse and touch input will
– be received regardless of where on the screen it happened.
– Learn more: https://defold.com/manuals/input/
– Remove this function if not needed
if action_id == hash(“up”) then
self.input.y = 1
elseif action_id == hash(“down”) then
self.input.y = -1
elseif action_id == hash(“left”) then
self.input.x = -1
elseif action_id == hash(“right”) then
self.input.x = 1
elseif action_id == hash(“fire”) and action.pressed then
self.firing = true
end
if vmath.length(self.input) > 0 then
self.moving = true
self.dir = vmath.normalize(self.input)
end
end
function on_reload(self)
– Add reload-handling code here
– Learn more: https://defold.com/manuals/hot-reload/
– Remove this function if not needed
end