Allegro 5 Audio Assertion Fail - c++
I'm wondering if anyone can point me in the right direction for this error.
I am learning 2D game programming using Allegro 5 installed in Visual Studio 2010.
I have been following a tutorial series and everything has been fine until the last lesson.
The final code will build successfully. The executable will load but will crash out when I hit the space bar to fire a bullet (it's a side shooter game). I get the following error:
"Assertion failed: spl, file allegro-git\addons\audio\kgm_sample.c line 321"
It obviously has something to do with the bullet sample sound linked in with the key press.
If I comment out the line: al_play_sample(shot, 1, 0, 1, ALLEGRO_PLAYMODE_ONCE, 0); in the FireBullet() function, then the game will play fine (without the bullet sound).
I have searched everywhere and cannot find a solution.
Here is the complete code for the game:
#include <allegro5\allegro.h>
#include <allegro5\allegro_primitives.h>
#include <allegro5\allegro_font.h>
#include <allegro5\allegro_ttf.h>
#include <allegro5\allegro_image.h>
#include <allegro5\allegro_audio.h>
#include <allegro5\allegro_acodec.h>
#include "objects.h"
//GLOBALS==============================
const int WIDTH = 800;
const int HEIGHT = 400;
const int NUM_BULLETS = 5;
const int NUM_COMETS = 10;
const int NUM_EXPLOSIONS = 5;
enum STATE{TITLE, PLAYING, LOST};
enum KEYS{UP, DOWN, LEFT, RIGHT, SPACE};
bool keys[5] = {false, false, false, false, false};
SpaceShip ship;
Bullet bullets[NUM_BULLETS];
Comet comets[NUM_COMETS];
Explosion explosions[NUM_EXPLOSIONS];
ALLEGRO_SAMPLE *shot = NULL;
ALLEGRO_SAMPLE *boom = NULL;
ALLEGRO_SAMPLE *song = NULL;
ALLEGRO_SAMPLE_INSTANCE *songInstance = NULL;
//prototypes
void InitShip(SpaceShip &ship, ALLEGRO_BITMAP *image);
void ResetShipAnimation(SpaceShip &ship, int position);
void DrawShip(SpaceShip &ship);
void MoveShipUp(SpaceShip &ship);
void MoveShipDown(SpaceShip &ship);
void MoveShipLeft(SpaceShip &ship);
void MoveShipRight(SpaceShip &ship);
void InitBullet(Bullet bullet[], int size);
void DrawBullet(Bullet bullet[], int size);
void FireBullet(Bullet bullet[], int size, SpaceShip &ship);
void UpdateBullet(Bullet bullet[], int size);
void CollideBullet(Bullet bullet[], int bSize, Comet comets[], int cSize, SpaceShip &ship, Explosion explosions[], int eSize);
void InitComet(Comet comets[], int size, ALLEGRO_BITMAP *image);
void DrawComet(Comet comets[], int size);
void StartComet(Comet comets[], int size);
void UpdateComet(Comet comets[], int size);
void CollideComet(Comet comets[], int cSize, SpaceShip &ship, Explosion explosions[], int eSize);
void InitExplosions(Explosion explosions[], int size, ALLEGRO_BITMAP *image);
void DrawExplosions(Explosion explosions[], int size);
void StartExplosions(Explosion explosions[], int size, int x, int y);
void UpdateExplosions(Explosion explosions[], int size);
void InitBackground(Background &back, float x, float y, float velX, float velY, int width, int height, int dirX, int dirY, ALLEGRO_BITMAP *image);
void UpdateBackground(Background &back);
void DrawBackground(Background &back);
void ChangeState(int &state, int newState);
int main(void)
{
//primitive variable
bool done = false;
bool redraw = true;
const int FPS = 60;
int state = -1;
//object variables
Background BG;
Background MG;
Background FG;
//Allegro variables
ALLEGRO_DISPLAY *display = NULL;
ALLEGRO_EVENT_QUEUE *event_queue = NULL;
ALLEGRO_TIMER *timer = NULL;
ALLEGRO_FONT *font18 = NULL;
ALLEGRO_BITMAP *shipImage;
ALLEGRO_BITMAP *cometImage;
ALLEGRO_BITMAP *expImage;
ALLEGRO_BITMAP *title = NULL;
ALLEGRO_BITMAP *lost = NULL;
ALLEGRO_BITMAP *bgImage = NULL;
ALLEGRO_BITMAP *mgImage = NULL;
ALLEGRO_BITMAP *fgImage = NULL;
//Initialization Functions
if(!al_init()) //initialize Allegro
return -1;
display = al_create_display(WIDTH, HEIGHT); //create our display object
if(!display) //test display object
return -1;
al_init_primitives_addon();
al_install_keyboard();
al_init_font_addon();
al_init_ttf_addon();
al_init_image_addon();
al_install_audio();
al_init_acodec_addon();
event_queue = al_create_event_queue();
timer = al_create_timer(1.0 / FPS);
shipImage = al_load_bitmap("spaceship_by_arboris.png");
al_convert_mask_to_alpha(shipImage, al_map_rgb(255, 0, 255));
cometImage = al_load_bitmap("asteroids.png");
expImage = al_load_bitmap("explosion.png");
title = al_load_bitmap("Shooter_Title.png");
lost = al_load_bitmap("Shooter_Lose.png");
bgImage = al_load_bitmap("starBG.png");
mgImage = al_load_bitmap("starMG.png");
fgImage = al_load_bitmap("starFG.png");
al_reserve_samples(10);
shot = al_load_sample("shot.ogg");
boom = al_load_sample("explosion.wav");
song = al_load_sample("war.wav");
songInstance = al_create_sample_instance(song);
al_set_sample_instance_playmode(songInstance, ALLEGRO_PLAYMODE_LOOP);
al_attach_sample_instance_to_mixer(songInstance, al_get_default_mixer());
srand(time(NULL));
ChangeState(state, TITLE);
InitShip(ship, shipImage);
InitBullet(bullets, NUM_BULLETS);
InitComet(comets, NUM_COMETS, cometImage);
InitExplosions(explosions, NUM_EXPLOSIONS, expImage);
InitBackground(BG, 0, 0, 1, 0, 800, 400, -1, 1, bgImage);
InitBackground(MG, 0, 0, 2, 0, 2400, 400, -1, 1, mgImage);
InitBackground(FG, 0, 0, 4, 0, 2400, 400, -1, 1, fgImage);
font18 = al_load_font("arial.ttf", 18, 0);
al_register_event_source(event_queue, al_get_keyboard_event_source());
al_register_event_source(event_queue, al_get_timer_event_source(timer));
al_register_event_source(event_queue, al_get_display_event_source(display));
al_start_timer(timer);
while(!done)
{
ALLEGRO_EVENT ev;
al_wait_for_event(event_queue, &ev);
if(ev.type == ALLEGRO_EVENT_TIMER)
{
redraw = true;
if(keys[UP])
MoveShipUp(ship);
else if(keys[DOWN])
MoveShipDown(ship);
else
ResetShipAnimation(ship, 1);
if(keys[LEFT])
MoveShipLeft(ship);
else if(keys[RIGHT])
MoveShipRight(ship);
else
ResetShipAnimation(ship, 2);
if(state == TITLE)
{}
else if(state == PLAYING)
{
UpdateBackground(BG);
UpdateBackground(MG);
UpdateBackground(FG);
UpdateExplosions(explosions, NUM_EXPLOSIONS);
UpdateBullet(bullets, NUM_BULLETS);
StartComet(comets, NUM_COMETS);
UpdateComet(comets, NUM_COMETS);
CollideBullet(bullets, NUM_BULLETS, comets, NUM_COMETS, ship, explosions, NUM_EXPLOSIONS);
CollideComet(comets, NUM_COMETS, ship, explosions, NUM_EXPLOSIONS);
if(ship.lives <= 0)
ChangeState(state, LOST);
}
else if(state == LOST)
{}
}
else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
{
done = true;
}
else if(ev.type == ALLEGRO_EVENT_KEY_DOWN)
{
switch(ev.keyboard.keycode)
{
case ALLEGRO_KEY_ESCAPE:
done = true;
break;
case ALLEGRO_KEY_UP:
keys[UP] = true;
break;
case ALLEGRO_KEY_DOWN:
keys[DOWN] = true;
break;
case ALLEGRO_KEY_LEFT:
keys[LEFT] = true;
break;
case ALLEGRO_KEY_RIGHT:
keys[RIGHT] = true;
break;
case ALLEGRO_KEY_SPACE:
keys[SPACE] = true;
if(state == TITLE)
ChangeState(state, PLAYING);
else if(state ==PLAYING)
FireBullet(bullets, NUM_BULLETS, ship);
else if(state == LOST)
ChangeState(state, PLAYING);
break;
}
}
else if(ev.type == ALLEGRO_EVENT_KEY_UP)
{
switch(ev.keyboard.keycode)
{
case ALLEGRO_KEY_ESCAPE:
done = true;
break;
case ALLEGRO_KEY_UP:
keys[UP] = false;
break;
case ALLEGRO_KEY_DOWN:
keys[DOWN] = false;
break;
case ALLEGRO_KEY_LEFT:
keys[LEFT] = false;
break;
case ALLEGRO_KEY_RIGHT:
keys[RIGHT] = false;
break;
case ALLEGRO_KEY_SPACE:
keys[SPACE] = false;
break;
}
}
if(redraw && al_is_event_queue_empty(event_queue))
{
redraw = false;
if(state == TITLE)
{
al_draw_bitmap(title, 0, 0, 0);
}
else if(state == PLAYING)
{
DrawBackground(BG);
DrawBackground(MG);
DrawBackground(FG);
DrawShip(ship);
DrawBullet(bullets, NUM_BULLETS);
DrawComet(comets, NUM_COMETS);
DrawExplosions(explosions, NUM_EXPLOSIONS);
al_draw_textf(font18, al_map_rgb(255, 0, 255), 5, 5, 0, "Player has %i lives left. Player has destroyed %i objects", ship.lives, ship.score);
}
else if(state == LOST)
{
al_draw_bitmap(lost, 0, 0, 0);
al_draw_textf(font18, al_map_rgb(0, 255, 255), WIDTH - 10, 20, ALLEGRO_ALIGN_RIGHT, "Final Score: %i", ship.score);
}
al_flip_display();
al_clear_to_color(al_map_rgb(0,0,0));
}
}
al_destroy_sample(shot);
al_destroy_sample(boom);
al_destroy_sample(song);
al_destroy_sample_instance(songInstance);
al_destroy_bitmap(bgImage);
al_destroy_bitmap(mgImage);
al_destroy_bitmap(fgImage);
al_destroy_bitmap(title);
al_destroy_bitmap(lost);
al_destroy_bitmap(expImage);
al_destroy_bitmap(cometImage);
al_destroy_bitmap(shipImage);
al_destroy_event_queue(event_queue);
al_destroy_timer(timer);
al_destroy_font(font18);
al_destroy_display(display); //destroy our display object
return 0;
}
void InitShip(SpaceShip &ship, ALLEGRO_BITMAP *image = NULL) {
ship.x = 20;
ship.y = HEIGHT / 2;
ship.ID = PLAYER;
ship.lives = 3;
ship.speed = 6;
ship.boundx = 10;
ship.boundy = 12;
ship.score = 0;
ship.maxFrame = 3;
ship.curFrame = 0;
ship.frameCount = 0;
ship.frameDelay = 50;
ship.frameWidth = 44;
ship.frameHeight = 41;
ship.animationColumns = 3;
ship.animationDirection = 1;
ship.animationRow = 1;
if(image != NULL)
ship.image = image;
}
void ResetShipAnimation(SpaceShip &ship, int position)
{
if(position == 1)
ship.animationRow = 1;
else
ship.curFrame = 0;
}
void DrawShip(SpaceShip &ship)
{
int fx =(ship.curFrame % ship.animationColumns) * ship.frameWidth;
int fy = ship.animationRow * ship.frameHeight;
al_draw_bitmap_region(ship.image, fx, fy, ship.frameWidth,
ship.frameHeight, ship.x - ship.frameWidth / 2, ship.y - ship.frameHeight / 2, 0);
/*al_draw_filled_rectangle(ship.x - ship.boundx, ship.y - ship.boundy, ship.x + ship.boundx,
ship.y + ship.boundy, al_map_rgba(255, 0, 255, 100));*/
}
void MoveShipUp(SpaceShip &ship)
{
ship.animationRow = 0;
ship.y -= ship.speed;
if(ship.y < 0)
ship.y = 0;
}
void MoveShipDown(SpaceShip &ship)
{
ship.animationRow = 2;
ship.y += ship.speed;
if(ship.y > HEIGHT)
ship.y = HEIGHT;
}
void MoveShipLeft(SpaceShip &ship)
{
ship.curFrame = 2;
ship.x -= ship.speed;
if(ship.x < 0)
ship.x = 0;
}
void MoveShipRight(SpaceShip &ship)
{
ship.curFrame = 1;
ship.x += ship.speed;
if(ship.x > 300)
ship.x = 300;
}
void InitBullet(Bullet bullet[], int size)
{
for(int i = 0; i < size; i++)
{
bullet[i].ID = BULLET;
bullet[i].speed = 10;
bullet[i].live = false;
}
}
void DrawBullet(Bullet bullet[], int size)
{
for( int i = 0; i < size; i++)
{
if(bullet[i].live)
al_draw_filled_circle(bullet[i].x, bullet[i].y, 2, al_map_rgb(255, 255, 255));
}
}
void FireBullet(Bullet bullet[], int size, SpaceShip &ship)
{
for( int i = 0; i < size; i++)
{
if(!bullet[i].live)
{
bullet[i].x = ship.x + 17;
bullet[i].y = ship.y;
bullet[i].live = true;
al_play_sample(shot, 1, 0, 1, ALLEGRO_PLAYMODE_ONCE, 0);
break;
}
}
}
void UpdateBullet(Bullet bullet[], int size)
{
for(int i = 0; i < size; i++)
{
if(bullet[i].live)
{
bullet[i].x += bullet[i].speed;
if(bullet[i].x > WIDTH)
bullet[i].live = false;
}
}
}
void CollideBullet(Bullet bullet[], int bSize, Comet comets[], int cSize, SpaceShip &ship, Explosion explosions[], int eSize)
{
for(int i = 0; i < bSize; i++)
{
if(bullet[i].live)
{
for(int j =0; j < cSize; j++)
{
if(comets[j].live)
{
if(bullet[i].x > (comets[j].x - comets[j].boundx) &&
bullet[i].x < (comets[j].x + comets[j].boundx) &&
bullet[i].y > (comets[j].y - comets[j].boundy) &&
bullet[i].y < (comets[j].y + comets[j].boundy))
{
bullet[i].live = false;
comets[j].live = false;
ship.score++;
StartExplosions(explosions, eSize, bullet[i].x, bullet[i].y);
al_play_sample(boom, 1, 0, 1, ALLEGRO_PLAYMODE_ONCE, 0);
}
}
}
}
}
}
void InitComet(Comet comets[], int size, ALLEGRO_BITMAP *image = NULL)
{
for(int i = 0; i < size; i++)
{
comets[i].ID = ENEMY;
comets[i].live = false;
comets[i].speed = 5;
comets[i].boundx = 35;
comets[i].boundy = 35;
comets[i].maxFrame = 143;
comets[i].curFrame = 0;
comets[i].frameCount = 0;
comets[i].frameDelay = 2;
comets[i].frameWidth = 96;
comets[i].frameHeight = 96;
comets[i].animationColumns = 21;
if(rand() % 2)
comets[i].animationDirection = 1;
else
comets[i].animationDirection = -1;
if(image != NULL)
comets[i].image = image;
}
}
void DrawComet(Comet comets[], int size)
{
for(int i = 0; i < size; i++)
{
if(comets[i].live)
{
int fx = (comets[i].curFrame % comets[i].animationColumns) * comets[i].frameWidth;
int fy = (comets[i].curFrame / comets[i].animationColumns) * comets[i].frameHeight;
al_draw_bitmap_region(comets[i].image, fx, fy, comets[i].frameWidth,
comets[i].frameHeight, comets[i].x - comets[i].frameWidth / 2, comets[i].y - comets[i].frameHeight / 2, 0);
/*al_draw_filled_rectangle(comets[i].x - comets[i].boundx, comets[i].y - comets[i].boundy, comets[i].x + comets[i].boundx,
comets[i].y + comets[i].boundy, al_map_rgba(255, 0, 255, 100));*/
}
}
}
void StartComet(Comet comets[], int size)
{
for(int i = 0; i < size; i++)
{
if(!comets[i].live)
{
if(rand() % 500 == 0)
{
comets[i].live = true;
comets[i].x = WIDTH;
comets[i].y = 30 + rand() % (HEIGHT - 60);
break;
}
}
}
}
void UpdateComet(Comet comets[], int size)
{
for(int i = 0; i < size; i++)
{
if(comets[i].live)
{
if(++comets[i].frameCount >= comets[i].frameDelay)
{
comets[i].curFrame += comets[i].animationDirection;
if(comets[i].curFrame >= comets[i].maxFrame)
comets[i].curFrame = 0;
else if( comets[i].curFrame <= 0)
comets[i].curFrame = comets[i].maxFrame - 1;
comets[i].frameCount = 0;
}
comets[i].x -= comets[i].speed;
}
}
}
void CollideComet(Comet comets[], int cSize, SpaceShip &ship, Explosion explosions[], int eSize)
{
for(int i = 0; i < cSize; i++)
{
if(comets[i].live)
{
if(comets[i].x - comets[i].boundx < ship.x + ship.boundx &&
comets[i].x + comets[i].boundx > ship.x - ship.boundx &&
comets[i].y - comets[i].boundy < ship.y + ship.boundy &&
comets[i].y + comets[i].boundy > ship.y - ship.boundy)
{
ship.lives--;
comets[i].live = false;
StartExplosions(explosions, eSize, ship.x, ship.y);
al_play_sample(boom, 1, 0, 1, ALLEGRO_PLAYMODE_ONCE, 0);
}
else if(comets[i].x < 0)
{
comets[i].live = false;
ship.lives--;
}
}
}
}
void InitExplosions(Explosion explosions[], int size, ALLEGRO_BITMAP *image = NULL)
{
for(int i = 0; i < size; i++)
{
explosions[i].live = false;
explosions[i].maxFrame = 31;
explosions[i].curFrame = 0;
explosions[i].frameCount = 0;
explosions[i].frameDelay = 1;
explosions[i].frameWidth = 128;
explosions[i].frameHeight = 128;
explosions[i].animationColumns = 8;
explosions[i].animationDirection = 1;
if(image != NULL)
explosions[i].image = image;
}
}
void DrawExplosions(Explosion explosions[], int size)
{
for(int i = 0; i < size; i++)
{
if(explosions[i].live)
{
int fx = (explosions[i].curFrame % explosions[i].animationColumns) * explosions[i].frameWidth;
int fy = (explosions[i].curFrame / explosions[i].animationColumns) * explosions[i].frameHeight;
al_draw_bitmap_region(explosions[i].image, fx, fy, explosions[i].frameWidth,
explosions[i].frameHeight, explosions[i].x - explosions[i].frameWidth / 2, explosions[i].y - explosions[i].frameHeight / 2, 0);
}
}
}
void StartExplosions(Explosion explosions[], int size, int x, int y)
{
for(int i = 0; i < size; i++)
{
if(!explosions[i].live)
{
explosions[i].live = true;
explosions[i].x = x;
explosions[i].y = y;
break;
}
}
}
void UpdateExplosions(Explosion explosions[], int size)
{
for(int i = 0; i < size; i++)
{
if(explosions[i].live)
{
if(++explosions[i].frameCount >= explosions[i].frameDelay)
{
explosions[i].curFrame += explosions[i].animationDirection;
if(explosions[i].curFrame >= explosions[i].maxFrame)
{
explosions[i].curFrame = 0;
explosions[i].live = false;
}
explosions[i].frameCount = 0;
}
}
}
}
void InitBackground(Background &back, float x, float y, float velx, float vely, int width, int height, int dirX, int dirY, ALLEGRO_BITMAP *image)
{
back.x = x;
back.y = y;
back.velX = velx;
back.velY = vely;
back.width = width;
back.height = height;
back.dirX = dirX;
back.dirY = dirY;
back.image = image;
}
void UpdateBackground(Background &back)
{
back.x += back.velX * back.dirX;
if(back.x + back.width <= 0)
back.x = 0;
}
void DrawBackground(Background &back)
{
al_draw_bitmap(back.image, back.x, back.y, 0);
if(back.x + back.width < WIDTH)
al_draw_bitmap(back.image, back.x + back.width, back.y, 0);
}
void ChangeState(int &state, int newState)
{
if(state == TITLE)
{}
else if(state == PLAYING)
{
al_stop_sample_instance(songInstance);
}
else if(state == LOST)
{}
state = newState;
if(state == TITLE)
{}
else if(state == PLAYING)
{
InitShip(ship);
InitBullet(bullets, NUM_BULLETS);
InitComet(comets, NUM_COMETS);
InitExplosions(explosions, NUM_EXPLOSIONS);
al_play_sample_instance(songInstance);
}
else if(state == LOST)
{}
}
Check that a pointer you are using is not NULL when you try to load the file. If it stays NULL then that exception is always thrown because the system will try to read from memory address 0x0 which frankly does not exist
Related
SDL: How to render multiple different textures based on mouse event
I'm trying to make a simple menu with 3 different options. Play, Options, Exit. I want them to change colors when you hover over them and when you mouse up on them. I tried using lazy foo's reference for mouse events, but I'm confused on how to do it with different "buttons". It would be one thing if they were saying all the same thing. Here is my code: #include "Menu.h" #include <iostream> std::string tmpCap; SDL_Color tmpColor; SDL_Color colorW = { 255, 255, 255, 255 }; SDL_Color colorG1 = { 65, 65, 65, 255 }; SDL_Color colorG2 = { 85, 85, 85, 255 }; SDL_Color colorG3 = { 125, 125, 125, 255 }; SDL_Texture* currentPlaySet[3]; SDL_Texture* currentOptionsSet[3]; SDL_Texture* currentExitSet[3]; SDL_Texture* currentPlay; SDL_Texture* currentOptions; SDL_Texture* currentExit; SDL_Texture* currentTexboo[3]; enum mMenuNum { PLAY_MOUT = 0, PLAY_MON = 1, PLAY_MUP = 2, OPTIONS_MOUT = 3, OPTIONS_MON = 4, OPTIONS_MUP = 5, EXIT_MOUT = 6, EXIT_MON = 7, EXIT_MUP = 8, MENUNUM_TOTAL = 9 }; enum mCheckButton { B_OUT = 0, B_ON = 1, B_UP = 2, B_TOTAL = 3 }; int xCenter = 1024 / 2; int yCenter = 768 / 2; SDL_Rect rtmp[3]; SDL_Texture* btmp[9]; class Button { public: //Initializes internal variables Button(); //Sets top left position void setPosition( int x, int y ); void setSize(int x, int y, int w, int h); //Handles mouse event void handleEvent(SDL_Event* e); //Shows button sprite void renderButtons(); private: //Top left position SDL_Point mPosition; SDL_Rect mSize; //Currently used global sprite mCheckButton mCurrentSprite; }; void Menu::init() { const char* buttonCaptions[3] = { " Play ", " Options ", " Exit " }; for (int i = 0; i < 9; i++) { if(i < 3) { tmpCap = buttonCaptions[0]; } if(i < 6 && i > 2) { tmpCap = buttonCaptions[1]; } if(i < 9 && i > 5) { tmpCap = buttonCaptions[2]; } if(i == 0 || i == 3 || i == 6) { tmpColor = colorG1; } if(i == 1 || i == 4 || i == 7) { tmpColor = colorG2; } if(i == 2 || i == 5 || i == 8) { tmpColor = colorG3; } btmp[i] = TextureManager::TextTexture("../src/assets/Arial Black.ttf", tmpCap, 40, tmpColor); //std::cout << tmpCap << " " << i << std::endl; } currentPlaySet[0] = btmp[0]; currentOptionsSet[0] = btmp[3]; currentExitSet[0] = btmp[6]; currentPlaySet[1] = btmp[1]; currentOptionsSet[1] = btmp[4]; currentExitSet[1] = btmp[7]; currentPlaySet[2] = btmp[2]; currentOptionsSet[2] = btmp[5]; currentExitSet[2] = btmp[8]; Menu::getSize(); } Button::Button() { currentPlay = btmp[0]; currentOptions = btmp[3]; currentExit = btmp[6]; mCurrentSprite = B_OUT; } Button f[9]; void Button::setPosition(int x, int y) { mPosition.x = x; mPosition.y = y; } void Button::setSize(int x, int y, int w, int h) { mSize.x = x; mSize.y = y; mSize.w = w; mSize.h = h; } void Menu::getSize() { SDL_QueryTexture(btmp[0], NULL, NULL, &rtmp[0].w, &rtmp[0].h); int aX = xCenter - (rtmp[0].w / 2); int aY = (yCenter - (rtmp[0].h / 2)) - 100; int aW = rtmp[0].w; int aH = rtmp[0].h; f[0].setPosition(aX, aY); f[0].setSize(aX, aY, aW, aH); SDL_QueryTexture(btmp[3], NULL, NULL, &rtmp[1].w, &rtmp[1].h); int bX = xCenter - (rtmp[1].w / 2); int bY = (yCenter - (rtmp[1].h / 2)); int bW = rtmp[1].w; int bH = rtmp[1].h; f[1].setPosition(bX, bY); f[1].setSize(bX, bY, bW, bH); SDL_QueryTexture(btmp[6], NULL, NULL, &rtmp[2].w, &rtmp[2].h); int cX = xCenter - (rtmp[2].w / 2); int cY = (yCenter - (rtmp[2].h / 2)) + 100; int cW = rtmp[2].w; int cH = rtmp[2].h; f[2].setPosition(cX, cY); f[2].setSize(cX, cY, cW, cH); } void Button::handleEvent(SDL_Event* e) { if( e->type == SDL_MOUSEMOTION || e->type == SDL_MOUSEBUTTONDOWN || e->type == SDL_MOUSEBUTTONUP ) { int x, y; SDL_GetMouseState(&x, &y); //Check if mouse is in button bool inside = true; //Mouse is left of the button if( x < mPosition.x ) { inside = false; } //Mouse is right of the button else if( x > mPosition.x + mSize.w ) { inside = false; } //Mouse above the button else if( y < mPosition.y ) { inside = false; } //Mouse below the button else if( y > mPosition.y + mSize.h ) { inside = false; } //Mouse is outside button if( !inside ) { std::cout << "Outside " << " " << mCurrentSprite << std::endl; //currentPlay = currentPlaySet[mCurrentSprite]; //currentOptions = currentOptionsSet[mCurrentSprite]; //currentExit = currentExitSet[mCurrentSprite]; mCurrentSprite = B_OUT; } //Mouse is inside button else { switch( Game::event.type ) { case SDL_MOUSEMOTION: mCurrentSprite = B_ON; //currentPlay = btmp[(mCurrentSprite/3)+1]; //currentOptions = btmp[(mCurrentSprite/3)+1]; //currentExit = btmp[(mCurrentSprite/3)+1]; //currentPlay = currentPlaySet[mCurrentSprite]; //currentOptions = currentOptionsSet[mCurrentSprite]; //currentExit = currentExitSet[mCurrentSprite]; std::cout << "In " << mCurrentSprite << std::endl; break; case SDL_MOUSEBUTTONDOWN: //currentPlay = currentPlaySet[mCurrentSprite]; //currentOptions = currentOptionsSet[mCurrentSprite]; //currentExit = currentExitSet[mCurrentSprite]; //mCurrentSprite = B_DOWN; //currentTex = mTex3; break; case SDL_MOUSEBUTTONUP: //currentPlay = currentPlaySet[mCurrentSprite]; //currentOptions = currentOptionsSet[mCurrentSprite]; //currentExit = currentExitSet[mCurrentSprite]; mCurrentSprite = B_UP; //currentTex = mTex4; break; } } } } void Button::renderButtons() { while( SDL_PollEvent( &Game::event ) != 0 ) { for( int i = 0; i < 3; ++i ) { f[i].handleEvent(&Game::event); //isMouseOverText(); } } SDL_RenderCopy(Game::mRenderer, btmp[mCurrentSprite], nullptr, &mSize); //SDL_RenderCopy(Game::mRenderer, currentOptionsSet[mCurrentSprite], nullptr, &mSize); //SDL_RenderCopy(Game::mRenderer, currentExitSet[mCurrentSprite], nullptr, &mSize); } void Menu::render() { for( int i = 0; i < 3; ++i ) { f[i].renderButtons(); } }
I was able to figure it out using an old SDL tutorial code from here. Is it viable to delete and create these textures on interact? I've updated my code to avoid deleting textures every time at the bottom. Is there a better way to do this? It seems clean to me but I'm concerned about resource usage. Any insight is appreciated. My code: const int NUMMENU = 2; const char* labels[NUMMENU] = {"Continue","Exit"}; SDL_Texture* menus[NUMMENU]; bool selected[NUMMENU] = {0,0}; SDL_Color color[2] = {{0,0,0,255},{255,0,0,255}}; SDL_Rect pos[NUMMENU]; int x,y; const char* font = "../assets/Arial Black.ttf"; void MainMenu::init() { menus[0] = TextureManager::CreateFontTexture(font, labels[0], 40, color[0]); menus[1] = TextureManager::CreateFontTexture(font, labels[1], 40, color[0]); SDL_QueryTexture(menus[0], NULL, NULL, &pos[0].w, &pos[0].h); SDL_QueryTexture(menus[1], NULL, NULL, &pos[1].w, &pos[1].h); pos[0].x = (1024/2) - (pos[0].w / 2); pos[0].y = (768/2) - (pos[0].h / 2) - 100; pos[1].x = (1024/2) - (pos[1].w / 2); pos[1].y = (768/2) - (pos[1].h / 2); } void MainMenu::render() { SDL_RenderCopy(App::appRenderer, menus[0], NULL, &pos[0]); SDL_RenderCopy(App::appRenderer, menus[1], NULL, &pos[1]); if( App::event.type == SDL_MOUSEMOTION || App::event.type == SDL_MOUSEBUTTONDOWN || App::event.type == SDL_MOUSEBUTTONUP ) { switch(App::event.type) { case SDL_MOUSEMOTION: x = App::event.motion.x; y = App::event.motion.y; for(int i = 0; i < NUMMENU; i += 1) { if(x>=pos[i].x && x<=pos[i].x+pos[i].w && y>=pos[i].y && y<=pos[i].y+pos[i].h) { if(!selected[i]) { selected[i] = 1; SDL_DestroyTexture(menus[i]); menus[i] = TextureManager::CreateFontTexture(font, labels[i], 40, color[1]); } } else { if(selected[i]) { selected[i] = 0; SDL_DestroyTexture(menus[i]); menus[i] = TextureManager::CreateFontTexture(font, labels[i], 40, color[0]); } } } break; case SDL_MOUSEBUTTONDOWN: x = App::event.button.x; y = App::event.button.y; for(int i = 0; i < NUMMENU; i += 1) { if(x>=pos[i].x && x<=pos[i].x+pos[i].w && y>=pos[i].y && y<=pos[i].y+pos[i].h) { SDL_DestroyTexture(menus[0]); SDL_DestroyTexture(menus[1]); } } break; } } } UPDATED code without deleting textures every time: const int NUMMENU = 3; const char* labels[NUMMENU] = {"New Game", "Options","Exit"}; SDL_Texture* menus[NUMMENU]; SDL_Texture* selectedMenus[NUMMENU]; SDL_Texture* toRender[NUMMENU]; bool selected[NUMMENU] = {0,0}; SDL_Color color[2] = {{0,0,0,255},{125,125,125,255}}; SDL_Rect pos[NUMMENU]; int x,y; const char* font = "../assets/Arial Black.ttf"; int aOne = 0; void MainMenu::init() { for(int i = 0; i < NUMMENU; i++) { menus[i] = TextureManager::CreateFontTexture(font, labels[i], 40, color[0]); toRender[i] = menus[i]; selectedMenus[i] = TextureManager::CreateFontTexture(font, labels[i], 40, color[1]); SDL_QueryTexture(menus[i], NULL, NULL, &pos[i].w, &pos[i].h); } pos[0].x = (1024/2) - (pos[0].w / 2); pos[0].y = (768/2) - (pos[0].h / 2) - 100; pos[1].x = (1024/2) - (pos[1].w / 2); pos[1].y = (768/2) - (pos[1].h / 2); pos[2].x = (1024/2) - (pos[2].w / 2); pos[2].y = (768/2) - (pos[2].h / 2) + 100; } void MainMenu::inputD() { aOne++; std::cout << aOne << std::endl; switch(App::event.type) { case SDL_MOUSEMOTION: x = App::event.motion.x; y = App::event.motion.y; for(int i = 0; i < NUMMENU; i += 1) { if(x>=pos[i].x && x<=pos[i].x+pos[i].w && y>=pos[i].y && y<=pos[i].y+pos[i].h) { if(!selected[i]) { selected[i] = 1; toRender[i] = selectedMenus[i]; } } else { if(selected[i]) { selected[i] = 0; toRender[i] = menus[i]; } } } break; case SDL_MOUSEBUTTONDOWN: x = App::event.button.x; y = App::event.button.y; for(int i = 0; i < NUMMENU; i += 1) { if(x>=pos[i].x && x<=pos[i].x+pos[i].w && y>=pos[i].y && y<=pos[i].y+pos[i].h) { std::cout << labels[i] << " button clicked" << std::endl; } } break; } } void MainMenu::render() { for(int i = 0; i < NUMMENU; i++) SDL_RenderCopy(App::appRenderer, toRender[i], NULL, &pos[i]); }
C++ SDL image gets black and disappears
I started writing a little game but something with the image is not working. They're working fine at the beginning but after some moments there become black and then they disappear. Don't be worried about the long code the relevant things with the images happen mostly in the following methods: build_mode_draw() and play_mode_draw(). I tested the program with a blue cube instead of a image and it worked fine Probably I don't really understand how the image gets loaded #include <SDL2/SDL.h> #define WindowWidth 1500 #define WindowHight 800 #define ArrayGrosseBuildMode 100 #define StartFensterBlockmenge 10 // in Plockgröße bezüglich der kleineren Achse bool end = false; bool programm_part_run = true; unsigned int play_mode_speed = 0; unsigned int counter; unsigned int counter_2; unsigned int counter_3; unsigned int blocksize; unsigned int blocks_fit_in_X; unsigned int blocks_fit_in_Y; unsigned int play_mode_blockamount; //unsigned int blockamount = 0; bool build_mode_block_pos[ArrayGrosseBuildMode][ArrayGrosseBuildMode]; unsigned int play_mode_block_pos_X[WindowWidth]; // Fächer beschreiben unsigned int play_mode_block_pos_Y[WindowHight]; // || //mouse variables unsigned short int pressed_mouse_button = 0; // 0 = no , 1 = left , mouse Button pressed unsigned int MouseX; unsigned int MouseY; //keyboard variables //set window SDL_Window* window = NULL; //set renderer SDL_Renderer* renderer = NULL; //set event SDL_Event event; void input() { SDL_PollEvent(&event); // reset variables pressed_mouse_button = 0; // set to no mouse button pressed switch(event.type) { case SDL_QUIT: end = true; programm_part_run = false; break; case SDL_MOUSEMOTION: MouseX = event.motion.x; MouseY = event.motion.y; break; case SDL_MOUSEBUTTONDOWN: switch(event.button.button) { case SDL_BUTTON_LEFT: pressed_mouse_button = 1; break; } break; case SDL_KEYDOWN: switch(event.key.keysym.sym) { case SDLK_SPACE: programm_part_run = false; break; } } } void put_build_mode_grid_in_renderer() { SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0); for(counter = 0; counter <= blocks_fit_in_Y; counter = counter + 1) { SDL_RenderDrawLine(renderer,0,counter * blocksize,blocks_fit_in_X*blocksize,counter * blocksize); } for(counter = 0; counter <= blocks_fit_in_X; counter = counter + 1) { SDL_RenderDrawLine(renderer,counter * blocksize,0,counter * blocksize,blocks_fit_in_Y*blocksize); } } void build_mode_draw() { SDL_SetRenderDrawColor(renderer, 255, 255, 255, 0); SDL_RenderClear(renderer); put_build_mode_grid_in_renderer(); SDL_Surface * image = SDL_LoadBMP("stealcube.bmp"); SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer,image); SDL_FreeSurface(image); for(counter = 0; counter <= blocks_fit_in_X; counter = counter + 1) { for(counter_2 = 0; counter_2 <= blocks_fit_in_Y; counter_2 = counter_2 + 1) { if(build_mode_block_pos[counter][counter_2] == true) { SDL_Rect dstrect = { counter * blocksize, counter_2 * blocksize, blocksize, blocksize}; SDL_RenderCopy(renderer, texture, NULL, &dstrect); } } } SDL_RenderPresent(renderer); } void build_mode() { while(programm_part_run) { input(); if(pressed_mouse_button == 1) { build_mode_block_pos[MouseX/blocksize][MouseY/blocksize] = true; } build_mode_draw(); } } void play_mode_draw() { SDL_SetRenderDrawColor(renderer, 255, 255, 255, 0); SDL_RenderClear(renderer); SDL_Surface * image = SDL_LoadBMP("stealcube.bmp"); SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer,image); SDL_FreeSurface(image); for(counter = 0; counter < play_mode_blockamount; counter = counter + 1) { SDL_Rect dstrect = { play_mode_block_pos_X[counter], play_mode_block_pos_Y[counter], blocksize, blocksize}; SDL_RenderCopy(renderer, texture, NULL, &dstrect); } SDL_RenderPresent(renderer); } void play_mode() { counter_3 = 0; for(counter = 0; counter <= blocks_fit_in_X; counter = counter + 1) { for(counter_2 = 0; counter_2 <= blocks_fit_in_Y; counter_2 = counter_2 + 1) { if(build_mode_block_pos[counter][counter_2] == true) { play_mode_block_pos_X[counter_3] = counter*blocksize; play_mode_block_pos_Y[counter_3] = counter_2*blocksize; counter_3 = counter_3 + 1; } } } play_mode_blockamount = counter_3; while(programm_part_run) { for(counter = 0; counter < play_mode_speed; counter = counter + 1) { input(); SDL_Delay(1); } for(counter = 0; counter <= play_mode_blockamount; counter = counter + 1) { if(play_mode_block_pos_Y[counter] < blocks_fit_in_Y * blocksize - blocksize) { play_mode_block_pos_Y[counter] = play_mode_block_pos_Y[counter] + 1; } } play_mode_draw(); } } int main (int argc, char** argv) { SDL_Init(SDL_INIT_VIDEO); window = SDL_CreateWindow ( "Test Fenster :)", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WindowWidth, WindowHight, SDL_WINDOW_SHOWN ); renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED); //setup if(WindowWidth < WindowHight) { blocksize = WindowWidth/StartFensterBlockmenge; } else { blocksize = WindowHight/StartFensterBlockmenge; } blocks_fit_in_X = WindowWidth/blocksize; blocks_fit_in_Y = WindowHight/blocksize; while(!end) { programm_part_run = true; build_mode(); programm_part_run = true; play_mode(); } }
Error creating game objects in c++
I have been working in a zombie arcade game, I am experimenting an strange problem. I created a class called GameObject and a class called Human that inherits from GameOBject, then I declared two more called; Zombie and Player. The problem is that when I create two or more characters (instances) of this four classes the game stops working, I detected that in the classes Zombie and Player the problem only occurs when I call the method update (only these classes use it). This method is supposed to control the activities of each character. The graphics and animated sprites are managed separately from the character, they (the characters) only call some methods to control the sprite update, those orders are processed when updating the screen. I just want you to tell me what is happening, I think the problem is in the update method of the classes Zombie and Player. The project is divided in different files. I don't think this matters but I am using CodeBlocks and tdm-gcc. main.cpp: #include "game_classes.h" bool working = true, redraw = true; int main(){ init_game_classes(); Player player(200, 200); std::vector<Zombie *> zombie_list; for(unsigned int i = 0; i < 2; i++){ Zombie *zombie = new Zombie(i * 100, 12, &player); zombie_list.push_back(zombie); } while(working){ input(); if(event.type == ALLEGRO_EVENT_TIMER){//main loop player.update(); for(unsigned int i = 0; i < zombie_list.size(); i++){ zombie_list[i]->update(); } redraw = true; } else if(event.type == ALLEGRO_EVENT_DISPLAY_CLOSE){ working = false; } if(redraw and al_is_event_queue_empty(event_queue)){//updating display update_animated_models(); blit_models(); update_display(); redraw = false; } } for(unsigned int i = 0; i < zombie_list.size(); i++) delete zombie_list[i]; quit(); return 0; } render.h: #include <vector> #include <stdio.h> #include <allegro5/allegro.h> #include <allegro5/allegro_image.h> int global_ticks_per_frame = 0; ALLEGRO_BITMAP *map_background = NULL; class Model; std::vector<Model *> model_list; class Model{ protected: int x = 0, y = 0, width, height; int source_x = 0, source_y = 0, source_width, source_height; public: ALLEGRO_BITMAP *sheet = NULL; bool hide = false; int flags = 0; Model(const char *path, int width, int height){ this->sheet = al_load_bitmap(path); al_convert_mask_to_alpha(this->sheet, al_map_rgb(255, 0, 255)); this->source_width = al_get_bitmap_width(this->sheet); this->source_height = al_get_bitmap_height(this->sheet); this->width = width; this->height = height; model_list.insert(model_list.begin(), this); } Model(ALLEGRO_BITMAP *image, int width, int height){ this->sheet = image; al_convert_mask_to_alpha(this->sheet, al_map_rgb(255, 0, 255)); this->source_width = al_get_bitmap_width(this->sheet); this->source_height = al_get_bitmap_height(this->sheet); this->width = width; this->height = height; model_list.insert(model_list.begin(), this); } ~Model(){ al_destroy_bitmap(this->sheet); model_list.erase(model_list.begin() + this->index()); } void show(){ if(not this->hide){ al_draw_scaled_bitmap(this->sheet, this->source_x, this->source_y, this->source_width, this->source_height, x, y, width, height, this->flags); } } void set_x(int x){ this->x = x; } unsigned int index(){ for(unsigned int i = 0; i < model_list.size(); i++){ if(model_list[i] == this) return i; } } bool set_y(int y){ this->y = y; model_list.erase(model_list.begin() + this->index()); int this_relative_y = this->y + this->height; unsigned int i = 0; while(i < model_list.size()){ int from_list_relative_y = model_list[i]->y + model_list[i]->height; if(this_relative_y < from_list_relative_y){ model_list.insert(model_list.begin() + i, this); return false; } i += 1; } model_list.push_back(this); return false; } int get_y(){ return this->y; } int get_x(){ return this->x; } unsigned int get_width(){ return this->width; } unsigned int get_height(){ return this->height; } }; void blit_models(){ for(unsigned int i = 0; i < model_list.size(); i++) model_list[i]->show(); } class AnimatedModel; std::vector<AnimatedModel *> animated_model_list; class AnimatedModel : public Model{ private: unsigned int ticks_per_frame, ticks_counter = 0; unsigned int current_frame = 0, frame_count; public: bool stop = false; void set_speed(unsigned int new_speed){ this->ticks_per_frame = new_speed; } AnimatedModel(const char *path, unsigned int frames, unsigned int ticks_per_frame, int width, int height) : Model(path, width, height){ this->ticks_per_frame = ticks_per_frame; this->frame_count = frames; this->source_width /= frames; animated_model_list.push_back(this); } AnimatedModel(ALLEGRO_BITMAP *image, unsigned int frames, unsigned int ticks_per_frame, int width, int height) : Model(image, width, height){ this->ticks_per_frame = ticks_per_frame; this->frame_count = frames; this->source_width /= frames; animated_model_list.push_back(this); } ~AnimatedModel(){ for(unsigned int i = 0; i < animated_model_list.size(); i++){ if(animated_model_list[i] == this){ animated_model_list.erase(animated_model_list.begin() + i); } } } void fix_sheet_looking(){ if(not this->stop) this->source_x = this->current_frame*this->source_width; } void play(){ if(this->ticks_counter >= this->ticks_per_frame + global_ticks_per_frame){ this->current_frame += 1; if(this->current_frame >= this->frame_count) this->current_frame = 0; this->ticks_counter = 0; } else{ this->ticks_counter += 1; } } void update(){ if(not this->stop){ this->play(); this->fix_sheet_looking(); } } void set_frame(unsigned int i){ this->current_frame = i; } unsigned int get_frame(){ return this->current_frame; } }; void update_animated_models(){ for(unsigned int i = 0; i < animated_model_list.size(); i++) animated_model_list[i]->update(); } game_classes.h: #include "render.h" #include "touch.h" #include "window_control.h" #include <string> #include <iostream> ALLEGRO_BITMAP *zombie_sprite = NULL; ALLEGRO_BITMAP *human_sprite = NULL; void init_game_classes(){ init_window_control(); zombie_sprite = al_load_bitmap("textures/zombie/sprite.png"); human_sprite = al_load_bitmap("textures/human/sprite.png"); } int control_key_up = ALLEGRO_KEY_UP, control_key_down = ALLEGRO_KEY_DOWN, control_key_right = ALLEGRO_KEY_RIGHT, control_key_left = ALLEGRO_KEY_LEFT; int control_key_run = ALLEGRO_KEY_Z; HitBoxList character_body_reg; HitBoxList item_body_reg; class GameObjec{ protected: unsigned int walking_speed; HitBoxList *last_coll_test = NULL; int last_x, last_y; int body_high; int left_distance; public: HitBox *body = NULL; AnimatedModel *sprite = NULL; void set_x(int x){ this->sprite->set_x(x); this->last_x = this->body->x; this->body->x = x + this->left_distance; } void set_y(int y){ this->sprite->set_y(y); this->last_y = this->body->y; this->body->y = y + this->body_high; } int get_x(){ return this->sprite->get_x(); } int get_y(){ return this->sprite->get_y(); } void slide_x(short int direction){ character_body_reg.pop(this->body); this->last_coll_test = this->body->slide_x(this->walking_speed*direction, &character_body_reg); character_body_reg.push(this->body); this->set_x(this->body->x - this->left_distance); } void slide_y(short int direction){ character_body_reg.pop(this->body); this->last_coll_test = this->body->slide_y(this->walking_speed*direction, &character_body_reg); character_body_reg.push(this->body); this->set_y(this->body->y - this->body_high); } void show_hitbox(){ al_draw_rectangle(this->body->x, this->body->y, this->body->x + this->body->width, this->body->y + this->body->height, al_map_rgb(255, 0, 0), 1); } GameObjec(int x, int y, unsigned int walking_speed, const char *sprite_image_path, int frames, int ticks_per_frame, int sprite_width, int sprite_height, int body_high, int body_len){ this->walking_speed = walking_speed; this->body_high = body_high; this->sprite = new AnimatedModel(sprite_image_path, frames, ticks_per_frame, sprite_width, sprite_height); this->left_distance = (this->sprite->get_width() - body_len)/2; this->body = new HitBox; this->sprite->set_x(x); this->sprite->set_y(y); this->body->width = body_len; this->body->height = this->sprite->get_height() - this->body_high; this->body->x = x + left_distance; this->body->y = y + this->body_high; this->last_x = this->body->x; this->last_y = this->body->y; character_body_reg.push(this->body); } ~GameObjec(){ delete this->sprite; character_body_reg.pop(this->body); delete this->body; } void draw_hitbox(){ al_draw_rectangle(this->body->x, this->body->y, this->body->x + this->body->width, this->body->y + this->body->height, al_map_rgb(255, 0, 0), 0); } }; class Human : public GameObjec{ protected: bool walking = false; public: Human(int x, int y, const char *sprite_image_path) : GameObjec(x, y, 2, sprite_image_path, 2, 7, 64, 80, 60, 32){} ~Human(){} void walk_down(){ this->slide_y(1); this->sprite->stop = false; this->walking = true; } void walk_up(){ this->slide_y(-1); this->sprite->stop = false; this->walking = true; } void walk_right(){ this->slide_x(1); this->sprite->stop = false; this->sprite->flags = 0; this->walking = true; } void walk_left(){ this->slide_x(-1); this->sprite->stop = false; this->sprite->flags = ALLEGRO_FLIP_HORIZONTAL; this->walking = true; } }; class Player : public Human{ public: Player(int x, int y) : Human(x, y, "textures/human/sprite.png"){ } void control(){ if(get_key(control_key_down)) this->walk_down(); else if(get_key(control_key_up)) this->walk_up(); if(get_key(control_key_right)) this->walk_right(); else if(get_key(control_key_left)) this->walk_left(); if(not this->walking){ this->sprite->set_frame(0); this->sprite->fix_sheet_looking(); this->sprite->stop = true; } if(this->last_x == this->body->x and this->last_y == this->body->y) this->walking = false; } void update(){ this->control(); } }; class Zombie : public Human{ private: //Player *to_kill; int to_kill_x, to_kill_y; unsigned int walk_ticks_counter = 0, follow_ticks_counter = 0; public: Player *to_kill; void fix_to_kill_position(){ if(this->to_kill){ this->to_kill_x = this->to_kill->body->x; this->to_kill_y = this->to_kill->body->y; } else{ this->to_kill_x = this->body->x; this->to_kill_y = this->body->y; } } Zombie(int x, int y, Player *to_kill) : Human(x, y, "textures/zombie/sprite.png"){ this->sprite->set_speed(23); this->walking_speed = 1; this->to_kill = to_kill; this->fix_to_kill_position(); } void control(){ if(this->body->y < to_kill_y) this->walk_down(); else if(this->body->y > to_kill_y) this->walk_up(); if(this->body->x < to_kill_x) this->walk_right(); else if(this->body->x > to_kill_x) this->walk_left(); if(not this->walking){ this->sprite->set_frame(0); this->sprite->fix_sheet_looking(); this->sprite->stop = true; } } void update(){ if(this->follow_ticks_counter == 78){ this->fix_to_kill_position(); this->follow_ticks_counter = 0; } else{ this->follow_ticks_counter += 1; } if(this->walk_ticks_counter == 2){ this->control(); this->walk_ticks_counter = 0; } else{ this->walk_ticks_counter += 1; } if(this->last_x == this->body->x and this->last_y == this->body->y) this->walking = false; } };
Why is my Allegro 5 Map Editor bugging?
I am making a Map Editor using Allegro 5, and it works with tiles. However, the bitmaps in it are extremely buggy, and I don't really know why. Here's my code: #include <allegro5\allegro.h> #include <allegro5\allegro_font.h> #include <allegro5\allegro_image.h> #include <allegro5\allegro_primitives.h> #include <allegro5\allegro_native_dialog.h> #include <stdio.h> #include <vector> //ENUMS DEFINITION SECTION enum TYPE{LEFT,RIGHT,UP,DOWN}; //CLASS DEFINITION SECTION class bmplist { public: ALLEGRO_BITMAP *bmp; TYPE type; }; class T_center { public: //place int p; int y; //place bound y up, x left, y down, x right int pbyu; int pbxl; int pbyd; int pbxr; ALLEGRO_BITMAP *img; bmplist a; }; class bmpdata { public: bmplist bmp; }; class bmphold { public: ALLEGRO_BITMAP *bmp; }; const int tileamount = 196; T_center tile[tileamount]; int height = 700; int width = 700; ALLEGRO_DISPLAY *display; ALLEGRO_EVENT ev; ALLEGRO_EVENT_QUEUE *queue; ALLEGRO_BITMAP *curr; ALLEGRO_BITMAP *tilelr; ALLEGRO_BITMAP *tileud; ALLEGRO_BITMAP *tileltd; ALLEGRO_BITMAP *tileltu; ALLEGRO_BITMAP *tilertd; ALLEGRO_BITMAP *tilertu; ALLEGRO_BITMAP *pathup; ALLEGRO_BITMAP *pathdown; ALLEGRO_BITMAP *pathleft; ALLEGRO_BITMAP *pathright; ALLEGRO_FONT *actual; bool isClicked; bmplist bmps[2]; bool MAPMOUNTING = true; bool MAPCOORDINATING = false; bmplist arrows[4]; bmplist bmpindex[20]; bmpdata arrowindex[4]; char tilenow[15]; //FUNCTION DECLARATION SECTION void func_start_system(); void func_start_tiles(int tilesize, T_center *tile, int tilearray, int xsize); void func_start_variables(); void func_detect_mouse_move(T_center *tile, int tilearray, int bmpsize); void mapper_init(); //THE TOOL ITSELF int main() { al_init(); al_init_font_addon(); al_init_image_addon(); al_init_primitives_addon(); mapper_init(); } //FUNCTION DEFINITION SECTION void func_start_system() { al_install_keyboard(); al_install_mouse(); } void func_start_tiles(int tilesize, T_center *tile, int tilearray, int xsize) { int xcount = 0; int tile_x = tilesize; int tile_y = tilesize; int y_count = 1; for (int i = 0; i < tilearray; i++) { if (xcount == 14) { xcount = 0; tile_y = tile[i-1].pbyd + tilesize; tile_x = tilesize; } tile[i].p = tile_x, tile[i].y = tile_y, tile[i].pbxl = tile_x - tilesize, tile[i].pbxr = tile_x + tilesize, tile[i].pbyu = tile_y - tilesize, tile[i].pbyd = tile_y + tilesize; tile_x = tile[i].pbxr + tilesize; printf("%i, %i, left: %i\n", tile[i].p, tile[i].y, tile[i].pbxl); xcount++; } } void func_start_variables() { display = al_create_display(width, height); tilelr = al_load_bitmap("tilelr.png"); tileud = al_load_bitmap("tileud.png"); tileltu = al_load_bitmap("tireltu.png"), tileltd = al_load_bitmap("tireltd.png"), tilertu = al_load_bitmap("tirertu.png"), tilertd = al_load_bitmap("tirertd.png"); pathup = al_load_bitmap("up.png"), pathdown = al_load_bitmap("down.png"), pathleft = al_load_bitmap("left.png"), pathright = al_load_bitmap("right.png"); arrows[1].bmp = al_load_bitmap("up.png"), arrows[1].type = UP, arrows[2].bmp = al_load_bitmap("down.png"), arrows[2].type = DOWN; arrows[3].bmp = al_load_bitmap("left.png"), arrows[3].type = LEFT, arrows[4].bmp = al_load_bitmap("right.png"), arrows[4].type = RIGHT; bmpindex[1].bmp = tilelr, bmpindex[2].bmp = tileud, bmpindex[3].bmp = tileltu, bmpindex[4].bmp = tileltd, bmpindex[5].bmp = tilertu, bmpindex[6].bmp = tilertd; bmpindex[7].bmp = pathup, bmpindex[7].type = UP, bmpindex[8].bmp = pathdown, bmpindex[8].type = DOWN; bmpindex[9].bmp = pathleft, bmpindex[9].type = LEFT, bmpindex[10].bmp = pathright, bmpindex[10].type = RIGHT; curr = bmpindex[1].bmp; actual = al_load_font("app850.ttf", 12, 0); queue = al_create_event_queue(); al_register_event_source(queue, al_get_mouse_event_source()); al_register_event_source(queue, al_get_keyboard_event_source()); al_register_event_source(queue, al_get_display_event_source(display)); } void func_detect_mouse_move(T_center *tile, int tilearray, int bmpsize) { int index = 1; int a = true; while (a) { printf("%i", index); al_clear_to_color(al_map_rgb(0, 0, 0)); for (int i = 0; i < tilearray; i++) { if (tile[i].img != NULL) al_draw_bitmap(tile[i].img, tile[i].pbxl, tile[i].pbyu, 0); if (tile[i].a.bmp != NULL) al_draw_bitmap(tile[i].a.bmp, tile[i].pbxl, tile[i].pbyu, 0); } al_wait_for_event(queue, &ev); { if (ALLEGRO_EVENT_MOUSE_AXES) { for (int i = 0; i < tilearray; i++) if (ev.mouse.x >= tile[i].pbxl && ev.mouse.x < tile[i].pbxr && ev.mouse.y >= tile[i].pbyu && ev.mouse.y < tile[i].pbyd) { al_draw_tinted_bitmap(bmpindex[index].bmp, al_map_rgb(200, 200, 200), tile[i].pbxl, tile[i].pbyu, 0); al_flip_display(); } } if (ALLEGRO_EVENT_MOUSE_BUTTON_DOWN) { if (ev.mouse.button & 1) for (int i = 0; i < tilearray; i++) { if (ev.mouse.x >= tile[i].pbxl && ev.mouse.x < tile[i].pbxr && ev.mouse.y >= tile[i].pbyu && ev.mouse.y < tile[i].pbyd) { if (bmpindex[index].type == NULL) { tile[i].img = curr; al_flip_display(); } if (bmpindex[index].type != NULL) { tile[i].a.bmp = bmpindex[index].bmp; tile[i].a.type = bmpindex[index].type; } } } if (ev.mouse.button & 2) for (int i = 0; i < tilearray; i++) { if (ev.mouse.x >= tile[i].pbxl && ev.mouse.x < tile[i].pbxr && ev.mouse.y >= tile[i].pbyu && ev.mouse.y < tile[i].pbyd) { tile[i].img = NULL; al_flip_display(); } } if (ALLEGRO_EVENT_KEY_DOWN) { if (ev.keyboard.keycode == ALLEGRO_KEY_1) index = 1; if (ev.keyboard.keycode == ALLEGRO_KEY_2) index = 2; if (ev.keyboard.keycode == ALLEGRO_KEY_3) index = 3; if (ev.keyboard.keycode == ALLEGRO_KEY_4) index = 4; if (ev.keyboard.keycode == ALLEGRO_KEY_5) index = 5; if (ev.keyboard.keycode == ALLEGRO_KEY_6) index = 6; if (ev.keyboard.keycode == ALLEGRO_KEY_UP) index = 7; if (ev.keyboard.keycode == ALLEGRO_KEY_DOWN) index = 8; if (ev.keyboard.keycode == ALLEGRO_KEY_LEFT) index = 9; if (ev.keyboard.keycode == ALLEGRO_KEY_RIGHT) index = 10; al_flush_event_queue(queue); } curr = bmpindex[index].bmp; } } } } void mapper_init() { func_start_system(); func_start_variables(); func_start_tiles(25, tile, tileamount, tileamount); al_flip_display(); func_detect_mouse_move(tile, tileamount, 10); } The problem with this map editor is that sometimes, just by moving the mouse, the index, which is an integer that selects a bitmap in the bmpindex array, bugs out and a completely random bitmap appears in the mouse's position. For example, I am placing some bitmaps on the screen with a number 2 index, but then all of a sudden the index number becomes 4. Also, whenever I press a key in the keyboard, the actual selected bitmap is drawn in a completely random part of the screen. Why is this bug happening? How can I fix it?
I'd say it's because you have a small typo there. Those conditions, i.e.: if (ALLEGRO_EVENT_MOUSE_AXES) if (ALLEGRO_EVENT_MOUSE_BUTTON_DOWN) if (ALLEGRO_EVENT_KEY_DOWN) Will always evaluate as TRUE and therefore the statements will always run. This way you'll end up in situations you described that does not seem make sense (at least on the first sight) but that actually are quite logical Like reading ev.mouse.x even though mouse did not move at all (but that did not matter because your condition if (ALLEGRO_EVENT_MOUSE_AXES) is always true) and contents of ev do not match mouse union part because it could have been the keyboard that caused the event, so the resulting coordinates are nonsensical (because there were none in that part of the memory) Solution is actually quite simple - you just need to check type of ev for that value in condition, i.e. replace: if (ALLEGRO_EVENT_MOUSE_AXES) With: if (ev.type == ALLEGRO_EVENT_MOUSE_AXES) And so on.
SDL Tiling situation
I am making a TBS game, at least im trying to. So i've started off by following a tutorial on lazyfoo.net (lesson 29) on how to make a tiled environment and making my own changes along the way. Every time i try to compile it it gives me two main errors: No. 1: 255 error: expected primary-expression before ',' token No. 2: 267 error: expected ';' before 'myUnit' Here is the source code, i am fairly certain the that the problem is not with the images or the map. CODE: #include "SDL/SDL_image.h" #include "SDL/SDL.h" #include <string> #include <fstream> const int SCREEN_WIDTH = 600; const int SCREEN_HEIGHT = 600; const int SCREEN_BPP = 32; const int FPS = 30; const int UNIT_WIDTH = 50; const int UNIT_HEIGHT = 50; const int LEVEL_WIDTH = 600; const int LEVEL_HEIGHT = 600; const int TILE_WIDTH = 60; const int TILE_HEIGHT = 60; const int TOTAL_TILES = 100; const int TILE_SPRITES = 3; const int TILE_GRASS = 0; const int TILE_WATER = 1; const int TILE_MOUNTAIN = 2; SDL_Surface *screen = NULL; SDL_Surface *Unit = NULL; SDL_Surface *tileMap = NULL; SDL_Rect clips[ TILE_SPRITES ]; SDL_Event occur; class Tile { private: SDL_Rect box; int type; public: Tile(int x, int y, int tileType); void show(); int get_type(); SDL_Rect get_box(); }; class Unit { private: SDL_Rect Box; bool movement; public: Unit(); void handle_input(); void move( Tile *tiles[]); void show(); }; SDL_Surface *load_image(std::string filename) { SDL_Surface* loadedImage = NULL; SDL_Surface* optimizedImage = NULL; loadedImage = IMG_Load(filename.c_str()); if(loadedImage != NULL) { optimizedImage = SDL_DisplayFormat( loadedImage ); SDL_FreeSurface( loadedImage ); if(optimizedImage != NULL) { SDL_SetColorKey(optimizedImage, SDL_SRCCOLORKEY, SDL_MapRGB(optimizedImage->format, 0,0xff,0xff)); } } return optimizedImage; } void apply_surface(int x, int y, SDL_Surface* source, SDL_Surface* destination, SDL_Rect* clip = NULL) { SDL_Rect offset; offset.x = x; offset.y = y; SDL_BlitSurface(source, clip, destination, &offset); } bool init() { if(SDL_Init(SDL_INIT_EVERYTHING) == -1) { return false; } screen = SDL_SetVideoMode(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_BPP,SDL_SWSURFACE); if(screen == NULL) { return false; } SDL_WM_SetCaption("Strategy Game", NULL); return true; } bool load_files() { Unit = load_image("infantry_red.png"); if(Unit == NULL) { return false; } tileMap = load_image("tilemap.png"); if( tileMap == NULL) { return false; } return 0; } void clean_up(Tile *tiles[]) { SDL_FreeSurface(Unit); SDL_FreeSurface(tileMap); for(int t = 0;t < TOTAL_TILES; t++) { delete tiles[ t ]; } SDL_Quit(); } void clip_tiles() { clips[TILE_GRASS].x = 0; clips[TILE_GRASS].y = 0; clips[TILE_GRASS].w = TILE_WIDTH; clips[TILE_GRASS].h = TILE_HEIGHT; clips[TILE_WATER].x = 60; clips[TILE_WATER].y = 0; clips[TILE_WATER].w = TILE_WIDTH; clips[TILE_WATER].h = TILE_HEIGHT; clips[TILE_MOUNTAIN].x = 120; clips[TILE_MOUNTAIN].y = 0; clips[TILE_MOUNTAIN].w = TILE_WIDTH; clips[TILE_MOUNTAIN].h = TILE_HEIGHT; } bool set_tiles( Tile *tiles[]) { int x = 0, y = 0; std::ifstream map("strategy_game.map"); if(map == NULL) { return false; } for(int t = 0; y < TOTAL_TILES; t++) { int tileType = -1; map >> tileType; if(map.fail() == true) { map.close(); return false; } if( (tileType >= 0) && (tileType < TILE_SPRITES)) { tiles[t] = new Tile(x,y,tileType); } else { map.close(); return false; } x += TILE_WIDTH; if(x >= LEVEL_WIDTH) { x = 0; y += TILE_HEIGHT; } } map.close(); return true; } Tile::Tile(int x, int y, int tileType) { box.x = x; box.y = y; box.w = TILE_WIDTH; box.h = TILE_HEIGHT; type = tileType; } void Tile::show() { apply_surface(box.x, box.y, tileMap, screen, &clips[type]); } int Tile::get_type() { return type; } SDL_Rect Tile::get_box() { return box; } Unit::Unit() { Box.x = 0; Box.y = 0; Box.w = UNIT_WIDTH; Box.h = UNIT_HEIGHT; } SDL_Rect rect; int mouseX,mouseY; void Unit::handle_input() { if(occur.type == SDL_MOUSEBUTTONDOWN) { mouseX = occur.button.x; mouseY = occur.button.y; } } void Unit::move(Tile *tiles[]) { Box.x += mouseX; if( Box.x < 0 || Box.x + UNIT_WIDTH > LEVEL_WIDTH ) { Box.x -= mouseX; } Box.y -= mouseY; if( Box.y < 0 || Box.y + UNIT_HEIGHT > LEVEL_HEIGHT) { Box.y -= mouseY; } } void Unit::show() { int BoxX; int BoxY; Box.x = BoxX; Box.y = BoxY; SDL_Rect unitOffset; unitOffset.x = BoxX; unitOffset.y = BoxY; SDL_BlitSurface(Unit,NULL,screen,unitOffset); } Uint32 start; int main(int argc, char* args[]) { bool quit = false; Unit myUnit; Tile *tiles[TOTAL_TILES]; if(init() == false) { return 1; } if(load_files() == false) { return 1; } clip_tiles(); if( set_tiles(tiles) == false) { return 1; } while(quit == false) { start = SDL_GetTicks(); while(SDL_PollEvent(&occur)); { myUnit.handle_input(); switch(occur.type) { case SDL_QUIT: quit = false; break; } } myUnit.move(tiles); for(int t = 0;t<TOTAL_TILES;t++) { tiles[t]->show(); } myUnit.show(); //render SDL_FillRect(screen,&screen->clip_rect,0); SDL_Flip(screen); if(1000/FPS > SDL_GetTicks() - start ){ SDL_Delay(1000/FPS - (SDL_GetTicks()-start)); } } clean_up( tiles ); return 0; }
Remove semi-colon from while(SDL_PollEvent(&occur)) Change: SDL_Surface *Unit = NULL; to `SDL_Surface *unitSurf = NULL;' Change: Unit = load_image("infantry_red.png"); if(Unit == NULL) { return false; } to unitSurf = load_image("infantry_red.png"); if(unitSurf == NULL) { return false; } Change: SDL_BlitSurface(Unit,NULL,screen,unitOffset); to SDL_BlitSurface(unitSurf,NULL,screen,unitOffset);
Remove the semicolon after while(SDL_PollEvent(&occur))