Devlog #2 Isometric Projection

I want to render the map of the game as isometric. So, I need to use basic math tricks for it. Let's draw a sketch for it. Normally, the map's structure could be represented by a 2d grid. If we convert the map to isometric, the tiles of the map's positions look like it visually:


The red dot on the map represents the top left of the tiles. The isometric tile's height size could be half of the tile's width as the lowest value: I use pygame for making a game that doesn't work according to the cartesian coordinate system. The display just shows objects with (|x|, |y|) (positive) coordinates. Anyway, It's not important for now. I need to create an algorithm with reference to the above image. There are some calculations in the below image that contains what we use the formula for locating tiles on the screen correctly:
If we code according to what we've got and the result:
Isometric Tilemap
I can generate a texture for square texture, but it's not valid for the diamond shape. My next goal is creating a texture for use in an isometric map. ❔

That's our struct of isometric tile:
struct of isometric tile

So I generated an isometric surface according to the above image's struct. The function is returned this result. Well, I didn't remove the black background from the surface, but I will.
Also, we have to give a texture effect to this surface. I will do it via bitwise operations on the pixels' color. Finally, I can generate isometric tiles with a texture like the below image:
The game map has to be an isometric view. We're going to convert the top-down map to the isometric map. That's going to be tough.. (15 minutes later) No, it's not 🐣.
isometric game programming

But I couldn't see half of the map as can be seen from the above image  That's normal, because if you look at the second image in the post gives an idea of why we got this result.

When I look at the task manager:

Oh boy! I have to find a more efficient rendering system for my prototype. Normally, I'm using the render method that is every tile blitting on the one surface before the game loop. This method could be useful in some situations like low size map. However, we want to generate an immense world and there is bound for surface's dimension and of course, it's the reason for the high ram usage, I guess. Pygame uses CPU instead of GPU. So, I settled to use the chunk method. Make it clear, we have tiles and some parts of these tiles will be located on the chunk, so this chunk will contain tiles as we determine the amount. These chunks have a position to render it. Let's draw somethings about the chunk:
Chunk Render Method
I made inferences about chunks data structs in the below image:
Chunking Algorithm

This change will be not easy on the current project with broken form therefore, I'm creating a new template for it, IMO the less the better.

I created an example map array and I try to my chunk function to split the array into chunk:
Split array into chunk with python
It fits my array and we got part of the solution. Those chunks will appear if certain conditions are valid. The range values calculated for the chunks between range values will be displayed in the image below:
chunking algorithm

Finally, I could start implementing this chunking algorithm for rendering maps according to the image above in my code(in template code). So it's the result:
Chunks in Pygame

It doesn't work as well, but it works. I looked Task Manager for prototype:
Pygame Efficient Usage
When the program started, surfaces of the chunks are created at the beginning. But what if, we are just creating the surfaces on the running loop when the conditions are met. We wouldn't store surfaces in brief, we will just render them when they are needed:
Pygame Performance Optimization
Looks like there is no difference (ram usage efficiency 15%) between them, however, there are very few surfaces, I suppose It is going to be useful for creating a massive map. In addition, if you have noticed, then we can generate an unlimited world. Because we are no longer dependent on surface maximum size.

So I created a map that is occurred by 800x800 = 640,000 tiles. Each tile's dimension is 64x64, so the map's width is 800x64 = 51200px and when I looked at the task manager, I think the results are good:
Final Result of tilemap
According to these results, If I implement this chunking algorithm in my original code, I hope I will get better efficient results.

The project code is a mess for reviewing and reusable. Before implementing of chunking algorithm, I have to make better my code with an understandable struct of the project.

I arranged my project, and that looks fine except chunking algorithm. The algorithm works well at top-down rendering but there is a problem according to isometric rendering in the running of the game. Probably, It's about the location of the chunks. I'm putting this issue aside currently. I would like to work on the isometric movement of the character(temporary object). 

I typed a converter function called cartesian_to_isometric. After a few struggling problems, the character can move according to isometric calculations. Okay, I think that's enough for a devlog. I'm going to play BF3 now.

No comments:

Post a Comment