Placeholder Image

Subtitles section Play video

  • Hello.

  • A nice quick video This time let's look att isometric tiles on as usual, a quick demonstration of the application before we get going.

  • The isometric approach to tile rendering gives it a pseudo three d feel.

  • So here we can see I'm selecting tiles, but the tiles are no longer axis aligned are aligned with the edges of the screen.

  • So that's out some complication about working out which tile is currently highlighted on.

  • You can get appreciable feel of depth by using sprites that a larger than the tile itself.

  • So here we've got some trees being planted, different type of tree.

  • There on all of this simple demonstration is going to do is allow us to scroll through a fixed election of tile types.

  • I really want to keep this one nice and quick and simple.

  • Working with conventional to detail maps is something we have done many times on the one loan coded channel.

  • We would assume a world that looks like this on here.

  • We would have an X axis and here we would have a Y axis which would employ we have an origin of the top left here.

  • Once we establish that are tiles have a wit on a height in screen space?

  • A how many pixels of the screen the tile occupies.

  • We can then quite easily translate the mouse location into the discreet form required to access the array that represents this tile map.

  • So assuming our mouse cursor is somewhere here, we can take this mouse coordinates.

  • Let's call it M X on M Y on.

  • What we want to work out is what is the coordinates off the cell that the mouse is within.

  • And this has always been simple because we allow interview division to sort all this out for us.

  • So we can assume that sell X is equal to the mouse's location.

  • X interview divided by the tiles width and it's the interview divide.

  • That's important because that will give us a whole number and discard any remainder is part of the division, so that will always give us a location that represents the cell conveniently weaken.

  • Do exactly the same for why, but this time we'll do an interview divide by the tile height.

  • It could be that your tiles are square, but I prefer to program it in a more flexible way.

  • Sometimes It's also convenient to no word is the mouse lie within that particular cell?

  • Well, that's trivial, too.

  • So let's assume this is called Offset X.

  • We can take our mouths, coordinate, and we'll take the module ISS with the tile width.

  • So this will give us a offset in screen pixels of how far the mouse coordinates is into the tile.

  • And naturally, we have a corresponding for why.

  • Sometimes it's helpful to normalize this value by dividing as well by tile whipped and tell height to give us a value between zero and one to represent where the mouse is within the cell.

  • And if we know the overall width of our world, then we can easily take our cells X and Y location and convert that into a one dimensional index into an array that represents this world.

  • We have done this countless times on the channel.

  • It is simply going to be I equals C.

  • Why Times wit plus c X.

  • For regular viewers of the channel, all of this should be very familiar when working with isometric tiles.

  • The rules aren't quite as simple simply because there is no access alignment anywhere in our world.

  • map when rendered on the screen.

  • So I'm going to make some assumptions that up here is our 00 coordinate.

  • And along this edge is our X axis on along this edge is R Y axis.

  • The first problem we have is it a particular tile is no longer square.

  • And so transforming the mouse coordinates as we did before is no longer really that applicable.

  • Secondly, if we look at adjacent tiles in this map, we see that they aren't necessarily adjacent in the isometric map.

  • And so we need to think of things a little differently.

  • I've created some rudimentary isometric tile graphics on dhe.

  • It's quite important that to get my approach to work, I'm going to make an assumption that the aspect ratio of my tiles is 2 to 1.

  • So the tile fundamentally is going to be twice as wide as it is high.

  • And in this instance, I've chosen tiles which are 40 pixels wide on 20 pixels high, and I've created a selection off them.

  • So along the top here, I've got a highlighted yellow one which will represent which one?

  • The cursor is over.

  • I've got an empty tile.

  • I've got one filled with grass, and I've got some larger tiles here at the bottom, which are populated with simple objects.

  • So let's start at first by simply rendering a plane off empty isometric tiles.

  • As usual, I'm going to use my pixel game engine to do this.

  • So I've created a class called isometric demo on.

  • It doesn't have anything in it yet, other than it will clear the screen toe white so we don't load anything on on user create on per frame or were drawing is the background at the window itself is constructed to be 512 pixels wide by, 480 pixels high on each pixel is going to be represented by two screen pixels.

  • Fortunately for this demonstration, there isn't very much code about 100 lines.

  • I'm going to start by adding some variables that describe the world.

  • So here I've added a interject to D vector to describe the size.

  • It's going to be 14 in the X axis and 10 in the Y Axis has established my isometric tiles.

  • Principally are going to be 40 pixels wide by 20 pixels high, and I'm going to establish that the origin of my world.

  • That's his worship.

  • The 00 isometric tiles start to be rendered is going to be at 51 and that means five isometric tiles across on one down from the top left of the screen.

  • I know I've got some graphic stated to load, so I'm going to create an ol sea Sprite pointer to store that on.

  • I'm going to create another pointer to store the two D World array in on user create.

  • The first thing I'll do is load my PNG file that contains my isometric tile data.

  • It contains all of those spikes on will use the drawer partial sprite to extract regions of it to draw to the screen.

  • Then I'm going to initialize my wilder ray.

  • Depending on the size of the world that we've specified earlier on, I'm going to make sure that that defaulted to all zeros, which is going to represent an empty tile for each frame.

  • The first thing I'm going to do is clear the screen, and I know I'm going to render the entire world for this application.

  • We're not going to do any clipping, so I'm going to create two nested four loops that iterated through all of the cells in the world.

  • In this instance, I've chosen to render why first and then X, because I want to rent it from the top of the screen towards the bottom.

  • And this is because, conceptually, the bottom of the screen is closer to the player than the top of the screen.

  • So we want objects at the bottom to be drawn last.

  • We've already established that the world does not exist in the same space is the screen, so we're going to need a transformation function.

  • I'll call that to screen and populated in a minute, but ultimately that should give us a to D Coordinate of were to draw a particular isometric tile on the screen.

  • Now we just need to decide which type of tile we should be drawing.

  • And so here I'll take the Y coordinate on the X coordinate on the width of the whole world to index sleepy world array.

  • If the value of the rate that location is zero, that's going to be a blank tile.

  • I call this an invisible tile here on.

  • I'm going to use the pixel game engines, drawer, partial sprites, function pass it to the transformed coordinates of the world.

  • So it's in screen space on then select the appropriate Sprite out of the Sprite sheet I showed earlier, and for now, that's it.

  • Because of a feeling I'm going to be using to screen several different places.

  • I'm going to create a small lambda function to do that transformation for me.

  • And I'll put that up here.

  • So this will take in an X and A Y in world space and give me the screen coordinates in return.

  • The image file amusing has transparency.

  • It has two types of transparency.

  • One is simply there is a transparent pixels or there isn't on with this glowing rectangle.

  • We've got varying degrees off translucency per pixel.

  • The pixel game engine can render these differently, and it's more optimal to choose the appropriate method before trying to draw the sprite.

  • Since most of my graphics have a binary alfa value for the pixel, I'm going to use the masking mode of the pixel game engine to perform the rendering.

  • This means if there is a pixel with any transparency, it all it grown.

  • Draw it on.

  • It's important that when you start playing with the pixel modes that at some point you set them back to normal because they're persistent, wants their changed.

  • Now let's have a look of this transformation to start with.

  • We know that each isometric tile is in fact a two dimensional Sprite.

  • And so even though the tiles coordinate exists here in the top center, the Sprite coordinate actually exists here.

  • And therefore our transform will take this world cornet and generate this screen space coordinate In return, we can deduce this transformation empirically just by looking at the data starting at 00 We know the Sprite needs to be in this location on relative to the world origin.

  • This is half the sprite width to the left.

  • If we increase just in the X axis of world space, our next Sprite is here.

  • So we have moved along half the tile wits and we've also moved down half the tile height on.

  • This is true for all increments in X so we can make an assumption.

  • That's our screen.

  • X coordinate contains a component like this world ex multiplied by tile width over to on our screen.

  • Why co ordinate Similarly, as X multiplied by tile height over too.

  • However, our world is not one dimensional.

  • We're not going to just traverse along the X axis.

  • We also have a Y component which also influences both the screen X and screen.

  • Why locations So very simple analysis Again.

  • If we increase in just the y axis, we can see we've moved backwards one tile with over two and we've also moved down one tile height over to So as why increases?

  • We're going to move backwards in X, so I'll subtract the white component.

  • Also tile with over two.

  • But I do move down the screen so it's plus the white component tile height over to hopefully, it's easy to see that these could be rearranged to the form.

  • S X is therefore X take why multiplied by tile wits over too on dhe screen.

  • Why coordinate is X plus y tile height over to we're almost done here, but we must realize that the origin off the world in screen space is no longer the top left of the screen.

  • So we have to also offset our screen X and Y position to this origin location.

  • This means our to screen Lambda transform function isn't very complicated.

  • I'm going to make it return a interview to D Vector, and here you can see I've taken the origin and multiplied it by the tile size.

  • And to that, I add the offsets we've just calculated.

  • And as I iterated through each location in the world, I calculated screen position on I draw the Sprite.

  • So let's take a look Very nice.

  • We specify that the world was 14 along the X axis, which is along here on 10 along the Y axis.

  • I've chosen those numbers just so.

  • The whole world fits on the screen.

  • You can, of course, implement your own panning and zooming using this approach.

  • But this video is specifically about how do we select the tiles on Well, tell?

  • Selection implies that we need some mouse information, some creating a to D vector on populating it with the mouse location in screen space.

  • As a demonstration at the start of this quick video, we can work out approximately, which sell the mouse's in by using interview division.

  • Now that doesn't necessarily make much sense right now, but bow with me and I'll explain shortly.

  • I also want to calculate the offset into the cell, and you can see I'm using the module, its operator, to do just that.

  • But hang on a sec.

  • These cells are in screen space.

  • In fact, let's draw where this Sal is to visualize this effect to draw the selling screen space we're currently hovering over.

  • I'm just going to draw a rectangle at the cell's location, multiplied by the size of the tile, and I'm also going to throw in some on screen text so we can visualize the coordinates.

  • So here you can see as I move the mouse around, a scream cell is selected, and if I moved to the top left, it even says sell 00 This is something we've done many, many times.

  • This is traditionally how you would work with the two detail map, but you'll notice that this cell only rarely lines up with the tile in our isometric grid.

  • And so it isn't actually possible for me to get the rectangle to go on alternate adjacent tiles.

  • Also, the cell value doesn't make much sense, either.

  • Here in world space, there should be 00 but we can see that that sell 51 and that's because we've offset from world space to screen space using our origin vector.

  • And as I move along the X axis, we can see both sell values of changing.

  • Clearly, the cell coordinate is not in world space.

  • I'm going to have another vector called Selected on this Vector.

  • I'm not going to use a lambda function to do it, but we do need to have a method of transforming the cell in screen space back into world space.

  • And that will, of course, then represent are selected cell in the isometric tile.

  • The process for working out this transformation is not too dissimilar here.

  • I've drawn our screen space cell grid over laid with our world space isometric grid and particularly this cell in the middle.

  • Here in world space is 11 Let's observe what happens as we transition around screen space.

  • As I move up one in world space, I have deck remitted in both the X on Dwight axes and as I move downwards, I've incriminated in both the X and Y axes in world space.

  • As I move left, I have Decker minted in the X axis, but increment ID in the Y axis, and as I moved right.

  • I've increment ID in the X axis, but deck remitted in the Y axis as before, we're going to need a transformation that takes our now screen cell space coordinate and transforms it into a world coordinate.

  • And again, it's a multi component equation as both X and wind screen space factor into the Individual X's and y's in our world.

  • Given that we already have the cell value, we no longer care about the tile width gentile height.

  • Let's again consider our X component first.

  • MacCaulich World X straightaway.

  • We can see that our World X coordinate directly aligns with our cell.

  • Why coordinate so taking the origin into account as well?

  • We know that World X is going to be reliant on See why, minus origin why we also see that our world ex cornet directly aligns with our screen X coordinate, which is very convenient.

  • So we can simply add that as well, and in a similar fashion will calculate the transformation for why, in just the same ways X, we see that our worlds why values are directly in line with our screen cell.

  • Why values?

  • So that's just a repeat.

  • But this time our world.

  • Why values are going in the opposite direction to our screen ex.

  • So you can see here they're actually deck remain ting as our screen X is incriminating.

  • Therefore, very simply, we're going to subtract our cell X value accounting for the offset.

  • So I'm just going to pace that directly into our transformation and at the bottom of the program.

  • I'm also going to output our selected cell value after we've drawn the world.

  • I want to draw the highlighted selected sell.

  • This cell had multiple levels of Alfa in it.

  • So I'm going to use the pixel game engines Alfa blending mode, which is slow, but we're only using it for a handful of pixels.

  • The current selected cell coordinates is in world space, so I'm going to use the to screen Lander that we created earlier to convert that to screen space.

  • And then I'm going to draw the required graphic on top of what is already there, so appear will have drawn the contents of the tile, but down here will then overlay the content of the tile with a highlight.

  • So let's take a look.

  • Well, we can see that the highlighted cell is certainly being drawn wherever the red rectangle waas before, so that implies that hasn't really been any different.

  • But what we can see is that the selected cell value now this coordinate appear in the top left accurately reflects the selected cell in the world.

  • So as I move along this top edge, that's our X axis.

  • We can see that that's increasing, but our why value doesn't on.

  • Similarly, if I move along the Y axis, we see that's increasing.

  • But our X value doesn't.

  • Don't we see that it actually works for anywhere in the screen?

  • So we probably want to put some boundary checks in later to make sure we can't choose elements.

  • The towns in our world array.

  • But there's a problem straightaway.

  • I can only select the cells that exist in the rectangular cell space of the screen.

  • How do I select these ones in between?

  • See, I can't select it.

  • Well, the answer is quite simple.

  • We're going to cheat.

  • Recall that we now know which cell in screen space are mouse exists in on.

  • We've managed to work out which isometric tile in world space.

  • That screen cell corresponds to the problem is we can't access these tiles because they don't fully occupy a salad screen space.

  • We also managed to work out where the mouse exists, so we know that the mouse must exist somewhere in this cell because that's given us this coordinates here on.

  • We also worked out the offset of the mouse into the cell.

  • Therefore, if we could detect the mouse is in this region or this region or this region or this region, we could buy us our world.

  • Coordinate accordingly to either increment or deck lament along the X axis or Y axis.

  • There are several approaches to this, and you may expect, because of the nature of this channel that will now do some geometry and look at line into section equations and which side of the line a point lies.

  • But no, I'm going to really brute force this, and I do it by creating a cheating tile.

  • So here I've created a solid tile is the same dimensions as my other isometric tiles.

  • But the regions in the top corners are identifiable by unique color, and since this tile represents an onscreen cell on, I know the offset of the mouse into this cell, I can determine quite easily which corner of the cell my mouse lies in just by looking at the color by sampling that sprite at that location, we've already got the offset into the cell of the mouse, so I'm just going to call the get pixel function on the source.

  • Spite at that location.

  • It's offset a little bit because this was a spike containing all of the sprites, but it's sampling from the right location to give me a pixel value.

  • And then once I've worked out what my selected cell is, I'm going to modify that location by looking at the returned pixel color on adjusting the X and Y value accordingly.

  • Let's take a look.

  • So now we can see as my mouse goes into the corner of the screen cell, it's selecting the appropriate world cell underneath it, and therefore I can put my mouse over anywhere in the isometric tile array on dhe.

  • Accurately get the cell underneath it.

  • Let's just finish off this quick demonstration by adding the other graphics.

  • Firstly, I'm going to stop drawing the red rectangle.

  • We don't need that anymore.

  • And now that we have the selected cell accurately in world space.

  • I'm going to be responsible to the mouse button being clicked on all the mouse button being clicked is going to do is increment the inter GIs stored in our world array at that location.

  • I'm also wrapping it round to the total number of sprites available on because our selected world value could be anywhere.

  • I'm going to guard our array with an if statement to make sure that it's within bounds on the bounds.

  • Aaron World space, too.

  • So I don't need any fancy transforms for that.

  • I'm just comparing with world size we specified at the start.

  • Since the value of the graphics can now be something other than zero, we're going to choose the appropriate sprites, depending on their value.

  • There's nothing especially clever going on here, but I will draw your attention to the sprites that exist along the bottom off The image thes sprites are effectively to isometric tiles high, so I need to offset it by that before I draw it to make sure that they draw it in the correct location.

  • Because I don't want to just draw the top half of this tree where the tile should be.

  • And so, if the tile it a particular I d has height, I'm taking that into account.

  • And so, finally, we can now click on a particular cell to color it in on the more times we click on a cell, we increment the cells.

  • Value allows us to scroll through the graphics as we're always drawing from top to bottom.

  • We can be assured that things closer to the camera a drawn on top of those further away, giving that lovely feel of depth.

  • And so that's that a quick and simple method of getting away from always having to use a top down to the entire perspective in your games.

  • You could add some pseudo three D retro loveliness without much code or complexity it all as usual.

  • The source code for this project could be found on Get hope in the link bit low.

  • I just updated the pixel game engines to make sure that you have to.

Hello.

Subtitles and vocabulary

Click the word to look it up Click the word to find further inforamtion about it