- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我开始使用 Allegro 5 在 C++ 的 Visual Studio 2017 中创建游戏。为了更轻松地管理图像,我创建了一个 ImageLoader 类,该类将加载和存储所有事件图像,并在必要时销毁它们。它使用将文件名与相应图像匹配的映射来实现这一点。目前我的 main() 代码如下所示:
int main(){
if (!al_init()) {
al_show_native_message_box(NULL, NULL, NULL, "Could not intialize allegro 5.", NULL, NULL);
return -1;
}
ALLEGRO_DISPLAY *display = al_create_display(DEFAULT_SCREEN_WIDTH, DEFAULT_SCREEN_HEIGHT);
al_set_window_title(display, "Game title");
// make usre the display was created correctly
if (!display) {
al_show_native_message_box(display, "Title", "settings", "Could not create Allegro window.", NULL, NULL);
}
// intialize fonts, primitives, keyboard,etc.
al_init_font_addon();
al_init_ttf_addon();
al_init_primitives_addon();
al_install_keyboard();
if(!al_init_image_addon()) {
al_show_native_message_box(display, "Error", "Error", "Failed to initialize al_init_image_addon!",
NULL, ALLEGRO_MESSAGEBOX_ERROR);
return -1;}
ImageLoader image_loader;
ImageLoader 然后为播放器加载图像:
ALLEGRO_BITMAP *image = al_load_bitmap(filename);
if (image == NULL) {
std::cout << filename << std::endl;
std::cout << "loader failed to load image" << std::endl;
}
image_map[filename] = image;
当我测试这部分时,它似乎工作正常,因为图像不为空。请注意,image_map 在 ImageLoader.h 中的声明方式如下:
std::map<const char *, ALLEGRO_BITMAP*> image_map;
当我尝试从 ImageLoader 获取图像时,问题出现在我的主游戏循环中:
for (GameImage image : imageList) {
ALLEGRO_BITMAP *draw_image = image_loader.get_current_image(image);
if (draw_image == NULL) {
//TODO: error handling
std::cout << "no image" << std::endl;
}
else
al_draw_bitmap(draw_image, image.get_x(), image.get_y(), NULL);
}
我的检查总是显示 draw_image
一片空白。这是 get_current_image 的代码:
ALLEGRO_BITMAP * ImageLoader::get_current_image(GameImage image)
{
return image_map[image.get_image_filename()];
}
我已通过检查 if (image_map.find(image.get_image_filename()) == image_map.end())
进行测试,以确保我在此处使用与加载图像并将其存储在 map 中时相同的文件名。 ,但即使这返回 false,ALLEGRO_BITMAP 指针仍然为空。我已经尝试让 map 存储位图而不是指针,但是当我尝试向 map 添加元素时这给了我一个错误,因为我不允许像这样修改 map 值。为什么这些指针在我设置它们的时间和我检索它们的时间之间会变为空?我也乐于接受有关如何存储位图的其他建议。
编辑:我修改了我的项目,将作为 char 数组的文件名实例更改为 std::strings。图像映射现在声明为 std::map<std::string, ALLEGRO_BITMAP*> image_map
在 ImageLoader.h 中,GameImage 存储的文件名现在是 std::string image_filename
. load_image
在 ImageLoader.cpp 中现在看起来像这样:
ALLEGRO_BITMAP *image = al_load_bitmap(filename.c_str());
if (image == NULL) {
std::cout << filename << std::endl;
std::cout << "loader failed to load image" << std::endl;
}
image_map[filename] = image;
最后,get_current_image
还是一样:
ALLEGRO_BITMAP * ImageLoader::get_current_image(GameImage image)
{
return image_map[image.get_image_filename()];
}
但是,同样的问题仍然存在。我还检查了图像映射的大小,它在我的程序的整个持续时间内保持在 1,我插入的图像的文件名作为键,值从指向位图的非空指针开始,并且看起来变成在某些时候为空。
编辑 2:
将字符数组更改为字符串并修复 get_current_image()
之后因此,如果找不到搜索到的文件名,它就不再添加到 map 中,我发现在将图像加载到我最初发布问题时忘记包含的行中时也犯了一个错误:
current_screen.load_images(image_loader);
事实证明,我写了load_images()
像这样:
void MainGameScreen::load_images(ImageLoader loader)
...意味着调用函数对 loader
进行的调用实际上并没有应用于我传入的 ImageLoader。我将其更改为:
void MainGameScreen::load_images(ImageLoader& loader)
...现在一切正常。
最佳答案
你的问题是,使用 const char *
作为键意味着 map
将执行直接地址比较,即“字符串的地址是否等于我保存在内存中的字符串的地址”。这几乎肯定不是您想要执行字符串比较的方式。
这个问题实际上有两种解决方案,具体取决于您的用例。第一种是简单地将 const char *
更改为 std::string
,这是最简单的解决方案,默认情况下您应该这样做。
std::map<std::string, ALLEGRO_BITMAP*> image_map;
而且,从广义上讲,无论在何处使用字符串,都应该使用 std::string
或 std::string const&
。没有理由使用其他任何东西。
...除非您关心性能。如果您正在编写游戏,性能几乎肯定是您关心的事情,这将我们带到了第二个解决方案。必须对 map 进行大量查找将调用大量比较,虽然这通常不是一个大问题,但之所以会出现,是因为每次比较都是基于字符串的完整相等性检查。
解决方案是,当您加载图像时,为每个图像分配一个唯一的 ID(例如 int64_t
或 uint64_t
),并将这些值分配给 GameImage
对象而不是文件名或路径名。然后,当您进行查找时,使用该 ID 执行查找。
这取决于你。将 const char *
替换为 std::string
几乎肯定会修复代码中的逻辑错误并使其按预期方式工作。如果您发现必须进行所有这些字符串比较会显着降低您的程序速度,那么剩下的更像是一个优化问题。
编辑:
你的新问题是 std::map
的 operator[]
函数自动插入一个默认值(在这种情况下,nullptr
) 如果它找不到任何具有所请求名称的预先存在的图像。您想要的代码看起来更像这样:
ALLEGRO_BITMAP * ImageLoader::get_current_image(GameImage image)
{
auto it = image_map.find(image.get_image_filename());
if(it == image_map.end()) return nullptr;
else return it->second;
//return image_map[image.get_image_filename()];
}
这样,找不到图像就不会诱使您使用的任何调试工具认为该位置存储了有效(空)值。
如果您想改用内置异常工具,也可以将其简化为:
ALLEGRO_BITMAP * ImageLoader::get_current_image(GameImage image)
{
//Will throw an exception if nothing is found
return image_map.at(image.get_image_filename());
}
关于c++ - 快板 5 : trouble storing bitmaps in a std map,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43746948/
嗨,我必须编写一个代码,将 NASM(汇编)与 C 和 allegro 库结合起来 CC = gcc OBJ = main.o func.o BIN = program CFLAGS = -m32 $
我的问题与 Allegro 5 C++ 有关。这是我的代码的某些部分,它们必须在屏幕上绘制文本。我已经完成了所有的声明,错误肯定在这部分代码中。 所以一开始我声明了一个全局变量ALLEGRO_FONT
我的调试文件夹中有一个名为“x.bmp”的 114x114 位图和这个简单的代码 #include BITMAP *Sprite; int main(){ allegro_init();
这是困扰我多年的问题。 这是我的game.h 和game.cpp 文件: game.h #ifndef GAME_H_INCLUDED #define GAME_H_INCLUDED #include
如何让 allegro 5 在绘图时使用抗锯齿?我需要使对角线看起来平滑。目前,它们只是阴影像素线,边缘看起来很硬。 最佳答案 为图元启用抗锯齿: // before creating the dis
这个问题困扰我好久了。当我编译这部分代码时,它在位图上方显示黑线。可能是什么问题,是否有任何解决方案? void start() { FONT *verdana; PALETTE pa
我正在尝试制作一个简单的程序,其中包含一个作为“背景”的 BITMAP 和另一个我可以移动的 BITMAP,我尝试了不同的方法,比如将背景直接绘制到屏幕上,尝试制作两个缓冲区,我尝试将两者都放入一个缓
我是 C++ 的新手,由于统一要求,我们都在使用代码块。我在 10.10.5 OS X 上使用它。现在我必须做一个使用 allegro5 库的项目,但我无法安装它!我花了很多时间尝试学习不同的教程,例
我正在尝试通过 youtube 教程学习一些 allegro 5 原则,这是我的第一个问题。 #include #include #include #include #define ScreenWid
我刚开始用 allegro 编程,但我编写的第一个简单程序检查它是否处于工作状态返回错误: "Unhandled exception at 0x0F4C590B (allegro-5.0.7-mono
我一直在研究如何使用 Allergo 5 在屏幕上绘制字符串,并且知道 al_draw-textf() 据说它的工作方式类似于 stdio.h 中的 printf() 。所以当我想在控制台窗口上打印一
我正在使用 Microsoft Visual Studio 2010,尝试使用 Allegro.h 库编写游戏代码。 重点是 我使用缓冲区通过 draw_sprite(screen,buf1,0,0)
我已经构建了一个 C++ Allegro map 编辑器。其中一个请求是要有一个日志,所以我将它放在控制台窗口中进行的每个 Action ...现在的问题是控制台窗口位于主窗口下方(使用 GFX_AU
我正在 Visual Studio 2017 中的 Allegro 5 游戏中实现操纵杆控件。我尝试过两种方式:让我的事件队列在我的主循环中监听操纵杆事件,并使用 ALLEGRO_JOYSTICK_S
我想将第三方 lisp 库保存到独立的二进制文件中?这在 Allegro CL 中是否可行(我似乎在文档中找不到任何相关信息)? 最佳答案 看起来 Allegro 有一些关于这个主题的文档 here和
我一直致力于此平台化 Allegro 5 测试,稍后我将把它变成游戏。直到现在,当我尝试使用音频播放我在 Audacity 中制作的 .ogg 文件时,Allegro 的每个附加组件都运行良好。我正在
我开始使用 Allegro 5 在 C++ 的 Visual Studio 2017 中创建游戏。为了更轻松地管理图像,我创建了一个 ImageLoader 类,该类将加载和存储所有事件图像,并在必要
使用 Allegro 5,如何在全屏模式下初始化游戏,使其符合屏幕格式(宽屏 16:9 与普通 3:4) al_create_display (w, h) 让我们选择您想要的任何比例。例如,无论屏幕大
我是游戏编程新手。这里我有一些 Sprite ,比如 Sprite 表中的马里奥 Sprite 。每个 Sprite 只有 32 x 32 像素。一个 Sprite 包含一个 Action ,马里奥的
我是一名优秀的程序员,十分优秀!