下面是一个简单的SDL2程序,它使用SDL_Image,运行良好:
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <iostream>
// Manage error messages
void check_error_sdl(bool check, const char* message);
void check_error_sdl_img(bool check, const char* message);
// Load an image from "fname" and return an SDL_Texture with the content of the image
SDL_Texture* load_texture(const char* fname, SDL_Renderer *renderer);
int main(int argc, char** argv) {
// Initialize SDL
check_error_sdl(SDL_Init(SDL_INIT_VIDEO) != 0, "Unable to initialize SDL");
// Create and initialize a 800x600 window
SDL_Window* window = SDL_CreateWindow("Test SDL 2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
800, 600, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);
check_error_sdl(window == nullptr, "Unable to create window");
// Create and initialize a hardware accelerated renderer that will be refreshed in sync with your monitor (at approx. 60 Hz)
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
check_error_sdl(renderer == nullptr, "Unable to create a renderer");
// Set the default renderer color to corn blue
SDL_SetRenderDrawColor(renderer, 100, 149, 237, 255);
// Initialize SDL_img
int flags=IMG_INIT_JPG | IMG_INIT_PNG;
int initted = IMG_Init(flags);
check_error_sdl_img((initted & flags) != flags, "Unable to initialize SDL_image");
// Load the image in a texture
SDL_Texture *texture = load_texture("img_test.png", renderer);
// We need to create a destination rectangle for the image (where we want this to be show) on the renderer area
SDL_Rect dest_rect;
dest_rect.x = 50; dest_rect.y = 50;
dest_rect.w = 337; dest_rect.h = 210;
// Clear the window content (using the default renderer color)
SDL_RenderClear(renderer);
// Copy the texture on the renderer
SDL_RenderCopy(renderer, texture, NULL, &dest_rect);
// Update the window surface (show the renderer)
SDL_RenderPresent(renderer);
// Wait for 10 seconds
SDL_Delay(5000);
// Clear the allocated resources
SDL_DestroyTexture(texture);
IMG_Quit();
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
// In case of error, print the error code and close the application
void check_error_sdl(bool check, const char* message) {
if (check) {
std::cout << message << " " << SDL_GetError() << std::endl;
SDL_Quit();
std::exit(-1);
}
}
// In case of error, print the error code and close the application
void check_error_sdl_img(bool check, const char* message) {
if (check) {
std::cout << message << " " << IMG_GetError() << std::endl;
IMG_Quit();
SDL_Quit();
std::exit(-1);
}
}
// Load an image from "fname" and return an SDL_Texture with the content of the image
SDL_Texture* load_texture(const char* fname, SDL_Renderer *renderer) {
SDL_Surface *image = IMG_Load(fname);
check_error_sdl_img(image == nullptr, "Unable to load image");
SDL_Texture *img_texture = SDL_CreateTextureFromSurface(renderer, image);
check_error_sdl_img(img_texture == nullptr, "Unable to create a texture from the image");
SDL_FreeSurface(image);
return img_texture;
}
我编译它:
g++ -std=c++0x -Wall -pedantic sdl2_test.cpp -o sdl2_test `sdl2-config --cflags --libs` -lSDL2_image
它执行并正确显示图像。
然而,在我的游戏在同一个系统上,我得到这个错误时编译:
g++ -c frogmain.cc
In file included from level.hh:2,
from game.hh:1,
from frogmain.cc:2:
/usr/local/include/SDL2/SDL_image.h:27:10: fatal error: SDL.h: No such file or directory
#include "SDL.h"
^~~~~~~
compilation terminated.
make: *** [makefile:5: frogmain.o] Error 1
下面是我的makefile:
FrogGame: frogmain.o game.o level.o sprite.o actor.o vector.o
g++ -std=c++0x -Wall -pedantic -o FrogGame frogmain.o game.o level.o sprite.o actor.o vector.o `sdl2-config --cflags --libs` -lSDL2_image
#g++ -o FrogGame frogmain.o game.o level.o sprite.o actor.o vector.o
frogmain.o: frogmain.cc game.hh level.hh sprite.hh vector.hh
g++ -c frogmain.cc
game.o: game.cc level.hh sprite.hh actor.hh vector.hh
g++ -c game.cc
level.o: level.cc sprite.hh actor.hh vector.hh
g++ -c level.cc
actor.o: actor.cc vector.hh
g++ -c actor.cc
sprite.o: sprite.cc vector.hh
g++ -c sprite.cc
vector.o: vector.cc
g++ -c vector.cc
唯一需要SDL的类是level类,下面是.cc文件:
#include <iostream>
#include <sys/time.h>
#include <chrono>
#include "level.hh"
#include "sprite.hh"
#include "actor.hh"
#include "vector.hh"
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
using namespace std;
level::level()
{
this->levelPlaying = false;
this->levelPaused = false;
this->levelWon = false;
this->curTime = 0;
this->timeLimit = 0;
this->screen = 0;
this->renderer = 0;
this->imageArray = 0;
this->imLength = 0;
this->createScreen();
}
void level::setLevelPlaying(bool p)
{
this->levelPlaying = p;
}
bool level::getLevelPlaying()
{
return this->levelPlaying;
}
void level::setLevelPaused(bool p)
{
this->levelPlaying = p;
}
bool level::getLevelPaused()
{
return this->levelPlaying;
}
void level::setLevelWon(bool p)
{
this->levelWon = p;
}
bool level::getLevelWon()
{
return this->levelWon;
}
void level::setCurTime(int t)
{
this->curTime = t;
}
int level::getCurTime()
{
return this->curTime;
}
void level::setTimeLimit(int t)
{
this->timeLimit = t;
}
int level::getTimeLimit()
{
return this->timeLimit;
}
bool level::createScreen()
{
bool success = 0;
//get size of screen
SDL_DisplayMode dm;
SDL_GetDesktopDisplayMode(0, &dm);
if (dm.w < 1920 && dm.h < 1080)
{
screenW = dm.w;
screenH = dm.h;
}
else
{
screenW = 1920;
screenH = 1080;
}
success = this->checkSDLError(SDL_Init(SDL_INIT_EVERYTHING) == 0, "SDL Initialization failed");
this->screen = SDL_CreateWindow("Test SDL 2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
screenW, screenH, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);
success = this->checkSDLError(this->screen, "Window Initialization failed");
this->renderer = SDL_CreateRenderer(this->screen, -1, 0);
success = this->checkSDLError(this->renderer, "Renderer Initialization failed");
return success;
}
bool level::loadImageArrayToMemory(const char** imageNames, int length)
{
IMG_Init(IMG_INIT_PNG);
//allocate space for all textures
this->imageArray = new SDL_Texture*[length];
this->imLength = length;
//run through entire list
for (int i = 0; i < length; i++)
{
//load the image to a temp surface
SDL_Surface* tmp = IMG_Load(imageNames[i]);
this->checkSDLError(tmp, "Unable to load image");
//create a texture from the surface, for hardware rendering
this->imageArray[i] = SDL_CreateTextureFromSurface(this->renderer, tmp);
this->checkSDLError(imageArray[i], "Unable to create texture");
//destroy the surface
SDL_FreeSurface(tmp);
}
return 1;
}
bool level::destroyImageArrayFromMemory()
{
//loop through image array
for (int i = 0; i < this->imLength; i++)
{
//destroy the texture in each index of the array
SDL_DestroyTexture(imageArray[i]);
}
//delete the array
delete[] imageArray;
return 1;
}
bool level::loadSoundArrayToMemory()
{
//TODO
return 0;
}
bool level::destroySoundArrayFromMemory()
{
//TODO
return 0;
}
bool level::levelLoop()
{
const int TPF = 33;
auto curT = chrono::high_resolution_clock::now();
auto prevT = curT;
auto diff = 0;
vector p(4,5);
vector d(78,90);
actor a(p, d, 1, 100);
while (this->getLevelPlaying())
{
//create a destination rectangle for the images
SDL_Rect tmp;
tmp.x= 0;
tmp.y = 0;
tmp.w = 1920;
tmp.h = 1080;
//get current time
curT = chrono::high_resolution_clock::now();
//get the difference of the current time from the last time the screen was updated
diff = chrono::duration_cast<chrono::milliseconds>(curT - prevT).count();
if (diff > TPF)
{
//check for keyboard input
this->checkForInput();
//clear the screen
SDL_RenderClear(this->renderer);
//for every texture in the imageArray
for (int i = 0; i < imLength; i++)
{
tmp.x = tmp.x + 20;
tmp.y = tmp.y + 20;
// Copy the texture on the renderer
SDL_RenderCopy(this->renderer, this->imageArray[i], NULL, &tmp);
// Update the window surface (show the renderer)
SDL_RenderPresent(this->renderer);
}
prevT = curT;
//add to the current level time
this->curTime+=diff;
}
if (this->curTime > 4000)
{
this->setLevelPlaying(false);
}
}
//destroy images in memory to free up space and avoid leaks
this->destroyImageArrayFromMemory();
return this->getLevelWon();
}
void level::checkForInput()
{
cout << "inside checkforinput\n";
//create an empty event
//SDL_Event event;
//loop through all events in the queue
while (SDL_PollEvent(&event))
{
cout << "inside while loop\n";
switch(event.type)
{
//cout << "inside switch\n";
//a keyboard button is pressed down
case SDL_KEYDOWN:
cout << "inside case\n";
//if it is escape key
if (event.key.keysym.sym == SDLK_ESCAPE)
{
cout << "Escape key pressed" << endl;
this->setLevelPlaying(false);
}
else if (event.key.keysym.sym == SDLK_q)
{
cout << "Q key pressed" << endl;
}
continue;
default:
cout << "unhandled key pressed\n";
}
}
}
bool level::checkSDLError(bool c, const char* s)
{
if (c == 0)
{
std::cout << s << " " << SDL_GetError() << endl;
SDL_Quit();
return 0;
}
return 1;
}
我同时安装了SDL2和SDL2Image。我的makefile是否有问题,这就是为什么我可以在这个简单的示例中使用SDLImage,但不能在更复杂的程序中使用的原因?我还有另一个raspberry pi,其中示例和游戏的makefile都能正常工作。
2条答案
按热度按时间t3psigkw1#
当您 * 编译 *
.cc
[到.o
]时,您没有在makefile中将-I
传递到c++
。您只传递用于 link
.o
文件的c++
行上的标志。其中一个
.o
目标的c++
命令也需要sdl2-config
。那是你的当务之急不过...
当您这样做时:
sdl2-config --cflags
,它[部分]产生(例如)-I/usr/local/include/SDL2
,因此如果它产生.cc
,则源文件.cc
将工作:#include <SDL.h>
.但是,* 您的 *
.cc
文件:#include <SDL2/SDL.h>
.这可能不起作用,因为它位于不同的目录级别[除非添加
-I/usr/local/include
,这是次优的,因为您要硬连接路径]。/usr/local/include
是.h
文件路径的 * 默认 * 部分更新日期:
请原谅我不太擅长编译。我试着在一些不同的地方添加
-I/usr/local/include/SDL2/SDL.h
,但没有改变任何东西。你能为我拼得更清楚一点吗?您 * 不 * 希望:
-I/usr/local/include/SDL2/SDL.h
它指向一个 * 文件 *。您需要:
-I/usr/local/include/SDL2
它指向 * 目录 *。但是,你应该做两件事:(1)修复makefile,(2)更改
level.cc
中的#include
指令以使其兼容下面是我对makefile的调整:
如果你复制粘贴的话,
TAB
将会变成四个空格[因为代码块在SO是如何格式化的],所以你需要手动编辑来改变它(比如make
对TAB
的开头很挑剔)。在
level.cc
中,您使用的不是两个#include
指令:您需要:
qnyhuwrf2#
sudo pacman -S sdl2_image
可以修复此错误,请参阅SDL/SDL_image.h: No such file or directory