views:

262

answers:

4

I'm making a tile game in c++. Right now when the game loads all the tiles place themselves based on:

tilesize -> they are squares so this is width and height

tile_count_x

tile_count_y

I have the following variables:

desktop_width

desktop_height

game_window_width

game_window_height

tile_count_x

tile_count_y

Based on these values, I'm looking for an algorithm that will set an appropriate window size given the desktop and tile_count constraints. Then within this, I want my tiles to have an offset that will border x% around the window which will basically decide the tilesize too:

Example: If I have 10 * 3 of tiles then:

______________________________
Window Title              _[]X
------------------------------
|                            |
|    [][][][][][][][][][]    | 
|    [][][][][][][][][][]    |
|    [][][][][][][][][][]    |
|                            |
------------------------------

I'm just not sure the formula required to do this.

EDIT (from comments):

  • Tilesize changes, tilecountx and y are static
  • I want the gamewindow to be as big as it can be given the desktop resolution, but I also want its aspect ratio to respect the tilecoutx and tilecounty

I found an example of what I mean, open up Minesweeper in Windows

A: 

Simple linear algebra:

game_window_width = (tile_count_x * TILE_WIDTH) + 2*(game_window_width * X / 100)

We have 2 variables (TILE_WIDTH and X) and only 1 equation, so um, you're out of luck.

You will need to either specify TILE_WIDTH or X (the margin). Let's say you specify X, then you can solve the equation:

TILE_WIDTH = (game_window_width - (2*(game_window_width * X / 100))) / 
             tile_count_x

If we take into account the height, and require the same border, then we have 2 equations, and 3 unknowns. Still SOL.

Frank Krueger
+1  A: 

I'm not a C++ programmer but you should get something out of this:

// Amount of padding to leave around tiles (of window size)
int percentage = 10;

tile_ratio = tile_count_x / tile_count_y;
desktop_ratio = desktop_width / desktop_height;

// Determine the maximum window width and height
// according to tile and desktop aspect ratios
if(tile_ratio >= desktop_ratio) {
    window_width = desktop_width;
    window_height = window_width * (1 / tile_ratio);
} else {
    window_height = desktop_height;
    window_width = window_height * tile_ratio;
}

// Determine maximum width and height for tiles,
// taking account x% of padding on both sides, hence the * 2
tile_width = window_width * ((100 - (percentage * 2)) / 100);
tile_height = window_height * ((100 - (percentage * 2)) / 100);

// As the tiles must be square, determine the smaller side as the size
tile_size = tile_width < tile_height ? tile_width : tile_height;

// To maintain the x% padding, we must calculate the window size again as we just changed the tilesize
factor = (100 / (100 - (percentage * 2)));
window_width = tile_size * tile_count_x * factor;
window_height = tile_size * tile_count_y * factor;

Now you have the maximum window width and height so that:

  1. The window is in the same aspect ratio as the tiles
  2. The window is no bigger than the desktop
  3. The window has x% of padding around all sides of tiles

Note that I haven't tested this code at all, but it should work. If you find any errors, try to understand what I tried to do and fix accordingly.

Tatu Ulmanen
A: 

If you are working with Win32, then you could use something like the following to initially size the client-area of your window.

initial_width = (tile_count_x * tile_size) + (border_width * 2);
initial_height = (tile_count_y * tile_size) + (border_width * 2);

When the Window recieves resize events you would simply stretchblt each tile (i.e. enlarge or shrink each tile) by the number of pixels that the window has been expanded or shrunk by (Assuming that the axis are locked, that is you can't resize each independetly).

In other words the tile_size would vary:

tile_size += window_resize_amount;

This code is from memory, but it may give an idea.

DWORD dwStyle = WS_POPUP | WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX | WS_CAPTION;
DWORD dwExStyle = 0;

int border_width = tile_size; // make border 1 tile

RECT r, w;
SetRect(&r, 0, 0, (tile_count_x * tile_size) + (border_width * 2), (tile_count_y * tile_size) + (border_width * 2));
AdjustWindowRectEx(&r, dwStyle, FALSE, dwExStyle);
SystemParametersInfo(SPI_GETWORKAREA, 0, &w, 0);
int width = r.right - r.left;
int height = r.bottom - r.top;
int x = ((w.right - w.left) / 2) - (width / 2);
int y = ((w.bottom - w.top) / 2) - (height / 2);

hWnd = CreateWindowEx(dwExStyle, szClassName, szAppName, dwStyle, x, y, width, height, NULL, NULL, hInstance, 0);
A: 

Here is how I solved it...

     //WINDOW SIZE SETUP

     //choose the smaller TILE_SIZE
     if (DESKTOP_WIDTH / TILE_COUNT_X > DESKTOP_HEIGHT / TILE_COUNT_Y)
     {
      TILE_SIZE = DESKTOP_HEIGHT / TILE_COUNT_Y;
     }
     else
     { 
      TILE_SIZE = DESKTOP_WIDTH / TILE_COUNT_X;
     }
     //Set screen size and consider a 5 tile border
     SCREEN_WIDTH = TILE_SIZE * (TILE_COUNT_X + 5);
     SCREEN_HEIGHT = TILE_SIZE * (TILE_COUNT_Y + 5);

     //resize window until it satisfies resolution constraints
     while( SCREEN_WIDTH > (DESKTOP_WIDTH - (DESKTOP_WIDTH * 0.07)))
     {
      TILE_SIZE --;
     SCREEN_WIDTH = TILE_SIZE * (TILE_COUNT_X + 5);
     SCREEN_HEIGHT = TILE_SIZE * (TILE_COUNT_Y + 5);
     }

     while( SCREEN_HEIGHT > (DESKTOP_HEIGHT - (DESKTOP_HEIGHT * 0.15)))
     {
      TILE_SIZE -- ;
     SCREEN_WIDTH = TILE_SIZE * (TILE_COUNT_X + 5);
     SCREEN_HEIGHT = TILE_SIZE * (TILE_COUNT_Y + 5);
     }
for(int i = 0; i < 8; ++i)     //Ensure resolution is multiple of 8
{
    if (SCREEN_WIDTH % 8 != 0) //remainder means not multiple of 8
    {
     SCREEN_WIDTH += 1;
    }

    if (SCREEN_HEIGHT % 8 != 0)
    {
     SCREEN_HEIGHT += 1;
    }
}
     X_OFFSET = (SCREEN_WIDTH - (TILE_SIZE * TILE_COUNT_X)) / 2;
     Y_OFFSET = (SCREEN_HEIGHT - (TILE_SIZE * TILE_COUNT_Y)) / 2;
Milo