My old C++ code reads a spritesheet (rows = different buttons, cols = different button states) one row at a time using for loops and divides them into individual sprite clips. All the sprites are the same size. Works fine.
Now, I want to put the elements of the clipping for loops into a struct so that I can write a single clipping function to iterate through every graphic on a given spritesheet. Running into a few problems getting everything to work. Something changed with the enums when I put them in the struct, and I think I screwed up the nested for loop.
Old Code
const int LONGBUTTON_HEIGHT = 128;
const int LONGBUTTON_WIDTH = 256;
enum CreateButtonState { CREATE_DEFAULT, CREATE_HOVER, CREATE_PRESSED, CREATE_TOTAL };
enum CreditsButtonState { CREDITS_DEFAULT, CREDITS_HOVER, CREDITS_PRESSED, CREDITS_TOTAL };
enum MenuButtonState { MENU_DEFAULT, MENU_HOVER, MENU_PRESSED, MENU_TOTAL };
main
{
//Load long button spritesheet texture
SDL_Texture* longbutton_image = loadTexture("longbuttonSpriteSheet.png", renderer);
//Long Buttons
//Create Button Setup
SDL_Rect create_clips[CreateButtonState::CREATE_TOTAL];
for (int i = 0; i < CreateButtonState::CREATE_TOTAL; i++)
{
create_clips[i].x = i * LONGBUTTON_WIDTH;
create_clips[i].y = 0;
create_clips[i].w = LONGBUTTON_WIDTH;
create_clips[i].h = LONGBUTTON_HEIGHT;
}
int useCreate_Clip = CREATE_DEFAULT;
// Credits Button Setup
SDL_Rect credits_clips[CreditsButtonState::CREDITS_TOTAL];
for (int i = 0; i < CreditsButtonState::CREDITS_TOTAL; i++)
{
credits_clips[i].x = i * LONGBUTTON_WIDTH;
credits_clips[i].y = 1 * LONGBUTTON_HEIGHT;
credits_clips[i].w = LONGBUTTON_WIDTH;
credits_clips[i].h = LONGBUTTON_HEIGHT;
}
int useCredits_Clip = CREDITS_DEFAULT;
//Menu Button Setup
SDL_Rect menu_clips[MenuButtonState::MENU_TOTAL];
for (int i = 0; i < MenuButtonState::MENU_TOTAL; i++)
{
menu_clips[i].x = i * LONGBUTTON_WIDTH;
menu_clips[i].y = 2 * LONGBUTTON_HEIGHT;
menu_clips[i].w = LONGBUTTON_WIDTH;
menu_clips[i].h = LONGBUTTON_HEIGHT;
}
int useMenu_Clip = MENU_DEFAULT;
return 0;
}
New Code
int originalspriteH = 128;
int originalspriteW = 256;
int spritesheetcols = 2;
struct Graphic
{
typedef enum buttonstate {DEFAULT, HOVER, PRESSED, TOTAL};
SDL_Rect clip;
int useClip;
};
void clipSprites(int spritesheetcols, int originalspriteH, int originalspriteW, [Graphic &graphic])
{
for (int j =0; j < spritesheetcols; j++)
{
graphic.clip[graphic.buttonstate::TOTAL];
}
for (int i = 0, i < graphic.buttonstate::TOTAL; i++)
{
graphic.clip[i].x = i * originalspriteW;
graphic.clip[i].y = j * originalspriteH;
graphic.clip[i].h = originalspriteW;
graphic.clip[i].w = originalspriteH;
}
graphic.useClip = DEFAULT;
}
main
{
clipSprites(2, 128, 256, [create, credits, menu])
return 0;
}
Related
I managed with some help to know how when two rectangles are intersecting each other, from there it should be easy to make what i just said in the title but ...
So, short story of what i just did below:
Created a for loop from 1 to Number_of_Obstacles
In that for an random obstacle (rectangle/square) is created and it will be checked if it is overlaped with all other obstacles created from 0 to the loop contor (or in other words every obstacle stored in the vector)
Again, the doOverLap function works. Tested it with a square which i made a controller and other random rectangle created on the screen. It outputs in chat when i'm overlaping it and trust me, i overlaped it from all angles.
Here is a picture with the overlaping issue: https://imgur.com/a/ZzorOcD
bool doOverlap(A a, B b)
{
if (a.x1 > b.x2 || b.x1 > a.x2)
return false;
if (a.y1 > b.y2 || b.y1 > a.y2)
return false;
return true;
}
struct Obstacles {
int X, Y;
void Create_Random_Obstacles(Obstacles Obj[], int Numar_Obstacole)
{
srand(time(NULL));
A Rectangle_1;
B Rectangle_2;
/* To avoid rendering outside of the screen */
int X_Axis = X_RESOLUTION - 40;
int Y_Axis = Y_RESOLUTION - 40;
int obstacolX = rand() % X_Axis + 1;
int obstacolY = rand() % Y_Axis + 1;
Obj[0].X = obstacolX;
Obj[0].Y = obstacolY;
for (int i = 1; i < Numar_Obstacole; i++)
{
obstacolX = rand() % X_Axis + 1;
obstacolY = rand() % Y_Axis + 1;
Rectangle_1.x1 = obstacolX;
Rectangle_1.x2 = obstacolX + 40;
Rectangle_1.y1 = obstacolY;
Rectangle_1.y2 = obstacolY + 40;
for (int j = 0; j < i; j++) {
Rectangle_2.x1 = Obj[j].X;
Rectangle_2.x2 = Obj[j].X + 40;
Rectangle_2.y1 = Obj[j].Y;
Rectangle_2.y2 = Obj[j].Y + 40;
if (doOverlap(Rectangle_1, Rectangle_2))
{
std::cout << "Overlap\n";
}
else
{
Obj[i].X = obstacolX;
Obj[i].Y = obstacolY;
}
}
}
}
void Render(SDL_Renderer* renderer, Obstacles Obj[], int Numar_Obstacole) {
for (int i = 0; i < Numar_Obstacole; i++)
{
SDL_Rect r{ Obj[i].X, Obj[i].Y, 40, 40 };
SDL_SetRenderDrawColor(renderer, 255, 160, 15, 255);
SDL_RenderFillRect(renderer, &r);
}
}
};
Restart selection when collision occurs, something like:
bool Has_Overlap(const Obstacles& obj, const Obstacles* Objs, int Size)
{
B Rectangle_2;
Rectangle_2.x1 = obs.X;
Rectangle_2.x2 = obs.X + 40;
Rectangle_2.y1 = obs.Y;
Rectangle_2.y2 = obs.Y + 40;
for (int i = 0; i != Size; ++i) {
A Rectangle_1;
Rectangle_1.x1 = Obs[i].X;
Rectangle_1.x2 = Obs[i].X + 40;
Rectangle_1.y1 = Obs[i].Y;
Rectangle_1.y2 = Obs[i].Y + 40;
if (doOverlap(Rectangle_1, Rectangle_2)) {
return true;
}
}
return false;
}
void Create_Random_Obstacles(Obstacles* Objs, int Size)
{
/* To avoid rendering outside of the screen */
const int X_Axis = X_RESOLUTION - 40;
const int Y_Axis = Y_RESOLUTION - 40;
for (int i = 0; i < Size; i++)
{
do {
Objs[i].X = rand() % X_Axis + 1;
Objs[i].Y = rand() % Y_Axis + 1;
} while (Has_Overlap(Objs[i], Objs, i));
}
}
My code seems to have a bug somewhere but I just can't catch it. I'm passing a 2d array to three sequential functions. First function populates it, second function modifies the values to 1's and 0's, the third function counts the 1's and 0's. I can access the array easily inside the first two functions, but I get an access violation at the first iteration of the third one.
Main
text_image_data = new int*[img_height];
for (i = 0; i < img_height; i++) {
text_image_data[i] = new int[img_width];
}
cav_length = new int[numb_of_files];
// Start processing - load each image and find max cavity length
for (proc = 0; proc < numb_of_files; proc++)
{
readImage(filles[proc], text_image_data, img_height, img_width);
threshold = makeBinary(text_image_data, img_height, img_width);
cav_length[proc] = measureCavity(bullet[0], img_width, bullet[1], img_height, text_image_data);
}
Functions
int makeBinary(int** img, int height, int width)
{
int threshold = 0;
unsigned long int sum = 0;
for (int k = 0; k < width; k++)
{
sum = sum + img[1][k] + img[2][k] + img[3][k] + img[4][k] + img[5][k];
}
threshold = sum / (width * 5);
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
img[i][j] = img[i][j] > threshold ? 1 : 0;
}
}
return threshold;
}
// Count pixels - find length of cavity here
int measureCavity(int &x, int& width, int &y, int &height, int **img)
{
double mean = 1.;
int maxcount = 0;
int pxcount = 0;
int i = x - 1;
int j;
int pxsum = 0;
for (j = 0; j < height - 2; j++)
{
while (mean > 0.0)
{
for (int ii = i; ii > i - 4; ii--)
{
pxsum = pxsum + img[ii][j] + img[ii][j + 1];
}
mean = pxsum / 4.;
pxcount += 2;
i += 2;
pxsum = 0;
}
maxcount = std::max(maxcount, pxcount);
pxcount = 0;
j++;
}
return maxcount;
}
I keep getting an access violation in the measureCavity() function. I'm passing and accessing the array text_image_data the same way as in makeBinary() and readImage(), and it works just fine for those functions. The size is [550][70], I'm getting the error when trying to access [327][0].
Is there a better, more reliable way to pass this array between the functions?
I am trying to write a program that simulates a chess game with the FLTK library.
My problem is that I want to do two callbacks on an two dimension array of buttons, I want to click a button, then click another button and when the second button is clicked have the label of the first button switch to the label of the second button and then delete the label of the first button.
I feel like I need someway of storing the value of the the first button that is clicked, for example if I click FBoard[1][2] the i have a variable that is equal to FBoard[1][2] and open the second click replace the label of FBoard[1][2] to blank (assuming FBoard[1][2] is a cell on the board that has a piece on it. But I'm not sure how or even if this is the right approach.
Here is the cpp file:
#include"Window.h"
#include"ChessBoard.h"
const char * DisplayWindow::LastLabel;
bool DisplayWindow::flag;
DisplayWindow::DisplayWindow(int width, int height, const char*)
:Fl_Window(800, 650, "Chess"){
for (int X = 0; X <= 7; ++X){
for (int Y = 0; Y <= 7; ++Y){
// Leaves all positions that arent occupied by
// a figure at the start of the game blank
FBoard[X][Y] = new Fl_Button(10 + 50*Y, 100 + 50*X, 50, 50,"");
FBoard[X][Y]->callback((Fl_Callback*)DisplayWindow::ChangeButton);
}
}
flag = false;
MakeLabel();
LabelButton();
show();
}
DisplayWindow::~DisplayWindow(){}
void DisplayWindow::MakeLabel(){
for (int X = 0; X <= 7; ++X){
for (int Y = 0; Y <= 7; ++Y){
LBoard[X][Y] = (" ");
}
}
for (int X = 0; X <= 7; ++X){
LBoard[1][X] = ("WP");
// Occupies second row with white pawns
}
LBoard[0][0] = ("WR");
LBoard[0][1] = ("WH");
LBoard[0][2] = ("WB");
LBoard[0][3] = ("WQ");
LBoard[0][4] = ("WK");
LBoard[0][5] = ("WB");
LBoard[0][6] = ("WH");
LBoard[0][7] = ("WR");
for (int X = 0; X <= 7; ++X){
LBoard[6][X] = ("BP");
}
LBoard[7][0] = ("BR");
LBoard[7][1] = ("BH");
LBoard[7][2] = ("BB");
LBoard[7][3] = ("BQ");
LBoard[7][4] = ("BK");
LBoard[7][5] = ("BB");
LBoard[7][6] = ("BH");
LBoard[7][7] = ("BR");
}
void DisplayWindow::LabelButton(){
for (int X = 0; X <= 7; ++X){
FBoard[1][X]->label(LBoard[1][X]);
// Occupies second row with white pawns
}
FBoard[0][0]->label(LBoard[0][0]);
FBoard[0][1]->label(LBoard[0][1]);
FBoard[0][2]->label(LBoard[0][2]);
FBoard[0][3]->label(LBoard[0][3]);
FBoard[0][4]->label(LBoard[0][4]);
FBoard[0][5]->label(LBoard[0][5]);
FBoard[0][6]->label(LBoard[0][6]);
FBoard[0][7]->label(LBoard[0][7]);
for (int X = 0; X <= 7; ++X){
FBoard[6][X]->label(LBoard[6][X]);
}
FBoard[7][0] ->label(LBoard[7][0]);
FBoard[7][1] ->label(LBoard[7][1]);
FBoard[7][2] ->label(LBoard[7][2]);
FBoard[7][3] ->label(LBoard[7][3]);
FBoard[7][4] ->label(LBoard[7][4]);
FBoard[7][5] ->label(LBoard[7][5]);
FBoard[7][6] ->label(LBoard[7][6]);
FBoard[7][7] ->label(LBoard[7][7]);
for(int i=0 ; i<=7 ; i++)
{
for(int j=0 ; j<=7 ; j++)
{
int k=i+j;
if(k % 2 != 0 ){
FBoard[i][j]->color(FL_WHITE);
}
else if (k % 2 ==0 ){
FBoard[i][j]->color(FL_YELLOW);
}
}
}
}
void DisplayWindow::ChangeButton(Fl_Widget * o, void * v){
DisplayWindow* Win = (DisplayWindow *) v;
Fl_Button * NewBoard = (Fl_Button*) o;
if (Win->flag == false){
DisplayWindow::LastLabel = NewBoard->label();
NewBoard->label(" ");
Win->flag = true;
}
else{
NewBoard->label(DisplayWindow::LastLabel);
Win->flag = false;
}
}
And the Header file:
class DisplayWindow: public Fl_Window {
public:
DisplayWindow(int width, int height, const char* title=0);
virtual ~DisplayWindow();
void MakeLabel();
void LabelButton();
static void ChangeButton(Fl_Button * o, void * );
static bool flag;
bool flag1;
static const char * LastLabel;
private:
Fl_Button * FBoard[8][8];
char * LBoard[8][8];
};
#endif
cpp:
#include"Window.h"
#include"ChessBoard.h"
const char * DisplayWindow::LastLabel;
bool DisplayWindow::flag;
DisplayWindow::DisplayWindow(int width, int height, const char*)
:Fl_Window(800, 650, "Chess"){
for (int X = 0; X <= 7; ++X){
for (int Y = 0; Y <= 7; ++Y){
// Leaves all positions that arent occupied by
// a figure at the start of the game blank
FBoard[X][Y] = new Fl_Button(10 + 50*Y, 100 + 50*X, 50, 50,"");
FBoard[X][Y]->callback((Fl_Callback*)DisplayWindow::ChangeButton);
//FBoard[X][Y]->callback(ChangeButton);
}
}
flag = false;
MakeLabel();
LabelButton();
show();
}
DisplayWindow::~DisplayWindow(){}
void DisplayWindow::MakeLabel(){
for (int X = 0; X <= 7; ++X){
for (int Y = 0; Y <= 7; ++Y){
LBoard[X][Y] = (" ");
}
}
for (int X = 0; X <= 7; ++X){
LBoard[1][X] = ("WP");
// Occupies second row with white pawns
}
LBoard[0][0] = ("WR");
LBoard[0][1] = ("WH");
LBoard[0][2] = ("WB");
LBoard[0][3] = ("WQ");
LBoard[0][4] = ("WK");
LBoard[0][5] = ("WB");
LBoard[0][6] = ("WH");
LBoard[0][7] = ("WR");
for (int X = 0; X <= 7; ++X){
LBoard[6][X] = ("BP");
}
LBoard[7][0] = ("BR");
LBoard[7][1] = ("BH");
LBoard[7][2] = ("BB");
LBoard[7][3] = ("BQ");
LBoard[7][4] = ("BK");
LBoard[7][5] = ("BB");
LBoard[7][6] = ("BH");
LBoard[7][7] = ("BR");
}
void DisplayWindow::LabelButton(){
for (int X = 0; X <= 7; ++X){
FBoard[1][X]->label(LBoard[1][X]);
// Occupies second row with white pawns
}
FBoard[0][0]->label(LBoard[0][0]);
FBoard[0][1]->label(LBoard[0][1]);
FBoard[0][2]->label(LBoard[0][2]);
FBoard[0][3]->label(LBoard[0][3]);
FBoard[0][4]->label(LBoard[0][4]);
FBoard[0][5]->label(LBoard[0][5]);
FBoard[0][6]->label(LBoard[0][6]);
FBoard[0][7]->label(LBoard[0][7]);
for (int X = 0; X <= 7; ++X){
FBoard[6][X]->label(LBoard[6][X]);
}
FBoard[7][0] ->label(LBoard[7][0]);
FBoard[7][1] ->label(LBoard[7][1]);
FBoard[7][2] ->label(LBoard[7][2]);
FBoard[7][3] ->label(LBoard[7][3]);
FBoard[7][4] ->label(LBoard[7][4]);
FBoard[7][5] ->label(LBoard[7][5]);
FBoard[7][6] ->label(LBoard[7][6]);
FBoard[7][7] ->label(LBoard[7][7]);
for(int i=0 ; i<=7 ; i++)
{
for(int j=0 ; j<=7 ; j++)
{
int k=i+j;
if(k % 2 != 0 ){
FBoard[i][j]->color(FL_WHITE);
}
else if (k % 2 ==0 ){
FBoard[i][j]->color(FL_YELLOW);
}
}
}
}
void DisplayWindow::ChangeButton(Fl_Widget * o, void * v){
DisplayWindow* Win = (DisplayWindow *) v;
Fl_Button * NewBoard = (Fl_Button*) o;
if (Win->flag == false){
DisplayWindow::LastLabel = NewBoard->label();
NewBoard->label(" ");
Win->flag = true;
}
else{
NewBoard->label(DisplayWindow::LastLabel);
Win->flag = false;
}
}
h:
#ifndef WINDOW_H_
#define WINDOW_H_
#include<vector>
#include<limits>
#include<string>
#include<iostream>
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Button.H>
class DisplayWindow: public Fl_Window {
public:
DisplayWindow(int width, int height, const char* title=0);
virtual ~DisplayWindow();
void MakeLabel();
void LabelButton();
static void ChangeButton(Fl_Widget * o, void * );
static bool flag;
bool flag1;
static const char * LastLabel;
private:
Fl_Button * FBoard[8][8];
char * LBoard[8][8];
};
#endif
I am in the progress of making a game which uses SDL_TTF and SDL_Image. I have one function called browseinventory which allows you to check out the stats of an item once you hover over it. That's where the memory leak occurs. Baically once you've hovered over an item slot the program check if there's anything in said slot and if there is, Text class objects are set with the item's parameters and then rendered.
I am pretty sure that the fault lies within the Text class, as memory usage rapidly increases once I've hovered over an item.
Text class:
class Text
{
public:
Text() {w = 0; h = 0; saying = ""; Textthing = NULL;}
~Text(){destroy();}
void destroy(){SDL_DestroyTexture(Textthing); Textthing = 0; saying = "", w = 0, h = 0;}
void render(int, int, int, SDL_Renderer*);
void settext(string, SDL_Color);
void rendertest(int, int, SDL_Renderer*);
int rows;
private:
string saying;
SDL_Texture *Textthing;
int w, h;
unsigned int flag1 = 0, flag2, loops = 0;
string saying1;
unsigned int counter;
bool spaceflag = 0;
};
render():
void Text::render(int x, int y, int maxchars = 100, SDL_Renderer *Temp = Saviour)
{
rows = 0;
flag1 = 0, flag2 = maxchars, loops = 0;
int increment = maxchars;
if (resolution == "800x600")
{
flag2 = maxchars*0.8;
increment = maxchars*0.8;
}
spaceflag = 0;
do
{
spaceflag = 0;
for (counter = flag1; counter < flag2 && counter < saying.length(); counter++)
{
if (counter > flag2-10 && saying[counter] == ' ')
{
spaceflag = 1;
break;
}
saying1 += saying[counter];
}
asdfgfa1.settext(saying1);
asdfgfa1.rendertest(x, y + loops*(SCREEN_HEIGHT/19), Temp);
saying1 = "";
loops++;
rows++;
if (flag2 > saying.length())
break;
if (spaceflag == 0)
{
flag1 = flag2;
flag2 += increment;
}
else
{
flag1 = counter;
flag2 = counter + increment;
}
}while (1);
asdfgfa1.destroy();
SDL_DestroyTexture(Textthing);
Textthing = 0;
}
setText():
void Text::settext(string stuff, SDL_Color Colour = {255, 255, 255})
{
saying = stuff;
SDL_Surface *Surf = TTF_RenderText_Solid(Arial, stuff.c_str(), Colour);
w = Surf->w;
h = Surf->h;
Textthing = SDL_CreateTextureFromSurface(Saviour, Surf);
SDL_FreeSurface(Surf);
Surf = 0;
}
I had a previous question about a stack overflow error and switch to vectors for my arrays of objects. That question can be referenced here if needed: How to get rid of stack overflow error
My current question is however, how do I speed up the initialization of the vectors. My current method currently takes ~15 seconds. Using arrays instead of vectors it took like a second with a size of arrays small enough that didn't throw the stack overflow error.
Here is how I am initializing it:
in main.cpp I initialize my dungeon object:
dungeon = Dungeon(0, &textureHandler, MIN_X, MAX_Y);
in my dungeon(...) constructor, I initialize my 5x5 vector of rooms and call loadDungeon:
Dungeon::Dungeon(int dungeonID, TextureHandler* textureHandler, int topLeftX, int topLeftY)
{
currentRoomRow = 0;
currentRoomCol = 0;
for (int r = 0; r < MAX_RM_ROWS; ++r)
{
rooms.push_back(vector<Room>());
for (int c = 0; c < MAX_RM_COLS; ++c)
{
rooms[r].push_back(Room());
}
}
loadDungeon(dungeonID, textureHandler, topLeftX, topLeftY);
}
my Room constructor populates my 30x50 vector of cells (so I can set them up in the loadDungeon function):
Room::Room()
{
for (int r = 0; r < MAX_ROWS; ++r)
{
cells.push_back(vector<Cell>());
for (int c = 0; c < MAX_COLS; ++c)
{
cells[r].push_back(Cell());
}
}
}
My default cell constructor is simple and isn't doing much but I'll post it anyway:
Cell::Cell()
{
x = 0;
y = 0;
width = 16;
height = 16;
solid = false;
texCoords.push_back(0);
texCoords.push_back(0);
texCoords.push_back(1);
texCoords.push_back(0);
texCoords.push_back(1);
texCoords.push_back(1);
texCoords.push_back(0);
texCoords.push_back(1);
}
And lastly my loadDungeon() function will set up the cells. Eventually this will read from a file and load the cells up but for now I would like to optimize this a bit if possible.
void Dungeon::loadDungeon(int dungeonID, TextureHandler* textureHandler, int topLeftX, int topLeftY)
{
int startX = topLeftX + (textureHandler->getSpriteWidth()/2);
int startY = topLeftY - (textureHandler->getSpriteHeight()/2);
int xOffset = 0;
int yOffset = 0;
for (int r = 0; r < MAX_RM_ROWS; ++r)
{
for (int c = 0; c < MAX_RM_COLS; ++c)
{
for (int cellRow = 0; cellRow < rooms[r][c].getMaxRows(); ++cellRow)
{
xOffset = 0;
for (int cellCol = 0; cellCol < rooms[r][c].getMaxCols(); ++cellCol)
{
rooms[r][c].setupCell(cellRow, cellCol, startX + xOffset, startY - yOffset, textureHandler->getSpriteWidth(), textureHandler->getSpriteHeight(), false, textureHandler->getSpriteTexCoords("grass"));
xOffset += textureHandler->getSpriteWidth();
}
yOffset += textureHandler->getSpriteHeight();
}
}
}
currentDungeon = dungeonID;
currentRoomRow = 0;
currentRoomCol = 0;
}
So how can I speed this up so it doesn't take ~15 seconds to load up every time. I feel like it shouldn't take 15 seconds to load a simple 2D game.
SOLUTION
Well my solution was to use std::vector::reserve call (rooms.reserve in my code and it ended up working well. I changed my function Dungeon::loadDungeon to Dungeon::loadDefaultDungeon because it now loads off a save file.
Anyway here is the code (I got it down to about 4-5 seconds from ~15+ seconds in debug mode):
Dungeon::Dungeon()
{
rooms.reserve(MAX_RM_ROWS * MAX_RM_COLS);
currentDungeon = 0;
currentRoomRow = 0;
currentRoomCol = 0;
}
void Dungeon::loadDefaultDungeon(TextureHandler* textureHandler, int topLeftX, int topLeftY)
{
int startX = topLeftX + (textureHandler->getSpriteWidth()/2);
int startY = topLeftY - (textureHandler->getSpriteHeight()/2);
int xOffset = 0;
int yOffset = 0;
cerr << "Loading default dungeon..." << endl;
for (int roomRow = 0; roomRow < MAX_RM_ROWS; ++roomRow)
{
for (int roomCol = 0; roomCol < MAX_RM_COLS; ++roomCol)
{
rooms.push_back(Room());
int curRoom = roomRow * MAX_RM_COLS + roomCol;
for (int cellRow = 0; cellRow < rooms[curRoom].getMaxRows(); ++cellRow)
{
for (int cellCol = 0; cellCol < rooms[curRoom].getMaxCols(); ++cellCol)
{
rooms[curRoom].setupCell(cellRow, cellCol, startX + xOffset, startY - yOffset, textureHandler->getSpriteWidth(), textureHandler->getSpriteHeight(), false, textureHandler->getSpriteTexCoords("default"), "default");
xOffset += textureHandler->getSpriteWidth();
}
yOffset += textureHandler->getSpriteHeight();
xOffset = 0;
}
cerr << " room " << curRoom << " complete" << endl;
}
}
cerr << "default dungeon loaded" << endl;
}
Room::Room()
{
cells.reserve(MAX_ROWS * MAX_COLS);
for (int r = 0; r < MAX_ROWS; ++r)
{
for (int c = 0; c < MAX_COLS; ++c)
{
cells.push_back(Cell());
}
}
}
void Room::setupCell(int row, int col, float x, float y, float width, float height, bool solid, /*std::array<float, 8>*/ vector<float> texCoords, string texName)
{
cells[row * MAX_COLS + col].setup(x, y, width, height, solid, texCoords, texName);
}
void Cell::setup(float x, float y, float width, float height, bool solid, /*std::array<float,8>*/ vector<float> t, string texName)
{
this->x = x;
this->y = y;
this->width = width;
this->height = height;
this->solid = solid;
for (int i = 0; i < t.size(); ++i)
this->texCoords.push_back(t[i]);
this->texName = texName;
}
It seems wasteful to have so many dynamic allocations. You can get away with one single allocation by flattening out your vector and accessing it in strides:
std::vector<Room> rooms;
rooms.resize(MAX_RM_ROWS * MAX_RM_COLS);
for (unsigned int i = 0; i != MAX_RM_ROWS; ++i)
{
for (unsigned int j = 0; j != MAX_RM_COLS; ++j)
{
Room & r = rooms[i * MAX_RM_COLS + j];
// use `r` ^^^^^^^^^^^^^^^^^^^-----<< strides!
}
}
Note how resize is performed exactly once, incurring only one single allocation, as well as default-constructing each element. If you'd rather construct each element specifically, use rooms.reserve(MAX_RM_ROWS * MAX_RM_COLS); instead and populate the vector in the loop.
You may also wish to profile with rows and columns swapped and see which is faster.
Since it seems that your vectors have their size defined at compile time, if you can use C++11, you may consider using std::array instead of std::vector. std::array cannot be resized and lacks many of the operations in std::vector, but is much more lightweight and it seems a good fit for what you are doing.
As an example, you could declare cells as:
#include <array>
/* ... */
std::array<std::array<Cell, MAX_COLS>, MAX_ROWS> cells;
UPDATE: since a locally defined std::array allocates its internal array on the stack, the OP will experience a stack overflow due to the considerably large size of the arrays. Still, it is possible to use an std::array (and its benefits compared to using std::vector), by allocating the array on the heap. That can be done by doing something like:
typedef std::array<std::array<Cell, MAX_COLS>, MAX_ROWS> Map;
Map* cells;
/* ... */
cells = new Map();
Even better, smart pointers can be used:
#include <memory>
/* ... */
std::unique_ptr<Map> cells;
cells = std::unique_ptr(new Map());