Related
I am making a google chrome dinosaur game using an SDL Template for graphics and I am almost finished but I have run into the issue of needing to be able to reset to the starting values of the game just like how you reset when you hit spacebar after dying in the google chrome dinosaur game. I have made an isGameOver function but I don't know how to reset the values to start a new game which is my main problem.
this is my GameScene class where the game over logic is located
GameScene.h
#pragma once
#include "Scene.h"
#include "GameObject.h"
#include "Player.h"
#include "Floor.h"
#include "Obstacle.h"
#include "FlyingObstacle.h"
#include <vector>
#include "util.h"
#include "text.h"
class GameScene : public Scene
{
public:
GameScene();
~GameScene();
void start();
void draw();
void update();
std::vector<Obstacle*> spawnedObstacle;
std::vector<FlyingObstacle*> spawnedBird;
private:
Player* player;
Floor* floor;
float spawnTime;
float currentSpawnTimer;
void floorCollision();
void obstacleCollision();
void birdCollision();
void obstacleSpawn();
void birdSpawn();
void despawnObstacle(Obstacle* obstacle);
void despawnBird(FlyingObstacle* bird);
int points;
int highscore;
bool isGameOver;
};
GameScene.cpp
#include "GameScene.h"
GameScene::GameScene()
{
// Register and add game objects on constructor
player = new Player();
this->addGameObject(player);
floor = new Floor();
this->addGameObject(floor);
points = 0;
highscore = 0;
}
GameScene::~GameScene()
{
delete player;
}
void GameScene::start()
{
Scene::start();
// Initialize any scene logic here
initFonts();
isGameOver = true;
currentSpawnTimer = 300;
spawnTime = rand() % 300; //spawn time of 5 seconds
for (int i = 0; i < 1; i++)
{
obstacleSpawn();
}
for (int i = 0; i < 3; i++)
{
birdSpawn();
}
}
void GameScene::draw()
{
Scene::draw();
drawText(110, 20, 255, 255, 255, TEXT_CENTER, "POINTS: %03d", points);
if (player->getIsAlive() == true)
{
drawText(900, 20, 255, 255, 255, TEXT_CENTER, "PRESS SPACE TO START MOVING");
}
if (player->getIsAlive() == false)
{
if (isGameOver == false)
drawText(SCREEN_WIDTH / 2, 200, 255, 255, 255, TEXT_CENTER, "YOU LOSE! PRESS SPACE TO SHOW POINTS");
if (isGameOver == true)
{
drawText(SCREEN_WIDTH / 2, 200, 255, 255, 255, TEXT_CENTER, "HIGHSCORE: %03d", highscore);
if (points > highscore)
{
drawText(SCREEN_WIDTH / 2, 200, 255, 255, 255, TEXT_CENTER, "NEW HIGHSCORE: %03d", points, highscore);
}
}
}
}
void GameScene::update()
{
if (isGameOver == true)
{
if (app.keyboard[SDL_SCANCODE_SPACE])
{
isGameOver = false;
}
}
if (isGameOver == false)
{
Scene::update();
floorCollision();
obstacleCollision();
birdCollision();
if (currentSpawnTimer > 0)
currentSpawnTimer--;
if (currentSpawnTimer <= 0)
{
for (int i = 0; i < 1; i++)
{
obstacleSpawn();
}
for (int i = 0; i < 3; i++)
{
birdSpawn();
}
currentSpawnTimer = spawnTime;
}
//This is where Gravity strength is located
if (player->getOnFloor() == false) {
player->setY(player->getY() + 7);
}
else {
player->getY() + 0;
}
}
}
void GameScene::floorCollision()
{
//Checks for collisions
for (int i = 0; i < objects.size(); i++)
{
//Cast to floor
Floor* floor = dynamic_cast<Floor*>(objects[i]);
//Check if the floor was casted
if (floor != NULL)
{
int collision = checkCollision(
player->getX(), player->getY(), player->getWidth(), player->getHeight(),
floor->getX(), floor->getY(), floor->getWidth(), floor->getHeight()
);
if (collision == 1)
{
player->setOnFloor(true);
if (player->getIsAlive() == true)
{
points++;
highscore++;
}
break;
}
}
}
}
void GameScene::obstacleCollision()
{
for (int i = 0; i < objects.size(); i++)
{
Obstacle* obstacle = dynamic_cast<Obstacle*>(objects[i]);
if (obstacle != NULL)
{
if (obstacle != NULL)
{
int collision = checkCollision(
player->getX(), player->getY(), player->getWidth(), player->getHeight(),
obstacle->getX(), obstacle->getY(), obstacle->getWidth(), obstacle->getHeight()
);
if (collision == 1)
{
player->doDeath();
isGameOver = true;
break;
}
}
}
}
}
void GameScene::birdCollision()
{
for (int i = 0; i < objects.size(); i++)
{
FlyingObstacle* bird = dynamic_cast<FlyingObstacle*>(objects[i]);
if (bird != NULL)
{
if (bird != NULL)
{
int collision = checkCollision(
player->getX(), player->getY(), player->getWidth(), player->getHeight(),
bird->getX(), bird->getY(), bird->getWidth(), bird->getHeight()
);
if (collision == 1)
{
player->doDeath();
isGameOver = true;
break;
}
}
}
}
}
void GameScene::obstacleSpawn()
{
Obstacle* obstacle = new Obstacle();
this->addGameObject(obstacle);
obstacle->setPosition(1200, 300 + (rand() % 300));
spawnedObstacle.push_back(obstacle);
}
void GameScene::birdSpawn()
{
FlyingObstacle* bird = new FlyingObstacle();
this->addGameObject(bird);
bird->setPos(1200, 300 + (rand() % 300));
spawnedBird.push_back(bird);
}
void GameScene::despawnObstacle(Obstacle* obstacle)
{
int index = -1;
for (int i = 0; i < spawnedObstacle.size(); i++)
{
//If pointer matches
if (obstacle == spawnedObstacle[i])
{
index = i;
break;
}
}
//If any match is found
if (index != -1)
{
spawnedObstacle.erase(spawnedObstacle.begin() + index);
delete obstacle;
}
}
void GameScene::despawnBird(FlyingObstacle* bird)
{
int index = -1;
for (int i = 0; i < spawnedBird.size(); i++)
{
//If pointer matches
if (bird == spawnedBird[i])
{
index = i;
break;
}
}
//If any match is found
if (index != -1)
{
spawnedBird.erase(spawnedBird.begin() + index);
delete bird;
}
}
I tried making an isGameOver bool inside my GameScene.h and I made it so that pressing spacebar would reset the game but in reality when the player dies the screen pauses every movement instead of resetting and if I press space again the game continues to move even though the player is dead.
Your entry point for the game(probably main function will probably have some form like this)
#include ...
#include ...
...
int main()
{
bool game_running = true;
while(game_running)
{
GameInstance* game = new Game(); //Allocation and initialization of all resources needed to play the game.
game.play(); // This function will finish when you lose the game.
delete game; // Deallocation.
if(!run_again())
{
game_running = false;
}
}
return 0;
}
After deallocation, you check if user wants to play again, you enter the next iteration of while loop, and new instance of Game is allocated, where all the resource handling takes place. The only problem is that allocating Game instance for every iteration might be a little costly, but you can ignore that if you don't worry about performance much.
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
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
So I'm nearly done writing my first tic tac toe in C++ and SDL, ad I've run into a slight problem. I use a state machine to switch from title screen to shape choice screen, to player one or two to winning screen and back to the choice screen etc etc. On the choice screen I have two SDL_Rect arrays that act as buttons and the buttons are the X and O sprites I use from my sprite sheet. When the mouse hovers over them, they change colors. Everything is fine and dandy until the game resets to the choice screen after a win lose or tie. When it goes back to the choice screen and the mouse hovers over the button, it does not show the highlighted or mouse hovered sprite it clipped before. I pin pointed this problem to the initialization of my "set_grid_regions()" function. But this array doesn't even interact with the choice screen class in any way. How can this be affecting my hover sprites?
Just so anyone can see, here is the whole of the program:
#include "SDL.h"
#include "SDL_ttf.h"
#include "SDL_image.h"
#include "SDL_mixer.h"
#include <string>
#include <iostream>
//constants
const int SCREEN_HEIGHT = 300;
const int SCREEN_WIDTH = 300;
const int SCREEN_BPP = 32;
const int GRID_WIDTH = 96;
const int GRID_HEIGHT = 96;
//game states
enum States
{
S_NULL,
INTRO,
CHOICE,
START_O,
START_X,
PLAYER_ONE,
PLAYER_TWO,
O_win,
X_win,
Tie,
EXIT,
};
// CLASSES //
class GameState
{
public:
virtual void events() = 0;
virtual void logic() = 0;
virtual void render() = 0;
virtual ~GameState(){};
};
class intro : public GameState
{
private:
//hover variable
bool button_hover = NULL;
//rects and surfaces
SDL_Rect button;
SDL_Surface *title_message = NULL;
public:
void events();
void logic();
void render();
intro();
~intro();
};
class choice : public GameState
{
private:
bool O_hover = NULL;
bool X_hover = NULL;
SDL_Rect shape_O_button;
SDL_Rect shape_X_button;
SDL_Surface *choice_text = NULL;
public:
void events();
void logic();
void render();
choice();
~choice();
};
class playerOne : public GameState
{
public:
void events();
void logic();
void render();
playerOne();
~playerOne();
};
class playerTwo : public GameState
{
public:
void events();
void logic();
void render();
playerTwo();
~playerTwo();
};
class win : public GameState
{
private:
int winner = NULL;
SDL_Surface *Tie = NULL;
SDL_Surface *X_win = NULL;
SDL_Surface *O_win = NULL;
public:
void events();
void logic();
void render();
win(int winner);
~win();
};
class Exit : public GameState
{
public:
void events();
void logic();
void render();
Exit();
~Exit();
};
// GLOBALS //
GameState *currentState = NULL;
int stateID = S_NULL;
int nextState = S_NULL;
//event
SDL_Event event;
//surfaces
SDL_Surface *screen = NULL;
SDL_Surface *sprites = NULL;
//ttf
TTF_Font *font = NULL;
SDL_Color color = { 0, 0, 0 };
SDL_Color win_Color = { 0, 100, 0 };
//arrays
int grid_array[9];
//rects
SDL_Rect sprite_clip[10];
SDL_Rect grid_region[9];
int number_elements = sizeof(grid_region) / sizeof(grid_region[0]);
//bools
bool shape = NULL;
bool invalid = NULL;
bool winner = NULL;
//ints
int highlight = NULL;
int shape_winner = NULL;
// FUCNTIONS //
//load image
SDL_Surface *load_image(std::string filename)
{
//loaded image
SDL_Surface* loadedImage = NULL;
//optimized surface
SDL_Surface* optimizedImage = NULL;
//load image
loadedImage = IMG_Load(filename.c_str());
//if image loaded
if (loadedImage != NULL)
{
//Create optimized image
optimizedImage = SDL_DisplayFormat(loadedImage);
//free old image
SDL_FreeSurface(loadedImage);
//if optimized
if (optimizedImage != NULL)
{
//map color key
Uint32 colorkey = SDL_MapRGB(optimizedImage->format, 255, 255, 0);
//set all pixles of color 0,0,0 to be transparent
SDL_SetColorKey(optimizedImage, SDL_SRCCOLORKEY, colorkey);
}
}
return optimizedImage;
}
//apply image
void apply_surface(int x, int y, SDL_Surface* source, SDL_Surface* destination, SDL_Rect* clip = NULL)
{
//temp rect
SDL_Rect offset;
//offsets
offset.x = x;
offset.y = y;
//blit
SDL_BlitSurface(source, clip, destination, &offset);
}
//initiate SDL etc
bool init()
{
//initialize all SDL subsystems
if (SDL_Init(SDL_INIT_EVERYTHING) == -1)
{
return false;
}
//set up screen
screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE);
if (screen == NULL)
{
return false;
}
//check screen
if (screen == NULL)
{
return false;
}
//init TTF
if (TTF_Init() == -1)
{
return false;
}
//set window caption
SDL_WM_SetCaption("Tic-Tac-Toe", NULL);
//if evetything worked
return true;
}
//load files
bool load_files()
{
//sprite sheet
sprites = load_image("Sprites.png");
if (sprites == NULL)
{
return false;
}
font = TTF_OpenFont("font.ttf", 45);
if (font == NULL)
{
return false;
}
return true;
}
//quit
void clean_up()
{
//delete game state
delete currentState;
//free image
SDL_FreeSurface(sprites);
//quit ttf
TTF_CloseFont(font);
TTF_Quit();
//quit SDL
SDL_Quit();
}
void set_clip_regions()
{
//init clip array
//O
sprite_clip[0].x = 300;
sprite_clip[0].y = 0;
sprite_clip[0].w = 80;
sprite_clip[0].h = 82;
//X
sprite_clip[1].x = 300;
sprite_clip[1].y = 176;
sprite_clip[1].w = 80;
sprite_clip[1].h = 82;
//grid
sprite_clip[2].x = 0;
sprite_clip[2].y = 0;
sprite_clip[2].w = 300;
sprite_clip[2].h = 300;
//highlight
sprite_clip[3].x = 300;
sprite_clip[3].y = 82;
sprite_clip[3].w = 94;
sprite_clip[3].h = 94;
//left to right line
sprite_clip[4].x = 398;
sprite_clip[4].y = 188;
sprite_clip[4].w = 234;
sprite_clip[4].h = 12;
//diag up
sprite_clip[5].x = 393;
sprite_clip[5].y = 0;
sprite_clip[5].w = 188;
sprite_clip[5].h = 186;
//up down line
sprite_clip[6].x = 591;
sprite_clip[6].y = 0;
sprite_clip[6].w = 11;
sprite_clip[6].h = 208;
//Diag down line
sprite_clip[7].x = 0;
sprite_clip[7].y = 300;
sprite_clip[7].w = 188;
sprite_clip[7].h = 186;
//start button
sprite_clip[8].x = 202;
sprite_clip[8].y = 300;
sprite_clip[8].w = 94;
sprite_clip[8].h = 32;
//intro and choice background
sprite_clip[9].x = 300;
sprite_clip[9].y = 300;
sprite_clip[9].w = 300;
sprite_clip[9].h = 300;
//start hover
sprite_clip[10].x = 202;
sprite_clip[10].y = 332;
sprite_clip[10].w = 94;
sprite_clip[10].h = 32;
//X hover
sprite_clip[11].x = 202;
sprite_clip[11].y = 446;
sprite_clip[11].w = 80;
sprite_clip[11].h = 82;
//o hover
sprite_clip[12].x = 202;
sprite_clip[12].y = 364;
sprite_clip[12].w = 80;
sprite_clip[12].h = 82;
}
void set_grid_regions()
{
//set regions for images to be applied to
grid_region[0].x = 3;
grid_region[0].y = 3;
grid_region[1].x = 103;
grid_region[1].y = 3;
grid_region[2].x = 203;
grid_region[2].y = 3;
grid_region[3].x = 3;
grid_region[3].y = 103;
grid_region[4].x = 103;
grid_region[4].y = 103;
grid_region[5].x = 203;
grid_region[5].y = 103;
grid_region[6].x = 3;
grid_region[6].y = 203;
grid_region[7].x = 103;
grid_region[7].y = 203;
grid_region[8].x = 203;
grid_region[8].y = 203;
}
void init_grid()
{
//from left to right top to bottom
grid_array[0] = 0;
grid_array[1] = 0;
grid_array[2] = 0;
grid_array[3] = 0;
grid_array[4] = 0;
grid_array[5] = 0;
grid_array[6] = 0;
grid_array[7] = 0;
grid_array[8] = 0;
}
// STATE MACHINE FUNCTIONS //
void set_next_state(int newState)
{
if (nextState != EXIT)
{
nextState = newState;
}
}
void change_state()
{
if (nextState != S_NULL)
{
//change state
switch (nextState)
{
case CHOICE:
currentState = new choice();
break;
case PLAYER_ONE:
currentState = new playerOne();
break;
case PLAYER_TWO:
currentState = new playerTwo();
break;
case O_win:
currentState = new win(0);
break;
case X_win:
currentState = new win(1);
break;
case Tie:
currentState = new win(2);
break;
case EXIT:
currentState = new Exit();
break;
}
//change state
stateID = nextState;
//null nextState
nextState = S_NULL;
}
}
// CLASS DEFINITIONS //
intro::intro()
{
//button
button_hover = false;
//title
title_message = TTF_RenderText_Solid(font, "TIC TAC TOE", color);
//button bounds
button.x = 102;
button.y = 180;
button.w = 94;
button.h = 32;
}
intro::~intro()
{
SDL_FreeSurface(title_message);
}
void intro::events()
{
int x, y;
//mouse events
while (SDL_PollEvent(&event))
{
if (event.type == SDL_MOUSEMOTION)
{
x = event.motion.x;
y = event.motion.y;
if ((x > button.x) && (x < button.x + button.w) && (y > button.y) && (y < button.y + button.h))
{
button_hover = true;
}
else
{
button_hover = false;
}
}
if (event.type == SDL_MOUSEBUTTONDOWN)
{
if (event.button.button == SDL_BUTTON_LEFT)
{
x = event.motion.x;
y = event.motion.y;
if ((x > button.x) && (x < button.x + button.w) && (y > button.y) && (y < button.y + button.h))
{
set_next_state(CHOICE);
}
}
}
if (event.type == SDL_QUIT)
{
set_next_state(EXIT);
}
}
}
void intro::logic()
{
}
void intro::render()
{
apply_surface(0, 0, sprites, screen, &sprite_clip[9]);
apply_surface((SCREEN_WIDTH - title_message->w) / 2, 100, title_message, screen);
if (button_hover == true)
{
apply_surface(102, 180, sprites, screen, &sprite_clip[10]);
}
else
{
apply_surface(102, 180, sprites, screen, &sprite_clip[8]);
}
}
choice::choice()
{
O_hover = false;
X_hover = false;
shape_O_button.x = 0;
shape_O_button.y = 130;
shape_O_button.w = 80;
shape_O_button.h = 82;
shape_X_button.x = 220;
shape_X_button.y = 130;
shape_X_button.w = 80;
shape_X_button.h = 82;
font = TTF_OpenFont("font.ttf", 34);
choice_text = TTF_RenderText_Solid(font, "CHOOSE YOUR SHAPE", color);
}
choice::~choice()
{
SDL_FreeSurface(choice_text);
O_hover = NULL;
X_hover = NULL;
}
void choice::events()
{
int x, y;
//mouse events
while (SDL_PollEvent(&event))
{
if (event.type == SDL_MOUSEMOTION)
{
x = event.motion.x;
y = event.motion.y;
if ((x > shape_O_button.x) && (x < shape_O_button.x + shape_O_button.w) && (y > shape_O_button.y) && (y < shape_O_button.y + shape_O_button.h))
{
O_hover = true;
}
else
{
O_hover = false;
}
if ((x > shape_X_button.x) && (x < shape_X_button.x + shape_X_button.w) && (y > shape_X_button.y) && (y < shape_X_button.y + shape_X_button.h))
{
X_hover = true;
}
else
{
X_hover = false;
}
}
if (event.type == SDL_MOUSEBUTTONDOWN)
{
if (event.button.button == SDL_BUTTON_LEFT)
{
x = event.motion.x;
y = event.motion.y;
if ((x > shape_O_button.x) && (x < shape_O_button.x + shape_O_button.w) && (y > shape_O_button.y) && (y < shape_O_button.y + shape_O_button.h))
{
shape = false;
init_grid();
set_next_state(PLAYER_ONE);
}
if ((x > shape_X_button.x) && (x < shape_X_button.x + shape_X_button.w) && (y > shape_X_button.y) && (y < shape_X_button.y + shape_X_button.h))
{
shape = true;
init_grid();
set_next_state(PLAYER_TWO);
}
}
}
if (event.type == SDL_QUIT)
{
set_next_state(EXIT);
}
}
}
void choice::logic()
{
}
void choice::render()
{
apply_surface( 0, 0, sprites, screen, &sprite_clip[9]);
if (O_hover == false)
{
apply_surface(shape_O_button.x, shape_O_button.y, sprites, screen, &sprite_clip[0]);
}
else
{
apply_surface(shape_O_button.x, shape_O_button.y, sprites, screen, &sprite_clip[12]);
}
if (X_hover == false)
{
apply_surface(shape_X_button.x, shape_X_button.y, sprites, screen, &sprite_clip[1]);
}
else
{
apply_surface(shape_X_button.x, shape_X_button.y, sprites, screen, &sprite_clip[11]);
}
apply_surface((SCREEN_WIDTH - choice_text->w) / 2, 60, choice_text, screen);
}
//plyer O
playerOne::playerOne()
{
set_grid_regions();
}
playerOne::~playerOne()
{
}
void playerOne::events()
{
//mouse offsets
int x = 0, y = 0;
//if mouse moves
while (SDL_PollEvent(&event))
{
if (event.type == SDL_MOUSEMOTION)
{
//get the mouse co-ords
x = event.motion.x;
y = event.motion.y;
for (int grid = 0; grid < number_elements; grid++)
{
if ((x > grid_region[grid].x) && (x < grid_region[grid].x + GRID_WIDTH) && (y > grid_region[grid].y) && (y < grid_region[grid].y + GRID_HEIGHT))
{
//set highlight region
highlight = grid;
}
}
}
//when the player clicks on a grid_region
if (event.type == SDL_MOUSEBUTTONDOWN)
{
//mouse co-ordinates
x = event.motion.x;
y = event.motion.y;
if (event.button.button == SDL_BUTTON_LEFT)
{
//iterate
for (int grid = 0; grid < number_elements; grid++)
{
//if in region box
if ((x > grid_region[grid].x) && (x < grid_region[grid].x + GRID_WIDTH) && (y > grid_region[grid].y) && (y < grid_region[grid].y + GRID_HEIGHT))
{
//check region
//if O turn
if ((grid_array[grid] == 0) && (shape == 0))
{
//fill region
grid_array[grid] = 1;
shape = (!shape);
}
else if (grid_array[grid] != 0)
{
//raise "error"
invalid = true;
}
//if X turn
else if ((grid_array[grid] == 0) && (shape == 1))
{
if ((grid_array[grid] == 0))
{
//fill region
grid_array[grid] = 2;
shape = (!shape);
}
else if (grid_array[grid] != 0)
{
//raise "error"
invalid = true;
}
}
}
}
}
}
if (event.type == SDL_QUIT)
{
set_next_state(EXIT);
}
}
}
void playerOne::logic()
{
//check O win
for (int win = 0; win <= 6; win += 3)
{
if ((grid_array[win] == 1) && (grid_array[win + 1] == 1) && (grid_array[win + 2] == 1))
{
winner = 0;
set_next_state(O_win);
}
}
for (int win = 0; win < 3; win++)
{
if ((grid_array[win] == 1) && (grid_array[win + 3] == 1) && (grid_array[win + 6] == 1))
{
winner = 0;
set_next_state(O_win);
}
}
if ((grid_array[0] == 1) && (grid_array[4] == 1) && (grid_array[8] == 1))
{
winner = 0;
set_next_state(O_win);
}
if ((grid_array[2] == 1) && (grid_array[4] == 1) && (grid_array[6] == 1))
{
winner = 0;
set_next_state(O_win);
}
//check X's
for (int win = 0; win <= 6; win += 3)
{
if ((grid_array[win] == 2) && (grid_array[win + 1] == 2) && (grid_array[win + 2] == 2))
{
winner = 1;
set_next_state(X_win);
}
}
for (int win = 0; win < 3; win++)
{
if ((grid_array[win] == 2) && (grid_array[win + 3] == 2) && (grid_array[win + 6] == 2))
{
winner = 1;
set_next_state(X_win);
}
}
if ((grid_array[0] == 2) && (grid_array[4] == 2) && (grid_array[8] == 2))
{
winner = 1;
set_next_state(X_win);
}
if ((grid_array[2] == 2) && (grid_array[4] == 2) && (grid_array[6] == 2))
{
winner = 1;
set_next_state(X_win);
}
//check TIE
if ((grid_array[0] != 0) && (grid_array[1] != 0) && (grid_array[2] != 0) && (grid_array[3] != 0) && (grid_array[4] != 0) && (grid_array[5] != 0) && (grid_array[6] != 0) && (grid_array[7] != 0) && (grid_array[8] != 0) && (winner == NULL))
{
set_next_state(Tie);
}
}
void playerOne::render()
{
//logic
//rendering
//background
SDL_FillRect(screen, &screen->clip_rect, SDL_MapRGB(screen->format, 0xFF, 0xFF, 0xFF));
//grid
apply_surface(0, 0, sprites, screen, &sprite_clip[2]);
//highlight
if (highlight != -1)
{
apply_surface(grid_region[highlight].x, grid_region[highlight].y, sprites, screen, &sprite_clip[3]);
}
//APPLY PLAYER SHAPE
for (int grid = 0; grid < number_elements; grid++)
{
//O's
if ((grid_array[grid] == 1))
{
apply_surface(grid_region[grid].x + 7, grid_region[grid].y + 6, sprites, screen, &sprite_clip[0]);
}
else if ((grid_array[grid] == 2))
{
//X's
apply_surface(grid_region[grid].x + 7, grid_region[grid].y + 6, sprites, screen, &sprite_clip[1]);
}
}
}
playerTwo::playerTwo()
{
set_grid_regions();
}
playerTwo::~playerTwo()
{
}
void playerTwo::events()
{
//mouse offsets
int x = 0, y = 0;
//if mouse moves
while (SDL_PollEvent(&event))
{
if (event.type == SDL_MOUSEMOTION)
{
//get the mouse co-ords
x = event.motion.x;
y = event.motion.y;
for (int grid = 0; grid < number_elements; grid++)
{
if ((x > grid_region[grid].x) && (x < grid_region[grid].x + GRID_WIDTH) && (y > grid_region[grid].y) && (y < grid_region[grid].y + GRID_HEIGHT))
{
//set highlight region
highlight = grid;
}
}
}
//when the player clicks on a grid_region
if (event.type == SDL_MOUSEBUTTONDOWN)
{
//mouse co-ordinates
x = event.motion.x;
y = event.motion.y;
if (event.button.button == SDL_BUTTON_LEFT)
{
//iterate
for (int grid = 0; grid < number_elements; grid++)
{
//if in region box
if ((x > grid_region[grid].x) && (x < grid_region[grid].x + GRID_WIDTH) && (y > grid_region[grid].y) && (y < grid_region[grid].y + GRID_HEIGHT))
{
//check region
//if O turn
if ((grid_array[grid] == 0) && (shape == 0))
{
//fill region
grid_array[grid] = 1;
shape = (!shape);
}
else if (grid_array[grid] != 0)
{
//raise "error"
invalid = true;
}
//if X turn
else if ((grid_array[grid] == 0) && (shape == 1))
{
if ((grid_array[grid] == 0))
{
//fill region
grid_array[grid] = 2;
shape = (!shape);
}
else if (grid_array[grid] != 0)
{
//raise "error"
invalid = true;
}
}
}
}
}
}
if (event.type == SDL_QUIT)
{
set_next_state(EXIT);
}
}
}
void playerTwo::logic()
{
//check O win
for (int win = 0; win <= 6; win += 3)
{
if ((grid_array[win] == 1) && (grid_array[win + 1] == 1) && (grid_array[win + 2] == 1))
{
winner = 0;
set_next_state(O_win);
}
}
for (int win = 0; win < 3; win++)
{
if ((grid_array[win] == 1) && (grid_array[win + 3] == 1) && (grid_array[win + 6] == 1))
{
winner = 0;
set_next_state(O_win);
}
}
if ((grid_array[0] == 1) && (grid_array[4] == 1) && (grid_array[8] == 1))
{
winner = 0;
set_next_state(O_win);
}
if ((grid_array[2] == 1) && (grid_array[4] == 1) && (grid_array[6] == 1))
{
winner = 0;
set_next_state(O_win);
}
//check X's
for (int win = 0; win <= 6; win += 3)
{
if ((grid_array[win] == 2) && (grid_array[win + 1] == 2) && (grid_array[win + 2] == 2))
{
winner = 1;
set_next_state(X_win);
}
}
for (int win = 0; win < 3; win++)
{
if ((grid_array[win] == 2) && (grid_array[win + 3] == 2) && (grid_array[win + 6] == 2))
{
winner = 1;
set_next_state(X_win);
}
}
if ((grid_array[0] == 2) && (grid_array[4] == 2) && (grid_array[8] == 2))
{
winner = 1;
set_next_state(X_win);
}
if ((grid_array[2] == 2) && (grid_array[4] == 2) && (grid_array[6] == 2))
{
winner = 1;
set_next_state(X_win);
}
//check TIE
if ((grid_array[0] != 0) && (grid_array[1] != 0) && (grid_array[2] != 0) && (grid_array[3] != 0) && (grid_array[4] != 0) && (grid_array[5] != 0) && (grid_array[6] != 0) && (grid_array[7] != 0) && (grid_array[8] != 0) && (winner == NULL))
{
set_next_state(Tie);
}
}
void playerTwo::render()
{
//logic
//rendering
//background
SDL_FillRect(screen, &screen->clip_rect, SDL_MapRGB(screen->format, 0xFF, 0xFF, 0xFF));
//grid
apply_surface(0, 0, sprites, screen, &sprite_clip[2]);
//highlight
if (highlight != -1)
{
apply_surface(grid_region[highlight].x, grid_region[highlight].y, sprites, screen, &sprite_clip[3]);
}
//APPLY PLAYER SHAPE
for (int grid = 0; grid < number_elements; grid++)
{
//O's
if ((grid_array[grid] == 1))
{
apply_surface(grid_region[grid].x + 7, grid_region[grid].y + 6, sprites, screen, &sprite_clip[0]);
}
else if ((grid_array[grid] == 2))
{
//X's
apply_surface(grid_region[grid].x + 7, grid_region[grid].y + 6, sprites, screen, &sprite_clip[1]);
}
}
}
win::win(int winner)
{
shape_winner = winner;
font = TTF_OpenFont("font.ttf", 45);
X_win = TTF_RenderText_Solid(font, "X WINS", win_Color);
O_win = TTF_RenderText_Solid(font, "O wins", win_Color);
Tie = TTF_RenderText_Solid(font, "Tie", win_Color);
}
win::~win()
{
TTF_CloseFont(font);
SDL_FreeSurface(X_win);
SDL_FreeSurface(O_win);
}
void win::events()
{
while (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT)
{
set_next_state(EXIT);
}
}
}
void win::logic()
{
if (shape_winner == 3)
{
SDL_Delay(2000);
set_next_state(CHOICE);
winner = NULL;
}
}
void win::render()
{
//background
SDL_FillRect(screen, &screen->clip_rect, SDL_MapRGB(screen->format, 0xFF, 0xFF, 0xFF));
//grid
apply_surface(0, 0, sprites, screen, &sprite_clip[2]);
//highlight
if (highlight != -1)
{
apply_surface(grid_region[highlight].x, grid_region[highlight].y, sprites, screen, &sprite_clip[3]);
}
//APPLY PLAYER SHAPE
for (int grid = 0; grid < number_elements; grid++)
{
//O's
if ((grid_array[grid] == 1))
{
apply_surface(grid_region[grid].x + 7, grid_region[grid].y + 6, sprites, screen, &sprite_clip[0]);
}
else if ((grid_array[grid] == 2))
{
//X's
apply_surface(grid_region[grid].x + 7, grid_region[grid].y + 6, sprites, screen, &sprite_clip[1]);
}
}
if (shape_winner == 1)
{
apply_surface((SCREEN_WIDTH - X_win->w) / 2, (SCREEN_HEIGHT - X_win->h) / 2, X_win, screen);
//enable delay and reset
shape_winner = 3;
}
if (shape_winner == 0)
{
apply_surface((SCREEN_WIDTH - O_win->w) / 2, (SCREEN_HEIGHT - O_win->h) / 2, O_win, screen);
//enable delay and reset
shape_winner = 3;
}
if (shape_winner == 2)
{
apply_surface((SCREEN_WIDTH - Tie->w) / 2, (SCREEN_HEIGHT - Tie->h) / 2, Tie, screen);
//enable delay and reset
shape_winner = 3;
}
}
Exit::Exit()
{
}
Exit::~Exit()
{
}
void Exit::events()
{
}
void Exit::logic()
{
}
void Exit::render()
{
}
//MAAAAAAAAAAAAAAAAAAIN//
int main(int argc, char* args[])
{
//init SDL
init();
//load files
load_files();
//set clips
set_clip_regions();
//set state
stateID = INTRO;
//set game object
currentState = new intro();
while (stateID != EXIT)
{
//handle state events
currentState->events();
// do state logic
currentState->logic();
//change state if needed
change_state();
//render state
currentState->render();
if (SDL_Flip(screen) == -1)
{
return 1;
}
}
clean_up();
return 0;
}
It's pretty strange. But I'm 99% sure that it's the "set_grid_regions()" that is effecting the rendering inside the choice::render() or choice::event() class fucntions. Can anyone help with this?
The error causing the clipping problem is an incorrect declaration for sprite_clip. You've declared it as sprite_clip[10], but you have 13 sprites. Change this to sprite_clip[13].
Other things I noticed:
You allocate all these state objects with new, but you never delete them. You need to delete them when you change states. Otherwise you will leak memory.
The font font.ttf seems to be a global resource but is haphazardly managed by a mixture of global and local methods. Load it once in load_files() and release it once in clean_up().
While your project may be complete, you might tinker around with it and work on improving the implementation now that you have something working. (If this was a homework, keep a copy of a working version to hand in. ;-) )
Consider packaging all of your global state (your fonts, sprites, clipping arrays, etc.) into a single class for the game. Your init_xxx and load_xxx functions move to its constructor. Your clean_up moves to its destructor.
Consider converting your dynamic state objects into statically allocated state objects. They could even be members of the same global state class I mentioned in the previous bullet. Now you've encapsulated the whole game in one class.
Consider merging playerOne and playerTwo into a single class. Distinguish them at construction time, just as you did with win(0), win(1), win(2).
This is my code...how to run animation with joystick position. if joystick full strectched then animation show fast. otherwise slow
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"walkcycle.plist"] ;
spriteSheet = [CCSpriteBatchNode batchNodeWithFile:#"walkcycle.png"];
[heroWorldLayer addChild:spriteSheet];
float frameInt = 33.0f;
CCArray *jumpFrames = [CCArray arrayWithCapacity:33];
for(int i = 1; i <= 33; ++i) {
CCSpriteFrame *frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:#"Jump_Anim_V0200%02d.png", i]];
[jumpFrames addObject:frame];
}
CCAnimation *jumpAnim = [CCAnimation animationWithFrames:[jumpFrames getNSArray] delay:1/frameInt];
CCFiniteTimeAction *jumpAnimate = [CCAnimate actionWithAnimation:jumpAnim restoreOriginalFrame:YES];
_jumpAction = [CCRepeat actionWithAction:jumpAnimate times:1];
NSMutableArray *runFrames = [NSMutableArray array];
for(int i = 1; i <= 11; ++i) {
CCSpriteFrame *frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:#"Run_Anim00%02d.png", i]];
[runFrames addObject:frame];
}
CCAnimation *runAnim = [CCAnimation animationWithFrames:runFrames delay:1.0f/22.0f];
CCAnimate *runAnimate = [CCAnimate actionWithAnimation:runAnim restoreOriginalFrame:NO];
_runAction = [CCRepeatForever actionWithAction:runAnimate];
NSMutableArray *walkFrames = [NSMutableArray array];
for(int i = 1; i <= 8; ++i) {
CCSpriteFrame *frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:#"walkcycle00%02d.png", i]];
[walkFrames addObject:frame];
}
CCAnimation *walkAnim = [CCAnimation animationWithFrames:walkFrames delay:(1-(controls.joyStickPos.x))/16.0f];
CCAnimate *walkAnimate = [CCAnimate actionWithAnimation:walkAnim restoreOriginalFrame:NO];
_walkAction = [CCRepeatForever actionWithAction:walkAnimate];
if (controls.joyStickPos.x < 0) {
heroBodySprite.flipX = YES;
} else {
heroBodySprite.flipX = NO;
}
if(controls.joyStickPos.x ==0){ // joystick pos
if (_actionState != kActionStateWalk || _actionState == kActionStateIdle) {
[heroBodySprite stopAllActions];
[heroBodySprite runAction:_runAction];
_actionState = kActionStateWalk;
} else {
_actionState = kActionStateIdle;
}
}
//my animation at joystick.pos.x == 0 otherwise it not show animation
if(controls.jmpBtn) { //joystick control jump
if (_actionState != kActionStateJump || _actionState == kActionStateIdle) {
[heroBodySprite stopAllActions];
[heroBodySprite runAction:_jumpAction];
_actionState = kActionStateJump;
} else {
_actionState = kActionStateIdle;
}
[self jump];
}
when pressing only jump button no animation but if joystick and jump button move and press together then jump animation stop.
Check out sneaky input which has joystick/D-Pad capabilities : here
This does most of the work for you!
This is not the exact code, But it could be something like this
if (joystick.position.x <= joystick.position.x - 20) {
//Play slow animation
}
else {
//Play fast animation
}
int current_state = 0; // at class implementation time
if ((controls.joyStickPos.x >= 0.7 || controls.joyStickPos.x <= -0.7) && current_state != 1){
current_state = 1;
[self runAnimation];
} else {
}
if (((controls.joyStickPos.x > 0 && controls.joyStickPos.x < 0.7) || (controls.joyStickPos.x < 0 && controls.joyStickPos.x > -0.7)) && current_state != 2){
current_state = 2;
[self walkAnimation];
} else {
}
if (controls.joyStickPos.x == 0 && current_state != 0) {
[heroBodySprite stopAllActions];
[wheelSprite stopAllActions];
current_state = 0;
} else {
}
I am using the allegro_primitives.h header file, and when I go to draw a rectangle with al_draw_filled_rectangle, and I move the rectangle with the keys, the outline of the rectangle in the direction that the rectangle is going is changing colors. Here's the code:
#include <allegro5\allegro5.h>
#include <allegro5\allegro_primitives.h>
#include <iostream>
#include "Globals.h"
using namespace std;
bool keys[5] = {false, false, false, false, false};
enum KEYS {UP, DOWN, LEFT, RIGHT, SPACE};
const int WINDOW_WIDTH = 600;
const int WINDOW_HEIGHT = 600;
int main()
{
bool done = false;
bool redraw = true;
ALLEGRO_DISPLAY *display = NULL;
ALLEGRO_TIMER *timer = NULL;
ALLEGRO_EVENT_QUEUE *event_queue = NULL;
if(!al_init())
return -1;
al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 1, ALLEGRO_SUGGEST);
al_set_new_display_option(ALLEGRO_SAMPLES, 8, ALLEGRO_SUGGEST);
display = al_create_display(WINDOW_WIDTH,WINDOW_HEIGHT);
if(!display)
return -1;
al_init_primitives_addon();
al_install_keyboard();
event_queue = al_create_event_queue();
timer = al_create_timer(1.0 / 60);
if(!timer)
return -1;
if(!event_queue)
return -1;
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));
Character player;
Character lover;
player.x1 = 100;
player.x2 = player.x1 + 40;
player.y1 = (WINDOW_HEIGHT / 2) - 20;
player.y2 = player.y1 + 40;
lover.x1 = WINDOW_WIDTH - 140;
lover.x2 = lover.x1 + 40;
lover.y1 = (WINDOW_HEIGHT / 2) - 20;
lover.y2 = lover.y1 + 40;
al_start_timer(timer);
while(!done)
{
ALLEGRO_EVENT ev;
al_wait_for_event(event_queue,&ev);
if(ev.timer.source == timer)
{
if(keys[UP])
{
player.y1 -= 5;
player.y2 -= 5;
}
if(keys[DOWN])
{
player.y1 += 5;
player.y2 += 5;
}
if(keys[LEFT])
{
player.x1 -= 5;
player.x2 -= 5;
}
if(keys[RIGHT])
{
player.x1 += 5;
player.x2 += 5;
}
if(player.x1 <= 0)
{
player.x1 = 0;
player.x2 = 40;
}
if(player.x2 >= WINDOW_WIDTH)
{
player.x1 = WINDOW_WIDTH - 40;
player.x2 = WINDOW_WIDTH;
}
if(player.y1 <= 0)
{
player.y1 = 0;
player.y2 = player.y1 + 40;
}
if(player.y2 >= WINDOW_HEIGHT)
{
player.y1 = WINDOW_HEIGHT - 40;
player.y2 = WINDOW_HEIGHT;
}
}
if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
{
done = true;
}
if(ev.type == ALLEGRO_EVENT_KEY_DOWN)
{
switch(ev.keyboard.keycode)
{
case ALLEGRO_KEY_ESCAPE:
done = true;
break;
case ALLEGRO_KEY_LEFT:
keys[LEFT] = true;
break;
case ALLEGRO_KEY_RIGHT:
keys[RIGHT] = true;
break;
case ALLEGRO_KEY_DOWN:
keys[DOWN] = true;
break;
case ALLEGRO_KEY_UP:
keys[UP] = true;
break;
}
}
if(ev.type == ALLEGRO_EVENT_KEY_UP)
{
switch(ev.keyboard.keycode)
{
case ALLEGRO_KEY_ESCAPE:
done = true;
break;
case ALLEGRO_KEY_LEFT:
keys[LEFT] = false;
break;
case ALLEGRO_KEY_RIGHT:
keys[RIGHT] = false;
break;
case ALLEGRO_KEY_UP:
keys[UP] = false;
break;
case ALLEGRO_KEY_DOWN:
keys[DOWN] = false;
break;
}
}
if(redraw && al_is_event_queue_empty(event_queue))
{
al_draw_filled_rectangle(player.x1,player.y1,player.x2,player.y2,al_map_rgb(0,0,127));
al_draw_filled_rectangle(lover.x1,lover.y1,lover.x2,lover.y2,al_map_rgb(127,0,0));
al_flip_display();
al_clear_to_color(al_map_rgb(255,255,255));
}
}
al_destroy_timer(timer);
al_destroy_display(display);
al_destroy_event_queue(event_queue);
return 0;
}
Can anybody help me out here? "Globals.h" is just a small header file which contains a struct for Character defining their x1, x2, y1, and y2 variables. Thanks.
As your code currently is, your redraw is not being controlled by your timer. Your redraw variable is being initialized to true, but it makes more sense to set it to false, and let your timer set it to true when appropriate. When your timer event fires, set redraw to true.
ALLEGRO_EVENT ev;
al_wait_for_event(event_queue,&ev);
if(ev.timer.source == timer)
{
redraw = true;
}
Then when you check for redraw, set it back to false.
if(redraw && al_is_event_queue_empty(event_queue))
{
redraw = false;
al_draw_filled_rectangle(player.x1,player.y1,player.x2,player.y2,al_map_rgb(0,0,127));
al_draw_filled_rectangle(lover.x1,lover.y1,lover.x2,lover.y2,al_map_rgb(127,0,0));
al_flip_display();
al_clear_to_color(al_map_rgb(255,255,255));
}