[SOLVED] Help creating top-down movement controls?

I’m trying to make a game in which the character simply moves whenever you push the respective key, like a top-down game. It’s simple; there’s no gravity involved at all. Yet I can’t figure it out.

function on_input(self, action_id, action)
    if action.id == hash(“up”) then
        if action.pressed then
            --insert code for moving up when we have it
        end
    end
    elseif action.id == hash(“left”) then
        if action.pressed then
            --insert code for moving left when we have it
        end
    end
	elseif action.id == hash(“down”) then
        if action.pressed then
            --insert code for moving down when we have it
        end
    end
	elseif action.id == hash(“right”) then
        if action.pressed then
            --insert code for moving right when we have it
        end
    end
end

I have no clue how to approach the code that would normally go where the comments go. I know there’s a function called go.set_position() but I don’t know how to use it in this situation.

Please help me!

EDIT: Oh wow! This is the 1,000th question asked on the forums. Talk about milestones!

The input code doesn’t usually move the objects directly, but rather store the input state in a more digestible way. Also, using the “pressed” member, only catches if you press it for the first time, not continuously. Have a look at the Platformer tutorial for one example of how to do this. There’s usually many ways of doing this, and it will vary with what you wish to achieve.

Here’s a quick example:

function init(self)
    self.input = vmath.vector3(0,0,0)
end

function on_input(self, action_id, action)
    if action_id == input_left then
        self.input.x = -1
    elseif action_id == input_right then
        self.input.x = 1
    elseif action_id == input_up then
        self.input.y = 1
    elseif action_id == input_down then
        self.input.y = -1
    end
end

function update(self, dt)
    local speed = 32 -- pixels per second
    local deltapos = self.input * speed * dt
    go.set_position(go.get_position() + deltapos)
    self.input = vmath.vector3(0,0,0)
end
1 Like

Is there another way to calculate the local variable deltapos? Defold doesn’t want to perform arithmetic on self.input.

--line 20:
    local deltapos = self.input * speed * dt

I left out the init function, which I’ve now put into the example. There the self.input is reset, just as it is at the end of the update function…

1 Like

Thank you!

@gamedevSITHS

It’s probably worth having that error explained to you as it will help you understand a concept of coding. Also, coincidentally, it’s one of the few things that I can explain. I have spent the last three weeks building a top.down movement game in lua so I’ve been learning a lot.

on_input:
This is the part of the code that takes your key presses and makes them into something you can work with. In this case, we have created a property called “self.input”. The various inputs affect the x and y co-ordinates of that variable. For example, if left is pressed, self.input.x becomes -1.

function on_input(self, action_id, action)
    if action_id == input_left then
        self.input.x = -1
    elseif action_id == input_right then
        self.input.x = 1
    elseif action_id == input_up then
        self.input.y = 1
    elseif action_id == input_down then
        self.input.y = -1
    end
end

on_update:
This is the part of the code that happens 60 times per second (i.e. constantly). It changes the position of your actor to a new position based on self.input’s co-ordinates. In this case, we multiply the co-ordinates of self.input by 32 to get things moving a bit faster. So, if self.input.x is -1, we move the actor -32 pixels (which is to the left), 60 times every second.

function update(self, dt)
    local speed = 32 -- pixels per second
    local deltapos = self.input * speed * dt
    go.set_position(go.get_position() + deltapos)
    self.input = vmath.vector3(0,0,0)
end

on_init:
on_init is code that is run once when the actor is created. In this case it’s vital that we define self.input, so that the computer knows that it is a vmath.vector3(0,0,0). 0, 0, and 0 are the three co-ordinates for x y and z. Unless you define what self.input is as soon as you start the code, the computer doesn’t know how to perform arithmetic on it ( which it does in the update section!).

function init(self)
    self.input = vmath.vector3(0,0,0)
end
6 Likes

That clears things up! Thank you.

That’s pretty good and I think it could be a bit better using @britzl approach. You can remove self.input = vmath.vector3(0,0,0)from the update method replacing what it’s on on_input with:

if action_id == move_up then
    self.input.y = action.released and 0 or 1
elseif action_id == move_down then
    self.input.y = action.released and 0 or -1
end
if action_id == move_right then
    self.input.x = action.released and 0 or 1
elseif action_id == move_left then
    self.input.x = action.released and 0 or -1
end