Demilade Sonuga's blog

All posts

Some Mathematics II

2023-07-29 · 68 min read

In this post, we're going to get to the ball's motion and interaction.

The Problem

The paddle moves horizontally. The blocks don't move at all. The ball is the only character that moves and interacts with the other characters. The thing about the ball is that its motion and interaction can't really be separated (I think). Why? Because its interaction determines its motion and its motion determines its interaction.

To get what I mean, take a look at this:

Ball Moving in North-East Direction Towards Wall

In the above image, the ball is already in motion in a northeast direction. It then hits a wall (interaction). The problem that faces us now is how we determine which direction the ball should continue motion in after this interaction.

Or, even more precisely, how do we know the ball's direction at any point in time? How can we compute the direction that the ball should change into given a pre-interaction direction and an interaction with another character?

It's only after we have precise answers to these questions that we can implement the ball's motion and interaction.

To solve the problem of simple motion, we already have our coordinate system which we looked at in the previous post. To solve the problem of direction, we have to take a little detour to look at the notion of turning.

Turning

A scenario

Consider a scenario: suppose you're standing on a spot and for some reason or the other, you can't leave that spot. You're facing a place; let's call this place location A. To your right is location B. Behind you is location C. To your left is location D. From an omniscient eagle's eye view, you'll look something like this:

Standing on a Spot, Facing North

To have a reference point, we can define your current direction as north. Location B is east of you. Location C is south of you. And location D is west of you.

You are currently facing north. How can you face south, without moving from your spot? Well, you turn. You turn until your direction is somewhere between north and east. You keep turning until your direction becomes east. You then turn some more: your direction is between east and south. Then you make a few more turns until your direction finally becomes south.

If we were to describe the space you were standing in with a Cartesian coordinate system, like the one we settled on in the previous post, then you never changed your location. You remained in a single spot.

If you had decided to move in a straight line while you were still facing north, you would have ended up at location A. But after the turning, if you made that same straight-line motion, you would end up at location C. Why? Because that turning resulted in a change of your direction.

From this simple scenario, we can define direction as an invisible line along which a thing moves. Making this invisible line visible, we can view the change in direction like so:

Changing Direction From North To South

How can we precisely describe the direction and changes in the direction of the ball? Saying "facing north" and "turn to the south" is insufficient. Like in the previous post, to create motion, we needed a mathematical description of space, likewise, here we need a mathematical description of direction and changes in direction.

Well, luckily for us, we don't have to invent our own descriptions of direction/turning. Mathematicians of old have already studied the notion of turning and penned down their findings. The stuff we're going to use here is from little corners in branches of math known as trigonometry and Euclidean geometry.

Angles and The Unit Circle

I'm assuming that most people would be familiar with angles, basic trig and the trig functions sine and cosine. If you aren't, please check out the references and do a bunch of Google searches. You may also consider briefing through some trig sections of a math textbook.

The mathematical description for a "turn" or "rotation" of an object is an angle. Consider this:

Angle Rotation

In the above diagram, the angle θ is a number that precisely says how much the line X needs to be turned/rotated to become line Y. You can think of it as rotational distance.

Remember angles are measured in degrees (they can be measured in other units too, but we'll focus on degrees). In the scenario presented in the previous section, you turn 180 degrees to face location C.

Trig has a lot to do with the study of right-angle triangles and their properties. Remember that a right-angle triangle is a triangle in which one of the angles is a right angle (that is, 90 degrees).

For example:

Right Angle Triangle

In the diagram above, the bottom left corner of the triangle is a right angle. The other angles are labeled α and θ.

Trig functions are functions that describe a relationship between angles in a right-angle triangle and the sides of the triangle. The two that will be of use to us here are sine and cosine.

The sine of an angle in a right-angle triangle is defined as the side opposite the angle divided by the triangle's hypotenuse (the longest side). While the cosine of an angle is defined as the side adjacent to the angle divided by the hypotenuse.

For example, in the above right-angle triangle, the sine of angle θ is lengthofXlengthofY. Why? Because the side X is opposite the angle θ and the side Y is the longest side of the triangle (the hypotenuse). The cosine of angle θ will be lengthofZlengthofY because the side Z is the one adjacent to angle θ and Y is the longest side.

The trig functions of a right-angle triangle can also be defined on a unit circle (a circle whose radius is 1 unit):

Unit Circle With Triangle Showing Sine and Cosine

The above is a unit circle demonstrating how it can be used to compute trig functions sine and cosine of an angle labeled θ.

The radius acts as the hypotenuse. The angle of concern is the angle θ which lies between the radius and the line pointing to the east. The side opposite angle θ is sinθ because sinθ=lengthofX1=lengthofX. The same goes for the length of the adjacent side: it is cosθ because cosθ=lengthofY1=lengthofY.

Using this definition of angles in a unit circle, we can have well-defined descriptions of direction and descriptions of changes in direction:

Unit Circle Showing Angles

Going back to the scenario in the previous section, according to this system for defining directions, your initial direction was 90 degrees and after the turning, your final direction was 270 degrees.

With this arrangement, we have a precise description of direction. Instead of saying north, we say "90 degrees". Instead of saying "somewhere southwest", we say either "195 degrees" or "210 degrees" or "225 degrees" or "240 degrees" or "255 degrees", depending on how much towards the south or the west the direction is inclined.

A problem seems to arise here. How can we precisely determine a direction that lies between 195 and 210 degrees, since angles between those numbers are not defined in this system? Well, we don't need to. This system is already precise enough for our purposes, I believe.

That's it for defining direction. As for changing direction, all we have to do is simple arithmetic on these numbers. Going back to the previous scenario, initially, your direction is 90 degrees. To turn around, the direction is increased modulo 360. That is, it's increased from 90 to 115 to 130 to 145 to ... to 180 to ... to 270 to ... to 345 to 0 to ... to 90 degrees (full circle).

Diagonal Motion, Reflection

In the previous section, we have the answer to two of our problems: a precise description of direction and changes in direction.

The remaining problems which must be resolved before moving on: how do we determine the direction the ball ought to move in after an interaction (collision) with some other character? And how do we translate the ball's motion in a particular direction into a smooth movement on the screen (in as simple a way as possible)?

To resolve direction change after a collision, we look to another math concept: linear transformation.

We're using linear transformation here because it's simple, intuitive and direct (that is if you're already familiar with the Cartesian Coordinate system and basic trig which I assume you are). And also because the mechanisms used to effect it are just basic arithmetic.

The idea under linear transformations we'll be using to determine the ball's new direction after a collision is reflection.

When you hear the word reflection a mirror is one of the first things that may come to your mind. When you look in a mirror, you see an exact image of yourself looking right back at you. This mirror concept explains perfectly the idea of reflection.

Consider the following:

Reflection About The X-axis

In the above diagram, if the x-axis is a mirror, the dotted line B is the image that line A will see.

Similarly:

Reflection About The X-axis

This idea of imagining the x-axis as a mirror and drawing an identical image of some shape or line on the other side of the axis is a reflection about the x-axis.

Just like we have a reflection about the x-axis, we could also have reflections about the y-axis, too.

Reflection About The Y-axis

In the above diagram, if the y-axis is a mirror, then line B is what line A would see as its reflection.

Similarly:

Reflection About The Y-axis

Another reflection.

Another thing to pay attention to about these reflections is the angles. When a reflection takes place, the angle between each line and the x or y axes are equal. In each reflection diagram, these equal angles are labeled with the letters α and β.

Using these simple ideas of reflections, we can solve the problem of determining a new direction for the ball after collision.

To do that, you can view direction as an invisible line along which the ball will move. For example:

Ball With Visible Direction

The above diagram is a snapshot of a ball in motion. The ball is moving in direction α. The arrow is never actually seen (it's invisible). It's the representation of the ball's direction. The ball moves along that line.

How To Change Direction

Collision With The Vertical Side Of An Object

Moving Upward And Leftward (90 < Initial Direction < 180)

Now, when the ball collides with the wall, we can imagine the wall as a mirror for the invisible direction line. A reflection about the y-axis will determine the new direction for the ball.

Collision With The Vertical Side of An Object

The above diagram shows how the ball's direction will change. A reflection of the ball's direction about the y-axis will serve to produce the illusion that the ball bounced off the wall.

Before collision, the ball's direction is α:

Before Collision

After the collision, the ball's new direction is β

After Collision

Observe that before the collision, the angle between the direction line and the x-axis is β. And after the collision β becomes the new direction.

From our observation of this α-β relation, we can determine a formula that we can use anytime we need to compute a new direction after such a collision:

OldDirection:α
NewDirection:β
=180-α

The direction change above is for a left wall (or any vertical object, really) collision while the ball is moving upwards and leftwards.

Moving Downward And Leftward (180 < Initial Direction < 270)

But what if the ball is moving downwards?

Collision With The Vertical Side of An Object

Before the collision:

Before Collision

After the collision:

After Collision

Formula for direction change:

OldDirection:α
NewDirection:θ
=270+β
=270+(270-α)
=270+270-α
=540-α

These ideas are only useful when the ball hits the vertical side of an object from the ball's left.

Moving Upward And Rightward (0 < Initial Direction < 90)

How about hitting from the ball's right?

Collision With The Vertical Side of An Object From The Ball's Right

The above is a diagram of the ball hitting the vertical side of an object (the right wall) from the ball's right while the ball is moving upwards.

Before the collision:

Before Collision

After the collision:

After Collision

Formula for direction change:

OldDirection:α
NewDirection:θ
=90+β
=90+(90-α)
=90+90-α
=180-α
Moving Downward And Rightward (270 < Initial Direction < 360)

Now, for the ball hitting the same vertical side, but moving downwards instead of up:

Collision With The Vertical Side of An Object From The Ball's Right

Before collision:

Before Collision

After collision:

After Collision

Formula for direction change:

OldDirection:α
NewDirection:θ
=270-β
=270-(α-270)
=270-α+270
=540-α

These descriptions of direction changes are only for scenarios where the ball collides with the vertical side of an object.

Collision With The Horizontal Side Of An Object

But what if it collides with the horizontal side (like in the case of the paddle)?

To create the illusion of the ball bouncing off walls (or a vertical side of any object), we reflect the direction about the y-axis. But to create the illusion of bouncing off the horizontal side, we reflect the direction about the x-axis instead.

Moving Upward And Rightward (0 < Initial Direction < 90)

Collision With The Horizontal Side of An Object

The above is a diagram of the ball hitting the horizontal side of a block while moving upwards toward the right.

Before the collision:

Before Collision

After the collision:

After Collision

Formula for direction change:

OldDirection:α
NewDirection:θ
=270+β
=270+(90-α)
=270+90-α
=360-α
Moving Upward And Leftward (90 < Initial Direction < 180)

For the ball hitting the same horizontal side while moving upwards, but towards the left:

Collision With The Horizontal Side of An Object

Before collision:

Before Collision

After collision:

After Collision

Formula for direction change:

OldDirection:α
NewDirection:θ
=180+β
=180+(180-α)
=180+180-α
=360-α
Moving Downward And Rightward (270 < Initial Direction < 360)

Now, for the ball hitting a horizontal side, but moving downwards towards the right:

Collision With The Horizontal Side of An Object

Before collision:

Before Collision

After collision:

After Collision

Formula for direction change:

OldDirection:α
NewDirection:β
=360-α
Moving Downward And Leftward (180 < Initial Direction < 270)

And finally for the scenario in which the ball hits a horizontal side of an object while moving downwards towards the left.

Collision With The Horizontal Side of An Object

Before collision:

Before Collision

After collision:

After Collision

Formula for direction change:

OldDirection:α
NewDirection:θ
=180-β
=180-(α-180)
=180-α+180
=360-α

Edge Cases

The descriptions above assume that the direction is always either between 0 and 90 or between 90 and 180 or between 180 and 270 or between 270 and 360. But what if it's not?

Initial Direction == 0

In this case, the ball is moving horizontally towards the right. We simply reflect it to move in the opposite direction, giving us 180 degrees.

Initial Direction == 90

In this case, the ball is moving vertically upwards. We simply reflect it to move in the opposite direction, giving us 270 degrees.

Initial Direction == 180

Here, the ball is moving horizontally toward the left. A reflection to move in the opposite direction will make the ball's new direction == 0.

Initial Direction == 270

Here, the ball is moving vertically downward. A reflection will change its direction to 90 degrees.

Summary

And with these descriptions, we have laid down the arithmetic procedures that must be performed on the ball's direction to determine its new direction after a collision in any scenario.

More compactly:

For collisions on the vertical side of objects: Direction Change After Vertical Collisions

For collisions on the horizontal side of objects: Direction Change After Horizontal Collisions

For edge cases:

Before:α
After:(α+180)mod360

And that sums it up.

As for the edge cases, I think it would be a good idea to just avoid them. They're flaws in our system.

From Direction To Motion

Before we get on to implementation, we have to deal with one more problem: how do we convert the ball's direction into smooth motion on screen? To do this, let's return to the idea of the unit circle:

Unit Circle With Triangle Showing Sine and Cosine

The radius of the circle is the direction line of direction θ. When the ball's direction is θ, it moves along this diagonal line.

In the previous post, we saw how to make an object move diagonally. It's a simple matter of increasing the x and y coordinates by some amount. To translate direction in the unit circle diagram to motion, we can interpret sinθ to mean the amount by which the y coordinate should be changed to move along the direction line and cosθ to mean the amount by which the x coordinate should be changed to move along the direction line.

We can then redefine sinθ and cosθ for all possible direction values in the system to have values that can believably effect this interpretation.

For example, if we define sinθ=3 and cosθ=3 for some direction θ, then moving in that direction will go like this:

If The The Direction's Sine And Cosine Were Equal To 3

With this interpretation, the only work we'll have to do to get the system to work is to define values for sinθ and cosθ for each possible θ value.

In our system, sinθ is no longer OppositeSideLongestSide and cosθ is no longer AdjacentSideLongestSide.

So, if the ball is at point (y, x) and its direction is θ, then the next point it ought to move to will be (y + sinθ, x + cosθ).

Redefinitions of sinθ and cosθ

Now, we have to redefine sinθ and cosθ for degree values 0, 15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165, 180, 195, 210, 225, 240, 255, 270, 285, 300, 315, 330, and 345.

θ=0

Angle 0 This is one of those edge cases that should be avoided. Here, the direction is completely toward the right, there is no upward or downward component. So the result should be a pure horizontal motion.

It points towards the right, so it should result in a motion to the right.

We now put down definitions as follows:

sin0=0
cos0=1

Meaning if the object at point (y, x) has a direction of 0, then the next point to move to should be (y + 0, x + 1) = (y, x + 1).

θ=15

Angle 15 An object moving in this direction should result in a significant motion to the right and a slight motion upward.

Definitions (randomly chosen as what just felt right to me):

sin15=-1
cos15=3

Remember that in our game's coordinate system, going upwards requires a reduction in the y coordinate. That's why sin15 is defined as a negative number.

This definition means that if an object is at point (y, x) and has a direction of 15, then the next point to move to should be (y - 1, x + 3).

θ=30

Angle 30 An object moving in this direction should have a motion similar to that in direction 15 degrees, but the ascent should be sharper.

Definitions:

sin30=-1
cos30=2

Meaning if the object at (y, x) has a direction of 30, then the next point to move to will be (y - 1, x + 2).

θ=45

Angle 45 Again, an object moving in this direction should have a motion similar to that in 15 degrees, but the ascent should be sharper giving the impression that the ball is moving upward at a higher degree.

Definitions:

sin45=-1
cos45=1

Meaning if the object at (y, x) has a direction of 45, then the next point to move to will be (y - 1, x + 1).

θ=60

Angle 60 Similar to 45 degrees motion. Sharper ascent.

Definitions:

sin60=-2
cos60=1

Meaning if the object at (y, x) has a direction of 60, then the next point to move to will be (y - 2, x + 1).

θ=75

Angle 75 Similar to 60 degrees motion. Sharper ascent.

Definitions:

sin75=-3
cos75=1

Meaning if the object at (y, x) has a direction of 75, then the next point to move to will be (y - 3, x + 1).

θ=90

Angle 90 Here, the direction is solely upward. There is no horizontal aspect.

Definitions:

sin90=-1
cos90=0

Meaning if an object at (y, x) has a direction of 90, then the next point to move to will be (y - 1, x + 0).

θ=105

Angle 105 An object moving in this direction should have a significant motion upward and a slight one to the left.

Definitions:

sin105=-3
cos105=-1

Meaning an object at (y, x) has a direction of 105, then the next point to move to will be (y - 3, x - 1).

θ=120

Angle 120 Similar to 105 degrees motion. Duller ascent.

Definitions:

sin120=-2
cos120=-1

Meaning if an object is at (y, x) with direction 120, then the next point to move to will be (y - 2, x - 1).

θ=135

Angle 135 Similar to 120 degrees motion. Duller ascent.

Definitions:

sin135=-1
cos135=-1

Meaning if an object is at (y, x) with direction 135, then the next point to move to will be (y - 1, x - 1).

θ=150

Angle 150 An object moving in this direction should move more horizontally than vertically, but not too much.

Definitions:

sin150=-1
cos150=-2

Meaning that if an object is at (y, x) with direction 150, then the next point to move to will be (y - 1, x - 2).

θ=165

Angle 165 Similar to 150 degrees motion. Sharper motion to the left.

Definitions:

sin165=-1
cos165=-3

Meaning that if an object is at (y, x) with direction 165, then the next point to move to will be (y - 1, x - 3).

θ=180

Angle 180 Here, the direction is solely leftward. No vertical aspect.

Definitions:

sin180=0
cos180=-1

Meaning that if an object is at (y, x) with direction 180, then the next point to move to will be (y + 0, x - 1) == (y, x - 1)

θ=195

Angle 195 An object moving in this direction should move significantly to the left and slightly downward.

Definitions:

sin195=1
cos195=-3

Remember that in our coordinate system, a positive increase in the y coordinate results in a downward movement. That's why the sin value is positive.

This definition means that if an object is at (y, x) with direction 195, then the next point to will be (y + 1, x - 3).

θ=210

Angle 210 Similar to 195 degrees motion. Duller leftward motion.

Definitions:

sin210=1
cos210=-2

Meaning that if an object is at (y, x) with direction 210, then the next point to move to will be (y + 1, x - 2).

θ=225

Angle 225 Similar to 210 degrees motion. Duller leftward motion.

Definitions:

sin225=1
cos225=-1

Meaning that if an object is at (y, x) with direction 225, then the next point to move to will be (y + 1, x - 1).

θ=240

Angle 240 An object moving in this direction should move more downward than leftward and not too much.

Definitions:

sin240=2
cos240=-1

Meaning that if an object is at (y, x) with direction 240, then the next point to move to will be (y + 2, x - 1).

θ=255

Angle 255 Similar to 240 degrees motion. Sharper downward movement.

Definitions:

sin255=3
cos255=-1

Meaning that if an object is at (y, x) with direction 255, then the next point to move to will be (y + 3, x - 1).

θ=270

Angle 270 No horizontal component. Just vertical downward motion.

Definition:

sin270=1
cos270=0

Meaning that if an object is at (y, x) with direction 270, then the next point to move to will be (y + 1, x + 0).

θ=285

Angle 285 Significant Downward motion. Slight motion to the right.

Definition:

sin285=3
cos285=1

Meaning that if an object is at (y, x) with direction 285, then the next point to move to will be (y + 3, x + 1).

θ=300

Angle 300 Similar to 285 degrees motion. Duller downward motion.

Definition:

sin300=2
cos300=1

Meaning that if an object is at (y, x) with direction 300, then the next point to move to will be (y + 2, x + 1).

θ=315

Angle 315 Similar to 315 degrees motion. Duller downward motion.

Definition:

sin315=1
cos315=1

Meaning that if an object is at (y, x) with direction 315, then the next point to move to will be (y + 1, x + 1).

θ=330

Angle 330 Motion to the right should be more than the downward motion, but not too much.

Definitions:

sin330=1
cos330=2

Meaning that if an object is at (y, x) with direction 330, then the next point to move to will be (y + 1, x + 2).

θ=345

Angle 345 Similar to 330 degrees motion. Sharper rightward motion.

Definitions:

sin345=1
cos345=3

Meaning that if an object is at (y, x) with direction 345, then the next point to move to will be (y + 1, x + 3).

Summary

With these descriptions, we now know how to determine the way the ball should move based on its direction.

More compactly:

Directions With Motion Description

Why Avoid The Edge Cases

I mentioned that it would be a good idea to avoid edge cases, but why? Well, consider the following:

Ball Moving In Non-edge Case Direction

When the above ball hits the wall, it will eventually come back down in a different direction and if the human playing the game wants to win, the human will have to move the paddle to save the ball from going off-screen.

But if the ball was moving in an edge-case direction, like 90 degrees:

Ball Moving In Direction 90 Degrees

When it collides with the blocks, it will come back down in a straight line, collide with the paddle then go back up in a straight line, then collide the with blocks then come back down in a straight line then collide with the paddle, and this goes on and on, forever. Or until the user gets bored and deliberately moves the paddle out of the ball's path to lose the game.

That's horrible.

Although, there are ways these flaws could be patched. We could redefine the edge case sin and cos definitions to reflect the ball in such a way as to avoid this deadlock motion. But I'll just leave it as it is and avoid the edge cases.

Expressing The System In Code

To express our system in code, create a new file math.rs.

First, we create a structure to represent a point:

#[derive(Clone, Copy)]
pub struct Point(pub isize, pub isize);

And endow it with meaningful functions:

impl Point {
pub fn x(&self) -> isize {
self.1
}

pub fn y(&self) -> isize {
self.0
}

pub fn set_x(&mut self, x: isize) {
self.1 = x;
}

pub fn set_y(&mut self, y: isize) {
self.0 = y;
}
}

We can use this Point structure instead of littering code with tuples here and there.

For ease of use, we can also implement some traits:

impl core::ops::Add for Point {
type Output = Point;
fn add(self, rhs: Self) -> Self::Output {
Self(self.0 + rhs.0, self.1 + rhs.1)
}
}

impl core::ops::Sub for Point {
type Output = Point;
fn sub(self, rhs: Self) -> Self::Output {
Self(self.0 - rhs.0, self.1 - rhs.1)
}
}

impl core::ops::AddAssign for Point {
fn add_assign(&mut self, rhs: Self) {
self.0 += rhs.0;
self.1 += rhs.1
}
}

impl core::ops::SubAssign for Point {
fn sub_assign(&mut self, rhs: Self) {
self.0 -= rhs.0;
self.1 -= rhs.1;
}
}

With these trait implementations, we can add and subtract points as if they're regular primitives. The core::ops::Add implementation allows us to do:

let p1 = Point(5, 2);
let p2 = p1 + Point(7, 2); // Equals Point(12, 4)

The core::ops::Sub implementation allows us to do:

let p1 = Point(5, 2);
let p2 = p1 - Point(5, 2); // Equals Point(0, 0)

The core::ops::AddAssign implementation allows us to do:

let mut p1 = Point(5, 2);
p1 += Point(5, 2); // p1 is now Point(12, 4)

And the core::ops::SubAssign implementation allows us to do:

let mut p1 = Point(5, 2);
p1 -= Point(5, 2); // p1 is now Point(0, 0)

A structure to represent angles:

#[derive(Clone, Copy)]
pub struct Angle(usize);

We can impose a constraint on the usize contained so that it will always be a valid angle in the system (0, 15, 30, 45, 90, ..., 180, 195, 210, ..., 330, 345).

To do this, we leave the field private (so it can't just be changed to an invalid value elsewhere) and provide a new function that accepts a number and converts it to a valid degree.

The structure can then offer methods to manipulate the contained usize in such a way as to ensure it remains a valid degree value.

We don't have to worry about negative values because usizes can never be negative.

impl Angle {
// Creates a new angle guaranteed to have a valid degree value in the system
pub fn new(n: usize) -> Self {
// Should be wrapped around
let n = n % 360;
// And rounded to the nearest defined angle
let n = n - (n % 15);
Self(n)
}
}

To take care of given numbers greater than 360, we wrap them around with % 360. The let n = n - (n % 15) rounds the number down to the nearest multiple of 15. This results in a valid system degree because all the valid degrees are lesser than 360 and are multiples of 15.

To express the ideas of how to change direction after collisions:

pub enum SideCollided {
Vertical,
Horizontal
}
impl Angle {
pub fn reflect(self, side_collided: SideCollided) -> Self {
match self.0 {
// Edge cases
0 => Self(180),
90 => Self(270),
180 => Self(0),
270 => Self(90),
_ => match side_collided {
// Collision with the verical side of an object
SideCollided::Vertical => match self.0 {
0..=180 => Self(180 - self.0),
_ => Self(540 - self.0)
},
// Collision with the horizontal side of an object
SideCollided::Horizontal => Self(360 - self.0)
}
}
}
}

And for our sines and cosines:

impl Angle {
pub fn sin(&self) -> isize {
match self.0 {
0 => 0,
15 => -1,
30 => -1,
45 => -1,
60 => -2,
75 => -3,
90 => -1,
105 => -3,
120 => -2,
135 => -1,
150 => -1,
165 => -1,
180 => -1,
195 => 1,
210 => 1,
225 => 1,
240 => 2,
255 => 3,
270 => 1,
285 => 3,
300 => 2,
315 => 1,
330 => 1,
345 => 1,
// The number self.0 is guaranteed to always be a valid degree
_ => unreachable!()
}
}

pub fn cos(&self) -> isize {
match self.0 {
0 => 1,
15 => 3,
30 => 2,
45 => 1,
60 => 1,
75 => 1,
90 => 0,
105 => -1,
120 => -1,
135 => -1,
150 => -2,
165 => -3,
180 => 0,
195 => -3,
210 => -2,
225 => -1,
240 => -1,
255 => -1,
270 => 0,
285 => 1,
300 => 1,
315 => 1,
330 => 2,
345 => 3,
// The number self.0 is guaranteed to always be a valid degree
_ => unreachable!()
}
}
}

In main.rs:

// ...Others

mod machine;
mod alloc;
mod display;
mod event_hook;
mod game;
mod sync;
mod math; // NEW

Take Away

  • Direction is the invisible line along with the ball will move.
  • Consider the definitions of trig functions in a unit circle; if the direction line is the 1-unit radius in that unit circle, then the represented angle is the unique identifier of the direction.
  • Changing direction is by simple addition and subtraction of the direction's angle representation modulo 360.
  • sinθ is the amount by which the y coordinate should be changed to move in direction θ.
  • cosθ is the amount by which the x coordinate should be changed to move in direction θ.
  • If the ball is at point (y, x) and has a direction of θ, then the next point to move to will be (y+sinθ,x+cosθ).
  • Direction definitions and motions translations:

Directions With Motion Description

  • Direction change after collisions:

For collisions on the vertical side of objects:

Direction Change After Vertical Collisions

For collisions on the horizontal side of objects: Direction Change After Horizontal Collisions

In The Next Post

We'll be using the system described here to implement the ball's motion and interaction.

References