Placeholder Image

字幕列表 影片播放

  • Hello.

  • Let's continue making a top down city based car crime game.

  • In the first part of this series, I developed a little prototype, really, just to test the power of the pixel game engine on the three D rendering Andi.

  • Over the last few months, it's grown into something quite substantial.

  • Here you can see the graphics have had quite a significant overhaul on.

  • We've got non player entities wandering around our city.

  • We've got pedestrians marked in the pink dots on vehicles marked in the yellow dots.

  • There's no collision detection just yet, but what's nice to see is that we actually have traffic patterns forming.

  • So here we can see the pedestrians walking around on the pavement, and we can see the traffic queuing up on obeying the laws of the road at any one time.

  • There's a maximum off 20 non player units wandering around on the map, and they spawn and d spawn.

  • We're not in view of the camera.

  • 20 is a rather arbitrary number, but I feel it gives a good level of density because don't forget, we've got to allow the players space to actually drive the car around without hitting every obstacle in sight.

  • Now the first thing I will say is that everything has been overhauled from the first video.

  • That's not much of the original code left, but this plenty of the original ideas.

  • And if I go into edit mode now in the editor, we can see there's quite a great deal of complexity regarding how the non player characters manipulate themselves around the map on.

  • I should also point out the buildings have changed.

  • Yes, the texture is a bit high frequency.

  • I appreciate that, and we may consider filtering later on.

  • But what I wanted to get across here is that all of the models, including the car, are now assets generated by the one lone coder community.

  • So zoom in on the car for a second.

  • We can see it's actually a three D model, and he's got some directional lighting applied to it, too, is very subtle.

  • I'll just go back into edit mode on.

  • We can see that the nodes and a network that the non playing characters that follow around Onda the green nodes mean they they can pass through it, and the red nodes made that they can't.

  • So in this way I can emulate sort of a traffic light sequence.

  • The editor hasn't changed a great deal in terms of how it functions.

  • We could still select multiple cells on place new entities on the map.

  • Johnson rode here on a loop of road, but we'll see that there's no non player characters on the In fact, they're all clustered around the current center of the cameras viewing point that we go.

  • So when I zoom out, we can see them pop in and out of existence.

  • If I moved down here, we can see now that with cameras focused is where the non player character entities appear.

  • I'm just going to follow these round a little bit, so excuse the silent pauses.

  • But it does take a bit of time for things to happen now.

  • The player, during normal gameplay, wouldn't see the unit's pop in and out of existence that simply because the camera is restricted to a fairly local field of view on the boundary for spawning and D sporting of the non player entities is beyond that field of view.

  • So to the player, it looks as if everything is running around quite smoothly, not good we can see the traffic has stopped at the traffic lights here.

  • We'll just wait for this one to take over and see how the car's behave.

  • Now I've decided that the traffic lights are running.

  • A particular sequence in this sequence is is highly modifiable eso.

  • Right now it's completely dumb.

  • Any traffic coming in from one side completely prohibits traffic coming in from the other two sides of this T junction so we can see that the queue is forming.

  • But once the traffic lights take over to allow this cue to enter the T junction, there we go.

  • Perfect timing.

  • We can see that the car's choose a particular path on.

  • They follow the rules of the road.

  • The community response to the first video was far greater than I ever anticipated on assumes that video went out on quite a lot of requests for people to start generating buildings and vehicles and creating all sorts of assets.

  • They really latched onto the modifiable properties off the game, and so I thought, Well, hang up.

  • Let's let's actually pursue that.

  • After all, this is a community focus channel, and I wanted to be a sort of a community project and people might want to model this project at different levels of complexity will be those that can't wait to dig into the source code start poking around, but will also be those that are more interested in the creative side of it.

  • So creating the buildings, creating the camps, creating the plot and missions.

  • So I've decided to extend the engine to be predominantly based in the lower, and we'll see part of that today.

  • Now the approach I'm going to take with this video is a little bit different to my other videos.

  • There's a lot to get through here, so it's not really going to be possible for me to go line by line through all of the code.

  • I will be bringing in large chunks of code on giving it descriptions.

  • But of course, all of the source code is available from the get hub in the link below on.

  • Because I've restructured the project quite significantly, I'm going to start building it from scratch.

  • However, a lot of the ideas we used in part one are going to come over to, so let's get started.

  • The prototype developed in part one of the Siri's was my typical single file approach to developing a quick game.

  • And since there was a great deal of enthusiasm from the community, I thought it better to start to restructure the project in such a way that it can be easily maintained uneasily mod it.

  • Consequently, I've decided to create a new project, so let's do just that.

  • Here is a blank visual studio Windows Consul application project on All I've got so far is a main dot C P p, with a blank into main function.

  • I know now that I'm going to want to split to the project across multiple source files on going to abuse object oriented programming to help me out.

  • But that means we have to use the pixel game engine in object oriented programming mode on because the pixel game engine is a single had a solution.

  • This can add additional complexity.

  • The easiest way to use it in multiple files is to create a single CPP file.

  • I'll call it OLC pixel game engine dot c, p.

  • P.

  • And in that file, I'm going to include the head to file.

  • This gives the compiler long translatable unit on.

  • This means we can include the OLC pixel game.

  • Engine dot h fell from any other file, and we won't have any multiple instances problems in the same father.

  • I'm also going to include the graphics three D extension to the pixel game engine on.

  • In fact, we'll do this for any extensions that we load into the project.

  • The idea being that this CPP far gets compiled once by the compiler on any of the other project files that used these objects will be able to find them.

  • I'm not going to add a class to the project that represents the main game engine.

  • So this is the one that inherits from picture game engine.

  • I'm going to call it a car crime city.

  • And to this class, I'm going to add our three familiar functions that we must override on user create called Once on use update called every frame on on user destroy.

  • When the object is shut down, you'll notice that above the include were not defining o L c p g application.

  • That's because we've already done it once in our OLC pixel game engine dot CPP file.

  • So the instance of the pixel game engine exists here but we want the definitions available to multiple files else work as we have here with the C car crime city class.

  • Let me just give a brief overview of the project structure.

  • This isn't necessarily a class diagram, but it's showing how I'm breaking up the project on To start with.

  • We have our car crime city class.

  • This is where the main game is going to be executed on.

  • We're going to configure that class externally in Louis with an object that represents the game settings.

  • Now, this isn't just parameters to describe the resolution, et cetera.

  • It can also include things like the missions in the story and everything else that we want to externalize at the moment.

  • The game consists of five primary systems.

  • The first is an object that describes the map on the layout of the city.

  • The second is a system that brings the city to life.

  • This handles the traffic on the pedestrians.

  • The third handles the physics on.

  • We won't look at this in any detail in this video, but this will handle things such as collision responses between the cars on the handling of the vehicles when the player is driving them.

  • The fourth is the rendering system.

  • This is responsible for drawing things to this screen on.

  • We'll see that the rendering doesn't always happen in just one place.

  • The objects will be responsible for rendering themselves Howard, but something needs to bind that and bring it all together.

  • The fifth system is broadly labeled artificial intelligence, so this will handle the game mechanics things such as the police chasing the player or has the player fulfilled?

  • Mission objectives today will primarily be looking at the top two.

  • As with part one of the video Siri's.

  • The city is divided into cells, but unlike Part one, each cell is now particular type and so far have four cell types.

  • Plane, which represents an open space.

  • But it's driveable.

  • Water is not driveable but needs to be rendered in a different way.

  • Building cells contain well buildings and all buildings now R O.

  • B J files created externally.

  • We're not generating them based on their height, as we did in Part one.

  • This allows the game engine to import models created by the community and finally, roads on.

  • We'll be looking at roads quite a lot today.

  • Oughta Marta is also split into three different types, although for today I will be sticking with the base class Oughta Marta, rather than breaking it up into these three types, And that's just to keep the video simple, because right now there's no discernible difference between the three types of automatic.

  • But we're going to have one that represents the traffic and the cars, one that represents the pedestrians walking around and one that represents the police.

  • So to recap in this video, we're going to be looking at the game settings, the main game class to subsystems controlling the city map and the things that dwell within it, how the cells is structured and how the four types of cellar have so far are constructed.

  • This project is of a much larger scope than any of those I've tried before on the channel, and as a result, I'll be pulling code in rather than talking through it line by line.

  • Now, regular viewers of the channel may have noticed that so far this year have done videos on operator overloading, polymorphism, object collisions and luring bedding, all of which I'm going to use and abuse to great extent in this video, I'm going to start by introducing the game settings because we need thes before we actually do any of the game.

  • It's going to also contain information that defines the screen resolution and how the window appears to the user on as I did with code it yourself role playing game, I'm going to create a singleton object that's loaded once with all of this information, I'm going to add a class called Game Settings onto this class.

  • I'm going to add the necessary code to include Leuer.

  • This class is going to store information about how to display things to the screen, and it's going to get that information by loading a Louie file and executing it in the game, setting CPP far with lots of static variables.

  • So I'm going to initialize those two some default values in case the Louis file can't be found.

  • This set up blue file is not going to be persistent.

  • It's going to be loaded and executed once on this game.

  • Settings class will then contain all of the relevant information, so I'm going to create the Louis ST I'm going to attempt to open the file and then I'm going to attempt to execute the file.

  • If any of these fail, it will display a message in the council window attached to the game window, which is very useful for debugging.

  • I'm then going to extract the parameters one by one from the loo file.

  • Once I've got the information I need, I'm going to close the loop file on return.

  • Now I can go back to my main CPP file on include the car crime city class on the game settings class thegame settings is the first thing I want to load.

  • So I'm going to create an instance of my game setting Singleton on Call the load conflict file function passing to it the particular file path.

  • Once I've loaded the settings, I can then create an instance of the council game engine on.

  • I'll start the council game engine in the way that I usually do, but now I'm going to use the parameters stored in the singleton.

  • I'll call the construct function, and I'll use the properties to configure how the screen looks when we specify the width, the height, the pixel with the pixel height and finally, a mystery bonus parameter, which not many people know about.

  • But if you specify a Boolean value as 1/5 perimeter to the construct function, you can force the pixel game engine to use a full screen mode.

  • If it successfully constructs, then start the game.

  • I've added the conflict Louie file to my solution so I can easily find it and change it.

  • And the nice thing is, visual studio.

  • Will syntax highlight the lower correctly on right now all I have in my Louie file other parameters that we were looking for alongside these mechanical values.

  • I also want the settings class to contain other information about the objects I need to load into the games, such as textures on Mash is this way.

  • They're not hard coded into the game engine and can be modeled externally for textures.

  • I'm going to create a little struck that contains the name of the texture on the path to the file on.

  • I'm going to create a vector of thes stroked to store into my singleton thegame engine is going to require a minimal number of textures.

  • Want to represent the grass, the roads, the water, some clouds which reflect in the water the sides of the water.

  • Onda smoke decal.

  • In this case, these are fixed, so these must exist, though the user can change what they look like.

  • So in Lieu, I've created a blank table called textures on populated it with the name on the file path to the PNG file that represents that texture.

  • Reading tables into Lou is not something I covered in the embedding lure video, but it follows the same set of principles.

  • You just have to remember where Europe to when loading the table, I'm going to look for a global object called textures.

  • That's the table.

  • I was going to make sure that it exists.

  • As with many things in lower tables are key and value pairs.

  • So here is the key, and here is the value.

  • But what type of value is this?

  • Well, in fact, it's another table, so this description has in fact created a table off tables.

  • Now, in my c++ code, I'm not going to explicitly search for a particular key.

  • I just want to load in all of the textures that get defined here, so I could quite happily add more.

  • I'm not interested in the key, but I am interested in Iterating through the values on.

  • I can do that with the Lewin next statement going to sit in a loop, asking it to push to the top of the stack the next table.

  • And this is where Louis gets its reputation for being a little bit confusing when embedding and see what do these indexes mean?

  • Well, I did explain them in the video, but ultimately we found a table at the top of the stack on with Pushed an empty value there.

  • So when we're searching for things, the original table has moved down one.

  • So after this Lewin next function, the top of the stack potentially contains our value, which is another table.

  • So I'm going to validate that and in a similar way, get the table on it, a rate through its values.

  • In this instance, the values of these two strings grass on the path to the file name.

  • Now, the way I've set this up, I'm just asking Lewis to return those strings in order.

  • So I'm going to need to count through them to know what they are here.

  • I'm going to create an object of the texture on a stage counter on depending on this stage.

  • I know whether it's the name of the texture or the file.

  • Either way, for that particular returned object, I want to pop it off the top of the stack and increase my stage counter and likewise with my parent table containing all of the textures I want to pop the most recent one off the stack and store that texture in my vector of textures.

  • I get that in this brief description, this might seem quite complicated, but to recap, we find the parent table called textures, and then we iterated through that table element by element.

  • The elements themselves happen to be tables on those tables contain multiple elements through which we iterated on identify which element is which by maintaining a counter.

  • Once we've extracted the relevant information from the table, we can construct our texture, object and push it to the vector of textures.

  • The system textures are one type of asset, but we do have another, which is model files.

  • So the O.

  • B J files that represent the buildings in the cars for these assets on story who's created them and a description of what it is a path to the object file on a path to a single texture used to texture that object file.

  • I'm also storing some three dimensional transformation information on how to rotate it, scale it and translate it very quickly.

  • After starting this project and people contributing models, I realized that most of the models are going to come back in all sorts of shapes and sizes, not necessarily how I want to use them in the game.

  • So this information allows me to tweak the model externally before importing it into the game without actually needing to change its geometry.

  • And I'm going to store these two types of assets again in vectors one for buildings on one for vehicles, the loo.

  • If I'll works in a similar way, we can see the name of the creator of that object, what it's called a path to the object file on a path to its texture, along with nine pieces of information to describe how to transform it.

  • And so far I'm loading two types of buildings and six types of vehicles, all generously donated by the one lone coder community.

  • Regardless of whether the asset is a building or a vehicle, I'm going to load it exactly the same way.

  • So I'm going to create a lander function, not a little one this time to load the table off tables.

  • You'll see.

  • It follows a similar pattern toe how we loaded the texture.

  • There's just more stages this time.

  • I can then call that lambda Function toe load my buildings on my vehicles on, populate the appropriate vectors.

  • Now in a single user configurable Louie file, I can change many properties of the game on what assets are loaded into it.

  • This is great for modeling on all of this information is loaded into the game on start up.

  • Note that we've not actually loaded the textures of the objects.

  • We've just loaded the file paths to their location.

  • So now it's up to the pixel game.

  • Injured toe.

  • Load those resources, so I'll go to our car crime city class, and I'm going to add a load Assets function on three standard maps.

  • The maps allow me to associate the name of the asset with an instance of the acid, and I have three different types, one which is a map toe.

  • Hold all the textures which OLC sprites one, which is a map to hold the mess.

  • She's, which are part of the three D extension, no different from the code it yourself through the engine Siris on what we used in Part one on 1/3 map, which stores a matrix that contains that transformation.

  • Information for the red in objects.

  • So I'm going to give our car crime city class access to the three D graphics extension onto the game setting.

  • Singleton, the car crime city class, currently doesn't have anything in it, so let's force it to load and create The assets is required, as described in part one of the Siri's.

  • There's some assets, which is just going to be fixed, such as a flat unit quad.

  • In this case, I've created the mash manually on I'm going to add it to my map of meshes.

  • I'm going to label it unit quad on, give it the information.

  • There are other bits of fixed geometry to, such as the sides of the water.

  • In this case, it's four walls facing outwards again.

  • I'm going to add it to the map and call it walls out.

  • Now I'm going to load the system textures on These were the ones specified in the loo file.

  • To do that, I'm going to use an auto four loop, too literate through the vector of texture, assets for each texture assets I'm going to create a new sprite on.

  • I'm going to load the texture into that sprite.

  • But importantly, I'm also then going to add a pointer to that texture to my map of acid textures, using the name defined in the loo file.

  • I'll take advantage of this opportunity to inform the user if it can't find the file in Part one.

  • I spent some time describing how we break up the road because it comes in is a single texture, but it's more convenient to use as multiple textures defining each road pattern.

  • I'm going to do exactly the same here, loading up the road master Sprite and then breaking itself into individual road textures.

  • Here, you can see again, I'm naming them on adding them to the map of texture assets.

  • Now I've loaded all of the required textures for the game.

  • I can start to load the buildings.

  • The buildings are going to be self contained objects because that's how the community can easily create them and just donate them to the project.

  • I know that in my game settings class, I have a vector of assets that represent the buildings they contain.

  • The objects, information on the texture information.

  • So I'm going to add to my map of mesh is a new mesh.

  • Given the name of the building on that mesh could go and get its data by loading the object file associated with that building.

  • We can also load the texture associated with that building.

  • And here we see why naming the assets was a good idea because it keeps everything together.

  • We'll just have to be careful not to have assets with the same name identified in the loo.

  • If I'll fridge building, we had a mash a texture on a transform.

  • Transform was split up into nine components to represent scale, translation and rotation in each access.

  • I'm going to do some heavy handed matrix math here to take those nine values and construct one final matrix, which represents that transform and again using the name of the asset I'm going to store that transform in my map of transforms and in a rather clumsy but identical way, I'm going to do exactly the same for vehicle objects.

  • I did warn you this was going to go quickly.

  • Let's have a look at the structure of a cell object from the first video.

  • You may remember that cells contain very little information, just the exposition in the world, the white position in the world and whether they were solid or not.

  • We'll use the solid bullion to construct collision geometry later on.

  • Now I'm going to give the sells a lot more responsibility and has identified Alia.

  • We're going to derive subtypes of cell from some cell based class, and I'm going to exploit polymorphism to do that.

  • But I also want some rough reflection capability off the cell object so it can tell what type it is.

  • We can interrogate the cell and work out.

  • Is it a road, or is it a building quite easily?

  • So I'm also going to throw in a type of cell information, But what are the responsibilities?

  • Are we going to give the cells well?

  • Firstly, they're going to be responsible for drawing themselves.

  • Now they're going to have three types of drawing, so we're going to have a function called drawer base and that's responsible for drawing the contents of the cell for reasons that will become apparent later in the series.

  • I'm also going to have a drawer Alfa.

  • It's important that we draw transparent objects after we've drawn the base objects on, because this is a big project and it's going to get complicated very quickly.

  • And we'll have 1/3 drawing layer called Draw de Bug, which will allow me to visualize information aboutthe state of the cell as we saw when we were constructing the road networks.

  • The neighborhood of the cell is quite important to determine what the cell looks like and how it behaves.

  • So I'm also going to include a calculate adjacency function, which allows the cell to adjust itself based on its neighborhood.

  • And finally, this cell may contain assets such as buildings and other objects, so it needs a way to access the maps of the assets that we've loaded.

  • So I'm going to create a final function called Link Assets.

  • On the cell itself will decide what assets it's interested in using by using the names of the assets that we've specified, so lets out a base class cold cell.

  • Since the sale is going to be responsible for drawing itself.

  • I'm going to give it access to the game engine on the graphics three day extension and identified that cell is going to need some way of knowing what type of cell it is.

  • So our creator, an enumeration off various types of cell in the cell.

  • We're going to give it the basic properties so it can identify where it is in the world on whether it's solid or not on.

  • Because this is a base class, I'm going to define six virtual methods to be overwritten by the sub classes.

  • The three drawing functions will take in references to the pixel game engine on the current three D rendering pipeline.

  • I'm included an additional book date method to the cell, just in case it has behavior that changes over time.

  • On here.

  • With the Link assets function, we can see we're just passing references to the maps of the assets we created earlier for textures, meshes and transforms a cell on its own is meaningless.

  • It needs to belong to a collection of cells which, fortunately for us, defines the city.

  • So I'm going to create another class that's actually defines our city.

  • I'm going to call it C City map, and it's important that the cell knows which map it belongs to.

  • So I'm going to create a second constructor, which is going to take a pointer to the city map on its location within that map on our forward declare city map because the city map is going to contain cells which contain pointers to the city map.

  • So we've got a bit of a circular reference going out, and I want the pointer to the city map to be accessible to derived objects of this class because otherwise we won't be able to calculate the adjacency cell exist in isolation.

  • But when it wants to check, its neighbors is going to have to look at the map and then calculate what its neighbors are and get access to them.

  • The city map is really nothing more than an array off cells, the dimensions of which specified by the constructor.

  • So I've changed the constructor to pass in the width and the height, but I'm also going to pass in the maps to our assets, and it's going to need access to these maps because it's going to construct a default city which means it needs to construct all of the cells and the cells need access to these maps in order to draw themselves and behave appropriately, I'm going to have some rather mundane functions such a saving and loading cities, getting the width and height, getting a specific cell on replacing a specific cell.

  • I'm not going to go into detail on how those operate, but fundamentally we maintain the array of P cells.

  • Here.

  • I'll have two more methods to create the city, which is really a mirror of the constructor on destroy the city to free up all of the memory that we've allocated in the city map CPP file.

  • For now, our constructor is just going to call the create city function by default.

  • We're going to create a city that contains of nothing but grass and when the Destructor is called, is going to call our release city function.

  • I'll add in the more boring things, such as getting the width and the height on getting a specific cell.

  • If the cell is out of bounds, it's going to return no pointer.

  • Otherwise it returns a pointer to the cell that exists in the array.

  • The replace function.

  • Deletes the existing cell on replaces it with the new one.

  • Let's just run through the create city function.

  • If a city already exists, it's going to release it.

  • If not, it creates an array of pointers to cells.

  • And then, using a nested per four loops, I'm going to iterated through all of the cells and create them by default.

  • They're all going to be of type cell plane, which we must implement it yet, but it's just going to be a grassy square.

  • But as I create each cell, I need to give it access to the assets that it's going to use.

  • So every time I create a new cell, I'm going to call the Link.

  • Asked its function on used the maps to the assets that we've created earlier.

  • I've gone on toward the release city on.

  • I'm not bothering with saving or loading cities just yet, but here we can see there is an error to see cell plane, and that's because we've not created a derived cell type called Plain.

  • So let's do that.

  • That's at a new class cell plane on its going to inherit from the base class.

  • Just see cell.

  • Since this class does inherit from C cell, I'm going to implement the functions I want to override, which in this case is link assets updating on a couple of the drawing functions, and it's taken a long time getting here.

  • But now we can see why linking the assets is a good idea.

  • This cell plane requires a certain set of assets in order to draw itself appropriately.

  • It requires access to the unit quad, and it requires access to the grass texture or the pavement texture, and you'll see that these are just pointers.

  • So we only ever have one instance of that particular asset.

  • But we're going to re use it in multiple cells in my implementation.

  • Off the plane cell, the cell can either be a grass type or an asphalt type, which I'm going to specify with a little in you Marais Shin on.

  • I'm going to override the default constructor with this custom, one that links to the map, its position in the world and what type of plane it's going to be in the constructor for the plane.

  • You can see that we actually call the base cell constructor with this information We've just tagged on a little bit of extra information for this specific plane type.

  • The first functions override was link assets, and this is where we can see that mapping was quite useful.

  • Because if I want to draw this as a grass plain or an asphalt plane, I could just choose development texture.

  • So in this case, I'm storing pointers to both types on deciding when I'm drawing it, which want to use.

  • I'm also storing a pointer to the unit quad mesh, and so the cell can extract the information it needs quite trivially for the programmer.

  • For now update, is it going to do anything?

  • But we're going to draw the cell based on its type.

  • So this is the drawer base function which were overriding.

  • We construct a transformation matrix to translate it to the right place in world space.

  • On dhe, we take in the pipeline from the three D extension on set that transform to it.

  • We then choose which texture to apply to the quad on.

  • We tell the pipeline to render that unit Quat.

  • This is all exactly the same as the first video on other three D bits and pieces of Don since then.

  • For now, there is no Alfa component, so the functions not going to do anything.

  • Now we've got structures that represent a particular type of cell on the overall city.

  • We can go back to the core game part now on render something in on user create.

  • I'm going to load our assets, and I'm going to create a blank default city called P City, using the settings pulled in from the loo file.

  • I'm not going to pull in various parts from video one which were used to edit the city.

  • I'll speed through this, though, right so briefly.

  • What I've done is added the Mount Selection feature here with a function called Get Mouse on ground on in Unusual update, depending on whether the tab key has been pressed, were in edit mode or not before an edit mode.

  • Then the mouse selection code is executed so we can work out where the mouse cursor is on.

  • Apply the appropriate edits to the terrain, one of the slight differences.

  • Rather, if you've ever looked at my panning and zooming video, I've added that functionality.

  • Now that I've got the mouse will so I can hold down the mouse wheel to move the scene around and zoom in and out by scrolling it in much the same way.

  • In the previous video, I work out what the visible extent of the universe is on.

  • I update the cells for that visible extent, and then I start to render the scene, create a rendering pipeline on one little new feature I've added to the three D graphics engine, which I will go into a few more videos about in detail, which is the lighting engine that's been added to that.

  • So now you can add in several light sources as well.

  • And then I start to render the objects.

  • Remember, I have three different types of rendering call for an object.

  • So I scroll through the visible objects and render the base passing along references to the pixel game engine on the pipeline use for the three D rendering.

  • Then I render objects that may contain some Alfa components because they need to be drawn on top of existing objects on if we're in edit mode exclusively, I'm also going to call the drawer debug function for the cell, so these are all four loops doing exactly the same thing.

  • And again, if we're in edit mode, remember, we could select multiple cells and draw them.

  • This is exactly the same as it was in video part one, except this time I'm drawing the unit quarter from our map off pass.

  • It meshes as a wire frame.

  • And so, for the first time in this video, let's take a look on dhe.

  • As before, we can see a blue background with a green plane in the bottom quadrant, but I can use the mouse now to zoom in and out, consume right into the texture on.

  • I can use the middle mouse to sort of pick up and scroll the world around.

  • I can select cells at different zoom levels on right click to UN Select.

  • One thing to note is, let's test our Lou a framework.

  • Clearly, it's loaded the correct grass texture, but let's see if the other parameters have also come through.

  • So the first thing I'm going to change in our Louis file it's just the size of the pixel.

  • Before it was two by two scraping pixels.

  • Now I can run this.

  • You'll see there's no compilation, but yes, it has changed the pixel game engine.

  • Excellent.

  • That means our little file settings are being loaded.

  • We've only got the one type of cell at the moment, and that is plain.

  • So let's our buildings.

  • I'm not going to subject you to a line by line on this, but here is the cell building class on.

  • It's going to store locally its name, a link to its texture linked to its national, linked to its transform.

  • Now, because this cell building class may have lots of different types of building, we used the name parameter to identify which particular one this needs to link to, and we can extract the relevant resources from our maps of assets.

  • Drawing the building is very simple.

  • As usual, we create a translation matrix to offset it to the correct location in the world.

  • On dhe, we multiply that translation matrix by the building's transform matrix.

  • This is the one created from the parameters in the loo file, with then apply that combined transformation to the rendering pipeline on if it has a texture or not, we decided on the appropriate rendering method, and that's it.

  • I'm going to assume for now that buildings don't have alfa components.

  • Buildings were very simple.

  • So let's add another one, which is water.

  • So this is cells.

  • They're going to contain water now.

  • What has rendered slightly differently because I wanted to reflect the clouds on top of a water texture, and we'll take a quick look at how that's done.

  • But you can see it takes local links to the resources that it's going to need on water.

  • Is also going to override the calculator Jason See function.

  • And that's quite important because we want to render the water cell.

  • Depending on whether its neighbors are water to sew in.

  • The link assets function is going to be a unit quads.

  • To render the actual layer of water on, we're going to use our mesh of walls to independently draw north, south, east and west walls for the water.

  • Don't forget.

  • The water sits below the ground plane, so it has some walls there to keep the water in.

  • But we only want to draw the walls if the neighbors are not water.

  • And so that's exactly what we do in our calculated Jason see function.

  • This is called once when the whole map has been changed because there's no point in calling Jason.

  • See calculations as we're placing the items you need to do it on a map wide basis, and what we do is very simple.

  • We take this current cell's location in the world and we look at its immediate neighbors.

  • If those neighbors are off the type, sell water, then we populate this array of billions to say Yes, my neighbors are water.

  • When it comes to drawing the water, we take our usual translation matrix and we set up the pipeline.

  • But then we draw the four walls individually, depending on the state of the neighbors.

  • So we've got this information are calculated Jason see function, which allows them to render the appropriate scenery.

  • But water does involve drawing in the Alfa face because these are the walls of the water and the water level itself sits halfway up the walls on its transparent, so we can see a little bit of the world beneath the water.

  • I wrote detailed list, but I will highlight it just so you can go and have a look at it yourself.

  • Some of you may not be familiar with the pixel game engine, but it does have the ability to implement pixel shading.

  • You can specify your own shader as to how it blends textures together on.

  • In this instance, it's blending a water texture with a cloud texture, but the cloud texture remains in screen space, so it looks more static than the water texture.

  • Now that we have additional cell types, we need to be able to place them in the world, and this is done in the do edit mode function.

  • So remember the tab key will enable edit mode, allowing us to change the world.

  • The code at the start of this function is just a handle.

  • Multiple selected objects or not on was discussed in the first video.

  • If anything changes the map in a significant way, we need to run through all of the cells in the map.

  • On call the calculator Jason see function so they can all update themselves, depending on their neighbors.

  • And so, given a set of selected sells, the user compress a key to determine what those cells because in this case, if they press G, we go through all of the cells in the selected cell set on replace them with grass cells remembering to link the assets to the new cell, we flagged that the map has changed because we may need to get the cells to update themselves based on their neighbors.

  • We have two types of plain sell.

  • One is grass and one is asphalt.

  • So if the user presses, the peaky will change it into, well, pavement in this case.

  • And if the user presses, the W K will do the same for water.

  • For now, I'm going to assume one building type and I'm going to put a building that based on whether the CUCHI has been pressed, you see each time we using polymorphism just to override the cell that exists.

  • But in this case, we're sending the name of the particular building model into our building class constructor on its this name, which will be used to link the assets for that particular cell.

  • Specifically, this name comes from the loo file that we specified at the start.

  • But right now for this video, I've hard coded it in here.

  • The intention is to have a drop down menu that allows you to select a particular building type and use the name of that building to link all of this together.

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

  • I've got my map of empty grass.

  • I can select themselves, set them randomly and change them to pavement.

  • Very nice.

  • What was the other time?

  • But we've got We've got water.

  • So again, Simran themselves now water required adjacency information to draw the walls on.

  • We can see it's only now drawing the walls where it needs to put them on.

  • There's some transparency happening, so it's during the wall first and then drawing a layer of water on top, and you might not be able to make it out in the YouTube video.

  • But there's a static image off some clouds in the background to give the appearance of some kind of reflection.

  • Maybe I need to balance that a little bit more.

  • It looks a little bit like the map is floating about in the sky anyway.

  • Finally, we can try buildings, which was the cuchi, and so this is a building object created by a member of the one lone Code Discord server.

  • It's an object file is loaded up with the appropriate textures, even though we've got multiple buildings they're all linking to the one instance of the assets, so we're not wasting resources needlessly.

  • The final cell type is, of course, the road on.

  • We've got a bunch of different road types for this South, depending on what junction or corner it represents, and it works in a very similar way to the water.

  • It needs to know what its neighbors are.

  • So during the calculator Jason see function.

  • It can choose the appropriate texture for its unit quad.

  • In the previous videos, the road choice was selected during the rendering stage on This is perhaps a little bit not the best way to do it, so instead, we're doing it at the edit stage on those familiar with video.

  • One will immediately recognize how we're calculating what type of junction should be displayed for a given road cell at the link assets face.

  • We're just choosing the appropriate texture and creating a link to that particular sprite on drawing the road cell is even simpler.

  • We calculated position in world space, give it the appropriate texture and simply draw it to the screen in the main car crime city class.

  • In the edit function, we're going to respond to the R key being pressed, which just replaces the selected cell with a road cell type.

  • We indicate that the map has changed so it goes through and then calculates the adjacency for all of the new cells.

  • So let's just see that in action.

  • I just see a marriage a little bit on.

  • We'll draw a test pattern that will choose all of the road sections five by five grid So we get all the TI junctions, all the corners, vertical horizontal on a crossroad, not press the R key on it.

  • Selected the road and you can see I've updated the texture for the roads.

  • Now very nice.

  • Just throw a few buildings in here.

  • I probably had a way to rotate the buildings.

  • Let's have some water and some pavements, right?

  • So we spent the first half of this video essentially recreating what I made in part one of the Siri's.

  • But this time around, it's far more modular than easy to extend for the next part of this video.

  • I'm going to look at adding life to the city on.

  • This is going to get a little bit complicated because we're going to use multiple layers of transportation grids, and I'm going to start by issuing a big warning.

  • There's a lot more code to this than Aiken sensibly show in the remainder of this video, but I will talk through the main points of the algorithm.

  • And of course, the code is available for you to look at from the get hope linked in the description below.

  • There is a lot going on regarding transportation in this city, and it fundamentally involves the ownership of pointers to objects, as has been well established by now.

  • We know the city is a grid of cells on a subset of those cells.

  • Specifically, roads need to contain information for things to move around on them.

  • Here have constructed a small section of road network on we concede, divided into several pieces.

  • These two shaded in tiles are not road sections, but everything else is.

  • The blue line indicates the boundary of the pavement.

  • That's where our pedestrians air going.

  • Toe walk.

  • The green line represents the road markings, so we've got two lanes on all of our roads.

  • I'm going to assume that anything that moves around is going to stay on a track that follows the profile of the road.

  • I'm going to assume that all the things that move around are going to follow a track like a railway, so cars and pedestrians will follow a particular path around each road section.

  • So for this corner section, we've got a piece of track that behaves like this on a piece of track but behaves like this.

  • That's the handle.

  • The cars.

  • We also have additional track toe handle the pedestrians on a small one in this corner.

  • So far for this corner, we've got eight pieces of track because I'm going to define a track as being a straight line between nodes.

  • And so what we see here for this pedestrian.

  • We have a note here and a note here for the road and note here for the other lane and a note for the pedestrian in that corner.

  • But I'm also going to have a note that the cell boundaries strange sections of road a bit simpler.

  • They have a single piece of track linking one edge to the other.

  • T junctions offer several possibilities for the cars on the pedestrians.

  • Firstly, we can see that traffic coming in on this lane could go straight across or it can turn right.

  • Traffic coming from the bottom can immediately turn left, or it can join to the path of the top, and traffic coming in from the right could either turn right.

  • We'll go straight across.

  • So when I place um, nodes into here, we can see we get a fairly regularly spaced set of nodes to represent just the cars.

  • Pedestrians also have several options.

  • I want to draw them in orange this time, just so it's a bit clearer they can go straight across or they can choose to cross at this junction.

  • Now we know in these little corner pieces we have several path options available there.

  • They could go straight across again to several here on down so I can draw in the nodes for the pedestrians.

  • In this instance, you can see that I'm not linking the pedestrian tracks to the car tracks on.

  • This makes sense because I don't want the pedestrians to follow the cart paths.

  • We can make an assumption that the worst case scenario for tracks and nodes is a crossroad, which I've drawn here.

  • These corner sections are the little bits of pavement that eat into the crossroads section, starting with the traffic we know we're going to need nodes on the boundaries of the cells on.

  • We're going to need nodes to allow them to turn from any direction to other directions.

  • So I'll drawing the tracks between the nodes for traffic pedestrians to also come in from the boundaries.

  • But they also have the opportunity to cross the roads, which they do at the level crossing.

  • So even though we're using the same node and track structure, we can formulate it in such a way that the two don't interfere with each other.

  • So we've got one system for the automatic known as cars.

  • Another system for the automatic known as pedestrians.

  • If you remember in the project structure, we had 1/3 1 which was for cops on.

  • Cops are going to cheat because they're not going to drive on a particular lane to keep the implementation of this reasonably simple.

  • I don't want tohave the policeman trying to avoid all of the local traffic, so to give them a fighting chance, they're going to drive along the middle of the road sections.

  • So this implies we've got 1/3 transportation network, which is much simpler, which is for the police.

  • But it's also going to be used for the navigation aids within the game.

  • So things like GPS and and follow the path, that sort of thing.

  • We can use this very simple network toe handle navigation, perhaps using a star or flow like algorithm from one place in the city to another.

  • Tracks between nodes don't have any information about what direction the object that is on that track should travel in.

  • So when an object is placed on a track, it's placed one.

  • Here.

  • It keeps a track of which knowed it started at on will always travel towards the other note of the track.

  • This means that all track sections are bi directional.

  • When the object reaches the end node for a particular track section, it can choose to travel along any of the other connected tracks, but it cannot choose the track.

  • It's just coming on so naively it could choose to go up right or down.

  • In this instance, however, just giving it free rein like this would be catastrophic because cars would be coming in on their would be circling around here and moving up different roads.

  • They shouldn't be going up.

  • Generally, they'll be breaking the rules of the road.

  • So we need some additional information to make sure that they don't break these rules.

  • Since I'm British and I drive on the left of the road, if I have come in from this side of the junction, the only options available to me are to immediately turn left or to keep going straight on.

  • If I wanted to do a cuter, I could turn downwards.

  • But I'm not.

  • That's going to be breaking the rules.

  • So I need something to tell me that this particular route is invalid.

  • Likewise, let's say I have now travelled to this particular note.

  • I can't turn left, so that route is invalid.

  • I can go straight on or I can turn right.

  • Well, let's suppose I chose to turn right at this note.

  • The only option available to me is to continue going down.

  • I don't want to turn into the opposing lane of traffic, so that is an invalid option setting

Hello.

字幕與單字

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

B1 中級

大工程2合1!自上而下的城市汽車犯罪遊戲#2 (BIG PROJECT 2-in-1! Top Down City Based Car Crime Game #2)

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