War Battle Tutorial: Rockets not moving after adding animations

Hi all,

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.

What have I done wrong?

Any help will be greatly appreciated.

Thank you and regards

Frank

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.

1 Like

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

Hi all, and Mathias in particular,

I made some changes.

I added:

last_props = self.dir

to the player.script init function

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.

Regards

Frank

There is no silly questions, only learning curves :wink:
If you share you full player.script it will help to find the spot

Hi all,

As requested here is the full player.script.

Sorry for the formatting. I’m haven’t worked out the finer details of posting code here yet.

The current state of things is

  1. 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.

  2. 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

Ok, first in the forum you can use this Markdown syntaxe to post code example:


```lua
-- my lua code
Something=function(a) return a end

```

It will give you this result:

-- my lua code
Something=function(a) return a end

Next, regarding your code.
First problem is init() function:

Here there is 2 problems

  1. The last_props is a global variable, because you dont define it as a self attribute nor as a local variable.
  2. in the code for update, last_props is a lua table with a dir property equal to self.dir. So in init() it must be something like that too

So you should have

self.last_props = { dir= self.dir} -- initial last_props -> will be the props used as rocket factory creation if there is no input 

Then everywhere you refer to it you should also use self.last_props

I think this should solve your problem

1 Like