Placeholder Image

字幕表 動画を再生する

  • hello and welcome to code it yourself role playing game Part two.

  • If you've no watch the first video, you probably will need to.

  • This is a direct continuation from that video on.

  • If remember, at the end of the video, we ended up with Jerry.

  • Oh, oddly enough, from the platform game walking around a map on, we can see here that Dario can't overlap with anything that's in the map that we're considering static on what this video is going to be about is introducing dynamic objects I eat.

  • That's the things that move.

  • Now you might be thinking, Well, hang on.

  • We've already got a moving object.

  • Surely we've already covered that.

  • Well, yes, we have.

  • But we no need to make it more general purpose.

  • And we're going to use object oriented programming to do that for us.

  • In the most basic sense, anything that moves, we can consider a dynamic object.

  • But I'm going to extend this a little further that anything that isn't static or background is going to be a dynamic object, and we'll see later on that this can involve event triggers.

  • Andi switches on tele porters on all sorts of things that make the game happen once we've got the very basics of dynamic objects out, the way we look at how we can script sequences to form cut scenes.

  • We did actually describe what the dynamics objects were in the first video on in this game.

  • I'm going to restrict them to being one unit wide by one unit high on that.

  • That equates to about 16 by 16 pixels.

  • So all of our dynamic objects are going to occupy a single tile in the game, although they are free to move in a continuous domain, so they're not going to keep them locked on to particular cell boundaries.

  • So it's start with the basics.

  • We know that we're going to have to have a position for our dynamic objects, which is going to be an X and Y coordinates floating points.

  • We know we're going to need a velocity, which will update the positions depending on the elapsed time.

  • So we'll call that V X and V why we're going to have to.

  • Boolean flags determined the collision detection properties off the dynamic object.

  • Is it solid against the map?

  • For example, Dario can't walk through a tree or a building, However, things like a bird or a bat might be able to fly on top of things, so we don't always want things to be solid against the map.

  • We'll also see later on that sometimes we want to adjust these properties very briefly to help us get some certain effects we're going to check.

  • Is the object also solid against other dynamic objects?

  • So if we've got enemies in the game again, we don't want the play character to be able to walk through them.

  • But sometimes we might.

  • So we're gonna keep these flags a bit separate.

  • We're also going to record.

  • Is the dynamic object considered friendly or not on?

  • We'll see later on that this will determine what on interaction properties do we need to set.

  • For example, if the dynamic object is friendly and it interacts with a friendly, dynamic object, then probably it's a conversation or something.

  • Something interesting is going to happen.

  • However, if one of them is friendly and one of them is not friendly, it's most likely the intention was an attack so well wantto handle this differently, depending on the friendly state of our dynamic object on the way I'm going to strip to the dynamic object is to have a base class dynamic on for things that move around and perhaps have their own behaviors were going to inherit from it on.

  • Call it dynamic creature on because we may want to specify the individual behaviors of a dynamic creature.

  • This is where we're going to break it out into the different types of enemies.

  • So, for example, we might have a bat type enemy.

  • We may have a skeleton type enemy, and we may also have friendly characters.

  • So, perhaps, is an NPC type for things that aren't dynamic.

  • We don't necessarily need to create an intermediate class we can still just inherit from dynamic directly.

  • So this may be, for example, a cell that teleports the player to a new location.

  • It may be a sign post, so even though it's called dynamic, what I really mean is anything that isn't static or map doesn't necessarily mean it has to move around.

  • It's just it's an entity that we can interact with.

  • At the end of the last video, we ended up with the three main source files.

  • We had the main application, which contains the on user creator.

  • Nonusers update functions.

  • And we also created a Singleton class called RPG assets, and this loaded a single instance off.

  • Well, basically the sprites on.

  • We're going to add more things to this.

  • So I think the maps are also going to be something that will want global access to, but we only ever want to ensure one instance off them exists.

  • It's all update this class, too.

  • We also created a map class which basically stored the static information off the maps, and they were created very an external map editor created by this community.

  • Currently, moving Jerry around doesn't involve any additional classes.

  • In fact, we just store the values for position of velocity directly in the main class.

  • We're going to be changing this because the player object is indeed going to be a dynamic object to.

  • So this means we'll have to make quite a lot of changes to our our news update function to accommodate a new architecture.

  • The good news is, we've already got static collisions.

  • Don't we'll just have to re factor it a little bit to suit the new architecture, but we'll also need to add dynamic collisions So this is when dynamic objects interact or collide with other dynamic objects.

  • On the whole, we're going to move this class away from the idea that there is one central, dynamic object.

  • In this case, it's Jerry Oh.

  • Instead, we're going to maintain a list or a vector off.

  • Many dynamic objects on the law be handled independently, and we're going to rely on object oriented programming to differentiate between the behaviors and interactions necessary for each object.

  • Let's start by creating our base class for a dynamic object.

  • I've added two files.

  • RPG dynamics dot h an RPG dynamic start c p p.

  • I'm going to include all of my dynamics in one file simply because it makes it easier for me to make the videos without having to skip between different files.

  • In practice, However, you probably would want to separate all of the individual classes into their own files.

  • So let's start by creating a Class C dynamic.

  • I'm not going to put the method bodies into the head of file.

  • I'm just going to prototype the functions, so we need the constructor we'll put in a D structure to, and I'm going to add some public properties, so we know we need the position PX and why went after Velocity VX on V Y.

  • I'm going to have the three billions I discussed earlier when we'll call that be solid versus map solid versus other dynamics on whether or not this dynamic object is considered friendly, I'm also going to include a type of string to name the dynamic object.

  • This is going to be very important for differentiating between dynamic objects off the same class later on.

  • And it also becomes a game design element because it will be easier for the people writing the script for the game to work with objects that have sensible names.

  • And we've done that for the sprites already.

  • String isn't declared yet, but we'll come back to that in a minute.

  • Now I'm going to add some bass methods on these are going to be overridden, so we're going to exploit inheritance and polymorphism a lot in order to facilitate the different behaviors of the object.

  • So we'll start by creating a virtual function, and this means it is our intention that we're going to allow this function to be overwritten on.

  • This one is going to be called draw Self, so the object is going to be responsible for deciding how it looks on the screen.

  • And so to do that, I need to pass to it.

  • A pointer to an instance of the OLC Council game engine on.

  • If you remember from the first video, we modified it slightly to be object orientated in its own right.

  • So I'm going to just call that point graphics.

  • We'll need to include the council game engine at the top of our class.

  • Of course, now the council game engine does some naughty things.

  • One of the things it also does is include string and sets the name space.

  • I'm sure you'll have plenty to say about that in the comment.

  • One thing that's also important for the object to draw itself is it needs to know what the current global offset is of this screen.

  • I e.

  • The camera position, and this is because the object will only know where it is relative to the world coordinates, it wrote.

  • Know where it is relative to the screen coordinates, so we need to provide this offset now dysfunction for the base class doesn't need a body.

  • I could set it to be pure, which would make this class abstract, but in this case I'm just going to leave it with a blank pair of braces.

  • The second function I'm going to add again is going to be a virtual function, and it's going to be update on.

  • This is where the object can update itself using the F elapsed time provided by the game engine again by default.

  • This is going to do nothing, but you might be able to start to see where this is useful.

  • Let's assume they said dynamic object later.

  • Down the line is a bat.

  • During this update function, the bat will want to fly around and this will this will allow is a facility.

  • To do this.

  • I'm going to allow the dynamic object to be named Devere.

  • It's constructor, so I'll just put in those parameters.

  • So for our base Class C dynamic, the dynamic object, all we've got to the two methods left to fill in one is the constructor, and one is the destructive.

  • Right now, the destructor doesn't need to do anything, but the constructor does need to specify what the name is.

  • We'll also take advantage of this opportunity just to initialize all of our variables.

  • Now I'm going to assume that all dynamic objects to begin with are solid versus the map.

  • I'm also going to assume this solid versus each other.

  • It is likely that most of the dynamic objects created are going to be things that we don't want to walk through the scenery.

  • And I'll also ashamed.

  • Everything is friendly.

  • What a great place.

  • What you may have noticed is nowhere in this class have.

  • We provided a facility to know what the dynamic object looks like at this level of abstraction.

  • That's unimportant.

  • So let's start using the dynamic object system for the player character I'm going to inherit now.

  • Ah, a new class called C dynamic creature and I want to inherit publicly from our base class.

  • And what this means is anything that's declared public in here will remain public as usual, created a new class.

  • We're gonna have to create a constructive for it.

  • And this time I'm going to pass in the name.

  • But I'm also going to allow us to start using the assets.

  • So for drawing this particular creature, we need to give it a sprite pack, so it knows how to draw itself.

  • We also need to provide implementations for the drawer self on update routines.

  • So I'm going to copy those from up here, put them in down here, get rid of the virtual keyword.

  • He could leave it, though it doesn't make any difference, Really, get rid of these braces, but I'm going to use the override key words, so it's clear that we've overridden them.

  • But because this is an inherited class, we can give it some variables of its own.

  • So I'm going to create some that are protected.

  • In particular.

  • I want to store pointed to the sprite that were passing through, and I also want some additional properties s so we can assess the state of the creature on will assume because it's a creature that it's alive.

  • So this is where we can start thinking about some game variables, so we'll have health as an interview, and we'll also have Max health.

  • So consider if this was the player character, this would represent how much health they've got left on.

  • This represents how much health they can possibly have, so if they use some item that restores health we know that there is a maximum.

  • It can be restored to.

  • Of course, we'll also have to give bodies now to the new constructor.

  • So here it is.

  • Dynamic creature Constructor is taking the name and the sprite on.

  • I'm going to use this notation to say But also, please call your based constructor which will set the name for us.

  • Andi felt the variables.

  • The only thing we need to record now is the sprite variable and we're going to set a default.

  • Health and Max Health value, most say, will have 10 to begin with an IMAX health of 10 to So the creature has full health at the start later on, we'll probably want to overwrite these with different values for different creatures.

  • We also need to provide the update function on the drawer cell function.

  • I'm just going to use a line of comments here so we can see that there's some separation.

  • This is why it might be useful to do things in different files.

  • So I've got the base class on here.

  • I've got the derived class dynamic creature and this is where we can start to have a little bit of fun I have decided in advance off a format and layout of a sprite sheet for all creatures, and it looks like this here.

  • We've got individual sprites, which is 16 by 16 pixels on.

  • I'm using this strike viewer that the community created.

  • We can look at them individually, but we'll see.

  • The first column is the sprite walking downwards.

  • You see the animation in the top, right of the image.

  • The 2nd 1 is the sprite walking towards the West, and we've got north.

  • And then we've got east.

  • We've got some additional ones.

  • This is this point celebrating on this is the Sprite dead.

  • Now the artist that created this spy packers also included two more, which is just standing facing on standing facing away for this Siri's.

  • We won't be using these two.

  • But what is important is that all of our creatures in the game follow the same Sprite format layout because we're going to let the dynamic creature class handle which sprites need to be drawn, given on the status of the creature.

  • So, for example, in this case, we've got what we're calling, said it.

  • Slim's created by it said it on the discord server is the same thing.

  • So we've got walking towards the player, walking towards the west, walking away from this player, walking towards the east on we've got a celebration on a dead slime.

  • Additionally, again, a skeleton character.

  • This time exactly the same states of animation in the same locations on this is quite important.

  • Knowing that all creatures are going to be drawn with same Sprite layout means we can use some tricks.

  • So I'm going to use a new Marais Shin here to store which direction the player character is facing.

  • I'm just gonna hard code these in as a zero one two and eats east is three.

  • I'm going to store this as facing direction.

  • If you haven't seen this notation before, it's really I've just done a new Marais shin in a single line on dhe.

  • I've basically at the same time declared to this M and facing direction variable as having the type of this enumeration.

  • This means we can apply instead of 012 and three.

  • We can apply southwest, north and east as the facing direction on the compiler will be completely fine.

  • With that, I'm going to have exactly the same for other states.

  • That's a standing, walking, celebrating or dead.

  • I'm going to store that as graphic state.

  • So if you remember South, West, north and east, a tie up with which column of the Sprite sheets we're going to be using on depending on what the dynamic creature is doing well, choose whether it's standing, walking, celebrating or dead in the constructor.

  • I'll just default these somewhere to say the facing direction is south on dhe.

  • By default, it's doing nothing at all.

  • It's just standing there, just going back to the spite editor again.

  • I can see a walking animation.

  • Well, it's probably about 1/5 of a second between me pressing the open down keys.

  • So this means the dynamic creature is going to need to keep track of time to know which particular frame of animation to play.

  • Sleds aren't that in.

  • We want to create a floating point variable, which will just accumulate time.

  • And of course, I'll also need to add that to the constructor.

  • Set it to a zero, and this is where we'll start looking at the update function.

  • So every point to off a second I want the Sprite displayed to change now.

  • Fortunately, the game engine providers with how much time has elapsed.

  • So we just add that to our F time of variable.

  • And when the F time a variable gets beyond 0.0.2 of a second, I'm going to subtract 0.2 of a second from it.

  • So this means we get a consistent period of time irrespective of what the rest of the system is doing and will come back to that in just a little while.

  • But let's set some of the graphic states that a fairly obvious.

  • So if the dynamic creatures health is less than or equal to zero, we're going to assume it dead.

  • That's the sprite that we want to display.

  • If the creature has any velocity components, it all, it's moving, so we'll set it to the walking states are here.

  • I'm just looking at the absolute values of the V X and B Y components.

  • Of course, if it's not walking, it's just standing.

  • The final state celebrating it will probably look at in the next video when we start to add some of the finishing touches to the dynamic object classes.

  • We also need to determine which direction the player is facing, and we could do that based on the velocity components.

  • If they're negative, it's facing west or north, and if they're positive, it's facing east or south.

  • Now the drawer cell function for the creature needs to choose the sprite that is suitable for the state of the creature at this point in time.

  • So I'm going to create two variables.

  • Sheets, offset acts and sheet offset.

  • Why which are indexed into this Sprite location.

  • So in the top left here, that sir sheet offset zero on we go all the way over to celebrating that's sheet offset four.

  • And, of course, in the ex direction on if we've got ah, one sheet offset in the UAE direction with moved down to the next row of Sprite, so I'll use a switch block to determine based on the state how we set that these variables.

  • If the creature is simply standing still, the only property that matters is thief facing direction variable on the country.

  • If the player is dead, then we want to specifically choose s right location to display because there's only one option.

  • Walking, on the other hand, is a little bit tricky because we've two to choose from, depending on the state of M F timer.

  • So this implies we need an additional variable, which I'm going to add an interview called MN graphic counter again in the constructor.

  • I've defaulted this to zero.

  • I'm not going to show this each time.

  • From now on, I'm going to assume that you understand that it's important to give your variables a default value in the constructor.

  • And essentially, this variable that we've added is going to Ossa late based on