Placeholder Image

字幕列表 影片播放

  • Hello.

  • Let's make a top down, city based car crying game.

  • As you may have seen in the thumbnail.

  • This is a big project until all the newcomers to the channel welcome.

  • By the way, that means we'll be splitting this over several episodes, and I tried to start each episode by showing what we're aiming for.

  • And as you can see, we have a car here and we're driving around the city.

  • There's no collision detection yet, so I'm only really showing what will be getting done in this particular episode.

  • Now, when I do a big project, I like to use things that I've shown in previous videos on Build upon Them and show how it all comes together.

  • And here we can see the city is in using the three D engine, But I'm also using the pixel game engine.

  • At the moment.

  • All the graphics are quite simple and really just placeholders.

  • Whilst we developed the game, I think this is quite an important strategy just to make sure that first of all, you can get it to work on, then make it work well.

  • And when I say a top down city, I mean a top down city, so we'll be looking at how we're handling.

  • The three D graphics will be looking at things like collision detection will, of course, be adding non player units such as police cars and possibly pedestrians on.

  • We'll need some sort of mission based system, so there's quite a lot to get on with.

  • But I quite like the aesthetic already.

  • I've spent lots of a lot of time developing this city on that driving around it.

  • It's quite fun.

  • Now when we're working with a game that has a large amount of rich details such as this, it's quite important that we also developed the tools to help us develop the game.

  • So in this video will show some very basic city editing tools that I can show you something.

  • Now, using the mouse cursor, I can place it anywhere in the scene and place additional roads and you'll see that the roads automatically align themselves with the correct junctions and I could remove the roads as well.

  • I can also place buildings and I can place buildings of different height, grow the buildings up and I could grow them back down on there's a little bit of novel interaction.

  • I'm using the car to control the camera, but editing a city like this might take some time doing it tile by tile.

  • So I've also implemented the ability to select tiles in the scene and apply the same transformation to all the tiles simultaneously on the selection works at any zoom level.

  • One of the principles I tried to adopt when I'm developing a game is that the game on the game editors should try and use the same engine on The primary reason for this is that you can edit the game as necessary whilst you're playing it so you can find tune it quite easily.

  • I'll just show a little bit more road building that we can connect these two roads together.

  • As you can see right now, the game is in a very basic for the graphics look a little bit repetitive and a little bit square on that simply because they're placeholders.

  • Let's make it work before we make it work.

  • Well, we'll have to keep remembering this mantra on what is especially important before taking on any larger project is that you have a plan, so let's get started.

  • Clearly, this game is inspired by the classic Grand Theft Auto, Siri's, but I don't intend to clone it completely.

  • I'm going to be making a much more cooked down, simpler version.

  • So what are the features that I'm aiming for in this game?

  • Well, the first thing I want is a large city, and I want the ability to choose and drive cars.

  • You need cars to get from A to be, which implies some sort of mission based activities.

  • The city would be a bit boring if it was empty, So I'm going to need some traffic in there as well, so I'm gonna have to have some other carts on.

  • As with the classic Grand Theft Auto, the player could literally steal a car that they saw driving around.

  • Typically, the missions will involve with you being chased by police force.

  • So I think a particular game dynamic is to evade capture in games.

  • I personally like collecting things, so I'll probably have some pickups in there as well on because the city is quite large, we're probably going to need a few things to help us.

  • Might need some navigation aids, like a GPS system.

  • Perhaps we're doing some editing tools for the different cars.

  • They're probably going to have a unique properties such a speed and handling or resilience to damage if you crash them into things.

  • And that's quite an important thing, because if we're driving around, we're going to need some collision detection.

  • I don't want the missions to just be to go from random location a two random location.

  • B.

  • It would be more fun if they tell a bit of a story.

  • So we want the missions to be script a ble.

  • And this has already got me thinking, because if we're going to have assets with variable properties on, we're going to have game play with variable properties.

  • Perhaps, just maybe, we want these to be modifiable, so we might want to think about using an external scripting language to handle this.

  • Now traffic on DDE, in some ways evading capture.

  • We're going to need a degree of path finding, perhaps potentially some sort of a I realistically, pickups are the easy ones in this.

  • Now the nature of a big project.

  • Is it a big project?

  • It's quite large.

  • It's got a lot of elements to it, and there's such typically during a big project.

  • I don't go into as much detail on all of the precise elements, and I might skip over some of the code that we're going to write, which means these videos tend to move it a little faster pace than my normal videos.

  • I'm going to start with a blank visual studio project onto this project.

  • I've added the oil see pixel game engine on a blank source, file the video ccc one dot cbp In this instance, the first thing I'm going to do is take the template from the head of file and paste it into the source file.

  • This is just a very quick and easy way to get settled.

  • What I will add at this point is, Please don't forget to define ol CPG application before you include the game engine.

  • I'll just quickly modify the template to suit our needs, and I'll remove the things that we don't need.

  • An unused create and on user update if you knew to pixel game engine on user create is a place that only gets called once, so you can use this to load your resources.

  • Andan user update is called every frame I'm going to create a pixel game engine, which is 768 pixels wide by, 480 pixels high.

  • So it's a widescreen application, so I'm going to reduce the pixel size because it's quite a high resolution to So I wanted to fit on my monitor.

  • I want to keep many aspects of the game very, very simple indeed.

  • So I'm going to restrict my city to really just being a two dimensional array.

  • Were each cell in the array represents something different.

  • For example, I'm going to want to know if a cell contains road or not, so we'll have a flag that indicates if it's a road.

  • I think it might be quite useful later on when we're dealing with navigation to know that road's a distinct.

  • If the cell isn't a road, then presumably it contains some sort of scenery, and for now I'm going to represent that scenery using a single interview.

  • For example, if the scenery interview is zero, then it's just flat, so we'll draw some grass.

  • If the interview is less than zero, then for now the cells simply not going to exist.

  • But in the future, video I'm going to want that to be water, and this gives me 1/3 option for anything that is greater than zero.

  • And I'm going to assume that any value greater than zero is going to be a building on that.

  • The value indicates how many stories that building has.

  • So if it's a one, then we have a single story.

  • If it's too and we'll have two stories, there's the 1st 1 It will be a second on top.

  • So in my cell structure so far that means I've got something that indicates road.

  • You're probably going to be a Boolean, and I've got an interview I'm going to call height.

  • That's enough to get us started right now.

  • I'm making no attempt to optimize any of this at all, but I'm going to need some geometry for my three d engine to render.

  • I'm going to need several meshes.

  • So the first mesh is just going to be a simple flat quad two triangles and I'm going to use this quad for rendering roads grass on the roofs of the buildings, basically anything that's flat when look down from above the second type of mesh I'm going to use our sort of the outer walls.

  • So if we're looking at this, we got a Southern direction here.

  • We've got a quad that makes the Southern direction, but in the same match, I'm also going to attach the other side's as well.

  • Br westerly direction northerly on easterly.

  • I'm going to keep that as one single mesh.

  • I'm also going to keep all of my coordinate systems in unit values.

  • So our quant is a one by one unit quad on our outer walls are going to be a one by one by one, not a cube, because I've not got a top or a bottom.

  • However, whenever I'm working with three D onions, I also want to include a cube somewhere because it's a good way of testing that you've got everything settled correctly, have created some very simple placeholder assets to, and you'll notice that these are also based on a single cell sites, particularly for the roads and grass.

  • The top down stuff is indeed square.

  • The sides of the buildings here aren't, but laying out the texture in this way has revealed what kind of junctions I need.

  • So I got a north south East and West T Junction.

  • I've got horizontal and vertical road segments.

  • I've got four corners on in the middle.

  • I've got a crossroads, so I've covered all of the types of road I want to have.

  • This does imply single constraint, though, and that is that.

  • My roads must always be loops.

  • Not only does this make the production of the graphic simpler, it's also going to help later on when we're dealing with the artificial intelligence and non player vehicles, because I've got a feeling things like Dead ends.

  • My cause is a problem because I'm using the pixel game engine.

  • I can export all of this as a PNG file.

  • When I first created the Pixel game major, one of the things I wanted to use was extensions.

  • This is encapsulated code that serves a particular purpose.

  • We've already seen the graphics to de extension in the F Fine Transforms video, all for this series.

  • I've also created a graphics three D pixel game engine extension on it uses exactly the same code that I've used in the code it yourself for the engine Siri's.

  • But I've made a slight change to the structure just to make it a bit easier to use.

  • I'm going to include the extension at the top of our source file Now.

  • Admittedly, this extension is quite a large file, and that's because there was a lot of code for the three D engine Siri's.

  • But please be assured it is exactly the same.

  • We've got a vector to Deion Vector three D types were still using triangles were still using matrices on was still using meshes.

  • I've encapsulated all of the maths routines that we developed in a subclass cold math.

  • I've still not got around to doing operator overloading just yet, and so it's in here that I've got my Matrix and vector operations.

  • I've also got the clipping algorithms that we created, and if you are so inclined, you can compare the code in here to the code created for the graphics engine Siri's and you'll see.

  • It's exactly the same, however, to keep things neat and tidy in our source code, I've introduced the concept of a rendering pipeline, and this imitates the technique used by graphics cards from quite a while ago.

  • Certainly before we had shade er's and shade, a model based GP use.

  • The idea is that you submit geometry, put some geometry here.

  • Some triangles.

  • You submit that to the pipeline on the pipeline will do things in a fixed order.

  • So the first thing you might want to do is transformed the geometry.

  • So if you remember, that might take in, for example, the world matrix.

  • It might take in something like a view matrix to on Why not.

  • It may also take in the projection matrix.

  • Once the geometry has been transformed, it may go on to do some lighting.

  • Now, these might not be in the precise order that we end up doing things.

  • It may go on to do some cooling clipping, and finally, it will raster the transformed, lit, clipped and textured triangles to the screen.

  • Pipe.

  • Lining in this way does reduce the flexibility of what you can do, but it really simplifies using the three D engine.

  • And so I think it's worth showing this first to just simply put a rotating cube on the screen very quickly.

  • I'm going to represent my cube using a mesh.

  • So we're in the OLC name space than the graphics three D name space.

  • We're going to take a mesh.

  • I'm going to call it Mesh Cube and in the all news to create function.

  • I'm going to define what that Cube is on.

  • I'm literally copying and pasting the coordinates that we used in the three D engine Siri's.

  • You can see it's exactly the same alongside my mesh.

  • I'm also going to need a rendering Pipeline instance.

  • So again we dip into the GI effects three D name space, and I'm going to create an object of type pipeline.

  • We'll call it Pipe Render, and I could have several different pipelines or configured differently for different rendering operations.

  • But right now I only need the one in its current form.

  • The three D extension does require a little bit of initialization.

  • I'm going to do this in on music create.

  • Are all I need to do is simply call the configure display function.

  • This sets up some internal buffers toe handle, the depth I also use on user create to set up some of the more static properties of the rendering pipeline.

  • Specifically, the projection permits is, do you want to feel the view which is in degrees to set that to 90 degrees?

  • I want the aspect ratio on these parameters will look exactly the same as they did in the three D engine.

  • Siri's don't forget to cast that toe afloat.

  • We need the near plane distance, the far plane distance, and then I'm going to add additional four properties on these are the view port.

  • So if you remember, we did quite a bit of transformation after we did the projection transformation in the previous Siri's, and that was to scale it to the screen.

  • So I'm going to define the screen.

  • Is being a top left 00 on bottom, right?

  • Well, it's going to be the full screen, so we'll borrow screen width in screen height again.

  • Typically, the projection information isn't going to change in this application, of course, if it if you need something that changes per frame, you just have to set this up per frame with any three D seen.

  • We're also going to need some sort of camera, so I'm going to add in three Vector three D's here to define what the camera is forgotten.

  • Up direction are my direction, which is where the camera is in world space, on the direction the camera is looking in.

  • Let's have a go at doing some rendering in on user update.

  • First thing I want to do is clear the screen to black.

  • Now, if you remember, the camera matrix doesn't take a look at Direction Vector.

  • It takes the point the player is looking at them.

  • We can get that point by simply adding the direction vector to the ID vector.

  • So I'm going to do that here Creative vector called Look Target.

  • And I'm calling the vet ad function to add a look direction to our I point.

  • This will give us a point in three D space so our camera matrix can be assembled on.

  • We don't need to do that manually anymore.

  • We can let the pipeline handle that force.

  • So I'm going to tell the pipeline to set its camera up, using our eye location, the looking target onto the vector.

  • Now, as you know, by now, I like to test these things with a rotating cube, so we need to come up with the world transformed for the Cube.

  • I'll do this the long way around.

  • I'll create a matrix called Matt.

  • Rotate X on will call from our maths library.

  • G affects three day.

  • Matthew gets a little bit wordy.

  • I appreciate that.

  • But at least it's clear.

  • Matt make rotation in this case, the X axis.

  • We want to specify an angle in radiance.

  • I'll create a variable floating point called a theater.

  • I also want to rotate in the said access, so I'll copy that line.

  • Unchanged this over to Zed, but I want to rotate it a different speed, something to change our F theater.

  • So now I want to create a transform for the Cube.

  • We'll call this mad world to stay with Convention on.

  • We're going to multiply the two rotation matrices together rotate X on Matt rotate dead.

  • So we've now configured our pipeline with a projection transform.

  • We've configured it with a view transform.

  • The final thing to do is to configure it with world transformed for this object.

  • Now it's time to draw the geometry.

  • So I take our pipeline.

  • I'm going to call the Render function, which takes the vector of triangles associated with our mesh.

  • So it was Mesh Cube don't tries, but this is where things get a little bit different from the Siri's.

  • We've got several different ways of rendering things in this instance, I just want to render the wire frame.

  • So I want to specify the Render wire flag on before we test to see if this work, we need to change our F theater value per frame.

  • I'm just going to do that by accumulating F elapsed time.

  • So let's take a look and then we can see it's a bit small because our cameras far away, but we've certainly got a rotating cube in the middle of our view pot.

  • The pixel space screen on this elegantly shows the power of the pipeline.

  • Where's before we had lots of code were individually handling every aspect of the triangles that's now all encapsulated on abstracted away.

  • We just specify the properties that we want for rendering.

  • One of the things I know I'm going to need is my texture, which contains the road sections and building sections on.

  • The nice thing is, the textures are just standard.

  • OLC sprites are going to create a variable called SP are all which represents the entire sprite sheet on a non user create.

  • First thing I'm going to do is load up the PNG file that represents that sprite.

  • Now that we've got a sprite loaded.

  • We can use it as a test texture for our cube.

  • All we need to do is specify which texture the pipeline should borrow from set texture.

  • S P A.

  • All but we can't render a wire frame with the texture on.

  • In fact, given that most of the time you want to render with textures, the default options are to render using the texture and not wire frame.

  • So this will now do texture ing, clipping on back, face cooling all by default.

  • Just take a quick look, and it looks like a horrible little mess in the middle of the screen.

  • In fact, it's failed utterly and completely on.

  • There is a reason for this, as well as clearing the screen to black each frame.

  • We also need to clear the depth buffer of the three D system.

  • Unfortunately, this is also very simple to do it well, what is going to call the clear depth function of the extension?

  • So there we have it.

  • It's a bit small.

  • Let's see if we can zoom in.

  • The reason it's a bit small is the cube is rotating around the origin of the world 000 on our high point is 10 units back, so I'm going to change that to minus four.

  • There we go.

  • That's better.

  • A rotating cube.

  • Always a sign that you're on the right track Now I appreciate if you've come to this video without having seen the three D graphics engine Siri's.

  • A lot of this might seem a little bit confusing.

  • Well, it's probably really worth checking out that Siri's before carrying on with this big project, Siri's.

  • But hopefully what I've demonstrated to the people of our word is that by encapsulating using this pipeline system, we've now made access to three D graphics.

  • Very simple indeed.

  • Now that we've got the burn minimum of a three D rendering system, let's start implementing some of our game.

  • At this stage, the game's only going to consist of two mesh models.

  • The first is the flat.

  • Just quad On the second are the walls facing outwards will use the flat quad, surrender the ground, the roads and the roofs and, of course, the walls rendered.

  • This stories of the buildings will need to populate those message with some data.

  • So this is the flat quad, which consists of two triangles on a triangle, is made up of three points.

  • This is the first point second point third point, and then there were three texture coordinates.

  • Now you might notice that these Aaron additional dimension than what's needed.

  • And that's because we have the Omega parameters for W parameters as part of those vectors on the four outer walls.

  • Very similar, they're effectively quads but rotated 90 degrees around the relevant taxis.

  • One thing to note is that the texture coordinates are all quite simple.

  • I either not going to index my texture sheet at any particular location.

  • Right now it's taking the whole sheet.

  • So I'm actually going to do a little bit of a hack here instead of using texture transformations, which we will look at in the future part of this series, I'm going to break up my main sprite into the individual textures, and so along sign the maid's bright.

  • I was going to have a spite for the ground, despite for the roof, a sprite for the first stories.

  • That's the frontage where all the shops are.

  • Despite for each stories, windows and then the 12 road Sprite sections.

  • Also this point going to throw in a spite for the car.

  • We know we're going to need that later.

  • So the easiest way to break up the Sprite is to use the drawer partial Sprite function provided by the pixel game engine and redirect the drawer target.

  • So let's take the lowest floor of the building.

  • As an example, I know that the size of my spiting pixels is 32 by 96.

  • This is effectively going to be this part of our sprite.

  • If I tell the pixel game engine to redirect its drawer target to that sprite, all subsequent drawer calls will be happening to that spite rather than the screen.

  • So now I can just call the drawer partial Sprite function, which has been around since the early days of the console game engine.

  • I can specify the target location, which is 00 so the top left of our sprite frontage, the source Sprite, which is our entire sprite sheet.

  • I choose the exact coordinates within that sprite sheet on the width and height of the target Sprite on.

  • I want to do that for all of the Sprite sections I've deliberately laid out to the road sprites that look together in a three by four grid of sprites.

  • So 123 Yes, we've got some grass here that's falling into that 456789 10 11 12.

  • This makes it easy to algorithmic Lee break off the road Sprite instead of specifying them all individually.

  • I know this 12 off them, so I'm going to create a little four loop to iterated through 12 different positions and I've got my road Sprite.

  • I'm going to create a new one for each of those locations.

  • One of them is redundant because it contains grass, but it doesn't matter.

  • We'll just never use it on again.

  • As we've done before, I'm going to use the drawer partial spite routine to populate that spite with the correct section of road.

  • But the nice thing is, I can use interview division to choose that spite location for us out of the main texture so I can find the ex offset by modulating by the width of each of my sprite tiles.

  • So in this texture, one of these tiles is 96 by 96 pixels, so by modulating by three and times in 96 I can choose the right column across the screen and, conversely, doing an interview division by three times in by 96 I can choose the correct row.

  • I think this is quite important because it shows that how you organize your game assets can actually make your coding a lot simpler.

  • Once we're done loading all of the main asset textures, I want to set the drawer target back to Noel Pointer.

  • If you don't do this, you'll always be drawing to the Sprite that was last set of the drawer targets, and you may end up with a blank screen and finally, a quick, easy one.

  • I'm just going to load the car Sprite, too.

  • Let's define ourselves as a stroke s.

  • So and we know that this is going to contain the height value as an interject onda flag to indicate whether it's a road or not, we're going to want to de array of thes, so I'm going to specify a map with on a map height variable on a pointer to what will ultimately be an array off cells.

  • Andi, I'll create a default map in on user create.

  • Just find the bottom here.

  • There we go, so my map is going to be 64 wide by 32.

  • Hi, I'm just going to dynamically allocate that memory will then create two little four loops to iterated over all of the X and Y locations within that two D array.

  • I want to set all of the heights to zero on all of the road flags to false.

  • And here is something I've done in probably every video of the one loan coded channel we've got.

  • Why Time's Matt With Plus X?

  • That's translating our two D coordinates into a one D coordinate for our array.

  • Now it's time to start rendering our map.

  • I'm going to keep the clearing on the clearing of the debt buffer on setting up our camera and for now, no optimization it all.

  • I'm going to render everything.

  • So I'm going, going to create four interview variables.

  • Start X and index, which is going from zero to map with and start.

  • Why on N y for map height, I was going to render everything, even if we can see it or not, which means again, I'm going to want to four loops that that iterated through all of these locations for each cell that we're going to draw, I'm going to test.

  • Is it a road or not?

  • Right now, if it is a road, I'm going to ignore it.

  • It is not a road were drawing some scenery, so let's start with that first.

  • If you remember back to the plan, we know if the height is zero, then we're just drawing a flat grass quad.

  • So let's configure a rendering pipeline to do just this.

  • We've already set up the projection on the view matrices, so the only thing left is the world matrix.

  • Rendering the cell is quite easy because our cells are all that interview locations, and our two loops are iterating through insurgents.

  • It's all I need to do is translate this particular cell to its integer offset in world space.

  • I'm going to tell the pipeline that that's the world transform it should use, then going to tell the pipeline that it should use the grass texture on.

  • Finally, I'm going to tell the pipeline that its source of its geometry should just be the flat quad, and that's it.

  • So I'm going to get rid of our cube rendering stuff from before because I think blue is a slightly more appealing color on at the moment.

  • I wanted to kind of represent water.

  • I'm going to change our clear color to blue also.

  • So let's take a look and see how this works.

  • Well, we can certainly see a grass texture in the bottom quarter.

  • It's of the screen.

  • It looks like it's going to 000 in the middle.

  • Excellent, though I'd like to verify that it's drawing the whole world by including some rudimentary camera control went to add three variables which represent where our camera is going to be on in on user update.

  • I'm going to test if particular keys are held down on manipulate the camera accordingly.

  • So the 1st 1 will be checking if the W key is held down.

  • So we use W.

  • A, S and D to move the camera.

  • We'll see Key W.

  • If that's held down, we're going to change in the wind direction, which is open down the screen.

  • So cama y minus equals 2.0 on.

  • I'm going to modulate that with F elapsed time.

  • It's quite important to modulate things with every elapsed time, so that they move smoothly even though the frame rate is going to change.

  • So, in a similar way, I'm going to implement the other keys.

  • I'm also going to include two more so we can change things in the set access.

  • We can zoom in and out.

  • Zed Annex.

  • Now that we've got three floating point variables that represent where the camera is, we want to update our view matrix.

  • I'm going to set the I point to be at that camera location.

  • So let's take a look.

  • So I'm pressing the d key on dhe.

  • Very nice.

  • The grass is moving across the screen.

  • Yes, moving up on.

  • I should build to zoom out, have a look.

  • So there we can see all of the cells or worth What was it?

  • 64 by 32 being drawn to the screen and we can see right in and see the individual pixels of the grass texture.

  • Very nice and pleased with that.

  • I think at this point it would be fun at the car to the scene.

  • I'm not going to create additional geometry to do this.

  • I'm going to use our flat textured quad, but there are some transforms I'm going to need to do to this.

  • Our quality is currently one unit in sight.

  • It occupies an entire cell in our city.

  • Clearly, the car shouldn't occupy the entire cell.

  • And I also want the car to be able to rotate.

  • But right now, if I rotated, this quad is going to rotate around.

  • Its 00 position is going to look a bit strange.

  • I wanted to rotate around the middle and finally the car is actually a rectangle.

  • It's not a square, so we need to change.

  • The shape of this squad will do all of this with matrix transforms.

  • So the first transfer I want to do is to offset the quad so that its origin is in the middle.

  • So I want to offset by a o.

  • X on Oh, why value In this case, that's quite easy.

  • It's half in each access now.

  • The quad is centered around the origin.

  • I can rotate and scale it, so scale it first to soothe size of the car relative to the rest of the world.

  • On through a little bit of experimentation, I've determined that the car that should be scaled by no 0.4 and not point to.

  • Another, of course, will change this square into a rectangle.

  • So after it's been scaled, it'll look something like this.

  • After it scaled, I'm going to rotate the quad to suit the direction of the car.

  • Now, currently, after all of this, the car is still a 00 in the world, so I don't need to translate it into the world into its realistic position to translate into a world.

  • So there's a bunch of matrix transformations required here to put the car in the right size, the right orientation in the right place in the world.

  • I'm going to add some additional valuables toe handle the car First variable is going to be a floating point value that represents the angle of the car on.

  • The second value is going to be this speed.

  • The car can move that now.

  • We saw in the plan that we might want to externalize that later on, but for now I'm going to hard code it in and then going to want to additional three D vectors that represent the velocity on the position of the carp.

  • Now we've done velocity and position many times on this channel on.

  • It's no different in three D than it is in two D.

  • Using the arrow keys.

  • I'm going to detect if they're held down, and if they are, I'm going to adjust the angle of the car accordingly.

  • I now want to break down that angle into a normalized velocity vector to indicate which direction the car should move on.

  • We're is traditionally our break out the signs and co signs to do this well, we've now got an engine that can do.

  • Rotation transforms for us, so I'm going to create a unit vector, and I'm going to take a rotation matrix in the zed access so that is looking down from above and rotate that unit vector by the car angle on.

  • We'll take the products of that matrix on the vector and place it into our car velocity vector.

  • Now that's currently normalized to drive the car, we're going to respond to the up arrow being pressed.

  • That'll move the cart forwards.

  • So let's put in an event handler to deal with that on.

  • Since our velocity vector is normalized, I'm going to multiply it by car speed on modulated by F relapse time were effectively integrating our velocity to give us our position.

  • I've done that for the X axis needs to exactly the same for the y axis.

  • On.

  • Important thing to notice is that because Carvell is normal, were effectively changing the magnitude off it by multiplying by this scaler car speed.

  • So this is a very primitive way of handling a car.

  • It's not realistic car physics, it all.

  • We can rotate the car on the spot on.

  • It has no acceleration or deceleration.

  • Well, look at that sort of thing.

  • In a later video of this Siri's, I want to ensure that the car is always kind of visible.

  • So I'm going to draw the car after I've drawn the scenery on.

  • I'm just going to go through the transforms.

  • I've just been through in the slight.

  • The first thing is to offset the quad by half.

  • So now the origin is in the middle of the quad and then going to scale the quad to make it into a rectangle the size of the car.

  • That would seem realistic in the world that we're creating the order that we multiply matrices.

  • It is important s so I'm going to combine the translation on the scale matrix into what is now going to be the car's world matrix.

  • Next, I'm going to create a rotation matrix of the car is facing in the right angle on.

  • We can use the car angle variable that we've already got.

  • We don't need to reverse engineer the velocity vector, and I'm going to multiply that rotation matrix into the current world matrix for the car.

  • Finally, we want to translate the car into its real world position, so I'm just going to translate it by the cast Position X and why?

  • But I'm also going to give it a little tiny bit of elevation.

  • Spotted little typo there on this raises its slightly above the ground plane.

  • This means we won't get any depth buffer conflicts, but it also looks strange either.

  • It's so close to the ground plane that it'll look like it is on the ground so we can combine that translation matrix into the current world matrix so you can see there's quite a few transformations for the car, but they make sense now.

  • We'll tell our pipeline to draw the car Well, since we've just calculated the transform, let's apply that to the pipeline on.

  • We're going to be using the car texture, and here's a little bit off a pixel game engine peculiarity.

  • The car texture amusing contains Alfa components.

  • It's got transparency, so we don't want to draw those particular pixels.

  • Now.

  • This has nothing to do with three D graphics.

  • It has everything to do with the pixel game engine itself.

  • So I want to enable for this particular drawer.

  • Call Alfa blending.

  • Once I've enabled the Alfa blending, I'm going to tell the pipeline toe actually render the flat quad using its world transform.

  • So we're not adjusting.

  • The original geometry were just transforming it, as we've just seen with the matrices on, because Alfa blending can be a little bit expensive.

  • We don't want to do it all the time.

  • Will tell the pixel game engine to go back to rendering normal I.

  • It doesn't assume there is any transparency to the pixels and just does it very quickly.

  • So let's take a little look at our little car.

  • Well, there's certainly a yellow blob on the middle of the screen.

  • Let me zoom in a little bit, assuming out zooming in there, we go so we can see the car Sprite.

  • Very nice.

  • And it is Alfa blended.

  • We don't see sort of any white Sprite boundaries around the car.

  • It's also rectangular, which means are scaling has worked very nicely, so the left and right arrow keys should rotate the car.

  • Very good on the forward key should move the car a long.

  • It's rotated vector.

  • Oh, there we go.

  • It does museum out just a little bit and we can drive the car around.

  • I mean, it doesn't handle anything like a car that I've ever seen before, but it's, you know, it's a good enough approximation at this stage in the big project.

  • The only downside is I've got to now manipulate the camera and control the car simultaneously.

  • I just don't have enough fingers.

  • That's what I'm going to do is attach the camera going the wrong way, attached the camera to the car, and this is very simple.

  • Where we set our high point for the camera.

  • I'm just going to set the X and Y camera values to our corresponding car position X and Y values.

  • Let's take a look.

  • So now I can't control the camera anymore with W A S and D.

  • But the camera follows the car very nice.

  • I think now it's time to stop thinking about placing the roads to begin with.

  • I'm going to do this incredibly crudely, wherever the car is.

  • If the user presses the R key, I'm going to toggle the road flag for that particular cell.

  • So first, let's be sensitive to the R key being pressed on Al Truncate the cars floating point position to interview position so we can index into the map.

  • I'll do this for X and Y.

  • This is a really, really good advantage to having a cell based city is.

  • We can easily work out where we are, and this is working exactly the same way as the code it yourself platform game.

  • So since that we know where we are, we can simply toggle the flag from that location.

  • Why times and map wit again, plus X don't The road is equal to not all of that, so it depends which sell the car is in.

  • If we press the archy, it's going to Tuggle whether it's a road or not, but we don't render road yet, so we need to sort this out.

  • Looking at the complete spite sheet, we can see we've got 11 different types of road section as I'm rendering the roads.

  • If the flag is set to true, that's where I'm going to determine which particular road section I should draw on.

  • I'm not going to do anything too clever to determine this.

  • I'm just going to test it explicitly.

  • It'll start off by assuming that the road value is zero.

  • Now I'm going to be doing a lot of indexing into an out of the array on.

  • I think the code will get a bit of worldly if I've got white times and with plus X all over the place all the time.

  • So I'm going to create a little auto lambda function.

  • Oh, and this is going to take some offsets.

  • Inter eye on into J.

  • What I wanted to return is the state of the road flag for a given cell relative to the cell that I'm currently trying to render in our four loops using the X and Y coordinates.

  • So I'm going to look at the map array and I want to check for the current location that we're rendering why but plus the offset J.

  • And of course, that's times and map with.

  • And I want to do the same for X.

  • But this time plus the offset I So this will allow me to interrogate the neighbors of the cell that's currently being rendered on.

  • I want to return whether that is road or not.

  • So labeling our roads the top left one up here is zero and then one two and we got on to the next row of roads.

  • 345 So Road zero is a vertical strip.

  • That means this one is only applicable if the road above it is road on the road below It is road on its left and right Neighbors are not road.

  • So I'm going to test for that explicitly.

  • So if the road above me So my ex offset is zero.

  • But the one above me is minus one in the white.

  • If that is road and the road below me egg zero again, I'll put a plus one.

  • And of course the plus isn't necessary.

  • But it helps visualize what's going up.

  • So if the road above me and the road below me, his road and this is also important was test for our left and right neighbors at the roads to the left of me minus one on the x axis and not road plus one in the X axis.

  • So if my left and right neighbors are not road, then I want to choose the vertical section.

  • So if all of that is true, then I know that I want the vertical strip of road in a similar but kind of opposite way.

  • I can check for the horizontal strip which has a road idea of one Here we can see we've got no vertical components, but we've got both horizontal components.

  • That's the first top row of our sprite cheat The next road down, we're looking for a corner section a T junction on a corner section.

  • So the first corner section is true.

  • If the one of both me doesn't exist But the one below me does The one to the left of me doesn't exist, but the wants of the right does.

  • That's clearly a corner.

  • The next bright idea long was a T junction going horizontal, but with a southern opening.

  • So there is no no northern neighbor component, But all of the others must exist, and I'll keep going on like this until I've covered all possible road types.

  • So now that I know which Road Sprite to set us my texture for the pipeline, I can just go ahead and do that.

  • The world transformation for a section of road is exactly the same as drawing a section of grass, so I'm just going to couldn't pace that.

  • And in fact, so is the rendering.

  • That's all the same because it's just simply flat.

  • So let's take a look and see if that's working.

  • Just zoom in and I'm going to press.

  • The are key to toggle the cell that's underneath the car that we go.

  • It's turned into a road vertical section while it's got no information to actually make any sensible judgment.

  • But I'll go to the one next to it.

  • Still not quite right.

  • But if I go here and here and here and we keep going if I just just test the toggle nature, yes, I can disable and enable the road I'm going to turn down here.

  • We can see its chosen the correct corner for us.

  • Let's try and make a loop very nice.

  • There we go.

  • So it's got a nice loop of road.

  • I'm going to choose this middle cell now.

  • Well, I'm countries.

  • The middle cell is only too high.

  • So let's let's go over here and try a bit of a T junction.

  • Yep, there we go.

  • Very nice.

  • So that's but in okay.

  • So down here, this should also now become a bit of a dead end, which we shouldn't really allow on.

  • We could see its chosen the crossroad.

  • So let's loop this background here.

  • There we go.

  • So it looks like a long as we maintain loops for our roads.

  • It can choose the junction sprites accordingly, which is very nice.

  • That makes editing roads much, much simpler indeed, particularly when you consider how large the city can be.

  • At this point, you may notice that there's a few sampling glitches going on on.

  • Well, look at that in the future video.

  • Some of the eagle eyed viewers amongst you may have already noticed the term MIP in this code, and yes, we'll be considering that in the future episode.

  • But for now, I'm just not going to worry about it.

  • It's rendering the roads good Now it's implement the rendering of the rest of the scenery.

  • Well, the first thing, if you remember it, if we had a less than zero condition, we don't want to render anything at all.

  • So I'm just going to throw that in later on.

  • We will probably will want to render something for this condition.

  • I want to render water, but I'm going to leave that again for later episode.

  • That's a bit more of a cosmetic effect, but for now, if it's less than zero, we don't want to do anything at all.

  • And this leaves The final state is that if it is greater than zero, we want to draw the building.

  • Now some of you that have familiarity with DD graphics, maybe thinking it's quite wasteful to draw each story as a unique set of polygons.

  • Why don't we just take a cube model and scale?

  • It's the height of the building on.

  • We will at some point.

  • We'll look at how we can do that because somebody else I want to introduce texture transforms, which are also a necessary component of being able to do that.

  • If we were to just scale the building right now the texture would also stretch.

  • We need some way of compensating for that.

  • I'm also not going to look into making sure that we can render walls that we can see that's going to be coming up in the next part of this Siri's.

  • So if we've got two buildings the same height, which is next to each other, they're going to both render the walls that will be touching each other.

  • And of course, there's no need to do this.

  • But right now I just want to make it work and then I'll make it work well.

  • So depending on the height of each building, each story of the building is going to be a repeat of the outer walls mesh.

  • But we're going to have to translate it in height.

  • And given that I'm drawing, each story is a separate mash.

  • We're going to have to do multiple renders.

  • Depending on the height of the building.

  • I'm going to start by having a four loop that it's a rates through each story of the building, and I want to create a transformation world matrix for that particular mesh.

  • Here, I use the translation matrix as normal.

  • We can see the X and Y components offset the mesh into the correct world location.

  • But we need to think a little bit differently about the height.

  • The ground is it 000 on the camera is currently at minus 10 in the center axis, so things get more negative as they come towards the viewer.

  • So here you can see I'm multiplying by minus one to compensate for that.

  • The mess she's also defined as being 000 at the top on 111 at the bottom, which means if we were to just draw it directly, the first story would be level with the ground and therefore behind it.

  • So I'm going to offset the height by one.

  • Finally, I'm going to scale the said access displacement by not point to, because in our world, each story is not point to off a unit cube.

  • Hi.

  • Once we know where the story is in world space, we need to choose the appropriate texture if it's on the ground floor.

  • I wanted to use the frontage, but if it's off the ground floor, I wanted to use the windows, so I'm just going to use the turn of the operator to quickly choose which Sprite it should and finally render the walls in a very similar way.

  • I want to draw the roof for the building.

  • Now.

  • This is just the flat quad that we've been using before, but I need to change it.

  • Zed displacement.

  • And in fact, I'm just going to use the H value that were left with at the end of this loop.

  • Now that we can potentially render buildings, we need to be able to specify where the buildings are in the map.

  • I'm going to use the tiki to increase the height of a particular cell, and I'm going to do that in exactly the same way that I have for specifying the roads.

  • Except this time is going to be in height plus.

  • Plus, I'm going to use the E key to decrease the height of a particular cell so that plus plus becomes a minus minus.

  • So let's zoom in on press the tiki and we get what looks like the roof of a building.

  • Zoom in a little bit more, can't see the sides of the building until we start driving around.

  • So we have.

  • We've got a building there, So let's press t twice now.

  • We certainly see the building.

  • He's growing, and it's rendered very nicely, too.

  • Let's give it a neighboring building now.

  • Don't forget I'm not doing any optimization.

  • So there's loads of polygons.

  • They're being drawn that we can't see had another one.

  • Let's have one over here, one here on one here and in between these, I'm going to set some road.

  • Very nice.

  • It's starting to feel right on backing.

  • Drive into a building.

  • Of course.

  • Normally you won't be able to on if I press the e key, we're decreasing the height, and if I set it below zero, the cell doesn't get rendered a tall.

  • In fact, we can have very, very tall buildings indeed.

  • See how good we can go, pressing the key a lot.

  • That's very nice.

  • So we can have like a massive skyscraper in our city.

  • Using the car is a selection mechanism to determine which cell we want to operate.

  • Our is fun, but not very practical.

  • I'd rather use the mouse, but this had some complications in a two D game, working out where the mouse is relative to the game world is quite simple, but in a three D game, it isn't quite a simple because we can zoom in and out.

  • And so this will obviously change, which sells lie underneath the curse it.

  • So let

Hello.

字幕與單字

單字即點即查 點擊單字可以查詢單字解釋

B1 中級

大項目!自上而下的城市汽車犯罪遊戲#1 (BIG PROJECT! Top Down City Based Car Crime Game #1)

  • 6 0
    林宜悉 發佈於 2021 年 01 月 14 日
影片單字