我正在使用Allegro 5在C ++游戏中工作。从将所有代码放在main.cpp中的教程中,它看起来运行正常。我已经将代码组织成了类,但我现在在运行时遇到这个错误:
“Face Chase Allegro5.exe中的第一次机会异常0x57052F4B(allegro-5.0.10-monolith-mt-debug.dll):0xC0000005:访问冲突读取位置0x00000000。 Face Chase Allegro5.exe中0x57052F4B(allegro-5.0.10-monolith-mt-debug.dll)的未处理异常:0xC0000005:访问冲突读取位置0x00000000。 程序'[6020] Face Chase Allegro5.exe'已退出,代码为0(0x0)。“
以下是一些参考代码:
GameManager.h:
#pragma once
#include <allegro5\allegro.h>
#include "Singleton.h"
#include "SceneManager.h"
#include "InputManager.h"
typedef enum GAMESTATE { TITLE, MAIN, GAME_OVER };
class GameManager : public Singleton<GameManager>
{
private:
SceneManager* m_SceneManager; //manages the level and visual elements
InputManager* m_InputManager; //manages input variables
GAMESTATE m_gameState; //whether or not the game is at the title, main game, game over, etc.
ALLEGRO_EVENT_QUEUE* m_queue; //event queue, used for storing events to al_event
ALLEGRO_TIMER* m_timer; //timer for regulating FPS
bool m_gameEnd; //for keeping track of whether or not the program should close
bool m_redraw; //when certain conditions are met, the program will redraw the screen
protected:
Singleton<GameManager> *m_GameManager;
public:
GameManager();
~GameManager();
SceneManager* getSceneManager() {return m_SceneManager;}
GAMESTATE getGameState() {return m_gameState;}
ALLEGRO_EVENT_QUEUE* getEventQueue() {return m_queue;}
ALLEGRO_TIMER* getTimer() {return m_timer;}
bool getGameEnd() {return m_gameEnd;}
bool getRedraw() {return m_redraw;}
void setGameState(GAMESTATE newState) {m_gameState = newState;}
void setQueue(ALLEGRO_EVENT_QUEUE* queue) {m_queue = queue;}
void setTimer(ALLEGRO_TIMER* timer) {m_timer = timer;}
void setGameEnd(bool gameEnd) {m_gameEnd = gameEnd;}
void doControl(ALLEGRO_EVENT* ev);
};
GameManager.cpp:
#include "GameManager.h"
const int FPS = 60;
GameManager::GameManager() //This is where I encounter access violations at 0x00000000
{
m_SceneManager = new SceneManager;
m_InputManager = new InputManager;
m_gameState = TITLE; //when the program runs it starts at the title screen
m_queue = al_create_event_queue();
m_timer = al_create_timer(1.0 / FPS);
m_gameEnd = false;
m_redraw = false;
}
GameManager::~GameManager()
{
delete m_SceneManager;
m_SceneManager = NULL;
delete m_queue;
m_queue = NULL;
delete m_timer;
m_timer = NULL;
}
void GameManager::doControl(ALLEGRO_EVENT* ev)
{
if (ev->type == ALLEGRO_EVENT_MOUSE_AXES)
m_InputManager->setMousePos(ev->mouse.x, ev->mouse.y);
//code for tracking the mouse position; I plan to add button functionality and
//a custom cursor to the title screen in due time
if (ev->type == ALLEGRO_EVENT_DISPLAY_CLOSE ||
(ev->type == ALLEGRO_EVENT_KEY_DOWN && ev->keyboard.keycode == ALLEGRO_KEY_ESCAPE))
setGameEnd(true);
//instructs the program to close if the user clicks close or presses escape
switch (getGameState()) //gets the game state for evaluation
{
case TITLE: //event handling for the title screen
{
if((ev->type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN && ev->mouse.button &1) ||
(ev->type == ALLEGRO_EVENT_KEY_DOWN && ev->keyboard.keycode == ALLEGRO_KEY_ENTER))
setGameState(MAIN);
break; //if the left button is clicked or enter is pressed, starts the main game
}
case MAIN: //event handling for main game
{
switch (ev->type)
{
case ALLEGRO_EVENT_KEY_DOWN:
switch (ev->keyboard.keycode) //handles movement of player character
{
case ALLEGRO_KEY_UP:
{
m_InputManager->setKeys(UP, true);
break;
}
case ALLEGRO_KEY_DOWN:
{
m_InputManager->setKeys(DOWN, true);
break;
}
case ALLEGRO_KEY_RIGHT:
{
m_InputManager->setKeys(RIGHT, true);
break;
}
case ALLEGRO_KEY_LEFT:
{
m_InputManager->setKeys(LEFT, true);
break;
}
}
case ALLEGRO_EVENT_KEY_UP:
{
switch (ev->keyboard.keycode)
{
case ALLEGRO_KEY_UP:
{
m_InputManager->setKeys(UP, false);
break;
}
case ALLEGRO_KEY_DOWN:
{
m_InputManager->setKeys(DOWN, false);
break;
}
case ALLEGRO_KEY_RIGHT:
{
m_InputManager->setKeys(RIGHT, false);
break;
}
case ALLEGRO_KEY_LEFT:
{
m_InputManager->setKeys(LEFT, false);
break;
}
}
}
}
}
}
bool collision;
bool* tempKeys[3];
for (int i = 0; i < 4; i++)
*tempKeys[i] = m_InputManager->getKey(i);
//updates keys array and player data
m_SceneManager->updateEntityCoords(tempKeys, collision);
}
SceneManager.h:
#pragma once
#include <iostream>
#include <allegro5\allegro.h>
#include <allegro5\allegro_audio.h>
#include <allegro5\allegro_acodec.h>
#include "InputManager.h"
#include "Entity.h"
class SceneManager
{
private:
ALLEGRO_DISPLAY* m_display; //main window display
ALLEGRO_BITMAP* m_background; //background during the main game
ALLEGRO_BITMAP* m_titleScreen; //title screen image
ALLEGRO_SAMPLE* m_titleMusic;
ALLEGRO_SAMPLE* m_bgMusic; //various sound assets
ALLEGRO_SAMPLE* m_soundDog;
ALLEGRO_SAMPLE* m_soundEat;
Entity* m_face; //player entity
Entity* m_poop;//poop entity
public:
SceneManager();
~SceneManager();
ALLEGRO_DISPLAY* getDisplay() {return m_display;}
ALLEGRO_BITMAP* getBackground() {return m_background;}
ALLEGRO_BITMAP* getTitleScreen() {return m_titleScreen;}
ALLEGRO_SAMPLE* getTitleMusic() {return m_titleMusic;}
ALLEGRO_SAMPLE* getBGM() {return m_bgMusic;}
ALLEGRO_SAMPLE* getSoundDog() {return m_soundDog;}
ALLEGRO_SAMPLE* getSoundEat() {return m_soundEat;}
Entity* getFace() {return m_face;}
Entity* getPoop() {return m_poop;}
void setDisplay(ALLEGRO_DISPLAY* display) {m_display = display;}
void setFace(Entity newFace) {*m_face = newFace;}
void setPoop(Entity newPoop) {*m_poop = newPoop;}
bool isCollision(Entity* entity1, Entity* entity2); //returns true if there is a collision
void updateEntityCoords(bool* keys[3], bool collision); //adjust player coordinates and moves the poop if it is collected
void UpdateHitbox(Entity* entity, EntityType type); //updates entity hitboxes
void BuildBackground(ALLEGRO_BITMAP* background); //builds the entire background from a single tile
void playTitleMusic()
{al_play_sample(m_titleMusic, 255, 128, 1000, ALLEGRO_PLAYMODE_LOOP, NULL);}
//title music loop when the program starts
void playMainSounds(); //main game sound loop
void updateDisplay(); //redraws the screen with updated data
};
SceneManager.cpp:
#include "SceneManager.h"
const int screenWidth = 640;
const int screenHeight = 480;
SceneManager::SceneManager()
{
m_display = al_create_display(screenWidth, screenHeight); //creates a 640 x 480 display
m_background = al_create_bitmap(640, 480);
m_titleScreen = al_load_bitmap("assets/title.bmp");
m_soundDog = al_load_sample("assets/dog.wav");
m_bgMusic = al_load_sample("assets/music.wav");
m_soundEat = al_load_sample("assets/eat.wav");
m_titleMusic = al_load_sample("assets/title.wav");
m_face = new Entity(FACE);
m_poop = new Entity(POOP);
}
SceneManager::~SceneManager()
{
delete m_display;
m_display = NULL;
delete m_background;
m_background = NULL;
delete m_titleScreen;
m_titleScreen = NULL;
delete m_titleMusic;
m_titleMusic = NULL;
delete m_bgMusic;
m_bgMusic = NULL;
delete m_soundDog;
m_soundDog = NULL;
delete m_soundEat;
m_soundEat = NULL;
delete m_face;
m_face = NULL;
delete m_poop;
m_poop = NULL;
}
bool SceneManager::isCollision(Entity* entity1, Entity* entity2)
{
if (entity1->getHitbox()->x < entity2->getHitbox()->w &&
entity1->getHitbox()->y < entity2->getHitbox()->h &&
entity1->getHitbox()->w > entity2->getHitbox()->x &&
entity1->getHitbox()->h > entity2->getHitbox()->y)
return true;
else
return false;
}
void SceneManager::updateEntityCoords(bool* keys[3], bool collision)
{
getFace()->setY(getFace()->getY() - (*keys[UP] * 7));
getFace()->setY(getFace()->getY() + (*keys[DOWN] * 7));
getFace()->setX(getFace()->getX() - (*keys[LEFT] * 7));
getFace()->setX(getFace()->getX() + (*keys[RIGHT] * 7));
if (collision) //moves poop in case of collision
{
getFace()->setScore(getFace()->getScore() + 1);
getPoop()->setX(rand() % 448);
getPoop()->setY(rand() % 608);
}
}
void SceneManager::UpdateHitbox(Entity* entity, EntityType type)
{
switch (type)
{
case FACE:
{
entity->setHitbox(entity->getX(),
entity->getY(),
entity->getX() + 64,
entity->getY() + 64);
break;
}
case POOP:
{
entity->setHitbox(entity->getX(),
entity->getY(),
entity->getX() + 32,
entity->getY() + 32);
break;
}
}
}
void SceneManager::BuildBackground(ALLEGRO_BITMAP* background)
{
ALLEGRO_BITMAP *bgtile = al_load_bitmap("assets\bg.bmp");
al_set_target_bitmap(background);
//creates a struct of type ALLEGRO_BITMAP and sets Allegro's draw
//target to it
for(int i = 0; i <= 640; i++)
{
if(i % 32 == 0)
{
for(int j = 0; j <= 480; j++)
{
if(j % 32 == 0)
{
al_draw_bitmap(bgtile, 0, 0, NULL);
std::cout << "Placed tile at " << i << ", " << j << "\n";
}
}
}
}
al_destroy_bitmap(bgtile); //destroys bgtile since the background is generated
//and bgtile will no longer be needed
}
void SceneManager::playMainSounds()
{
al_stop_samples(); //stops looping title music and plays main game music
al_play_sample(m_soundDog, 255, 128, 1000, ALLEGRO_PLAYMODE_ONCE, NULL);
al_play_sample(m_bgMusic, 255, 128, 1000, ALLEGRO_PLAYMODE_LOOP, NULL);
}
void SceneManager::updateDisplay()
{
al_set_target_backbuffer(getDisplay()); //sets target back to display's back buffer and draws the objects to it
al_draw_bitmap(m_background, 0, 0, NULL);
al_draw_bitmap(m_face->getSprite(), m_face->getX(), m_face->getY(), NULL);
al_draw_bitmap(m_poop->getSprite(), m_poop->getX(), m_poop->getY(), NULL);
}
main.cpp中:
#include <allegro5\allegro.h>
#include <allegro5\allegro_font.h>
#include <allegro5\allegro_ttf.h>
#include <allegro5\allegro_primitives.h>
#include "GameManager.h"
int main(void)
{
GameManager* manager = GameManager::getInstance();
//create game manager
if (!al_init()) //returns a value of -1 if
return -1; //Allegro does not initialize properly
if (!manager->getSceneManager()->getDisplay()) //returns -1 if the display window is
return -1; //not initialized properly
al_init_primitives_addon(); //allows for drawing basic shapes via functions
al_init_font_addon(); //allows for drawing text to the screen
al_init_ttf_addon(); //allows for drawing true type fonts
al_install_keyboard(); //gets input from keyboard
al_install_mouse(); //gets input from mouse
//registers display, keyboard, mouse, and timer as sources of events
al_register_event_source(manager->getEventQueue(), al_get_display_event_source(manager->getSceneManager()->getDisplay()));
al_register_event_source(manager->getEventQueue(), al_get_keyboard_event_source());
al_register_event_source(manager->getEventQueue(), al_get_mouse_event_source());
al_register_event_source(manager->getEventQueue(), al_get_timer_event_source(manager->getTimer()));
//starts timer for regulating FPS
al_start_timer(manager->getTimer());
//start of main loop
while (!manager->getGameEnd())
{
ALLEGRO_EVENT al_event;
al_wait_for_event(manager->getEventQueue(), &al_event);
//creates an event that catches things that happen such as key presses and mouse clicks
//and then instructs the program to wait for one of these things to happen and store it
//to al_event
manager->getSceneManager()->updateDisplay(); //update window display
manager->doControl(&al_event); //handles input and updates data accordingly
}
}
Visual Studio告诉我问题出在SceneManager.cpp的构造函数中。首先,它不喜欢m_display。如果我评论该行,它不喜欢m_background。我评论说,它不喜欢m_titleScreen,它给我一个相同的错误,每一个这些变化。所以我完全难以理解这里的问题。有什么想法吗?
答案 0 :(得分:1)
GameManager* manager = GameManager::getInstance();
//create game manager
if (!al_init()) //returns a value of -1 if
return -1; //Allegro does not initialize properly
这只是猜测,但这看起来像危险的代码。必须1>之前(几乎)每隔一个Allegro方法调用al_init()
。
确保在调用先决条件init方法之前不调用任何Allegro方法。