War Battles tutorial support thread - post your questions here

thanks i will look into it, i appreciate the help so much!

Following the War Battles tutorial, and the rocket explosion animation plays but loops forever. Here’s the contents of rocket.script, it seems to match the example code.

I added a couple of print debugging statements, and it doesn’t look like this object ever receives any message, so never gets the the go.delete() call. Any ideas?

go.property("dir", vmath.vector3())

function init(self)
	self.speed = 200
	self.life = 1
end

function update(self, dt)
	local pos = go.get_position()
	pos = pos + self.dir * self.speed * dt
	go.set_position(pos)

	self.life = self.life - dt
	if self.life < 0 then
		self.life = 1000
		go.set_rotation(vmath.quat())
		self.speed = 0
		print("playing explosion")
		msg.post("#sprite", "play_animation", { id = hash("explosion") })
	end
end

function on_message(self, message_id, message, sender)
	print("got message of any kind")
	if message_id == hash("animation_done") then
		go.delete()
	end 
end

I think your explosion animation is on ‘Loop Forward’ instead of ‘Once Forward’ in the sprites atlas.
This is what it should look like.

Because the animation is on loop it never finishes and the animation_done message never gets send to the on_message function.

4 Likes

D’oh! That was it. Thanks so much @codescapade :slight_smile:

1 Like

You’re welcome :slight_smile:

How do i make a game object move towards another moving game object ?

You can do this by first getting the two vectors, of your gameobject and your target. Then you subtract them to get a difference vector. Pass the X and y coordinates of the difference vector as an argument to atan2 function in the math library to get an angle, which can be used with vmath.quat_rotation_z to get a quaternion.
Then use vmath.rotate with the quaternion you got above and a vector3 (0,1,0) to get a vector in the direction of the player. Then do this
Position = go.get_position()
position = position + vectorfromabove * speed* dt
go.set_position(position)
This will do the trick.

You asked this a week ago further up in this thread and I believe I gave multiple suggestions. Did you review the suggestions? Was there things you didn’t understand? If so, what? I’m happy to clarify.

2 Likes

thanks both TheKing009 and britzl for the help! i think my only problem now is that i need to send the players position from player.script to my chasing game objects script so i can use the player position as “self.target_position”, because if i for example make self.target_position = vmath.vector3(100,100,1) the chasing game object goes to that point, other than that it seems to be working good.

No, you can easily get the position of a game object from any other game object. There’s no need to send the position.

If the player game object has an id player then you get the position of the player from the chasing game object like this:

local player_pos = go.get_position("player")

oh thanks, i never realized that, by the way i feel like im a bit confused about what self.target_position is or even self.target, what is self.target? i feel dumb for asking all these questions and i’ve tried to learn online and come here as a last resort, which is turning out to be a bit too often perhaps

Self is a place to store variables accessible only to script instance itself:

function init(self)
    self.target =  foobar
end

function update(self, dt)
   print(self.foobar)
end

The self.target variable is accessible within the lifecycle functions of the script where it was created. You can read more here:

1 Like

thanks man

Hey there! I am new here and have recently started using Defold. I don’t have that much experience with coding and I am currently trying to do those extra challenges on the War battles tutorial, and can’t make my character have an idle animation. My code is the following:

if action_id == hash("up") then
		msg.post("#sprite", "play_animation", { id = hash("player-up") })
	elseif action_id == hash("down") then
		msg.post("#sprite", "play_animation", { id = hash("player-down") })
	elseif action_id == hash("left") then
		msg.post("#sprite", "play_animation", { id = hash("player-left") })
	elseif action_id == hash("right") then
		msg.post("#sprite", "play_animation", { id = hash("player-right") })
	elseif self.speed == 0 then
		msg.post("#sprite", "play_animation", { id = hash("idle") })
	end

For some reason, the idle animation won’t play. Shouldn’t it work when my character stopped?

The on_input code is only run when an input event happens. So you need to figure out a way to set the idle animation when no keys are pressed. You will get action.released set to true when a key is released.

1 Like

Most likely, you want to play the animation on the first keypress.
There is a boolean for that: action.pressed (as mentioned above, there is also a boolean for the last keypress)

Instead, try:

if action.pressed then
    if action_id == hash("up") then
        ...
    end
end
2 Likes

Thank you for your help, that worked! However, I seem to have run into another problem: if I move diagonally and then release one of the directions in order to go either just horizontally or vertically, the idle animation plays and my character just slides in that direction. Even though it looks kinda funny, I’d like to know if there is a way to prevent this. My current code is:

if action.pressed then
		if action_id == hash("up") then
			msg.post("#sprite", "play_animation", { id = hash("player-up") })
		elseif action_id == hash("down") then
			msg.post("#sprite", "play_animation", { id = hash("player-down") })
		elseif action_id == hash("left") then
			msg.post("#sprite", "play_animation", { id = hash("player-left") })
		elseif action_id == hash("right") then
			msg.post("#sprite", "play_animation", { id = hash("player-right") })
		end 
	elseif action.released then
		msg.post("#sprite", "play_animation", { id = hash("idle") })
	end

There is a good starting example with a character animation code

1 Like