Placeholder Image

字幕列表 影片播放

  • Hello.

  • I'm gonna take a quick break from the role playing game, Siri's to have a look.

  • ATT programming pseudo three dimensional planes.

  • And this was a technique made popular by the Super Nintendo, and I'm going to use a super Mario Kart is an example where an image is taken as the ground plane and it is rotated and scaled and translated around the camera is necessary to give the impression over three dimensional environment.

  • This was known as Mode seven, which for the Super Nintendo was just really implementing an F fine transform in hardware.

  • I'm not going to be using African transformed directly because I want to play with some of the parameters and see what happens.

  • And so this is what we're going to be developing.

  • Of course, it's in the console now.

  • To those of a certain age, this may look very familiar.

  • This is indeed the first track, I believe from Super Mario Kart, and for those expecting another episode of the role playing game, you can see it's vaguely related.

  • We're using exactly this technology for the world map.

  • What I think is really needs about this program is that is it.

  • There's barely anything to it.

  • A toss.

  • There should be a nice, short, quick video showing something interesting we might be able to use in other games and technologies.

  • So as we usually do on this channel, let's take a quick look to just explore what it is that we're going to do and try and understand that some of the concepts and principles behind the algorithm I'm going to create a big ol sea sprite, and we know that these behaved just like textures on that we can sample from them.

  • Assuming that the top left is 00 on, the extremities are 1.0 on 1.0, and if you remember from the code it yourself first person shooters, this makes sampling the texture scale.

  • In variant.

  • I'm going to treat this big texture as if it were my world map or the Mario kart track.

  • In this case, in this map, I'm going to have a position which represents where the camera is.

  • I'm going to call this position World X on worldwide.

  • The camera will also have an angle associated with it.

  • We're in a two D plane here, so we don't need a three dimensional camera on will assume that the angle is what direction is the camera looking at in this plane?

  • From this information, I'm going to create a viewing frost.

  • Um, but I need a little bit more information first.

  • Firstly, I need a field of view and we'll call that feta.

  • I don't need two more pieces of information.

  • I need to know what is the nearest location to the camera on which is the furthest location from the camera.

  • And there's going to be lines that straddle are viewing first room.

  • Let's draw these in.

  • And if we were to continue drawing our camera vector, what we can see about these two lines is they are right angles.

  • So where the camera is looking?

  • This gives me four coordinates.

  • Oh, Pierre.

  • Here, here.

  • I'm here, and I'm going to use those coordinates to give me a region which I will be Sampley to display to the user.

  • And this is my first time.

  • Once we've got the first, um, we can now determine the mapping between what the player can see on the two d plane versus what they can see on this screen now in the council window we know that the Y axis goes in this direction on the X axis goes in this direction.

  • Well, that maps on to our first, um too.

  • So the furthest away, why location is going to be towards the top of the command prompt window, which means this becomes out.

  • Why access and this becomes our X axis will notice that the X axis changes length depending on where it is in the Y axis when we're far away.

  • We're looking at a lot more ex than we are when we're close to it.

  • This means we can take any X Y coordinates in the command prompt window workout where it lies inside our first, um, and that becomes the sampled point that we will display on the screen.

  • It would appear that there's quite a degree of interpellation happening on the race, so I'm going to put some naming conventions in so we can follow the code.

  • This point up here is going to be known as far X one on why one this one down here is going to be known as near X one on why one this one is far X two, and why, too, and This one is near X two on Whitey.

  • When we extract a pixel location from the console screen, we will be normalizing it versus the screen with and screen height so well, getting in a value between zero and one.

  • Let's say our pixels location, axe, and why is no 0.5 by no 0.5?

  • That means we want to select somewhere in the middle of our first room.

  • But how do we know where the middle is on a shape like this?

  • Well, we know that the Y coordinate is going to be reasonably consistent for now.

  • Those who are thinking ahead we'll come back to that later.

  • No 0.5 will be somewhere halfway along the line between near and far.

  • And because we know the vector between far X one and near X one on the vector between farts too, and near x two, we can work out where those two points are.

  • And once you've got those two points, we create a new line.

  • I'm going to go see the middle.

  • So I'll just flag that in normalized space.

  • This is halfway along and then, of course, because we've got this line we can do exactly the same to this new line toe workout, the X location, which is halfway across this new line, which withdrawn in already it's there.

  • And so, by using this approach, we can specify any coordinates between zero and one and work out where it lies.

  • Within this shape, let's just do it.

  • A second example.

  • Just to make sure that let's assume that instead of no 0.5, we've got no 0.25 by no 0.75 So in this instance we would go 3/4 of the way a longer line linearly no 0.75 They're on about there on the same.

  • Create a new line between those two points, and it says we're no 0.25 along the X axis.

  • Well, we know that the middle is about thirst of not 0.25 Must be about they're.

  • So this becomes our sampling point Now.

  • You may have noticed that I subtly hinted something's not quite right with this approach, but we'll come back to that when we start writing some code.

  • So let's get started with the code.

  • I've already created a subclass called one lone code, a fake mod seven on I've created a main function which creates an instance of this class constructing the consul to be 3 20 wide by 2 40 High on each character is going to be four by four pixels.

  • Note that this is quite a high resolution on indeed, may not work on certain screens.

  • If you're not using a 10 80 p screen, it's not going to fit on that desktops.

  • You'll have to use a smaller console size.

  • Well, let's start by adding the very basics I know I'm going to need a Sprite that represents the ground later will show how to load the Sprite.

  • But to begin with, I'm going to create it Algorithmic Lee, because I wanted to be a sprite of lines so we can see.

  • How does the three D effects start to distort what the user can see on On the whole, I know that my map is going to be square on both sides are going to be 1024 so it's going to be like a one megapixel texture, quite a big thing for the console game engine.

  • So in the on user create function, I'm going to create it.

  • And here we go.

  • I've defined it as being a square sprite of size, map size by map size.

  • I want to populate this map by hand somewhere to create two nested four loops to draw lines going from one side of the map to the other in both the accent.

  • Why directions?

  • And I wanted to leave a gap off 32 pixels between each line for the opposing access.

  • I want to draw in every single pixel, so we skip by one pixel at a time.

  • Now, even though I've used the naming conventions X and why here?

  • I can actually both draw both the horizontal and vertical lines at the same time, and that's because the map will be reflected along the X Y axis.

  • It's fine, and sprites have accessing methods, so we can actually set the content of the Sprite manually.

  • So I'm going to set the color of that location to be magenta.

  • I'm going to send to the pixel type at that location to be the solid pixel.

  • In fact, I'm going to do exactly the same for the neighboring pixels because this will give the line some thickness, so this will be drawing lines in the Y axis.

  • We can simply flip the coordinates to draw lines in the X axis.

  • So these two nested four looks work to create a grid like pattern of magenta lines of one access on blue lines in the other.

  • Everything else we want to worry about is in on user update.

  • I'm going to have some variables that represent where the player is in the world X y and angle in radiance.

  • I will also need some variables that represent the first, um, I'm going to choose of numbers at random to begin with.

  • So the near plane is going to be not pointing out one on the far plane.

  • No 10.1.

  • I've really no idea what these mean in this scale of the map that we're creating.

  • I'm also going to need a field of view variable, but I'm going to store instead the field of view half variable.

  • So in this case, the field of view would be pi divided by two.

  • But I'm automatically having it already, so it's pi divided by four on.

  • The reason for this is because I'm taking the angle of the center line from the player into the map and I'm going to subtract half the field of you.

  • I'm going to add half of the field of view to give me the first of the points.

  • So let's do this now.

  • We want to create our first set of points, which was far X one and why one?

  • Well, if we assume that the player exists at World X, we can create a unit vector using co sign and sign off the angle that the player is facing minus the field of view times, the far plane.

  • So wherever the player is in the X axis, we're going to create a value between zero and one here on were multiplying that value by the far plane again.

  • I don't know where this exists in the space of our world.

  • It goes without saying that's to create B Y.

  • Component is exactly the same.

  • Except will you sign for the opposing Farpoint?

  • We're placing half the field of view instead of subtracting it and for the near points were using the near plane value instead of the far plane value.

  • So this gives us 42 dimensional points that represent the corners of our first um within the map.

  • When we're drawing the maps, we only want them to occupy half of the screen, not the full screen, because this assumes that are vertical.

  • Vanishing Point is halfway up the screen, so I'm going to work on a row by row basis within our council window.

  • Going from zero toe, half the screen height will need to normalize the screen height value to between zero and one.

  • I'm going to call this simple depth, and it's just simply the why value divided by the total range of the Y value in this case, knowing how far into the first room we need to bay, we can create two points that represent this scan line going across the first room.

  • So on the left hand side, the X one side, I get the direction vector off the line of the side of the first, Um, I multiplied by my normalized value to create a sampling point, and I offset it by the near plane, I guess an end point for the scan line by doing exactly the same thing.

  • Now we know where the scan line begins and ends.

  • In our first room.

  • We can use the X component of the screen coordinate toe workout were along that line.

  • We should sample the pixel in color.

  • So in exactly the same way, I'm going to create a normalized point between zero and one sample wit, and I'm going to find the sample location by inter plating along that line.

  • Once I have my sample coordinates, I can go and extract them from the OLC Sprite, using the sample cliff and sample cooler functions.

  • Now these functions will operate on a nearest neighbor principle, which means we don't really care about the spatial scale.

  • In this instance, the sampling algorithm will do what it should do on will never give us any holes or blanks.

  • Once we know which symbol to draw on which color it is, we should draw it.

  • But I'm going to draw, offset by half the screen height in the Y axis, so this gives us a ground plane along the bottom of the screen.

  • Let's take a look.

  • Mmm, Well, something's going on from that static image.

  • I can't really work out what's happening.

  • I need to add some user controls to move the player location around the map, and I will add these outside of our rendering loop.

  • We've seen this many times before.

  • I'm just going to see if the left Roky is held down.

  • And if it is, I'm going to deck.

  • Lament the angle.

  • If the right arrow keys held down, I'm going to increment the angle.

  • If the up arrow key is held down, then I want to increment the X and Y coordinate along the unit vector created by the angle.

  • We're going to increments.

  • At this particular speed, it's quite slow, but at the moment, slow is relative because I have no idea what the scale of our world is.

  • This will take a little bit of fiddling about on getting a feel for it, and I could do the same for reverse.

  • Except this time I'll let put a minus sign in front of the cosine sine.

  • Let's take a look.

  • Well, I'm turning in the world, and it's looking pretty funky.

  • What I notice, though, is that the world seems to end quite quickly.

  • Let's try moving backwards.

  • Well, that was strange.

  • And moving forwards.

  • Well, it's just outright psychedelic.

  • It's pretty but useless.

  • The problem here is I've just taken a guess at what are near and far plane should be on our field of view, so I'm going to make these controllable too similar code.

  • Just going to check for certain key presses on Alter the permitted by implementing it or deca menting it.

  • Let's see how this works, so without turning anything Q and a change The Plains near parameter Well, that seems to stretch things out.

  • W and s change the Plains Far perimeter.

  • We can see there is change, and it gets it kind of makes some sense.

  • The field of view is changed by said and X, and that's definitely affecting things in the X axis.

  • Let's rotate the player into the scene a little bit more, widen the field of view on.

  • We'll try changing the far playing a little bit.

  • Change the near playing a little bit.

  • That kind of looks like we're just looking top down.

  • So rotation and sampling and things are working, but something's not quite right.

  • If I orientate the camera, so we get vertical and horizontal lines somewhere in our scene, we can see that they behave kind of appropriately, but it looks like our scene has its perspective, firstly in the wrong direction and upside down.

  • So as the players moving forward here between the two magenta lines, the blue lines are behaving somewhat sensibly.

  • And if I rotate 90 degrees so that we're now traveling along the blue lines, the magenta lines behave somewhat sensibly.

  • So it is kind of working.

  • But it's clear that our perspective projection is, well, rubbish and surprise.

  • Surprise.

  • This is our problem.

  • We've made a rather naive assumption that our interpellation along the first room central axis away from the camera is linear.

  • And it isn't perspective assumes that we've got three components to an image X, y and Zed.

  • Where's that is equal to the death, and we intuitively know that things that a further away move less and have less significance.

  • And so if we were to look at the relationship between depth on X and why, what we might be able to assume is that some new Position X is equal to some Position X divided by depth, and the same goes for the Y axis on.

  • This implies that has said, approaches infinity.

  • Any changes to acts become minuscule.

  • Where's if Zedd approached?

  • Zero?

  • The changes become very large indeed, and in many ways.

  • I suppose this is why the stars in the night sky don't appear to move as you move your head around yet to the trees and lampposts in front of them do.

  • But what's interesting here is that we're seeing that depth is certainly a one over depth relationship to X and Y.

  • I thought it might be useful to quickly explore why this might be the case.

  • I want you to imagine for a minute that the camera is the man's head on.

  • The man is looking forwards into the world.

  • What could the man actually see if we broke the world up into scan lines?

  • So here I've projected to raise from the players I into the distance.

  • And if we were to attribute how much of this distant scan line can be seen by the player, we might want to estimate it by drawing a little arrow between the two.

  • We can see it's quite small.

  • Let's draw in some more lines, and now, if we look at the proportion of what can be seen for each skin line, we might be able to identify a bit of a trend, and I'll very carefully try and draw this line in joining all of the points of these up.

  • Look at that.

  • I'm getting somewhat better with the old drawing tablet.

  • We can see very clearly that we have indeed gotta y equals one over X relationship here.

  • What this means in real terms is that we're not looking in the right place for our first um instead off this line being broken up linearly.

  • We want to look at it in a slightly different relationship where those lines close to the player are close together.

  • But as we get further away from the player, they get further apart.

  • We can also see here that this equation is not quite correct.

  • We're starting with scan line that's furthest away.

  • Yet our sample depth variable assumes the nearest line.

  • So let's see what happens if we flip this round Well, it still looks a bit rubbish, but we could assume that now at least, things are moving in the right location.

  • As I move along.

  • Now the perspective is corrected towards the player on the vanishing point lines disappear into the distance.

  • We just play with the planes a little bit, So there we have it I can rotate 90 degrees, but there's still a great degree of curvature.

  • That's because we're still operating linearly, and I can do this in one hit.

  • We know that the first line we're calculating is the furthest away, but that requires our scan line to be the largest in wit and yet the most minimum in detail.

  • What I'm going to do is not flip this round.

  • Instead of multiplying, I'm going to divide.

  • So starting with the furthest away scan line, our sample depth is effectively zero.

  • Yes, there's a little bit of a divide by zero here, but in this case, let's assume that's infinity.

  • It means as far away as we can possibly see.

  • We can see everything.

  • But as we get closer towards the player, we start to approach one, which means the scan line becomes very small.

  • Now let's take a look.

  • And what's the difference that is made Already?

  • I can rotate the player and I'll move forwards into the map and we can see despite a few sampling issues, we can walk up to the boundaries of the map.

  • Let's just take a minute whilst it's working well to play without parameters so the field of view well whitens and narrows the field A few.

  • As you might expect, you have seen this effect in quite a lot of first person shooter games.

  • We also the near plane.

  • We can start to imply the degree of curvature to the map.

  • It's trying to straighten that back up again.

  • There we go.

  • And if we also the far plane, it gives us the impression that the camera has risen from the ground.

  • And, of course, that's because that's the only way that equation can be solved.

  • If we're saying that the far plane has to be wider, the player needs to be higher up and further away.

  • So this leads to some promising things.

  • We could have a jumping mechanic, but one thing I have notices, the world ends, and this might be undesirable for emulating things like globes in role playing games.

  • See where I'm going, So because our sample positions are calculated in world space, but our map is a finite texture between zero and one.

  • I'm going to take the floating point module is of our sample coordinates, so this should implement a wraparound functionality.

  • We've not got a record and we're currently at 00 s, so we don't have anything in the negative axis.

  • But we can see the map goes on indefinitely, away from 00 So what we might want to do is place the player somewhere in the middle of the world first, so they're nowhere near the negative edges of this map.

  • I'm gonna pick a number 1000.

  • That's nice so we can see that the player is now stood with in the middle of the world.

  • I think it's time to say goodbye now to our hands generated map on use, a preloaded texture.

  • So I'll comment that out.

  • Unload the texture directly.

  • Now I went online to have a look at Mario Kart maps and found a fantastic website which had them as PNG files on dhe A.

  • Some of you may know now, from quite a few videos, the Fantastic King from the Discord Server has been creating lots of algorithms to turn PNG files into a console game engine format sprites.

  • And so I converted the PNG into a sprite, ready to use in the game engine.

  • So let's have a look.

  • We can see Well, we've certainly got a map.

  • It looks a bit distorted and parallel lines aren't quite right.

  • But that's why we've got adjustable parameters.

  • So firstly, it looks like I'm floating in the air, so I'm going to adjust the far viewpoint down a little bit, so it brings me closer to the ground.

  • I'm going to bring in the near parameter to try and take out some of the curvature so I can put in lots of curvature.

  • It just makes it look like we're always going downhill.

  • I want to try and iron that out a little bit until it looks about right.

  • There we go.

  • That's not too bad.

  • The field of view seems reasonable anyway.

  • We can make it wider.

  • We could make it narrower.

  • I think in racing games you can change the field of you to give you different perceptions of speed.

  • So as I make the field of view wider, I'll just try and zoom along in a particular direction.

  • The field is getting very wide, but if I bring it in and come a bit narrower, yes, I think it starts to look like we're speeding up.

  • Maybe I don't know.

  • They need some playing with One thing I am curious to see is how does the Mario Kart map look?

  • If we don't do this perspective correction, maybe it'll be clearer to see what's going on without the blue and magenta lines so we can see its upside down again.

  • I mean, if I just seem out of it, are.

  • So now I'm altering the far plane and we're getting these sort of inception like rolling.

  • That's simply because it is upside down for a start, But we're attributing perspective in the wrong place.

  • We're basically seeing the furthest away parts of the world in the most detail.

  • It's very disorienting.

  • Let's put that back.

  • One of the benefits of having calculated all of this maths, for one texture is we can use exactly the same coordinates to sample a second texture for the sky.

  • Something to add another Sprite sprite sky.

  • In this instance, I'm going to load that, and here were sampling the ground texture and drawing the sky.

  • I'm going to just use exactly the same coordinates on variables again to sample the scaly texture.

  • We don't need to calculate it because it's in the same place relative to the ground, but this time, instead of drawing offset with screen height, I'm assuming I'm drawing from zero to the middle of the screen, but I want to draw it upside down in this instance, or else it'll look very strange.

  • Let's take a look.

  • Well, there's our screen.

  • For some reason, it's divided into squads that one looks to be like it's ah, close to zero sampling error somewhere to do with the sampling of the OLC Sprite.

  • But now we can see the sky behaves in exactly the same way as the ground.

  • This is very good.

  • So if we increase the far plane, it works for both of them.

  • That makes the environment appear a lot more vast.

  • Make it very big.

  • Takes a slight hit in frame right now, but we can make the environment appear very big or very claustrophobic.

  • Might be interesting to do some sort of first person shooter.

  • With this, we also the near plane.

  • Well, we start to get some weird curvature effects again.

  • I'm gonna have loads of fun playing with these promises.

  • What I have noticed is a big, ugly black line in the middle of the screen of the horizon and That's because of this infinity value that we talked about before.

  • We can see it is here in the ground map, and it's also here in the scaly map.

  • Well, I tell you what.

  • In this instance, I'm going to cheat.

  • I'm just going to draw a sigh in line at that location.

  • Take a look and there we go on.

  • The nice thing is, because this is just a two d map, we could store all sorts of additional information.

  • So, for example, these squares they could be solid on, we wouldn't be able to move the player past them.

  • We might be able to interpret a second re texture that contained track or not track information to give us different levels of grip.

  • This approach gives us quite a lot of possibilities for interesting games in the future.

  • Anyway, I hope this video has been of some use to you.

  • If you enjoyed it, please give me a big thumbs up.

  • Thanks to King on the discord server for creating his PNG to Sprite converter.

  • Have a think about subscribing and I'll see you next time.

Hello.

字幕與單字

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

B1 中級

偽三維平面編程又名MODE7(C++) (Programming Pseudo 3D Planes aka MODE7 (C++))

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