# Perspective View using Spritesheets

I am creating a Top-View 2D game. However, the only way i can get a good view of the objects, such as houses, trees, is to make the game in orthographic view. The same way games such as Pokemon games in GameBoy Advances used. Until i found out that, GTA 1 and 2 are originally in top-view. Whenever the car (your focus) passes a building, the view of the building changes, specifically, the "Skewness" of the building. Is it possible to do this using SpriteSheets? or atleast a single image and just dynamically change its attributes? or GTA 2 is already using a 3D game engine.

• GTA is from the era where the line between 2D & 3D gets blurry. Dedicated 3D graphics hardware wasn't yet widespread, so games with 3D effects achieved them by plotting transformed texture images pixel by pixel. The transformation math used is still 3D, and the results are often equivalent to rendering 3D polygons the modern way, but it's not using any dedicated 3D pathways — there's no 3rd dimension in the system but the one the game's own math invents (as opposed to modern pipelines with built-in depth buffering etc). So, it gets into semantics whether that "counts" as 2D spritesheets or not – DMGregory Aug 31 '17 at 11:57
• I'm using a 2D library - Slick2D. I created a house in Blender and rendered it. Of course, the rendered image is in perspective view. When I put it in the game and started some test, the house did not look good because its view is static. In reality, the view of the house depends on its distance from the camera/viewer. If the house is exactly in front of the camera, you'll only see the roof. But when the house is somewhere on top, you'll be able to see the front of the house. If I try to render the house at different points with 800x600 resolution, that would be 480,000 images! – Mr. Leeds Aug 31 '17 at 12:44

It's perfectly possible to do this. Most game engines (it's harder with graphics APIs, but it's possible) allow you to supply matrices, and these can represent skewing.

So, first of all, let's say you have a house (or a block of something) defined as the bottom polygon and the player's position: First, for each line in the polygon you get the vectors pointing from the player's position to the ends of the lines, multiply them by two and add them to the player's position to get a "shadow" of the lines: This gives you 4 points, which describe a quad.

If you have a way to draw custom quads, then just use this and texture it correctly. If you don't, then a line by line solution should work instead.

First, calculate the angle of the bottom line (the line you used to create the "shadow") and create a rotation matrix that transforms the line to a horizontal position. If the line is defined by the two points A and B, then this would be:

angle = atan2(B.y - A.y, B-x - A.x)

matrix = | cos -angle, -sin -angle |
| sin -angle,  cos -angle |


Then multiply every point of the quad with this matrix, this should result in the following effect: This is necessary to make the base of every quad aligned with the x axis. Now the line-by-line part. Get the distance on the y axis between the bottom and top lines of the quad (the base line and the "shadow") in pixels and loop through between 0 and this distance. The endpoints of the line parallel to the x axis, that's going across the quad at a specific y position are:

P1 = A + y / height * (D - A)
P2 = B + y / height * (C - B)


using the naming from the image above. For an example look at this image: Now, loop through this line pixel by pixel to get an x position. Now you have an x and y position in the quad's coordinate system. To convert this to uv coordinates, use the following formula:

u = (x - P1.x) / (P2.x - P1.x)
v = y / height

• That means, for a basic house, i have to create 5 separate images, for sides, and 1 for roof. Is it applicable if the roof is triangular? I mean, from your example, it would be easy if the top and and bottom shapes are the same. – Mr. Leeds Aug 31 '17 at 12:53
• @JayMarkParedesEstrera I think it is – Bálint Aug 31 '17 at 12:57