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.

  • This is quite nice because we can see in certain situations.

  • There are trees of collisions that need to be resolved before we can emulate the physical response to a collision.

  • We actually need to give the balls some physics now, so we need to update their velocities and positions accordingly.

  • I'm going to do this just by scrolling through them again in an auto four loop, and this is code we've seen time and time before.

  • In previous videos, I'm going to add in the ability for the balls to rotate around the screen, so if they go off one side, they reappear on the other.

  • It's a crude approximation.

  • Unlike asteroids, the ball will simply disappear.

  • We're not going to wrap the drawing routines as well on because we're dealing with floating point numbers.

  • And at some point I would like the balls to actually stop moving.

  • If the velocity approaches.

  • Zero, I'm actually going to hard code that in.

  • So if the overall scale is speed off, the velocity vector is less than no point, not one.

  • I'm going to clamp it to zero in much the same way as with the static collisions we needed to pick up the ball and pushes into others to test the dynamic collisions we need to give the bolts and velocity.

  • So I'm going to use the right mouse button to provide a cue, like on a pool table, to hit the ball in a particular direction at a certain speed.

  • I'm going to use the right mouse button to do this on.

  • I can use the same code I've already got here because I only want to manipulate the ball that I've currently clicked.

  • So I'm just going to add this in using an all and on my system mouse one is the right click.

  • If I'm clicking and dragging with the right mouse button, I don't want to move the ball.

  • So I'm not interested in an equivalent health state.

  • But I am interested in the release state because at this point, that's where I want to apply the velocity to the ball.

  • And so here.

  • If I release the right mouse button, I make sure that the ball is indeed selected and I set its velocity vectors directly.

  • And in this case, all I'm doing is creating a vector from the mouse coordinate on the screen to the center of the ball, a multiplying it by five.

  • This five is really just an empirical guesstimate, just to give the user chance of understanding how much velocity they're applying to the ball.

  • I'm going to draw in, well, a pool cue or a snooker cue, which is just going to be a line from the selected balls.

  • Current center position to the mouse corners on where to draw that in blue pixels.

  • So let's take a look.

  • So as before, I can pick up the ball with the left mouse button.

  • But now, if I hold down the right mouse button, we can see a line gets drawn from the cursor to the center of the object that I've selected.

  • And if I release the right mouse button, the ball moves of the lusty and it moves in a rather interesting way because we've not got any form of dynamic collision response.

  • But what we can see is the static response is still working quite nicely.

  • Let's set another one ofus.

  • Well, there we go now.

  • In this system, there's no friction.

  • The ball will just keep going forever and ever, and ever and ever.

  • It is really nice.

  • But not having any drag will make it quite complicated to understand what's going on.

  • So I'm going to add in some drag by setting the acceleration component of the ball to be a proportion off the velocity in the opposite direction.

  • So now if I selectable we can see over time, it slows down.

  • Just give it a little bit of a velocity and it should come to a nice stop on.

  • We've kept the velocity to actually clamp to zero, and you can see when that happens because they've lost the vector become zero.

  • The Aten to function, which were using to rotate the wire frame model, will just default to zero degrees.

  • We know that because the line is horizontally concede right now, they've lost the vector changes the rotation of the wife frame model.

  • We're now in a position to work out dynamic collisions.

  • This is where the fun starts.

  • Handling the dynamic resolution is a little bit more tricky, so let's just have a look at what comes into play during this collision.

  • Firstly, let's assume that this ball on the left is moving with a velocity in that direction.

  • On this ball on the right is moving with a velocity in this direction.

  • We know that the balls don't overlap on.

  • We can determine to useful characteristics.

  • Firstly, if we draw a line between the two center points and find the normal to that line a a line 90 degrees to it, try and draw it a straight as I can here.

  • Actually, it's 90 degrees this town, gentle line that we've just done because it's a tangent to the circumference of the circle effectively represents a solid object for a ball to bounce off.

  • I'll just label that one ton gentle on the line, normal to the tangent under simply going to retain the name normal Now in a perfect world, and assuming that the target ball was addressed, it had no initial velocity.

  • When this collision occurs, we would expect the target ball to travel along the normal factor, and we would expect the original ball to travel along the ton gentle vector.

  • I will always be 90 degrees between the two balls as they disappear along their trajectories.

  • I think this is true for all cases, except for when the original ball is also traveling along that vector.

  • I either balls collide absolutely bob on dead center.

  • So from this we can assume that we do have something called a ton gentle response.

  • I'll just put this velocity vector back in.

  • The problem is, we live in the real world.

  • Andare objects have mass and therefore they have momentum on the lower about.

  • Conservation of momentum suggests that the momentum of this whole system before the collision should be the same as the momentum after the collision or what's nice in R two d Circle Scenario is, we really only have to consider momentum in one dimension, and we can use the momentum equations to influence a normal response.

  • And so each ball will be affected along the normal unturned.

  • Gentle vectors.

  • So let's call this in.

  • The first thing I'm going to need is the distance between the two balls and was news accurately.

  • Now I could have stored this in the vector of collisions before when I've already calculated it, but I didn't.

  • I'm re calculating it here from this.

  • Of course, we can develop a normal vector simply by drawing a line between the two center points on.

  • We're going to normalize it with the distance.

  • Calculating the town gentle vector is very simple.

  • It's just the normal vector, except we flipped the Y axis and the X axis and make one of them inverted.

  • Now the town gentle response could be very simply described as the dot product between the balls, velocity vector and the town gentle vector.

  • I how much of the velocity in each direction is going to be transferred towards the tangent.

  • And then we can update both the ball and the target balls velocity.

  • In this case, we're just looking at the town.

  • Gentle response.

  • First, let's see what happens on.

  • Don't forget that the result of a dot product is a scale of values.

  • So we're taking that scale of value on dhe, multiplying it by the normalized dungeon vector.

  • Let's take a look.

  • So here are some balls and I will fire this one at that one, and we can see it deflected off it at 90 degrees is what we'd expect.

  • It's moving along the tangent, so the time gentle response seems okay.

  • Although it just doesn't seem very realistic, it doesn't seem to impart any energy into the target ball.

  • In fact, it treats the target ball as if it were a solid object.

  • So there's no consider the normal response to in exactly the same way we'll create the doc products.

  • So how much of our velocity vector gets attributed along the normal vector?

  • As always, Wikipedia is a great resource for all things games programming, and it does have a great article on elastic collisions, and it shows us here the equations that we will need to use in order to calculate the velocities after a collision.

  • Assuming the collision is elastic, of course.

  • Now this being the one loan coded channel, I would usually like to try and derive these equations from first principles, and so I did.

  • But I've decided not to include it in the video simply because it is quite a lot.

  • It's quite demanding.

  • There's a lot to do, so if you fancy the challenge, you can have a go at doing that.

  • Or you could just use the equations directly from Wikipedia.

  • But these equations included a new variable that we've not accounted for mass.

  • So let's not that into our bowl structure just going to be a floating point value.

  • And I'm also going to update our at bull function to set the mass, and I'm going to set the Mass based upon the radius.

  • I'm going to multiply it by 10.

  • Therefore, the bigger the ball.

  • We can assume it's heavier, although strictly speaking, this is a rubbish way to do this because the density of the ball would have to change.

  • For this to be true, you'll notice that our duck product, normal values are used in this equation on these equations yield to more scale of values, which we can use to scale our normal response.

  • And so the final balls velocity vector is simply the sum of the two responses.

  • So here we can see the town.

  • Gentle response simply summed with the normal response.

  • Let's take a look.

  • So it's had a velocity to a ball and it behaved like a Newton's cradle.

  • In that case, let's try a bit of a more angle.

  • Deflected shot.

  • Very nice.

  • His collisions look and feel legitimate.

  • Let's now quickly modify our own user.

  • Create function to add balls with random radius is and also random masses.

  • Two big ones.

  • That's good.

  • So let's tie this little tiny one against this big one.

  • Here, you see, it deflected right back and bounce and barely moved the big one.

  • That's how I would expect it to behave very nice.

  • Now, in the interest of full disclosure, I will say that this approach seems a little bit laborious and in fact, if we go back to the same Wikipedia article, it gives us two functions that calculate exactly the velocity vectors we need for the scenario that we've got.

  • So this is the interaction off two circles, but you'll see the maths is much simpler.

  • Well, simple can be deceptive on really.

  • What it boils down to is that the Wikipedia version is a cleverly deduced version of the same maths where they looked at all of the redundancies and got rid of them on they've broken it down into just its purest, most simple form.

  • I'm going to include this in the source files, but will be available on the get hope.

  • But there is no functional difference between the two today.

  • Having a very simple circle versus circle collision on dynamic response system.

  • This video is just the staff of the largest Siris on collision detection systems on.

  • We'll see in the next part of this series how implement a pool game.

  • Now.

  • This has been the first video of 2018 and I'm going to do things a little differently this year.

  • Firstly, I'm not going to be producing a video every single week.

  • I'm going to win for every two weeks, and I might do smaller little user update videos and featurettes in between.

  • I would also like to get a few more live streams don't.

  • Regardless, all of the code for this video is available on Gato.

  • You can chat with me and lots of other programs on the discourse service.

  • You can follow me on Twitter.

  • It's at Jeffrey next.

  • Nine.

  • If you've enjoyed this video a big thumbs up, please have a think about subscribing and I'll see you next time.

  • Take it.

Hello.

Subtitles and vocabulary

Click the word to look it up Click the word to find further inforamtion about it