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.