How to move forward on a desired angle without vectors

Hey everyone! Just wanted to share some code I made. I’m very new to lua and defold so I want to be able to give back anything that I can to the community.


I am not sure if someone else has figured this out already, but in my game, I needed to give a game object a direction and have it move in that direction.

For example, 90 degrees would be something like

function init(self)
     xspeed = 1
     yspeed = 0
end

function update(self, dt)
     go.set(".", "position.x", (go.get(".", "position.x") + xspeed)
     go.set(".", "position,y", (go.get(".", "position.y") + yspeed
end

And 180 degrees would be

     xspeed = 0
     yspeed = 1

But what about 45 degrees? You would think because its going towards the top left of the screen, it would be xspeed = 1 yspeed = 1 but that is incorrect because then whenever it travels towards the corners, it will travel faster than it would be if its going to the edges. How do we fix this? And how do we calculate all 360 degrees?

This problem took me a long time to figure out. After crawling the forums for hours, I found others with the same problem. Their solution was to use vectors, but I didn’t know how to use vectors because I didn’t understand quaternions. After a few hours on youtube trying to figure out quaternions, I figured, there must be a simpler solution for such a simple problem. All i want is the ball to move in a direction and the correct speed!

So… I asked one of my good friends what he thought. He’s good at math and he had a solution which was;
Cut the angles in to four quadrants, and manipulate each quadrant differently.

After a few hours of math later, I created this script:



     go.property("ballrotprop", 0)
function init(self)
     xspeed = 0
     yspeed = 0
     ballrot = self.ballrotprop
end

function update(self, dt)

	--Makes 361 degrees = 1 degree
	if ballrot >= 360 then
		ballrot = ballrot - 360
	end
	if ballrot < 0 then
		ballrot = ballrot + 360
	end


        --This code changes the angle of the ball
	if ballrot >= 0 and ballrot <= 90 then
                --Quadrant 1
		xspeed = ballrot / 90
		yspeed = 1 - xspeed
	elseif ballrot >= 91 and ballrot <= 180 then
                --Quadrant 2
		xspeed = 1 - ((ballrot - 90) / 90)
		yspeed = (1 - xspeed) * -1
	elseif ballrot >= 181 and ballrot <= 270 then
                --Quadrant 3
		xspeed = ((ballrot - 180) / 90) * -1
		yspeed = -1 - xspeed
	elseif ballrot >= 271 and ballrot <= 359 then
                --Quadrant 4
		xspeed = (1 - ((ballrot - 270) / 90)) * -1
		yspeed = 1 + xspeed
	else
		print("Quadrant Error!")
	end

     --This code makes the game object move in the direction of the angle
     go.set(".", "position.x", (go.get(".", "position.x") + xspeed)
     go.set(".", "position,y", (go.get(".", "position.y") + yspeed
end


For my needs, this code worked perfectly. If you want to just copy and paste it into your project, I believe it will work. If you want to make it turn, just change the value of ballrot during the game.

I’ll explain how the code works:

Everything inside the function init(self), is just establishing the variables and their default values. The go.property just makes it easier to test if its working or not.

The code that says “–Makes 361 degrees = 1 degree”, this just makes it so you never get a value above 359 or below 0. It also sets 360 to equal 0 (straight up)

The code that says “–This code changes the angle of the ball”, this code is split into four parts which correspond to these four quadrants (relative to the game object):

              ^
        4     |     1
              |
     x <------------->
              |
        3     |     2
              y

All that this code is doing is manipulating the xspeed variable so as to set it to the correct value, then it sets the yspeed value to whats left in the quadrant. In some quadrants, we desire the direction to be the mirrored result of previous quadrents, so thats why we multiply it by -1 and manipulate each quadrant differently.


Well that is my story guys! I’m using this code in a recreation of the Atari game “breakout”. I’ll make sure to share it with everyone when its finished.

This seems like a great community and I’m excited to keep learning more about lua and defold!

4 Likes

Thank you for sharing your code! I see that you didn’t go for the go.get_rotation() and vmath.rotate() solution that we discussed yesterday. As long as you have something that you understand and works then it’s all good!

Yesterday I was trying to figure out how to get the ball to bounce off the paddle and walls.

I ended up using this code inside the update function to allow the ball to bounce off the walls and ceiling:

	if insidebb == true then
		if go.get(".", "position.x") <= 10 or go.get(".", "position.x") >= 1270 then
			insidebb = false
			print("TriggerBounceOffWall")
			ballrot = (180 - (ballrot - 90)) + 90
		end
		if go.get(".", "position.y") >= 710 then
			insidebb = false
			print("TriggerBounceOffCeling")
			ballrot = 180 - ballrot
		end
	else
		if go.get(".", "position.x") > 11 and go.get(".", "position.x") < 1269 and go.get(".", "position.y") < 709 then
		insidebb = true
		end
	end

and this code for the paddle under the on_message function

	-- When Objects with collision mask touch...
    if message_id == hash("trigger_response") then
		--When the ball ENTERS only
    	if message.enter then
    			--Change Direction
    			ballrot = (180 - ballrot)
		end
    end

That seemed to work fine.

Anyway, yeah the vectors seemed foreign to me so I just figured it out this way instead. Im sure at some point I’ll have to sit down and figure out quaternions. But good grief that stuff is way above my skill level! I guess thats what you get when you were homeschooled. Hahaha

I decided to give this a try myself. I’ve created a very bare bones breakout project that you can checkout here:

The relevant logic for taking care of the bounce can be seen here: https://github.com/britzl/breakout/blob/master/breakout/ball.script#L19-L22

HTML5 export: http://britzl.github.io/publicexamples/breakout/index.html

4 Likes

Hi @natefromnorthgate!

Great to see that you’ve got started and have your code running.
Looking forward to seeing the results!

Looking at your code, and seeing that you’ve already discussed vectors and rotations, i might suggest that as a next step, you look into rotations in 2D using math.cos and math.sin as step towards learning more about rotations. Here is a small snippet that generates a rotation on the unit circle

function update(self, dt)
  ballrot = ballrot % 360 -- keep it in range [0,359]

  local radians = math.rad(ballrot) -- convert from degrees to radians

  -- rotate the vector (1,0) on the unit circle
  -- the resulting vector has the length 1
  local direction_x = math.cos(radians)
  local direction_y = math.sin(radians)
  
  -- update the position
  local pos = go.get_position()
  pos = pos + vmath.vector3(direction_x, direction_y, 0) * speed * dt
  go.set_position(pos)
  
end
4 Likes

if you intend to look into vectors at some point, you should check out the linear algebra section from this game developer blog. It’s really good imo. and puts everything into context.

http://blog.wolfire.com/2009/07/linear-algebra-for-game-developers-part-1/

2 Likes

Oh my goodness you guys are the best! I was looking for a site like that @Mathias_Westerdahl! and yes @CandyFace, I do need to figure out the vectors. Its not the linear algebra that scares me, its the quaternions! I graduated school without taking trig or anything higher than algebra 2, so thats going to start holding me back. I guess I need to start learning it now hahaha :laughing:

1 Like

Dude, you’re the best! How do you have time to do all this hahaha? Do you work for King?

1 Like

You generally don’t have to do anything complicated with quaternions in Defold. There’s convenience functions like vmath.quat_rotation_z() that gives you a quat from a 2D angle. That and vmath.rotate() will get you through basically everything. Oh, and you multiply two quats to add them together.

1 Like

That doesn’t seem so bad. Thanks!

Yes :slight_smile: I spend most days (and some evenings) working with Defold related stuff. I do everything from community support, internal and external Defold and Lua training, example projects and code snippets and also some very minor work on the engine itself.

You’ll find many of the Defold team members here on the forum (@sicher, @sven, @Mathias_Westerdahl, @Johan_Beck-Noren, @Ragnar_Svensson and several more).

2 Likes

Thats so coooool :heart_eyes:

2 Likes