Placeholder Image

字幕表 動画を再生する

  • hello and welcome to part one of a larger project.

  • Let's make words.

  • I'm sure most of you are familiar with worms.

  • It's a side scrolling game where you have teams of worms that battle each other with trajectory based weaponry.

  • The landscaping worms is randomly generated each time, and we can see we've got here the green landscape versus the blue sky or non landscape.

  • And I can press the M key to randomly generate to reigns as necessary using the pearly noise function.

  • And this this is a multi part video.

  • We won't be looking at the entirety of worms in this intro demonstration.

  • Instead, I'm going to show you what we're going to achieve today, which is the addition of units which you can see have collision detection and response with the terrain will also add arbitrary explosions so I can click somewhere and it causes an explosion on also damages the terrain with with a crater onder.

  • If you cause an explosion near a unit, it blasts them around screen.

  • Very nice.

  • On the final part will be adding is sequences an event.

  • So here we're creating a weapon object, which one collides, sort of combines all three things together.

  • Now, even though I'm splitting this project across several videos, there's still quite a lot to get through, so I'm going to be going through a slightly quicker pace than normal.

  • After all, a lot of the techniques we see in this video are based upon techniques I've already talked about in previous videos.

  • So it's all coming together to form one nice project at the end of the year.

  • And, of course, I'm going to be using the one lone Koda council game engine.

  • And I've already taken the liberty of just deriving a quick base class from this.

  • It does nothing other than implement the unused created on user update functions.

  • And in my in Maine, I'm constructing a console, which is 256 characters wide by 160 characters tall, and each character is going to be six by six pixels.

  • Just a quick introduction to, say, a big thank you to all the people that have joined the Discord server.

  • There's almost 100 loan code is out there now, and if you're interested in joining in and getting involved in the chapters, quite a lot of talent on that chat server.

  • Then I suggest you look at the leaks below for an invite to the discord.

  • Now I may be boring, but it is very important that with any big project you form a plan before starting on worms is no different.

  • I know that I've got randomly generated terrain sze on these around them we generated to the pixel level.

  • And given that worms is a game about accuracy, I think it's important that we have pixel level collisions.

  • So that's the first requirement.

  • Worms is again all about trajectories, so assuming you've got a little unit here and he can fire his weapon across the terrain, the terrain gets altered and then causes multiple more trajectories for debris and possibly all the units.

  • But when debris lands on the surface, it doesn't just immediately come to a stop.

  • It carries on bouncing a little bit, so we know we're going to need a very simple physics engine.

  • Well, both of these are hard.

  • Let's do what we can to simplify them, yet keep them working in a way which is suitable for game play.

  • And the first approximation I'm going to make is that even though sprites are traditionally rectangular.

  • I'm going to assume that all objects in my physics engine are circular, and so I've got a unit object, a debris object.

  • And even though we didn't see it, I've got a missile object.

  • Now, in a lot of games, when you want to do collisions with maps, you do things like make assumptions that the map is in fact created out of straight lines.

  • And so then, doing circular with straight line collisions is quite simple or circular, with polygon collisions is quite a simple thing to do.

  • But that's not how the original worms works it all.

  • And we want to try and retain the look and feel off that game, so we will have to do a per pixel collision detection routine for a circle.

  • And although we won't do it in this video circle circle collisions are actually quite easy to do.

  • On may be useful, for example, if we want units to knock all the units.

  • As you can see, there's quite a lot to do.

  • But I'm going to let object oriented programming and pull him officer, help us out.

  • Everything that can move in my game is going to be derived from a class which represents a physics object on this class will be abstract, but it'll contain useful information such as position, velocity, acceleration and a flag that represents whether it is moving or not a stability flag.

  • I'm also going to define a pure virtual method, which makes this object abstract draw, which will be used by sub classes to draw themselves on the screen, the missile and debris sub classes.

  • We're going to be represented by wire frame objects using the code that we made for the code it yourself asteroids video.

  • This is because I want the missile and debris to rotate to represent the angle is traveling in the third subclass unit or worm is going to be represented by a sprite.

  • I don't need these to rotate, and so each subclass will implement its own version of the drawer function, using the correct technique required.

  • This is a simple yet powerful use of polymorphism because I don't need to maintain any object management code.

  • In fact, all I'm going to do is have a list of the objects which I can.

  • Then it's direct through, calling the drawer routines and updating the physics.

  • But let's start at the beginning.

  • Let's create control the terrain as the terrain needs to be accurate.

  • Id a per pixel level.

  • I'm just simply going to create a map on this map is just a two dimensional array, in this case, 1024 by 512 pixels off unsigned charts.

  • At the moment, the map is just going to be filled with zeros and ones.

  • It's going to be one wherever there is land and zero wherever there isn't land.

  • You might think I could use use billions for this.

  • However, later on, I might want to add two different types of land or different colors to give it some texture.

  • And so, in the unused create function, I'm just going to allocate the memory for that two dimensional right and then use the members set command to clear it all to zero.

  • Why not?

  • I'm going to separate out the map generation to a create map function because I still want the ability to scroll through maps and interrogate them and find ones that I like.

  • Now.

  • I also know that my maps are going to require Perlin noise, so I'm just going to cook and paste absolutely character for character from the pearly noise video, The pearly noise one D function.

  • It's just a reminder takes account off the number of elements in the array a cedar, a full of noise.

  • The number of octaves were interested in generating on the bias, which was how do the octaves relate to each other?

  • And of course, we haven't output variable, too.

  • I'm not going to go into what pearly noises please click on the link above to find out.

  • But to use the pearly noise function, we need to prepare some data we need.

  • A one dimensional array, which represents the surface that is generated on this array, will be filled with heights.

  • We also need a second rate, which is going to be filled without noise values.

  • I'm just going to use the brand function to generate some noise going toe hack the pearly noise just a little bit by setting the first value to 0.5 because my pearly noise operates between zero and one.

  • This means that my first element will be halfway up.

  • It also means that the last element in the array will be halfway up because the pearl annoyed samples of it fixed interval.

  • This means that my terrain will both start and end halfway off the screen, and this just adds a little bit of consistency to the Syrian generation.

  • Otherwise, we could have two range, which stop at the very top of the screen and offer no place for the place to fight.

  • Or they could operate at the very bottom of the screen and actually have little tiny islands and bubbles with no land for the worm's toe walk.

  • Now we can call the pearly noise one D function.

  • Now.

  • Don't forget that the F surface variable is one dimensional, but I've got a two dimensional bit map representing the terrain.

  • So instead, what I need to do now is scroll through all of the elements in my map and compare them to the heights in the surface array.

  • Now all of my raise assume that top left is 00 And given that land is usually below the sky, I'm therefore checking that if the current pixel in the map is greater than the corresponding pixel in the surface map, set it to land or else leave.

  • It's a sky, and that's all that's required.

  • I'm just gonna tidy up those to dynamically allocated a raise.

  • Just so there's something there at the start I'm going to call the crate might function after I've created the map array in my own user.

  • Create function theon user update function for this project is going to get quite complicated, and occasionally we're going to have to throw in code just for debugging and checking on.

  • They sit in one of those cases.

  • I'm going to make it that whenever the user releases the M key, it's going to call the create map function again so I can create new maps whenever I want.

  • Drawing the landscape Terrain is quite simple.

  • I just iterated through all of the pixels on the screen, given by a screen with and screen height.

  • Find the location in the map and choose whether the droids are sky or ass terrain.

  • But we're missing one important thing here.

  • The size of my terrain Map 1024 by 512 is much larger than the size of my counsel, so I can't fit the whole map on my console display.

  • I'm gonna have to create a camera and some camera control code to choose which part of the map we display on screen.

  • I'm going to our two more variables camera position, X and camera position.

  • Why they're going to be floating point.

  • I'd like to build to control the camera by moving the mouse cursor to the edge of the console.

  • And when I do the map scrolls in that particular direction at this particular speed on for this project, you'll see me using lots of hard coded numbers, which I've already decided that the best value after all, it would be quite a frustrating and boring video.

  • What should be randomly trying numbers to see if it works by using the consul variables for mouse?

  • I can check.

  • Is the mouse within say, for example, on the left hand side, five pixels in from the edge.

  • And if it is, I want to update my cameras exposition using F elapsed time to make it smooth.

  • In fact, I'm going to do this for all four edges of the council.

  • But this leads to a rather dangerous situation that the camera could exist outside of the map space, which means we'd be drawing random elements of memory and all sorts of chaos would ensue.

  • So I'm going to maintain control over the camera by clamping its to the edges off the map.

  • So now when we draw a map in the draw landscape routine, I'm going to offset it by our camera positions, going to convert them to interview, Of course.

  • And we're using the now very established technique off.

  • Why multiplied by with plus X toe work out where we are in the two D array?

  • I think we're ready to take a look now.

  • So the council was started open.

  • We're in the sky, so if I move the cursor down, yep, that's good.

  • It's girls down the screen and up the screen on across the screen, in both directions, and we can find all the way to the edge when we see it stops automatically.

  • So we're not going to be looking at parts of the terrain, which we shouldn't be able to see.

  • Very nice.

  • If I pressed the M key, I'm not moving the mouse, but I'm generating different terrain teach time.

  • What we should notice, though, is that the terrain all start from the same point, and they do, and that's because we fix the first value to 0.5.

  • Of course, I could fix it to, say 0.25 and it would be higher.

  • Opal, lower down.

  • We've now created a two dimensional pixel level map that represents that serene, in fact, represents a very large terrain, and we could make it larger by playing with numbers.

  • And you can look at the pearly noise video that I've done earlier this year to look at the premises for generating pearly noise to generate different types of terrain.

  • I know that in original words, the terrain could have overhangs and floating islands in the sky and gaps, and these are all achievable, too.

  • But they probably did start with an element of pearly noise somewhere.

  • But to keep this video movie, I'm not going to do that.

  • We're just going to have a single terrain, right?

  • Let's get stuck into the fun stuff now and create our physics engine going to start by defining a base class called C physics object, And I'm gonna have some directly accessible properties just to annoy people that represent the position, the velocity on the acceleration they're all going to be in floating point.

  • In fact, the whole physics engine is going to be a floating point physics engine.

  • I'm also going to add a default constructor, which allows us to set the position.

  • There were two other variables.

  • We're interested in a radius, which represents the collision boundary of the object on the flag that represents whether the object is stable.

  • Stability is quite an important thing to know in a physics engine.

  • Firstly, if an object is stable, we don't need to perform or computation on it.

  • If it's not moving, we don't need to do collision checks, for example.

  • But in our game, it's also quite important to let's say, the worm has just been blown around on the terrain and he's finished bouncing around.

  • How do we know when to pass control on?

  • So the next word in the plan we said that see physics subject was going to be abstract because it defines a virtually pure draw method.

  • This draw method takes some parameters, the first being a pointer to the console game engine.

  • And this is quite important because my physics object sits outside of any of my console game engine stuff.

  • Yet I do want to exploit some of the drawing routines, such as drawing wire frame models and sprites.

  • So this is a way of getting the instance of the game engine into the object code.

  • I've also got two other arguments offset X and offset.

  • Why, As you can probably guess, these are going to be related to the camera on not the objects position in the world space.

  • To help debugged the physics engine, I'm going to create a dummy object which inherits from the sea physics objects.

  • In fact, I'm going to call it see dummy only to create a constructive for my dummy objects.

  • I was just passes through the X and Y position in world space because my based classes abstract.

  • I need to implement the draw method somewhere.

  • Now I'm going to add something which I'm sure is going to cause me no end of bother in the YouTube comments and on the discord server, I'm going to have a private static variable to a vector of pers of floats.

  • Now, this vector of pers afloat is exactly the same data time we used in the code it yourself asteroid video.

  • In fact, this is how we're going to start a wire frame model on.

  • I'm making it static because I might create 100 of these dummy objects.

  • But I don't want to re keep re creating and allocating resources to store the same model for each object.

  • So I want one model to be shared across all objects of the same class, and it's going to get a little more complicated because I need to initialize this variable, and I'm going to use a factory function to do it.

  • So when the program comes around to defining exactly what Back model is for the sea dummy class, it cost the define dummy function on the define dummy function produces a list of points in a circle.

  • In fact, it's a unit circle because we know the drawer wife framed functions will scale for us.

  • But this approach is nice because I only need to do this once, regardless of how many dummy objects are going to be floating around in my world.

  • And so to draw the object, I'm just going to call the drawer wire frame model, which is part of the one lone Koda Council game engine class, and that's why we've passed it in is a pointer, and so the perimeters are draw the model data, which we've already created its part of that static variable the X and y locations, which, of course, the local X and Y in world space of the object.

  • But offset by the camera, which we've also passed into this function, I also need to choose the angle at which we rotate the object because it's wife frame on.

  • To do this, I can use the Aten to a function off the velocity components, and I also want to scale the object size on.

  • I'm going to use the Radius variable to do this so that we can see the bounding radius for this object.

  • And finally, I'm going to use white characters to draw.

  • And for the one loan coded channel, this is some pretty advanced c++ stuff going on here.

  • Let's now start adding the objects into the game, and so I'm going to create a list of sea physics object pointers, and this is the reason that they're points is if they're not pointers on because the sea physics object is abstract, I'll get to compile time Era can highlight down here.

  • See physics object cannot.

  • In Stan, she ate abstract class.

  • And this is what allows us to have things to this list, which aren't necessarily directly see physics objects there some classes off so we can add worms and units.

  • Debris on dummy objects to this list on the wall get treated in the same way.

  • But there is a little caveat to this, which will see later.

  • I want to see if our drawing routine works on generally does our object hierarchy work?

  • So I'm going to make it that whenever the user presses the middle mouse button, which is to in my setup, I'm going to add a dummy object to the list.

  • So I've allocated memory for the new dummy object on I've set.

  • It's starting to position to be wherever the mouse has been clicked, but don't forget to include were offset into the world on the mouse.

  • Position is relative to the console position, and now we get to exploit the power of polymorphism because after we've drawn the landscape, we want to draw all the objects, and this is very simple indeed.

  • In fact, it's just this we just scroll through the list on we call its drawer routines.

  • And this is really nice because it doesn't really matter what object it is.

  • It'll just sort itself out.

  • Let's take a look, move it down so we can find some terrain.

  • And if I click on the screen with the middle mouse button, I can place an object and its crudely circular What you'll see it.

  • I've actually also added a line from the middle of the circle to the Radius, and this was defined as part of the object in that static definition on, we can use this line to say what angle of rotation has been applied to the wire fame object.

  • In this case, we haven't even looked a velocity yet, so they're all pointing in the same direction, which is just some default startup direction.

  • And of course, we've got no collision so I can put these things all over the screen.

  • If I move the camera, they move relative to the terrain.

  • We can use a similar it's oration to update all of the physics.

  • And in the asteroids and the flappy bird video, we can look at how we do the physics very simply for two D objects.

  • The first thing we might want to do is apply any additional forces to the acceleration on the velocity is just the integration of acceleration with respect to effort.

  • Lapse time on the position is just the integration of velocity with respect to every elapsed time.

  • You'll notice, however, I'm not doing it directly to the position members off the object.

  • Instead, I'm calculating a potential X and Y.

  • That's because we want to test for a collision.

  • And if a collision has occurred, I don't want it to move to that location because it means the object will be within the object it is collided with.

  • So we're just going to see if things carried on as they were.

  • Where is it going to be?

  • Once I've applied the forces, I'm going to reset the accelerations to zero, and I'm going to set the stability flag to False because the object is clearly not stable.

  • It's in a state of flux.

  • It's moved.

  • But since we're not doing collision detection just yet, let's update the objects position with its potential X and Y coordinates.

  • Let's take a look.

  • I'm gonna find the terrain to place an object that we can see It's pointing down and it's falling down, but it's accelerating as it's falling down due to the effects of gravity.

  • But a whole bunch of objects in and they all behave independently.

  • Very nice, although a bit slow physics engines and graphics engines really coexist at the same speed on proper physics.

  • Engine is not like this one really don't like having changes in time Step Now I know that with the one loco to counsel game engine, drawing to the screen is actually the slowest part and that the physics at this level of work out later.

  • But anyway, we'll really take up no CPS a tall.

  • So for every frame of graphics update, I'm going to do 10 frames off Physics of Death, which is simply a case of wrapping up the update physics loop in a second loop.

  • And so if I run it now, fund that's rain against cool it down.

  • You see the objects fall of a slightly faster pace because there's 10 times more updates happening.

  • Let's consider how we're going to handle the collision detection.

  • The first thing we need to know is, has a collision actually happened on because we represent all of our objects as circles.

  • It doesn't really matter what the object looks like.

  • We can use the same technique to see if it's interacting with the terrain.

  • I think the first optimization we can make it.

  • We don't need to check all of the points that lie on the circle.

  • We only need to check those that lie within a semi circle, rotated to the direction that the object is moving.

  • So this red arrow represents the velocity vector.

  • If we take 90 degree points, we only need to check along this part off the circle.

  • These points we don't care about because they can't possibly be colliding with anything.

  • The number of points along the circle's edge needs to be sufficient that at least one point is residing in one pixel of world space.

  • Now my simple demonstration.

  • I know that I could just simply choose a theater value sufficiently small enough that it will be because none of my radius is a very large, but a sensible approach would be to choose a theater value based on based on the radius.

  • That ensures that the pixel difference between the two points is always less than one.

  • We need to do this because it's goingto happen, What we've got one pixel floating around in space and that one pixel shouldn't be ignored, so it's not sufficient.

  • For example, we're inputting these big green crosses to just have a handful of detection points, because it's very easy for a pixel to fit in between the gaps.

  • However, I'm doing nothing more clever than just choosing a small theater value.

  • Once the object has been moved, we've calculated its potential new location.

  • We can then compare the red dots along with the conference with world map to see if collisions have occurred and we can see yes is a collision here, here, here, here, here and here.

  • If we create vectors to these positive collision points and some of them all and invert them, we end up with a response factor.

  • And this factor approximates the direction that the object needs to move to escape being in collision.

  • But it also has one bonus feature.

  • It also approximate ce the surface of pixels that have been collided with.

  • In fact, we can assume that the response factor is indeed normal to the tangent of the terrain surface.

  • At this point, of collision.

  • And so once we have discovered the normal to the collision point on, we know the trajectory of the object coming in.

  • We can calculate a reflection very simply, which is just incident on reflection.

  • Mathematics.

  • We'll see that in a bit.

  • Let's add in collision detection, and this is just collision with the map.

  • Not collision between objects on the first item I'm going to need is the actual angle in radiance derived from the velocity vector, as we saw for the rotation of the wire fame objects before, I'm also going to create an X and Y component off my response factor.

  • Once I know this angle, I'm in too great a four loop, which its rates from one side of the semi circle to the other at in this case affect step size but has just been describing.

  • You could probably do something more clever here to ensure that all of your points are within a unit distance from each other.

  • Using sign and co sign, I can take the radius of the current object, plus the angle of the point being tested on the potential new location toe workout wearing the world map.

  • I'm testing for a collision.

  • I'm going to call this test Prozacs and test pas y.

  • So these points other points that lie along with semi circle that's been rotated to the direction the object is moving.

  • I'm going to be reading from memory, so I want to make sure I've got control over these points.

  • I'm going to clamp them to the size of the map, and it's just simply a case of reading that location from the two D map array.

  • And I'm going to assume that anything that isn't zero so anything that's not sky is to rain.

  • So it's a positive collision, and so are some that point into my response factor.

  • I'm going to just create an additional variable called Collision.

  • I'm going to set that true here when a collision has occurred simply because I don't need to do anything further if a collision hasn't occurred.

  • So if a collision has occurred, I want to respond to it else.

  • I'm going to allow it to use the new potential positions.

  • Now we know the physics engines.

  • Collision resolution is a really fundamental part on it has to be very accurate, and I'm not striving for accuracy here.

  • It's a game of worms.

  • After all.

  • I know that in my physics engine, objects are gonna be stacking on top of each other and resting on each other and continuously interacting with each other.

  • So I just want to emulate the effect.

  • I'll break the rules of physics a little bit to make things simpler for me.

  • For example, when a collision occurs, I'm going to set my object to stable, and I don't allow it to update its position.

  • This means it will be the case that the object technically has collided with thinner.

  • Only its potential location for collision actually results in a collision.

  • But I don't want the objects to overlap with the terrain.

  • I'm going to use my response factor as the normal to the tangent off the terrain and use this in a reflection calculation so I can get a reasonably accurate bounce of the object.

  • The first thing I'm going to do for convenience is calculate the magnitude off my velocity and response.

  • Fact is, I'm gonna be using these several times.

  • The mathematics behind a reflection vector is quite well known.

  • Just find it on the Internet.

  • It's actually quite a simple equation.

  • I'm just going to use the code directly, so the first thing I'm going to do is create the DOT product between my objects Velocity vector on the response factor.

  • But the response factor has been normalized on I calculate my objects New Velocity Vector, which is the reflection vector based on the reflection equation.

  • Let's take a look.

  • Find a bit of terrain on dropping objects on it, and it bounces and bounces and bounces, and it keeps bouncing under its offer.

  • Ghosts on its way Very nice.

  • Who hits hits?

  • An alternative agent.

  • Now it's bouncing all the way back.

  • Very nice.

  • In fact, that's had a whole bunch.

  • Let's get them going all over the place.

  • You can see some are just bouncing directly open down.

  • And that's because there's not enough information in the area that they're hitting toe.

  • Actually give them any curvature.

  • It's just unlucky that they're finding the flats here, and this is exactly what I'm saying.

  • This is just an approximation to a physics engine.

  • It's good enough for a game of worms, but it would be quite an exciting game of worms because nothing is ever settling.

  • I'm going to add another variable to our physics object, which emulates energy loss or friction.

  • In this case on.

  • All I'm doing is taking the reflection vector and multiplying it by this coefficient.

  • So it'll be a value between zero and one.

  • Let's throw that in.

  • We'll set it to no 10.8 to begin with.

  • Justus, a default value Know when an object collides, it loses some of its energy.

  • Potentially, you see, it comes to rest.

  • The bounces answers Hi each time.

  • And also now that the objects are bouncing around, you can see that the wire mesh is being rotated to suit the velocity direction.

  • And it would seem in this video it depends on the frame rate of the YouTube video that two of these objects have become stable and two of them haven't.

  • And this is because of the Assam topic nature of how I'm updating the velocity vectors.

  • At some point, I just need to simply say, Look, there's not enough movement to actually counters movement, so I'm going to do that deliberately by looking at the magnitude off the objects for lost e vector and seeing if that's less than a small enough amount, and if it is, I'm forcing it to truth.

  • Now we've got a rudimentary physics engine.

  • Let's create some degree objects and some explosions.

  • The debris object is going to look very similar to the dummy object.

  • So I'm just basically cutting and pasting the same thing.

  • I have to find the class.

  • I've also created a static definition for the model, and in this case the model is just a square, a wire frame square.

  • And when the object draws its wire frame, it uses the dark green pixels to do it.

  • So in this way it's difference to the regular dummy object.

  • What I will add, though, is that when debris is created, its velocity vectors are assigned a random vector to make it shoot off in a random direction on.

  • We'll test this by using the mouse button two spawn debris, and this is where we see all of the effort that we put into the polymorphic objects hierarchy.

  • Payoff because all I need to do is add, say, 20 new debris objects to the list, and the position I'm going to give them is the mouse coordinates in screen space translated into world space.

  • I don't need to make any other alterations, but the objects will draw themselves, and the physics engine will look after them.

  • So let's find the terrain again.

  • Click the mouse.

  • You can see it spawns a whole bunch of objects, which just bounce around until the old one out of energy keep clicking and clicking and clicking loads of objects all being handled by the physics engine.

  • Okay, the frame rates taking a bit of a hit.

  • The nice thing is, they're all gathering in all in the pockets on the terrain.

  • But there's a problem here.

  • We can't just accumulate objects until the end of the game.

  • The debris needs to disappear after a while, and so what I'm going to do is limit the number of times it can bounce.

  • And once it hits this limit, it's going to flag itself for re raising.

  • I think limiting the number of bounces and object can do before it dies is quite fundamental.

  • For example, a missile Rome bounce it all but debris could bounce several times, have a grenade, may bounce, so I'm going to add some variables.

  • Bounce before death is the number of times the object can bounce before we set.

  • It's dead flag, too.

  • True on if this is set to a minus one, the object could just carry on bouncing.

  • We know that the object must be balancing if a collision has occurred, so we'll put our bounce detection in this.

  • If the object has a positive bounce before death, count them will decadent it one and set the flag if it's equal to zero.

  • But this leaves us with a bit of the memory problem.

  • Objects which are dead need to be a raised, and so we should remove objects which have the dead flag set when we're processing them during the physics update.

  • The nice thing about list is they have the removed if function, which takes a very small lambda function as a permitted on.

  • So it'll only remove the objects were the object contains a be dead flag, which is set to true.

  • However, this function doesn't delete the object.

  • It just removes it from the list on.

  • At this point, we've lost all control over a pointer.

  • We've actively created a memorably This is bad.

  • So what can we do about it?

  • I could create a system of alternate lists and loops and checks for validity on trying to rake through things and erasing myself.

  • Or I can use some c++ constructs to do the job for me and I will instead of just storing the point of directly in our list.

  • I'm going to use a smart point.

  • But I'm going to use a unique pointer which points to a physics object.

  • The nice thing about a unique pointer is that whenever it goes out of scope, it calls delete on the object that it's pointing to.

  • But we have to make a few changes to how we add things to the list.

  • We can no longer just push back directly.

  • The pointed to the object that we need.

  • We need to push back a unique pointer to the object on the same applies to a dummy pointer.

  • Well, just also modify the removing function in the list to accept a unique point to instead on the nice thing now is that a soon as the unique point it goes out of scope, it's deleted, so as soon as this is removed from the container as long as it has no owner, the delete function is called on our physics object, and this means we don't leak any memory.

  • We need to make one more change to our see debris object, which is at the number of bounces it can do before it dies.

  • I'm going to say it's five.

  • Let's take a look.

  • Let's find a part of the terrain will launch an explosion and we can see the objects disappear after they've bounced five times.

  • Let's create lots of explosions.

  • Lots of objects really hammer the frame rate, but eventually they all disappear and things go back to normal.

  • Explosion seemed to be one of the fun elements of this game, and I think we're going to need quite a lot of them, particularly when grenades explode.

  • So grenades, for example, in those explosions all over the map.

  • So I'm gonna create a function which handles just explosions.

  • I'm going to call it boom, and it takes a coordinate, which is X and Y in world space and has a radius, which is the area of effect of that explosion.

  • Do we know that one of the things are boom function is going to do?

  • It's spawned lots of debris, so it's just going to do what we did before on the mouse Click is going to iterated, threw up to a certain number, just adding debris objects to our list of objects to process.

  • I think probably the radius is is a good indication of how much debris we should create.

  • So for small explosions which have small radio, we generate few debris objects, whereas big explosions.

  • We generate lots, but I also want to affect the other objects that are nearby.

  • I want to knock them about a bit, so I'm going to have to reiterate through all of the other objects to see if they're near to where the explosion is happening.

  • This is a very simple calculation.

  • It's just Pythagoras theorem.

  • Take the explosion location, the object location on work out the distance between them, and if the distance is less than the explosions radius, then the object gets its velocity updated by the distance between the two objects.

  • So on object, which is very close to the explosion, gets a velocity boost larger than an object, which is slightly further away.

  • I'm also going to set the stable flag to false because you know it's just been exploded.

  • I will make one little security check here, which is to make sure we don't have a divide by zero.

  • Because then potentially, we're setting our objects velocity to infinity, and it will be blasted out of space and time.

  • And this may confuse the player.

  • So instead of launching the debris directly now, Ana Maris, click.

  • I'm just going to call the boom function.

  • I'm going to borrow the camera position.

  • Variables from before will say that's a little explosion as a radius off 10.

  • So let's take a look and see if it interferes with other objects.

  • Let's festival place some units.

  • Yeah, Andi, I'm clicking.

  • It's causing an explosion.

  • That's good.

  • And if I click in this cluster of objects, we can see they get knocked about.

  • And if I try and launch an explosion far away from the objects, he gets affected very little.

  • But if I launch it in the middle of the objects, he gets affected a great deal proportional to the size of the explosion.

  • But we can see we're not doing any damage to the terrain.

  • Given that our terrain map is simply a bit mapped image, I'm going to use the circle drawing routine to erase parts of it.

  • I am going to draw sky on top of the terrain in a filled in circle, and I'm going to use Bresnan Circle algorithm to do this.

  • I've just lifted this direct from Wikipedia.

  • They've even got it in see, but I have modified it slightly.

  • Instead of using put pixel to draw a circle outline, I'm using these coordinates to create a line that spent essentially a scan line horizontally across the screen to draw filled in circle.

  • And just because I like using them in my videos.

  • Here's a lambda function, which creates the filled in Breslin circle.

  • It just takes an X coordinate, a Y coordinate and a radius all in.

  • Introduced on this is in world specs is that this is affecting the bit map image that represents the terrain, and it is literally a couldn't paste from Wikipedia with a small modification for drawing lines.

  • So now I can create a crater.

  • It's difficult to say by drawing a circle of sky located around the world ex of worldwide coordinates that came in as part of our boom function on specifying the blast radius.

  • So let's take a look now that works very nicely indeed.

  • I mean, I can sort of create explosions within the terrain, which probably wouldn't be normal, but I can etch away at the terrain.

  • It creates debris.

  • Very nice.

  • One thing to try is now.

  • Of course, we can place an object and create an explosion underneath it on the object reacts to the terrain.

  • So this is a very dynamic terrain and physics engine.

  • In much the same way that we've defined the debris and the dummy object.

  • I'm now going to define a missile.

  • Andi, I've created a model here which is a little bit more sophisticated than just a rectangle or a circle.

  • So he's got multiple points.

  • I'm going to update my own use update function.

  • But when the user right clicks on the mouse, it adds a missile to the cute to be processed.

  • And again we're exploiting polymorphism just to take care of everything for us.

  • I'm not specifically checking what any object is as any time I don't want my missiles to bounce.

  • In fact, I want them to call the boom function and explode when they contact the terrain.

  • So I know they've contacted the terrain because of my collision routine.

  • And if I said the bounce before death number tow one, that will set the dead flag on the first contact so I could do something.

  • Under these conditions, I'm going to create a function called Bounce Death Action, which is a function of my C physics object, which I'm going to use to get information about what to do when the object dies.

  • And I need to add this to my base physics object as a pure virtual method, which also means I need to update it in all of my sub classes.

  • So for debris, it does nothing.

  • In this case, returning zero means you've bounced and died.

  • Just do nothing disappear, and we do the same with a dummy object.

  • However, for the missile, I'm going to get it to return 20 which means please call the boom function with a radius of 20.

  • So going back to where we're checking for this once the units has been declared is dead because it's bounced enough times.

  • We look at the response of the bounce death action, and if it's greater than zero, call the boom function at that location.

  • This approach allows us to create something like a grenade, which can bounce several times before exploding.

  • Let's take a look.

  • So if I right click, we can see it.

  • Missile falls, and when it contacts, the ground it calls is a big explosion.

  • Let's just put some objects in here, too, and drop bombs on them and we can see they get kicked around all over the place.

  • Very nice.

  • Let's now finally at our worm class except the worm class is going to load up the type of OLC Sprite.

  • I'm not going to use the wife remodel to represent the worm.

  • And so in the drawer routine.

  • I'm just calling the drawer partial spite function of the council game engine.

  • And of course, the units can bounce around, but I don't want them to die.

  • Unlike the other objects that we've derived, I don't need a factory function because I'm just simply loading up a sprite.

  • Let's change what happens now when the user right clicks.

  • So instead of creating a new dummy, we're going to create an object of tight worm.

  • The objects location will be wherever we clicked.

  • I don't need this.

  • Let's take a look.

  • So by pressing the middle mayor Spartan.

  • I could now drop units onto the map, which is sprites, and you can see this sit nicely on top of the surface of the terrain.

  • I've increased the damping factor of the sprites because I don't want them to be uncontrollably bouncing all over the map.

  • But they do have a small response.

  • It's fine tuning like this.

  • That takes a bit of time.

  • Let's drop some bombs on these guys.

  • Perfect.

  • And so hopefully no, you can see the advantages of using a polymorphic, object oriented system for handling your game engines.

  • It just makes coding simpler and easier.

  • So far, all we've created is a rudimentary physics simulation of some basic graphics will look in the next part of this series that's turning it into more of a game.

  • Oh, I got loaded the source code for this part already, so you can start to study it that's available on the ghetto.

  • If you like this video, big thumbs up, please don't forget to have a look at the discord server.

  • It's very active, and a lot of people on their offering a lot of help.

  • Have a think about subscribing on.

  • I'll see you next time.

hello and welcome to part one of a larger project.

字幕と単語

ワンタップで英和辞典検索 単語をクリックすると、意味が表示されます

B1 中級

自分でコードを書く!ワーム 第一弾 (C++) (Code-It-Yourself! Worms Part #1 (C++))

  • 28 1
    林宜悉 に公開 2021 年 01 月 14 日
動画の中の単語