Placeholder Image

Subtitles section Play video

  • Hello.

  • In this video, we're going to be programming balls.

  • Yes, Let's get all the giggling out the way.

  • Now I'll show you what I mean when I say balls, I really mean the two day equivalent circles on in this video.

  • We're going to be looking at building a collision on the response engine for circle Circle interactions.

  • So, for example, and in here, you can see I've got some circles in the console.

  • I can't pick up a circle, and I could move it around and we can see that it interacts and collides with the other circles in the field.

  • Red lines indicate that two circles Aaron Collision and we can see quite happily that circles can push circles in larger chains.

  • In addition to just the static responses we see here.

  • We're also going to add dynamic responses, so by giving the circle some rudimentary physics, we can get them to interact with accurate collisions.

  • Well, I say accurate.

  • I really mean approximate collisions on We also consider this road be a complete physics engine because we're not going to be considering the rotation or angular velocity off the circular objects.

  • In this simulation, the larger the circle, the bigger its mass.

  • So if we take a small circle, say this one, for example, on a meat it a large one at the bottom, it bounces off with little effect on the largest circle.

  • However, if we do it the other way around, take the big circle on hit the little one.

  • There's a considerably bigger impact now.

  • We can impart lots of energy into the system and what should come to a nice, stable conclusion.

  • Now it's my intention to do several videos where we keep adding to this basic engine.

  • Because cynical versus circle collisions are useful in not just games.

  • With also simulations on, you'll be surprised where else it can be useful.

  • We might see some of that later on.

  • There's no getting away from it with these sort of things, we need to do some maths.

  • However, I hope to demonstrate that the maths isn't really that complicated, and in fact, to do this particular program, he's only a handful of lines of code.

  • As usual, we're going to use the one loan coded console game engine to do the visualization and user input, which is a class that we override to particular methods on the on user create, which loads the resources on the on news update, which is performed once every frame.

  • I've subclass the council game engine with a class called Circle Physics and created an instance of it, and I'm going to construct the console to be 160 characters wide by 120 characters tall, where each character is eight by eight pixels.

  • You may notice this looks a little different from the previous videos, because I've also tried to capture the error.

  • I've noticed that some of you, when you're trying to create consoles on displays which are too small for the size that you're requesting, you're getting around the cryptic error message.

  • This should help you out.

  • I should also say that over the Christmas break, I've made some small changes to the council game engine.

  • Nothing will stop it being backward compatible with all of the other videos.

  • I just added more features, and we'll see those over the coming videos.

  • I have touched on physics on quite a few videos already, particularly asteroids game.

  • The Flappy Birds game on to decode it yourself worms.

  • Siri's.

  • So I'm not going to go through all of the basics off Kinnah Matics again, However, most of our objects here are going to be a circle on a circle is represented by a point which will call P X on P Y.

  • Cycles also have a radius.

  • But I'm also going to add to my circle object the velocity vector V X on D V y.

  • And for completeness.

  • I'm also going to add an acceleration factor, a x and A y.

  • And as before, if we integrate the acceleration vector over time we get the velocity.

  • And if we integrate the velocity over time, we get the position.

  • So let's start by creating a structure that represents the circles.

  • I'm going to call it ball because I reckon most of my demonstrations will involve some sort of ball physics.

  • So allowed to the position vector the velocity vector onto the acceleration factor.

  • Also at the Radius, you notice amusing floating point for all of these.

  • I'm also going to go ahead and add an integer, which is the I D and we'll see why that's useful.

  • Later on, before we get stuck into all of the physics and collision code, let's just draw the ball to the screen.

  • All of the balls here are going to be represented with wife frame models because the council game engine provides the drawer wire frame functionality.

  • And if you remember, this is a vector off pers off floats, so that each per contains an X and Y coordinate, and it will link all of the coordinates together with straight lines.

  • So if we want something that represents a circle, we've got to build up a circle out of straight line segments.

  • We only need one model of a circle because well created as a unit circle on will scale it accordingly.

  • Depending on the Radius will create the resource in the on user, create function.

  • So I'm going to start by adding a single point to the center of the circle.

  • Each circle is going to consist of 20 segments, and I'm going to use our old friends co sign and sign to create the X and Y coordinates off the points that lie on the circumference of the circle around its middle point.

  • Of course, on, because model circle is a vector, I can simply just push back the new groups of coordinates.

  • Our ball simulation will contain many balls.

  • So I'm going to create a vector to stall them all in, And I'm also going to add a utility function to make it more convenient to add balls to this vector.

  • So here I specify the location on I set the velocity and acceleration vectors to zero so it's not going to move.

  • Were to set the idea of the ball based on the current size of the vector.

  • So as we add more balls to the vector, the idea increases, meaning each ball will get a unique I.

  • D.

  • I'm making an assumption that will never remove balls from the vector on.

  • Once the ball has been set up, we'll put it in the back of the vector.

  • So it's not some balls to the simulation for convenience.

  • I'm just gonna throw in a default radius variable in case we want to change this later on, and I'm going to add two balls based on the screen.

  • Positions will be in the middle of the screen, are vertically, but they'll be offsets to the left and right horizontally.

  • Drawing the balls is very simple as usual.

  • The first thing we'll probably want to do is clear the screen because we always want to start from a blank canvas and to draw the balls.

  • I'm going to create a little four loop that automatically ITA rates through all of the elements of the vector, and we're going to use the model off the circle that we've created.

  • Remember, that's a unit circle, so we're going to scale.

  • It will take the current balls position to offset the wife frame model.

  • And if you remember in the Worms game, the circle actually has a line going from the middle point to the edge of the circle.

  • On this week, we can use as an indication off the velocity or the direction that the ball is traveling in.

  • Of course, we don't want to move this line around manually.

  • What we want to do is rotate the entire wife very model on.

  • We can do that quite easily with the eight and two F function using the bowls, current velocity components in the Y axis on in the X axis.

  • Finally, we want to scale the bull points radius.

  • I'm going to draw it as white, solid pixels.

  • Let's take a look so that we have the screen with two balls.

  • They look a little small.

  • I'm going to make them bigger.

  • There we go, Bigger balls.

  • Stop giggling.

  • Let's start with a rather naive implementation off collision detection.

  • I We're going to test every object against every other object.

  • I'll create two little four loops, which automatically scroll through the vector off balls on the 1st 1 is going to represent the current ball.

  • The 2nd 1 is going to represent the target ball Now.

  • There's one thing to make sure, and that is that we don't test a ball against itself because it will always collide with itself.

  • And this might cause interesting results in the physics simulation.

  • So it's important that we filter out self collisions.

  • So I'm going to use that the ideas that we specified in order to test for this, And if the ideas are not the same, then we know that we're not testing a ball against itself.

  • So the first thing we should check is half the balls actually collided on.

  • The way to do this is to see if they overlap, and this is quite simple trigonometry because they have overlapped.

  • If the sum of the radius is of the two balls is less than the distance between their centers.

  • So we'll calculate this distance and use this radius on this radius.

  • And if we know that this condition is true, where a distance is less than the radius is some together, then there's an overlap.

  • The balls have collided, and in fact we could be really precise by also suggesting that we can tell when the balls are just touching, too.

  • I feel that knowing whether the two balls overlap is quite a useful utility tohave.

  • So I'm going to wrap it up in a little lamb to function.

  • Do circles overlap and the parameters were going to pass through to this lambda function Are the coordinates off?

  • One of the balls will call that X one on Why one?

  • We also need its radius too.

  • So I won't.

  • Then we need the other ball, which is X two.

  • Why two and now to you do, too.

  • Now, calculating the distance I could use.

  • Pythagoras sits there on I am going to, but I'm going to modify it slightly to remove the square root because the square root can be quite costly to compute and we'll be doing a lot of them.

  • So normally we would do it like this.

  • We would take the difference between the two X coordinates and square them added to the distance between the two.

  • Why coordinates and square them?

  • We would check that that distance is less than the two Radius is some together, as we've just seen in the slides.

  • But we can remove this square root if we also then square the radius summation together.

  • And instead of doing the square root, we look at the absolute value in this case using the family function, the floating point, absolute value, which removes the sign.

  • We'll check if the bulls are overlapping or touching.

  • Because if that's the case, then we want to respond to that collision.

  • So my lambda function is simply going to return a Boolean as to whether that condition is true.

  • Now we can add another clause to our collision detection.

  • We can check to see if the circles are in fact in conflict with each other, so we'll have the X coordinate off the ball we're currently operating up and its radius on the same for the target.

  • If this condition is true, then we've got a collision.

  • Even though I'm making attempt to optimize the code now, I don't consider it the most important priority.

  • And in fact some of the pros out there will notice.

  • Actually, there's a lot more scope for optimization in this program, but I want to keep it simple so people can follow along.

  • Now that we have determined that the balls have collided, what can we do about it?

  • Well, the first thing we must do is resolve the static collision on this is what makes the balls obey the laws of physics.

  • One ball cannot exist inside the other.

  • We have to resolve this on a sensible way to resolve this is to displace both the ball on the target away from each other by half the distance they overlap.

  • So in this case, we'd want to move the ball slightly this way on the target slightly this way.

  • And if we look at the distance at which they overlap, want to put a little marker in there?

  • That's called a day, then the length of this displacement is D over, too.

  • Now, you may also notice that I've not drawn these balls deliberately, actually aligned and that's to make us think about vectors from the gecko.

  • So this displacement has a direction.

  • It doesn't just go in the X or the Y axis.

  • It goes in both, and we can determine what that vector is simply by creating a line between the two centers off the objects.

  • Once we know this factor, we can normalize it and use this vector to determine the direction off the displacement.

  • So let's first work out the distance between the ball centers Now.

  • This time there's no getting around it.

  • This is straight up.

  • Pythagoras is there square root of the difference between the X's and Y's of both balls.

  • Calculating the overlap is the same as our lambda function before what we want to do something a little bit different this time so we can see it as it's the distance between the two points.

  • Subtracting both the radius is of each ball.

  • However, we only want half the overlap because that's how much we're going to displace each ball.

  • So I put a multiplied by half at the front to resolve the static collision.

  • We completely ignore all of the rules of physics.

  • We will physically move from one frame to the next.

  • The position of the balls.

  • They can never overlap assuming, of course, that the ball's not actually solid and not some sort of nebulous entity.

  • So we're going to alter the Bulls position directly and the current ball will naturally move away from the target ball.

  • So we're going to put a minus sign here and it's going to move away by the amount of overlap which is currently half the overlap.

  • And it's going to do that in the direction of the vector created between the two centers of the balls.

  • But we need to normalize this.

  • Such sensible.

  • We can just do that by dividing by the distance between them.

  • Spell it right though it follows that the Y is very similar to we just look at the white components of all of the objects involved.

  • But we must also displaced the target bowl as well and it's exactly the same formula, just a different object.

  • But the target ball will have to be displaced away from the collision, so we will add to it instead.

  • In order to test this, we're going to build in a facility that means we can interact with the balls on the screen.

  • I'm going to add a private variable to the class, which is a pointer to the currently selected ball.

  • Well, just initialize that, too.

  • No pointer to begin with.

  • Nothing is selected and I'm going to make it.

  • So if the user left clicks on a ball, they can basically pick it up and move it around.

  • So will respond to the left mouse button being pressed.

  • Which on my system, his element.

  • Zero of the mouse erect provided by the council game engine.

  • The first thing I'll do.

  • It's just set this to Noel Pointer because they may click somewhere that isn't a ball.

  • And in which case, we wanted to insulate any previously selected entity to determine if any of the balls have been selected.

  • We're going to have to scroll through them all and check their positions against the mouse cursor, as we did with the do circles Overlap Lambda function.

  • I'm going to create another little utility lambda function because it might come in handy.

  • It's a very similar one, but this time, instead of checking two circles overlapping, it checks whether a point exists within a circle.

  • It's much simpler this time.

  • So for each ball in the vector of balls, I'm going to make that test against the ball's position, its radius on the current mouse position in screen space.

  • If this function returns true, then I'm going to set the selected ball pointer to the address off that ball.

  • I'm also going to break then so we don't go and test unnecessarily or the balls we've already hit one.

  • It'll do because we're implementing a dragon drop like behavior.

  • We also need to consider what happens if they use that releases the mouse button, so we'll check the released flag.

  • And in this case, all we want to do is simply set to the peace elected ball points up, back to know again.

  • So nothing is selected Now.

  • I know it's no longer the fashion to use pointers anymore, or so I'm told.

  • But I quite like the fact that you get to functions for the price of one expert pointer.

  • Firstly, it points to something interesting, and secondly, if it's set to no points that we know that the point is no valid and I like the fact that we can leverage the validity of a point that's part of the program.

  • Now we've handled the mouse button being pressed on.

  • We've handled the mouse putting being released.

  • The dragging option requires that the mouse button is held down on by using the validity of the pointer to make sure everything's okay.

  • I you were checking.

  • If it's not in your pointer, we're just going to directly set to the PX and P Y values to the mouse coordinates.

  • Let's take a look.

  • So now I should be able to pick up a ball with the left mouse button, and if I push it into the other ball on the screen, we can see they don't overlap, and they do what they can to avoid overlapping.

  • Try it the other way around.

  • Let's add a few more balls.

  • I'm just going to comment these out because they might come in useful later on.

  • When we're looking at the dynamic resolutions, let's not 10 bowls to the screen in random locations.

  • What we can see is the balls can interact with multiple static collisions at the same time we cost of them altogether.

  • We can create chains of balls that push each other a bit like a Newton's cradle.

  • We haven't even considered physics yet, and I can already see many uses for this.

  • The first thing that comes to my mind is in the game commanded, Conquer.

  • Let's see, you've got a whole selection of units and you're trying to get in tow.

  • Walk through a narrow opening.

  • Well, now they don't overlap.

  • A little tussle with each other to form an orderly queue until they're all on the other side.

  • We're almost ready to start handling the physics, but we only want to do physics for balls that have collided.

  • So we're going to record pers off colliding balls that will deal with for the dynamic collision later on.

  • I'm just going to keep the vector of purse off pointers to the two balls.

  • And so if two balls have overlapped, therefore they have collided.

  • I'm just going to add to the addresses of those balls to this vector, and this means once we've worked out where all the collisions have occurred, we can then deal with them with a reasonably accurate approximation to physics.

  • By having a factor that contains just the colliding objects, we can use a full loop toe automatically school through these colliding pears and update them with approximations to physics.

  • Accordingly.

  • We'll come back to that in a minute, But first I'd like to draw which balls are in contact with each other and because we have a vector of collisions, This is very simple to we just scroll through the vector on.

  • We draw a line from the center off one of the colliding pairs to the center of the other, and I'm going to draw it as a red line.

  • I don't need to empty the specter because when this function returns, the vector goes out of scope and it will be destroyed.

  • Let's take a look.

  • So if I pick up a ball and force it into collision with something else, we can see there is a collision line indicator.