Dev Log #5: Back to FuetEngine / Resolutions / Room management

(Once again another somewhat technical post)

Back to FuetEngine.
After some weeks studying the posibility of developing the new game in Unity, I decided to come back to my own engine for the development of Maria Akane. Although Unity brings me the possibility of targeting several more platforms where to release the game, it lacks some things I already have with my framework, engine and tools. I’ve released 7 games using it, not counting prototypes and unreleased projects, and there are many things already done there, that I will have to implement from scratch if I wanna use Unity for a new game. In my case, using my own solution will bring me the possibility of focusing on the game itself. What a paradox!

On the other hand, releasing the game on the 3DS and also on the PC will be enough for me, as it can cover the expeses of the development of the project and maybe let me start a new one once I finish it. Okay, I’m assuming something important here: the earnings of this project will be at least the same as those of Cubit, and I think they will, since Maria Akane will be  at least as good as Cubit (if not way more)… that’s the idea.

Yes, I know, the more platforms I cover the better, but anyway, I’m currently the only developer so, 2 platforms is too much work for me, and as I said, most probably more than enough.

FuetEngine Application

Resolutions.
I’ve prepared the framework for the game development, and one of the things I had to deal is the resolution the game will be designed. This is, the dimensions in pixels the game will use during the development.

The most important thing here are not the dimensions themselves but the screen ratio. Nowadays, on the PC world, and also in non portable consoles, the most common aspect ratio is 16:9, and a resolution of 1920×1080 has become the standard (this is what they call: Full HD).

The fact that I’m targeting the 3DS as one of the consoles the game will run, means I have to keep in mind this device while developing the game. Imagine I start designing rooms for the game, and then I have to cut the sides of the room to make them fit into the 3DS screen. This would probably break the entire level design of the game!

Ok, so I face once again the problem of making a videogame that should fit perfectly in both, the 3DS and the PC.

In previous projects I usually worked with a screen resolution of 1600×960. This is high enough to let me publish a game in Hi Res for the PCs, in case I need, and the good thing is that just reducing everything to exactly the 25% makes the game look good on a 3DS. Ok, pixel art is something to take care, but everything else works.
This is a 5:3 aspect ratio. This means I have to introduce some bands at the sides of a 16:9 screen to make it look correctly, i.e. on the PCs. More over, as the complete height of a 1920×1080 screen is not totally filled with my 1600×960 designs, some bands should also be introduced in the top and the bottom of the image. This ends loosing many pixels: 1920-1600=320 horizontal and 1080-960 = 120 vertical, so I’m loosing about 16% of the screen horizontally and about 14% vertically.

This time, I’ve taken another approach. I will work with a screen resolution of 1800×1080 pixels. This is a 5:3 aspect ratio, and it looses only a bit of screen. Specifically, 120 pixels of the horizontal resolution (6,25%), which in my oppinion is almost unnoticeable by the Full HD users. In order to make the graphics fit into the Nintendo 3DS, I’ll have to reduce everything 4,5 times.

Room management.
This week I started working in the management of the rooms for the game.
I imagine rooms being an independent entity and, as the player can be in one and only one at a time, only one should be managed at any given moment. We don’t need the resources of other rooms in memory. This way, we split the whole world in little chunks, every chunk being one room. This has some interesting benefits:
– We can have virtually any number of rooms there. The whole world resource occupation could be bigger than the device’s memory, as we split it in little pieces with a very low memory budget.
– Load time is really fast. Rooms are loaded and unloaded on demand.

But what happens with objects that move across several rooms in the game? For instance an elevator / lifter? What happens with elements locked or unlocked when we exit from a room and enter it again, later in time? There should be a higher entity that manages this kind of information. The game World will keep these global objects, events an state.

On the other hand, I realized a system like this is very similar to the menu system I already use. The Menu Manager handles the flow from one menu page to another menu page, while the behaviour of a single page is managed by the logic behind it. There are pages really generic, which only handle transitions to other set of pages (like the options page, which brings the player to the stats, credits and setup pages) and there are pages with some specific and unique logic (like the enter player name page, which checks if the player name already exists or not and shows a message in that case). These specific menu pages are derived classes from the base class. There is also a specific object responsible of deciding which menu page needs to be created, a generic or an specific one, this is the MenuPageFactory class.

Ok, now if we change the word MenuPage by the word Room we realize, the exact same system can be used to manage the room system I had in mind for the game. More over, Ican use the event handlers in the menu system to my advantage. I can use the OnEnterPage event to setup things in a specific room before the room is presented to the player (a trigger was activated before so the player expects that a wall should be hidden once we enter the room). I can use Update to handle something that needs to be checked in the room every frame. I can use OnIdlePage to trigger something  when the player stands idle in the room for a given amount of time, for intance a fairy spawning which will give full energy to the player (like the one in Maze Of Galious)…

It worked … flawlessly.

How to manage the world position?
Inside a room, we use local coordinates, but what happens when the player moves from the coordinate 1799 to the 1800? He has to enter into the room to the right, ok but with the 1800 coordinate? Nope! We have to decrease the width of a room to the X coordinate of its position.

This is easier to say than to implement. Physics can be here a problem. We’re telling the system that one object has moved from coordinate 1799 to 0 in just a frame, 1/60th of a second!

In the other hand, what happend with those objects that move across rooms we’ve talked before, like an elevator or a lifter?

(I’m thinking right now about of it, and I’m realizing that the player is one of these objects! This means, applying the same treatment to these objects will be enough! Ok, I imagine I will have to decompose the object position in 2 tuples an (i,j) room identifier, and a (x,y) vector for the position of the object inside the room)

Why don’t we use whole world coords for every room? If edition is a problem, we can just translate everything to its right place just after loading the room…

The problem here is floating point precission. I use pixels as coordinates. My character’s height is not 1.70 cm, she’s 192 units (pixels). Each room is 1800 units (1792.0 to be honest) . In world coordinates the 10th room to the right of the current one is at 18000 units. Floating point precission can be a problem here, may be not for static objects, but sure for dynamic ones like enemies, or the player itself. We’ll soon see jittering if we use those high numbers on moving object. Ok, let’s keep these position values as low as possible then…

Finally some numbers:

const FEReal ROOM_WIDTH       = 1792.0f;
const FEReal ROOM_HEIGHT      = 1024.0f;
const uint ROOM_TILE_WIDTH    = 128;
const uint ROOM_TILE_HEIGHT   = 64;
const uint ROOM_XTILES        = 14; // ((uint)ROOM_WIDTH/ROOM_TILE_WIDTH);
const uint ROOM_YTILES        = 16; // ((uint)ROOM_HEIGHT/ROOM_TILE_HEIGHT);
const uint ROOM_LEVELS        = 4;
const uint ROOM_LEVELS_YTILES = 4;

(where is the HUD?!?!?!)

FuetEngine Application_2

 

This entry was posted in Blog. Bookmark the permalink.

Comments are closed.