Placeholder Image

字幕列表 影片播放

  • Hello.

  • It's time for another big project.

  • Let's make a top down role playing game.

  • Without a doubt, the most popular request I've had for a project is to create something along the lines of a Zelda game.

  • Now I love Zelda, but I've always been a bit more of a final fancy fan, so I thought would be an interesting project to try and merge the two together.

  • So we've got sort of Zelda game play battle and exploration dynamics.

  • But we've got a plot given in this style of final fancy, and this is what we've come up with so far.

  • So I'm currently controlling this little character walking around the map and you can see some effort has gone into the graphics.

  • Now all of the graphics have been created by the one lone coder community from people on the discord server on they're all still a work in progress because of this is a big project.

  • I don't have the time or resources or the skill, frankly, to create all of the graphics necessary.

  • I've needed other people to do that for me anyway, So we're looking around the map here, and of course, the we've got some collision detection.

  • We can't crash into the buildings or trees on.

  • One of the things we can do is end to the other building.

  • We could see the tile set has changed, and again we've got collision.

  • Whilst we control the guy around, we can exit the building and we go back into the town level map, all familiar stuff.

  • But for me, RPGs aren't just about walking around finding things on fighting enemies.

  • I like story driven RPGs.

  • And so a lot of effort has gone into this project to develop a system which will allow us to deliver a story to the player.

  • So here we've got another character and I'm going to interact with him.

  • By pressing the space bar.

  • We could see straight away the character or intakes to a known position, and some dialogue starts.

  • In fact, this guy wearing an orange T shirt is me.

  • Hello?

  • Let's make a no death on the character.

  • We called him Witty for now, don't know if that's going to stay or not.

  • For the end game on DSO.

  • I've still no control, but the script engine I've been calling it, the theater engine has taken over, and it's moving the characters around in presenting the dialogue.

  • I've got control again.

  • Now on.

  • I'll go on.

  • I'm not going to talk Thio myself, oddly, just yet.

  • I'm going to go step outside because one of the important things with a game like this is persistence.

  • But having that conversation has triggered other things to happen.

  • For example, now I've got the introduction of two enemies.

  • Now, before they come and kill me, I'm gonna go back inside.

  • I'll finish off this conversation so well.

  • I talked to the character again.

  • It's no good.

  • I can't make a video.

  • Why not?

  • Well, two things really, firstly, over lost the source.

  • Secondly, I've lost my glasses.

  • So this is the start of sort of two additional quests.

  • I'm witty because he's a helpful, resourceful type of guy, jumps up and down and says, I can help.

  • Then again, I've got control over the place that's all handled by this theater engine in the background.

  • We'll go outside and try and take on these enemies so the enemies have a limited amount of a eye.

  • At the moment, they just sort of follow me in a Terminator style mode on.

  • But they have to abide by the rules of the map, too, so you can see they can get stuck on solid things.

  • There's nothing clever going on here yet on.

  • We'll see throughout the course of this project that we can really sort of fine tune things on a per object level.

  • Because even though this is a video about an RPG, it's really a video about object oriented programming.

  • Let's take on this skeleton.

  • So we've killed one of them.

  • Now let's kill deal.

  • There we go.

  • This project is far too big for a single video, so it will be split over several videos.

  • I'm not yet quite sure the release schedule will be.

  • I'm still actively developing this budget, not to be different to a lot of my previous videos.

  • This one is highly object oriented on, but that's because I think people aren't really exposed to object oriented programming through most of the stuff that I've been working on.

  • Yes, we've used classes and strokes, but we've never really used them in any form of anger on object oriented programming approaches.

  • I deal in this situation because we've got lots of objects in the game that interact with each other indifferent and customized ways.

  • Also, even though I'm responsible for programming the engine, the best of the community is contributing incidents off graphics and maps and quests for at least they can do if they want to.

  • So this means we want to find a form of separation between the core on what we call it the assets.

  • And this is important because if the graphics, all the quests, all the objects, change, we don't want to have to hard code changes into the core engine.

  • An individual's approach to object orientated programming is polarizing.

  • No doubts about that, absolutely the way I am going to show how I Iove you.

  • Start excited.

  • Programming in this video is going to upset somebody so little personal disclaimer that this video is probably not going to be an example best practice when using object oriented techniques, but nonetheless, for the most part, I think you'll get a really good understanding of how object oriented programming can really enhance a partition, your development process.

  • But I will be breaking some rules now before we get started.

  • I got three of the things to say.

  • Firstly, I'm not going to be putting the source up at the end of this video.

  • I'll put the source or completed at the end of the project.

  • Secondly, at the end of the Post also puts up a compiled version of the game.

  • And thirdly, I won't be showing every line of code necessary in detail.

  • You'll see why object oriented programming has a lot of repetition and the size of this project.

  • If I was to show me typing out every single life, it would get quite boring.

  • And so, with all that's out the way, let's get started.

  • This first video of the Siri's is really about the structure of the project, and you can't start a big project without having to think about what the requirements are.

  • And for me, the most important requirement of a role playing game is to tell a story we also want to explore.

  • And this is traditionally split into towns and dungeons.

  • We know that just walking around isn't enough, so we probably also want to have some battles and as well as just battling, exploring on dhe, enjoying the story, The player also needs to feel rewarded, so we need some items weapons on power ups.

  • So let's just have a little bit more.

  • I think about telling a story.

  • Well, we know the story is going to have to involve some sort of plot.

  • There's got to be compelling.

  • It's got to keep the player engaged, and we're going to use the plot on the rest of the system to develop an atmosphere.

  • You know, something that will really absorb the play's interests in order to tell a story we're going to need.

  • Characters on DTH e cast of characters in some way needs to be scripted to form cooked sequences to facilitate exploration.

  • We're going to need maps on these Could be things like towns and dungeons.

  • This sort of stuff you saw at the start of the video well, separately, What hidden stuff?

  • So you get that real bus from finding something that you think nobody else will have found.

  • We're going to need a way for the player to move around these maps, so we're going to need in navigation on adjacent towns, and dungeons can simply load to each other.

  • But we may also want to go from one town to another.

  • So perhaps we also need a world map.

  • Battles are important, too, because that's how the play is probably going to grow their character through the game.

  • So we're going to need ah array of enemies so different enemies and will probably want the enemies to behave in different ways.

  • So we're going to need some sort of behavior.

  • A.

  • I battles also need to be balanced on.

  • This might take a bit of fine tuning.

  • It's no good if the first enemy of the game comes and kills you character straight away.

  • But they also need to be fun.

  • They can't be cripplingly strong.

  • They can't be boring on mind numbing button bashing to reward the player.

  • We're also going to use items, weapons and parables, and so this invariably form some sort of treasure system.

  • It couldn't it could be gold.

  • It could be exploring chest.

  • I think.

  • More commonly these days, it's known as loot, and by parents.

  • I don't mean turning the character into some unstoppable force.

  • It's usually an upgrade thio the weapons or armor.

  • But of course we're going to need something to keep track of all of this, so we're going to need an inventory on Dhe.

  • It's quite possible, the players going to collect lots of loot in the game, so we're going to need somewhere for them to get rid of it.

  • We'll have some shops.

  • It's interesting to see from this list already that we can start to identify what's game design and what engine design.

  • So, for example, the plot here that's a game design thing.

  • The game engine has to facilitate the plot.

  • But ultimately it's the game designers role to come up with the story, and the same goes for creating the atmosphere.

  • What does the art style look like?

  • What's the music like?

  • And how do those things tie into the plot?

  • The characters is a bit of both, of course, that's plot and atmosphere.

  • But what I think is important here is that we're going to have to have multiple characters.

  • So perhaps that's an engine design thing, and the same goes for cut sequences.

  • We need to think of.

  • How do we structure an order of events to display animation, dialogue, interaction to the player?

  • When we start thinking of maps, we know that the game engine must support the loading and transition between maps, but also the layout of the maps becomes a bit of a game design thing, too.

  • So we'll highlight later's game design and certainly hidden things.

  • That's purely a game designer thing.

  • However, moving between maps is probably an engine thing.

  • They'll be something on the map that says I must load another map.

  • And certainly the world map is an engine thing, too, because even though the world map will be designed by the game designer, it's it's basically the central hub through which the player confined all of the other dungeons and towns to visit.

  • When we start to look a different enemies, that's implies that we're going to need assets which behave and do things differently.

  • They look and feel different to the player, so that's an engine thing.

  • And how their behavior is implemented is also an engine thing to you won't expect the game designer to necessarily decide on the maths and physics involved to implement a particular a I.

  • So we're going to leave that in the engine collar.

  • However tuning of the enemies.

  • That certainly is a game design thing because that needs to fit in with the plot on what they expected experience level of the player is on making the battles fun.

  • Well, that's probably a bit of both, but that's still a game design thing to the types of treasure and loots.

  • Well, that certainly game design.

  • That's where you can potentially inject a little bit of humor into the game on the nature of the upgrades is also getting designed because we don't want to give the player the most powerful weapons right at the start of the game, however, upgrades have a minimal impact on the engine.

  • All they're going to do is increase or decrease a stat supporting and maintain an inventory, though that's an engine responsibility.

  • And so is implementing the shopping system by drawing it admittedly blurry line between the game design on the game engine design, we can start to see how to partition the project.

  • The player will mostly be interacting with the game through the top down view on, so that means we should probably start there.

  • So let's consider we've got the player character on The first design decision I'm going to make is that everything is based on tile maps on DDE.

  • Everything that's interesting in the game is going to be one tile wide by one tile.

  • Hi.

  • Now I know that my player character can move in the compass directions north, south, east and west.

  • But some sort of environmental map will say where the player can and cannot go.

  • So, for example, if we've got, say, a tree here Onda tree here on, say some more trees, why not?

  • Yes, those are trees.

  • Told you I'm not very good.

  • Well, we know that these tiles, well, these are solid.

  • So even though they've got a graphic in them will mark them with a red outline to say that these tiles are solid locations, the player cannot enter that tile.

  • And so this starts to yield some information about what we want to store in our tiles.

  • We're going to need an I D.

  • That represents the graphic that's displayed, and we're going to need something to say whether it's solid or not.

  • Now some of you will have seen some very similar ideas in the code it yourself platform game, and in fact, that's where I'm going to start because I'm not going to reinvent the wheel if you think about it.

  • If Mario didn't have gravity, it would be a top down, walking about gang or settled.

  • It did have gravity.

  • Link would be falling to the bottom of the screen all the time.

  • They're actually the same thing.

  • So I'm going to exploit the fact that I've already created a title map system with collision detection for this top down role playing game.

  • So this means we have a map in the background with static, solid objects in based on their cell location.

  • This would imply that it's anything that interacts with the map.

  • For example, the player character is a dynamic object it could move around on.

  • This is where we stopped it with the code itself platformer because we assumed we had one dynamic object, which was the player character on the rest of the map.

  • What solid, however, in the RPG were probably going to have multiple dynamic objects.

  • So let's say we've got a non playing character, an NPC well, we know that for cut sequences and other things that we probably want to move them around, so that makes him a dynamic object.

  • So let's not having to think about what a dynamic object is.

  • Well, we know that it's going to have a position somewhere in the world.

  • And because it's dynamic and we have a position, it's very likely we're going to need some velocity to.

  • We don't know yet what the full extent off the dynamic objects will be capable of doing, but we can probably make some assumptions.

  • For example, dynamic objects probably cannot pass through all solid tiles.

  • Herbert.

  • What is the dynamic object?

  • Was a ghost well or a bird.

  • It could effectively fly through the solid tiles, so I'm going to create a flag, which is, Ah, solid versus solid objects.

  • So that's sort of things in the map in the background.

  • But then I don't want my play character to be able to walk through other player characters that sometimes that could be quite route.

  • So I'm also going to have a flag, which is solid versus dynamic, and we'll see by manipulating these flags that we can extend the range of behaviors of what the dynamic object can and can't do.

  • But let's extend this idea of a dynamic object even further by considering that all dynamic objects are interact herbal on.

  • I think this is an important distinction to make, so if my player character walked over to the NPC on dhe interacted with it.

  • Something happens.

  • And so this makes me think that somewhere we need to handle an event, which is an on interaction between one dynamic object on another.

  • At the moment, I'm really throwing ideas at the screen to see how things come together.

  • We may change some of this in the future, but for now it's just to get us started.

  • Now this does raise a slightly curious question.

  • How do we handle, for example, interactions with things that look like scenery?

  • So let's say we had a sign post in the map.

  • Well, that sign post is indeed part off the map, and it's solid.

  • The player can't walk through it.

  • It becomes a solid tile.

  • But we could also place on top of this solid tile, a different type of dynamic object and this dynamic.

  • But it will have all of these properties, but most of them we ignore.

  • What we care about is the interaction.

  • So when the player interacts with this dynamic object, it displays that I don't know the name of the town or the direction to the shop.

  • We may also have other types off non obvious dynamic objects, for example here and this one might be slightly different that instead of the player choosing to interact with it, the play it interacts with it bite walking over it.

  • So in this case, we would set the solid properties of this dynamic object to false.

  • It's not solid, so my player can walk over it.

  • But when the player does walk over it, there's an interaction.

  • And in this case, this interaction might be to go and load another map.

  • Let's say I have another type of dynamic object.

  • In this case, it's an enemy.

  • The dynamic object in this case is controlled fear, behavioral A.

  • I.

  • So something else takes control of the position and velocity components to give some sort of movement behavior around the map.

  • And we could make an assumption that if our player character interacts with an enemy character than it's an attack of some sort.

  • But if our play a character interacts with the NPC, then it should be the start of a conversation.

  • It's a friendly thing on the third option.

  • Here is, of course, that the enemy character can choose to interact with the player which again is an attack.

  • So I think that a fundamental level, we need to decide whether things are friendly or not.

  • So I'm going to have another flag here, which is is the dynamic object, something that is friendly towards the player.

  • So already we've got quite a few different things.

  • They're all essentially dynamic objects that can interact with each other.

  • But for example, the sign post is is something static that cannot be moved around and cannot be walked over.

  • The NPC is against something that can move around by itself, as is the the enemy character that can use an air behavioral.

  • Aye, aye, to move it around and decide what needs to do.

  • And some dynamic objects are invisible to the pyre but perform functions because they're still interacted with in one way or another.

  • So even at this stage, we can start to think about class structure which would be suitable for a role playing game.

  • We know we're going to need a map on our map is going to have many tiles now.

  • I'm not using any formal notation here, but typically, if you're using something like UML, you put little star here to say This is a one too many relationship.

  • We also know that we're going to have something that's dynamic.

  • We can start to tell already that something with inherits from dynamic is going to be a creature, something living that's moving around.

  • So for inheritance, I'm going to draw an arrow that way.

  • We also know that something else.

  • It can also be dynamic of things like the teleport panels are the sign post.

  • So they're in some way some other type of interaction.

  • I don't know what we'll call these yet, but that also is going to inherit from dynamic.

  • And it's us creatures go.

  • We may have something like the player, which is a type of creature, which is dynamic, and we may have a particular NPC, which is a again, some type of creature.

  • And so, for interactive ble objects may have things like Guess that the teleport Oh, the sign post And you might be thinking, Well, why don't we just create teleport sign?

  • Post NPC and players all separate things?

  • Well, the reason being is we can make all of our control and management code much simpler if we classify them all is the same type, and this is really where the power of object oriented programming comes in.

  • So let's say, in our base class, which is dynamic, we have a function which is on Interact when we implement a player subclass well, the player doesn't really interact with itself, so this probably doesn't do anything.

  • However, when we override beyond interact function for an NPC, something may happen this related to the current quest, and we'll talk about quests in a later video.

  • But it could you know, for example, that produce some dialogue on the screen or give the player an item.

  • When we interact with the teleport, we know we can move the player to some other location on when we interact with a sign post we display information on the nice thing here is I don't need to code all the special cases.

  • All I need to do is provide the implementation for that particular object on because all of these objects are fundamentally a dynamic object.

  • I can store them all regardless of their subtypes in a single vector off dynamic objects, which means all I need to do is call the on interact function and the compiler will sort out which particular on into act code to execute.

  • And this is gold polymorphism, which fundamentally means that all of these sort of leaf classes here these are the main sub classes share something in common.

  • They share this interface specified by dynamic.

  • Yet how they implement that interface is up to the sub class.

  • This will become quite apparent once we start coding things up now, even though I've just shown that we're really getting ahead of ourselves.

  • Let's start with the basics.

  • Let's take the platform game engine and converted to something a bit more similar to what we want for this role playing game.

  • And so here it is.

  • This is the one lone Koda platform, a game code.

  • I'll just run it to prove it.

  • And it looks quite similar to the video that went out about this engine, and we're going to modify this to suit our role playing game.

  • After all, it handles all of the collisions between a dynamic object on the static background, and so the first language change is, of course, the name.

  • In keeping with the Nintendo entertainment system resolution, I'm going to use a 256 by 2 40 Array with the pixels are four by four.

  • We will want to make some significant alterations to this code.

  • For example, the original map was stored is a big string.

  • This isn't quite sufficient for a role play game.

  • Firstly, there's a lot more tiles in the role playing game than there is in Mario.

  • So representing the mall with characters becomes quite difficult.

  • But also there's not enough information captured here.

  • It assumes that anything that is not the period symbol is solid.

  • And that might not be the case for us, a typical example being that the before we saw our play a character walking across the grass on walking across the path so there isn't enough information here.

  • Additionally, editing these maps is quite tricky because it's not a faithful visual representation of what the map will ultimately look like.

  • Also, right now, the level is part of the executed, all on dhe.

  • This does have some advantages.

  • It can sort of be distributed as a single file, but it makes it quite tricky for the game design team to include the changes.

  • So I think it's time we start looking at the levels as being a separate file on a separate entity entirely.

  • And so I'm going to add an additional class and we'll call it RPG map.

  • And this is an important moment for the one loan coded channel, because the first time I think that we've done a project that's included multiple source files.

  • So it's gonna be rid of a test for me to see how we navigate around all this.

  • I'm going to use the ad class wizard just to add to files a dot agent adopt CPP called RPG maps, and we can see now it's created two additional source files.

  • However, I don't want a class called RPG maps, which is being lazy and using it as a way to create the file names.

  • What I'm actually going to call it is see map on because he's a lower case C to indicate that this is a class.

  • Of course, I'll need to change the names off the constructor on the destructor.

  • We must also make sure to change these in the CPP file, too.

  • Now, I'm not a fan of using setters and get is everywhere, particularly for simple basic variables, so I'm not going to on this case.

  • So if I want the width and the height of the map, I'm just going to make them accessible directly by declaring them is public.

  • I'm going to other function, which is get index on.

  • This is going to return the tile index for a given location index on in.

  • Why so the usual request to coordinate.

  • And it will return a single number, which represents which tile to display out of the tile map that's been associating with this physical map, and we'll see a little bit more about that in a minute.

  • But I also want another one, which is get whether the tile is solid or not.

  • In this instance, I'm not.

  • Creating the tile is a separate structure.

  • It's really not necessary.

  • But these two functions imply that I'm going to have a couple of a raise to I'm going to create.

  • These is private, and this means they won't be accessible to anything other than inside the sea map class.

  • And so my physical map is going to be stored as Honore Off Indices, and I'm just going to default to Noel Pointer.

  • We're also going to have a second array of billions, we'll call that solids.

  • There's some additional public variables that I'm also going to need.

  • Firstly, I'd like to store the name of a map.

  • So what map is this location?

  • Is it the village one?

  • Is it a castle?

  • What is it on?

  • I'm also going to want a pointer to a one lone code, a Sprite which you have seen in many of the previous videos on.

  • This is going to be the imagery that is used to display inside the map.

  • It's gonna be appointed to it on what is going to say, P Sprite.

  • Now we can see that a well sea Sprite is not defined.

  • And that's because it's part off the council game engine.

  • So I'm going to include that appear so it gets defined.

  • Now you'll notice that because of lots of bad practice reasons, by including this file, we've also just defined string on this because this head of file uses Ah, using name space S t d.

  • You really shouldn't do it that way.

  • But in this case, I'm going to justify it by simply saying I know I'm not going to be including any other package as part of this project final function, I'm going to add is a create function, which takes a path to the external file containing the level data, the pointer to the strike on the family name.

  • So it populates all of our internal variables.

  • So let's give these functions some code in the map CPP file.

  • I'm going to just give all of my variables a default value on whenever the map gets destroyed.

  • I know that I've got to a race, so I'm going to call the delete function to delete those a race for the get index function.

  • I'm going to check that the requested coordinate is within the bounds of the map on Return, the appropriate index for the array.

  • Well, so I'm going to return zero.

  • On the one hand, this means that the program will never crash.

  • It won't access memory that it shouldn't, but on the other, it will give a graphical glitch.

  • If there has been something that's gone wrong, you whatever tile is it Index zero will be displayed on the game.

  • Designers will probably quickly realize that things aren't looking the way they should.

  • Another option is to return minus one here, but I don't know how that get index function will be used later.

  • Down the line and minus one probably isn't appropriate for indexing into a different array.

  • So I'll return zero.

  • And it goes without saying that the get solid code looks exactly the same.

  • Accepted Index is a different array, so let's consider the create function well, The first thing that will happen is we're going to store the name on the pointed to the Sprite locally, so they're now part of the map class.

  • However, we now need to load the file that contains the level data on.

  • I'm going to use I F.

  • Stream to do this and to use my extreme, I need to include extreme thing.

  • This is another first for the one encoded channel reading an external file.

  • Well, it's always good to make sure that the file was opened correctly, so we know the file name was given.

  • It was proper, so we can check using the is open function to see if that's true.

  • If the file wasn't open correctly, we can return false.

  • So that gives some indication to the calling function that the file couldn't be found.

  • But if we did read the far successfully, We're going to return true now.

  • So you may be sent screaming Any computers?

  • No, no, no, no, no.

  • This is totally the wrong way to do this.

  • I I agree.

  • What we should really be doing is putting error checking in a fundamental levels on.

  • I'm not going to do that because most of the video would then be about how do we do error checking.

  • So I'm going to make some assumptions that my assets are in the correct format unnamed correctly.

  • I feel that the code at the end of this will be more useful for study if it hasn't got all the area checking stopping here.

  • I've got a text file full of numbers on This represents a level.

  • In this case, it's the the single house village scene you saw at the start of this video.

  • The 1st 2 numbers represent the width and the height of this area on after the width and height have been declared with then got pairs of numbers which represent which graphic to use on whether or not the tile is solid.

  • Now, in this case, that little village scene was surrounded by trees on the trees represented by Graphics index.

  • Nine.

  • Let's just take a minute to look at a tile sheet, so a tile sheet is basically a one line Koda format Sprite that contains all of the imagery required to assemble the map on it's indexed by moving along on checking what its width this.

  • So in this case, it's with its 10 Andi it's it's three high, so Index zero is in this top corner.

  • That's left sides we go zero on 23456789 So Index nine is this tree.

  • And by the way, this spreadsheet was created by Tom L.

  • On the discourse over.

  • And this Sprite viewers a really nice to always created my cross X on the discourse service.

  • Thank you very much for that on the spike was quite nice, because it allows you to zoom in and out and see the spikes an individual level, but also do some sort of analysis of what characters are there.

  • So knowing that Index nine represents this tree, we can start to see that we've got a border of trees around the level.

  • However, these trees are classified is not solid.

  • Why is that.

  • Well, let me introduce you another tool, this tools created by it A from the discord server on.

  • It's a simple map editor for the role playing game, and I just want to say this is a really good example of how the community is coming together to create utilities to support this project.

  • Without them, it just would be simply too much work for me to do on my own in the time scales that I have available on The Spite.

  • Editor allows us to select sprites fromthe sheet that we saw before and place them around so I can place trees anywhere in the scene.

  • And we can assemble interesting looking scenes we see at the top.

  • We've got the coordinates of the cell were interested in.

  • Now the file format we looked at before showed the row of trees with index nine, but it indicated that they weren't solid.

  • The map editor will allow us to specify whether a tile is solid or not, and we can see by going into the solid tool.

  • We've got a little red rectangle in the top corner of each tile to indicate the do salted.

  • So in this case, the building is solid.

  • The trees that we've just placed aren't solid on all.

  • So you could see that the door here isn't solid either.

  • That allows the player to step over the door, but this top row of trees is also not solid.

  • I could make them solid, but I don't need to because I know that surrounding the whole area is a solid wall.

  • The player can't get through to it anyway, So that explains why our top row of the map doesn't have solid trees.

  • So reading data using I extreme is quite easy.

  • We can read the 1st 2 numbers simply by reading them directly into the width and height.

  • Once we've done that, we can create our two arrays solids on indices on because we know the width and height.

  • Now, we then just iterated through the whole file one element of the time reading in the appropriate number into the appropriate array.

  • So now we have our map based class, but individual maps in the game are going to be sub classes off this class, so let's create one for the first village, so I'll create a class that inherits publicly from seem app called Village One.

  • And don't forget you semi colons and in the CPP file for the maps.

  • Now, because we've derived the village class from the basement class, we just need to provide the constructor on in this constructor, we're going to call the create function.

  • The first parameter is the path to the level files.

  • That was the file that contained all of the numbers we saw before.

  • The second parameter is a pointer to a Noel sea Sprite.

  • Now the constructive royal seeks Bright takes the path to the point cheats that we saw which in this case is located at RPG Data graphics on it's called Tom L Spite Cheat Duck.

  • The third parameter is the name of the area and I'm gonna call it Koda Town.

  • Why not?

  • And so, in this simple little bit of code, we've created the whole map and it's self contained.

  • We know that when village one comes into existence, it'll go on, populate itself with the relevant data.

  • Let's go back to our main program now on include our map class.

  • So let's start making the relevant changes to get rid of the built in map information to start using our external maps.

  • And so I'm going to do that by creating a pointer off Type C map to store current map.

  • And I can do this.

  • I don't need to make this pointer of type Village one, because we're going to use the inheritance and polymorphic attributes off object oriented programming toe handle.

  • That for us on visual studio is very kindly showing us now all of the things that are wrong with the code.

  • So these are all the locations that we need to modify to suit the new way of doing things.

  • So the first change we need to make is looking at the collision detection in the platform game.

  • If the cell was anything other than a period symbol, it was considered solid.

  • That's not the case anymore.

  • Now.

  • Instead, we want to look at our current map, and we want to get at the weather.

  • That's location is solid or not, so we want to use our get solid function.

  • Of course, we don't need to check for this anymore, and so I can make all of these changes anywhere.

  • We have a width and height of the level.

  • We also need to change, too So in this case, we can access these properties directly now and wit on n height.

  • This was all of the code to handle the camera following the object on the screen.

  • We don't need to change any of this is all completely valid.

  • However, the way that we draw the map to the screen is now very different.

  • We still need to get an index that represents the tile.

  • When I returned to type into now, it's no longer a Character Cola index.

  • But instead of this switch block, we want to calculate the X and Y coordinates off that index in the sprite sheet.

  • So to convert from a one D to a two day, usually we do it the other way around.

  • We're going to use modern and dip.

  • So our sprites X location, I'll say into SX is equal to the linear index.

  • Mod the number of tiles on our map, which I know in this case is Ted.

  • I know I'm putting in a hard number here.

  • In a later video, this will be updated and to get to the spike tiles y position we divide by 10 and it's important that this is all kept in the interview domain because this will give us the row that the tile is on because any information as after the remainder of this divide is just lost on this will give us the column that the Sprite is on in the tile sheet.

  • Now all we need to do is modify the drawer partial Sprite function with the new parameters.

  • So the X location is that still the same.

  • The tile with is still the same.

  • The tile offset.

  • None of that changes, however.

  • The Sprite does, so that's now currently stored as a pointer in our current map piece Sprite on the location we're not specifying by hand anymore, we're going to use our new coordinates.

  • This is really nice, because that means ultimately we can get rid of all of this, which makes our drawing routine much more compact.

  • To debunk this, let's initialize RP current map to be Village one.

  • That's compile.

  • Oh dear, we've got our first set of problems.

  • Can you tell how this was old scripted?

  • If we look at the error information at the bottom and I appreciate it's a bit small fundamentally, says one or more multiple E defined symbols found, and this is something we've always been able to avoid by doing things in a single file for the previous videos.

  • We now need to think about things a bit differently.

  • In fact, it's the consul game engine itself, which is causing the problem.

  • And if we look at the council game engine code right at the bottom, we can see we've got three global variables, which he used to handle the tidying up code.

  • When the user closes the application, well, they're not strictly global.

  • They're actually static variables that need to be defined somewhere on.

  • The problem we've got here is that our main program is calling the one lone code a console game engine file.

  • But also our maps program is calling the file, so they're being defined twice.

  • And this is because in ordinary circumstances, CPP files only get compiled.

  • One spider compiling, but heather files can be pulled in multiple times by whichever CPP file needs this stuff, and things like this should be declared in a c p p file to ensure that it's only compiled once.

  • So it's time to make the council game engine object oriented programming proof something to remove it.

  • I've already done this.

  • It's actually not a big deal.

  • I will add in that what I've called, I will see counsel game engine on.

  • What we'll see is it's exactly the same file with all of the same information.

  • And except for when you get to the core engine file, it's now slightly called it a different class.

  • It's just got the prototypes for all of the functions.

  • There is nobody to it onto the static variables that were causing us problems before our declared in the head of file.

  • But they're not defined here.

  • They're not given any substance.

  • Instead, that's done in the CPP file, where the rest of the council game engine functions are also filled in.

  • And this really has just been a couldn't paste job.

  • There is no difference to any of the internal code or workings, but at the bottom of the CPP file, we can see we've now got the definitions off the declared variables, so this means our main no longer inherits from the original council game engine is going to inherit from our object oriented version.

  • We must also change in our maps dot h file to include the object oriented version, too.

  • And we can see now when we've compiled there's not been a problem.

  • We've only defined the Cymbals once, and you'll see that this is a common pattern in object oriented programming.

  • Tohave ahead of file under CPP file where it's important not to do too much in the head of file other than declare the things that you might want to use.

  • So let's see what it looks like.

  • Well, it's pulled in the map that looks good on.

  • We could see Jerry Oh, from the platform.

  • Game is still available and he can stand on the treats.

  • Could you remember we didn't make all of the tree solid?

  • Yes, that means there should be on opening somewhere.

  • I think maybe, maybe not.

  • So I can't actually get Jerry oh into the world.

  • But gravity is also still in effect, which is something we don't want.

  • There we go.

  • So the map routine is handling itself.

  • It's drawing itself perfectly fine.

  • Good.

  • Both.

  • This brings about the secondary problem, and it's slightly complicated one, and that's regarding asset management.

  • Let's have a look at how we created that map in the first place to create the map.

  • We created a class called Village One.

  • Let's assume I wanted a second village called Village, too.

  • Very enough.

  • Go to our maps.

  • On we go down to the constructor where we'll create the definition for village too.

  • Assume this village to file.

  • But I want to use the same Sprite data We can see here, though, that each village will reload the strike data.

  • And this is inefficient because I could have 20 or 30 villages in this game.

  • I don't need 20 or 30 instances of the same Sprite information just to make this even more different.

  • We'll just call this bug town.

  • The better solution would be to load all of the assets we need.

  • Once on dhe, usually asked its where we need them.

  • And this means we need to break another rule of object oriented programming.

  • We're going to need to create a singleton.

  • I've added another class to the project called RPG assets on.

  • This is going to be a single location that's responsible for loading all of the artwork and extra information that we need for the game.

  • I know that first, not we're going to be loading sprites, so we need the definition over the OLC Sprite, but I want to make this class a singleton, which means the first time an instance of this class is created.

  • It's going to load all of its resources on they're going to remain persistent throughout the lifetime of the process.

  • It is, in effect, one gigantic global variable.

  • Now there are some quirks to a singleton.

  • The first thing I'm going to need is a function so we can access an instance of itself.

  • And this is where things start to get a bit weird to create a public static function which is called Get on, that's going to return an instance to itself and you can see it creates a static local variable in this case called me.

  • And so once this is created, it remains persistent here.

  • So we will always return the same reference to the variable me, which is of type RPG assets.

  • So the first time this is called it creates the instance and then that instance remains persistent.

  • To ensure that this does remain persistent, we need to do to more quite advanced things.

  • The first thing I'm going to do is get rid of the default copy constructor that's created by the compiler.

  • I don't want to create copies of this because every time I do, it will reload all of the assets again, so we'll get rid of the copy constructor at the same time.

  • I also want to get rid of the load operator.

  • In this case, it's equal.

  • So if we're assigning on an instance of this to something else, it would create a small copy off it.

  • We don't want to do that for the same reasons.

  • We've already loaded the sprites once, and this is quite a common pattern for declaring Singleton's to make sure they use a uses.

  • This is a singleton.

  • We can get rid of the constructor by making it private.

  • We might still want these things to execute, but it means the user won't be able to directly create an instance off this Singleton.

  • And it's part of this singleton.

  • I want to store a container that stores all of the sprites.

  • I'm going to use something we haven't used before on this channel.

  • I'm going to use a map on the map, allows you to pair up a key with a value on the type of the key is going to be a string on.

  • The value in this case is going to be a pointer to a Sprite.

  • We'll call this M map sprites only to include map, but it's all for the file.

  • The map is a little bit like an array, although far less efficient but potentially a lot more useful.

  • Instead of using numbers to index the location in battery, we can use other objects and in this case, because I know that we're only going to be accessing spikes relatively infrequently by accessing the point of despite infrequently.

  • But I don't need to worry about the performance hits that that would involve and the benefits are going to get from using a map here is like a noose friendly naming conventions throughout the whole program, which means if I do end up having all the people designing parts of this, they can stick this friendly naming convention, and the engine doesn't need to be altered, and this may still seem a little bit weird.

  • But once I put this function in here, which is get Sprite, you can see that we apply a name on.

  • We're using the name as the index to the map, so it works in a very similar way to an array.

  • But it's a lot more sophisticated to our assets class.

  • I'm also going to add a function which is Load Sprite.

  • Let's go implement the body of this function here.

  • I've got the constructor in the destructor and here I'm going to implement my load sprites function.

  • And this is where I want to do the single one off load of everything that I'm going to need for the game.

  • I'm going to start by defining a little Lambda function called Load, which takes a friendly name on the file name to the asset that were trying to load on in this Lambda function.

  • The first thing that happens is we create the OLC Sprite using the file name.

  • We get appointed to it, and then I'm going to storing our map.

  • Using the friendly name is the index that pointer and the reason I want load function like this is I can now easily load new resources.

  • So, for example, let's say we take our village map that we had before I call Load on.

  • I'm going to create an accent which I'm just simply going to call Village and I'll pass to it the file path to the Sprite sheet that represents all of the tiles, and that's all we need to do.

  • So wherever we want to use the asset that represents this Sprite sheet, we just simply going to call our get Sprite function with this friendly name.

  • And so in this function, we can start to load all sorts of assets.

  • We know they're only going to be loaded once.

  • We'll need to load the assets at some point, so we'll go back to the main file now on include assets class.

  • I don't need to create an instance of it somewhere because it's a singleton, so I can go straight to the on user, create function RPG assets.

  • Remember, it's a method directly applied to the class.

  • In this case, we're going to get an instance of it, and we're going to load the sprites.

  • So at that point, we've now loaded all of the artwork for our entire game.

  • I could get away with this because this is a small game I can load everything at once.

  • The memory footprint will be minimal for really large projects you probably do swan.

  • Something's a little bit more sophisticated than loads.

  • Things hasn't when they're needed.

  • My Singleton has now loaded all of the Sprite for the time being.

  • I'm going to leave in the Jarrow spite because will handle that when we start looking at dynamic objects in the next video.

  • But let's go back to our maps now.

  • We no longer want to load the spikes here.

  • Instead, we want to use our assets.

  • Singleton.

  • So in the maps, head of file, let's include all rights.

  • It's on.

  • All we need to do here is instead of going directly to the file and creating a new instance, we could go to RPG assets, gets an instance of it and get the Sprite, and we gave it the friendly name Village and that will return the pointer to the one instance of that spite sheet that we've got in the game.

  • We'll do the same for the other village, so we're no longer duplicating resources coming up to the end of this video now, So I'm just going to make some tidy modifications.

  • Thio make it so we can move carry around a little bit more sensibly So let's take a look.

  • So here we've got our map loaded in the background.

  • We've got Jerry.

  • Oh, and we could move Jerry around.

  • He can't go over solid objects.

  • He can fit into narrow gaps, and we know that all of our resources have been loaded in an efficient way.

  • I think we'll do one more thing before finishing this video, and that's showing larger text on the screen.

  • You know that this is a consul on displaying Texas what it does.

  • Naturally, however, this resolution, the text is very difficult to

Hello.

字幕與單字

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

B1 中級

編碼-自己動手!角色扮演遊戲第1部分 (Code-It-Yourself! Role Playing Game Part #1)

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