【问题标题】:Allegro program displays a black screen then crashAllegro 程序显示黑屏然后崩溃
【发布时间】:2014-06-15 22:39:51
【问题描述】:

我正在学习面向对象的编程和allegro库,所以我开始编写一个简单的菜单,但代码显示黑屏然后崩溃。

我将不胜感激有关类外观、使用标题拆分代码、代码的一般语法以及最重要的是找到代码无法解决的问题的建议。

main.cpp

#include "Menu.h"

int main() {
    Menu m;
    return 0;
}
END_OF_MAIN()

菜单.h

#ifndef MENU_H_
#define MENU_H_
#include <allegro.h>

class Menu {
    static bool isWorking;
    static const int WIDTH = 800;
    static const int HEIGHT = 600;
public:
    Menu();
    virtual ~Menu();
};

#endif

菜单.cpp

#include "MenuPointer.h"
#include "Menu.h"
#include <string>
using namespace std;

bool Menu::isWorking = true;

Menu::Menu() {
    allegro_init();
    install_keyboard();
    install_timer();
    set_color_depth(8);
    set_gfx_mode(GFX_AUTODETECT_WINDOWED, WIDTH, HEIGHT, 0, 0);
    string * menuOptions = new string[2];
    menuOptions[0] = "New Game";
    menuOptions[2] = "Exit";

    // menu pointer is an object highlighting menu options

    MenuPointer menuPointer(2, 0, WIDTH, HEIGHT/2, menuOptions);
    while (isWorking) {
        menuPointer.menuInit();
        blit(menuPointer.getBuffer(), screen, 0, 0, 0, 0, WIDTH, HEIGHT);
    }
}

Menu::~Menu() {
    allegro_exit();
    clear_keybuf();
}

MenuPointer.h

#ifndef MENUPOINTER_H_
#define MENUPOINTER_H_

#include <string>
#include <allegro.h>
using namespace std;

class MenuPointer {
    int pointerNumber;
    BITMAP * buffer;
    const int optionsNumber;
    const int pointerWidth;
    const int pointerHeight;
    BITMAP ** optionsImages;
    const string * optionsTexts;
    void paintPointer();
public:
    void menuInit();
    BITMAP * getBuffer();
    MenuPointer(int, int, int, int, BITMAP **);
    MenuPointer(int, int, int, int, const string *);
    virtual ~MenuPointer();
};

#endif

MenuPointer.cpp

#include "MenuPointer.h"
#include "Menu.h"
#include <string>
using namespace std;


// this constructor creates menu pointer when options are array of images
MenuPointer::MenuPointer(int i, int j, int k, int l, BITMAP ** optionsImages)
    :pointerNumber(j), optionsNumber(i), pointerWidth(k), pointerHeight(l) {
    buffer = create_bitmap(pointerWidth, pointerHeight);
    optionsTexts = NULL;
    this->optionsImages = optionsImages;
}

// this constructor creates menu pointer when options are array of text
MenuPointer::MenuPointer(int i, int j, int k, int l, const string * optionsTexts)
    :pointerNumber(j), optionsNumber(i), pointerWidth(k), pointerHeight(l) {
        buffer = create_bitmap(pointerWidth, pointerHeight);
        optionsImages = NULL;
        this->optionsTexts = optionsTexts;
}


// draws a rectangle in the range from the beginning to the next option which highlights
void MenuPointer::paintPointer() {
    rectfill(buffer, 0, pointerNumber*pointerHeight, pointerHeight, (pointerNumber+1)*pointerHeight, makecol( 128, 30, 30 ) );
}


void MenuPointer::menuInit() {
    clear_to_color(buffer, makecol( 128, 128, 128 ));
    paintPointer();
    if (optionsTexts != NULL) {
        // converts string to char array
        for (int i = 0; i < optionsNumber; ++i) {
            char *a = new char[optionsTexts[i].size()+1];
            a[optionsTexts[i].size()] = 0;
            memcpy(a, optionsTexts[i].c_str(), optionsTexts[i].size());
            textout_ex(screen, font, a, 0, i*pointerWidth, makecol(255,0,0), -1);
        }
    } else {
        // draws option image for images array
        for (int i = 0; i < optionsNumber; ++i) {
            masked_blit(optionsImages[i], screen, 0, 0, 0, i*pointerWidth, optionsImages[i]->w, optionsImages[i]->h);
        }
    }
}

BITMAP * MenuPointer::getBuffer() {
    return buffer;
}

MenuPointer::~MenuPointer() {
    destroy_bitmap(buffer);
}

【问题讨论】:

    标签: c++ allegro


    【解决方案1】:

    始终检查返回值!尤其是当事情开始崩溃时。

    您已要求 Allegro 以 8 位色深运行。这可能会失败,即使在 32 位系统上请求 24 位也可能会失败。您可以使用 desktop_color_depth() 找出主机正在运行的内容。

    确保 set_gfx_mode() 在继续之前不会返回错误,并且所有位图都已实际加载。 (不 == 空)

    【讨论】:

      【解决方案2】:

      你有更多关于崩溃的调试信息吗?

      首先,可能导致崩溃的问题之一是对数组菜单选项的错误访问。

      string * menuOptions = new string[2];
      menuOptions[0] = "New Game";
      menuOptions[2] = "Exit"; // THIS IS WRONG
      

      你在这个循环中有泄漏:

          for (int i = 0; i < optionsNumber; ++i) {
              char *a = new char[optionsTexts[i].size()+1]; //this is never freed
              a[optionsTexts[i].size()] = 0;
              memcpy(a, optionsTexts[i].c_str(), optionsTexts[i].size());
              textout_ex(screen, font, a, 0, i*pointerWidth, makecol(255,0,0), -1);
          }
      

      各种提示:

      1. 使用 strncpy 而不是 memcpy 来复制字符串。
      2. 方法/函数参数的名称必须更清楚。 (永远不要使用 i,j,k)
      3. 我也总是喜欢在方法/函数声明中加上名称。
      4. 将循环方法从构造函数中取出。 (一个叫做 update 的方法就可以了)

      【讨论】:

        猜你喜欢
        • 2018-02-28
        • 1970-01-01
        • 1970-01-01
        • 2019-03-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-21
        • 1970-01-01
        相关资源
        最近更新 更多