Thanks, I figured it out, whilst changing the code for collisions, I forgot to put a hash in front of the sprite XD
Guess I’ll highjack this nice thread for all the small/beginner questions related to the War Battles tutorial, both text and video. Everybody is welcome to ask questions.
War Battles tutorial:
Text: https://www.defold.com/tutorials/war-battles/
Video: https://www.youtube.com/playlist?list=PLXsXu5srjNlz1HvCPytEVZggLqWBoF1pz
Github: https://github.com/defold/defold-examples/tree/master/war-battles
Has anyone else noticed that the game fires too many rockets at once? It seems as though I’m shooting at least two rockets per input. Any thoughts where I could look in my code? I know I’m firing at least two b/c my logic for when self.firing = true
looks like this:
if self.firing then
print("here\n")
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
Check your input message that you should react the button fire with the message.pressed so that it will fire one per press or click. Or you can make a timer that controls the fire cooldown time, for example 0.5 tps.
Hey!
So, I finished the tutorial and now I’m trying to implement the suggestions it makes at the end, starting with the other animations for the player. The code I wrote works fine with the one-direction movements, playing the animation only once every time the player changes direction, but with the diagonal movements it seems like it’s trying to replay the animation at every frame. I don’t know how to fix it.
Also (and this also happens in the web version in this page), I can’t fire rockets while moving in two specific diagonal directions (down-right and up-left), and I have no idea how to fix that.
Please help me with these, and any feedback on the code that the tutorial didn’t tell me how to make is very appreciated.
function init(self)
msg.post(".", "acquire_input_focus")
self.moving = false
self.speed = 100
self.input = vmath.vector3()
self.dir = vmath.vector3(0, 1, 0)
self.firing = false
self.anim_updated = false
end
function final(self)
msg.post(".", "release_input_focus")
end
local function update_anim(self)
if self.dir.x > 0 then
if self.dir.y > 0 then
msg.post("#sprite", "play_animation", { id = hash("player_upright") } )
elseif self.dir.y < 0 then
msg.post("#sprite", "play_animation", { id = hash("player_downright") } )
elseif self.dir.y == 0 then
msg.post("#sprite", "play_animation", { id = hash("player_right") } )
end
elseif self.dir.x < 0 then
if self.dir.y > 0 then
msg.post("#sprite", "play_animation", { id = hash("player_upleft") } )
elseif self.dir.y < 0 then
msg.post("#sprite", "play_animation", { id = hash("player_downleft") } )
elseif self.dir.y == 0 then
msg.post("#sprite", "play_animation", { id = hash("player_left") } )
end
elseif self.dir.x == 0 then
if self.dir.y > 0 then
msg.post("#sprite", "play_animation", { id = hash("player_up") } )
elseif self.dir.y < 0 then
msg.post("#sprite", "play_animation", { id = hash("player_down") } )
end
end
self.anim_updated = true
end
function update(self, dt)
if self.moving then
local p = go.get_position()
p = p + self.dir * self.speed * dt
go.set_position(p)
end
if not self.anim_updated then
update_anim(self)
end
if self.firing then
local angle = math.atan2(self.dir.y, self.dir.x)
local rotation = vmath.quat_rotation_z(angle)
local props = { dir = self.dir }
factory.create("#rocketfactory", nil, rotation, props)
end
self.input = vmath.vector3()
self.moving = false
self.firing = false
end
function on_input(self, action_id, action)
if action_id == hash("up") then
self.input.y = 1
end
if action_id == hash("down") then
self.input.y = -1
end
if action_id == hash("left") then
self.input.x = -1
end
if action_id == hash("right") then
self.input.x = 1
end
if action_id == hash("fire") and action.pressed then
self.firing = true
end
if vmath.length_sqr(self.input) > 0 then
self.moving = true
local temp = vmath.normalize(self.input)
if self.dir ~= temp then
self.anim_updated = false
end
self.dir = temp
end
end
Hi,
Yes, that is what happens. Your main problem stems from the following:
When you press “up” and “left” at the same time, two separate calls are made to on_input()
each frame before update()
is called. On each call, a different component of the self.input
vector is set. So looking at the value of self.input
if you hold “up” and “left”, you would see:
DEBUG:SCRIPT: vmath.vector3(-1, 0, 0)
DEBUG:SCRIPT: vmath.vector3(-1, 1, 0)
-- new frame
DEBUG:SCRIPT: vmath.vector3(-1, 0, 0)
DEBUG:SCRIPT: vmath.vector3(-1, 1, 0)
-- new frame
DEBUG:SCRIPT: vmath.vector3(-1, 0, 0)
DEBUG:SCRIPT: vmath.vector3(-1, 1, 0)
-- new frame
DEBUG:SCRIPT: vmath.vector3(-1, 0, 0)
DEBUG:SCRIPT: vmath.vector3(-1, 1, 0)
-- new frame
DEBUG:SCRIPT: vmath.vector3(-1, 0, 0)
DEBUG:SCRIPT: vmath.vector3(-1, 1, 0)
...
Since self.dir
is updated each of these calls, the flag self.anim_updated
will be set to false each call too and you get your problem.
A way to solve this, and also simplify the code is to remove the flag setting in on_input()
and do a check right with the animation code. For instance (4-way movement, but the idea works with 8-way too):
local function update_anim(self)
local anim = hash("player_idle") -- default
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_up")
elseif self.dir.y < 0 then
anim = hash("player_down")
end
if anim ~= self.current_anim then
msg.post("#sprite", "play_animation", { id = anim })
self.current_anim = anim
end
end
I could not reproduce this which makes me suspect that it may be an issue with your keyboard. Check this thread for more info: Input behavior multiple buttons pressed (SOLVED)
It may be solved by using different keys for movement. Try WASD?
That actually makes a lot of sense. I tried your code and it works just fine with the 8 directions too.
It does work with WASD for some reason. As said in the thread you sent, it’s probably about the keyboard.
Thank you so much! I didn’t think I would be answered so fast.
I think that since most games use WASD, they treat those keys specially when manufacturing.
Who knows, what’s going on with my viewport and how can I fix it?
I’m pretty sure I did nothing, just tried to follow the tutorial.
Looks like your content might be placed a bit off, in relation to the x/y axes – could you check to see if this might bee the case?
Thanks for the reply.
Indeed, the map has been placed on 0,0,0 position:
Even if I place it as you suggest, it still looks weird:
How can I know the size of the screen to place the map correctly? I see no frame or any other origin anchor.
What about the distance to the player eyes? Should I zoom the map and all my other sprites instead of set some viewport settings?
Should I move and zoom the map manually in the Editor every time when I change the map size? Aren’t there any virtual camera settings?
I’m trying to make the tanks chase the player and i have added a spherical collision object to the tanks connected to a box shaped collision object on the player. I’ve created a tanks.script that contains the following:
function init(self)
self.speed = 200
end
function update(self, dt)
local pos = go.get_position()
pos = pos + self.speed * dt
go.set_position(pos)
end
function on_message(self, message_id, message, sender)
if message_id == hash("colllision_response") then
end
end
and i dont know what to write under the if statement, i want to write something like pos = player.pos or similar to make the tank move towards the player but that doesnt seem to work and i dont really have enough knowledge i feel. Any help would be appreciated! =)
Here’s an example of movement towards a moving target: https://github.com/britzl/publicexamples/tree/master/examples/simple_ai
I’ve been looking at the example but i dont understand so much of it ;/ i’ve read zombie.script many times but i understand how i should write my code in the defold project to make the tanks move. I’ve failed at trying to make the tanks respawn also, aswell as making them select a random point to move towards. I feel like i just lack the knowledge and any help would be so apprecieted ! maybe you can try to add more explanations in the code for the example you linked or try to help with the things i’ve been trying to code? =)
You typically spawn new items using a factory. We have a manual describing how to work with factories:
You select a random point like this:
local random_x = math.random(1, 1000) -- random value between 1 and 1000
local random_y = math.random(100, 800) -- between 100 to 800
local random_point = vmath.vector3(random_x, random_y, 0)
The easiest way to move from one point to another is to start an animation:
local duration = 2 -- seconds
go.animate(".", "position", go.PLAYBACK_ONCE_FORWARD, random_point, go.EASING_LINEAR, duration)
Read more here: https://www.defold.com/manuals/animation/#_property_animation
You can also animate in the update() function, step by step, frame by frame, but if you can it is recommended to use go.animate().
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.
You’re welcome