正确地在多文件项目中#CRUDING SDL

Correctly #including SDL in multi-filed project

本文关键字:#CRUDING SDL 项目 文件 正确地      更新时间:2023-10-16

我刚刚开始使用C 和SDL,我已经开始创建一个基本的突破克隆,以使我的头围绕语义。为了模块化我到目前为止的内容,我创建了两个标题文件core.hpaddle.h

我很难正确地包括SDL和这些模块。最初,当我只有主文件breakout.cpppaddle.hpaddle.cpp时,该项目编译为汇编。在此阶段,"核心"类位于breakout.cpp中,一旦我将其迁移到自己的文件中,编译器就开始感到不安。

就目前而言,这是一个非常简单的设置,可以说明如下:

breakout ---> core ---> paddle

这使我相信我正在做新秀的监督。或者我正在makefile中错误地链接文件。

这是代码:

Breakout.cpp

#include "SDL2/SDL.h"
#include "SDL2/SDL_image.h"
#include <stdio.h>
#include <string>
#include "core.h"
int main(int argc, char* args[]) {
    Core gCore;
    gCore.runGame();
    return 0;
}

core.h

#pragma once
#include "paddle.h"
class Core {
public:
    Core();
    ~Core();
    void runGame();
private:
    static const int SCREEN_WIDTH = 640, SCREEN_HEIGHT = 480;
    SDL_Window* gWindow;
    SDL_Renderer* gRenderer;
    Paddle* p1;
    void render();
};

paddle.h

#pragma once
#include <string>
class Paddle {
    friend class Core;
public:
    Paddle( SDL_Renderer* gRenderer );
    ~Paddle();
    void free();
private:
    static const int VELOCITY = 5;
    int xPos, yPos, pWidth, pHeight;
    SDL_Texture* pSprite;
    SDL_Rect* pRect;
    bool loadFromFile( SDL_Renderer* gRenderer, std::string path );
    int getXPos();  int getYPos();
    int getWidth(); int getHeight();
};

core.cpp

#include "SDL2/SDL.h"
#include "SDL2/SDL_image.h"
#include <stdio.h>
#include "paddle.h"
#include "core.h"
Core::Core() {
    // Set up SDL
    if ( SDL_Init( SDL_INIT_VIDEO ) < 0 ) {
        printf( "SDL could not initialise! SDL Error: %sn", SDL_GetError() ); 
    }
    else {
        if ( !SDL_SetHint( SDL_HINT_RENDER_SCALE_QUALITY, "1" ) ) {
            printf( "Warning: Linear texture filtering not enabled!" );
        }
        else {
            gWindow = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT,
                                        SDL_WINDOW_SHOWN );
            if ( gWindow == NULL ) {
                printf( "Could not create window. SDL Error: %sn", SDL_GetError() ); 
            }
            else {
                gRenderer = SDL_CreateRenderer( gWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC );
                if ( gRenderer == NULL ) {
                    printf( "Renderer could not be created! SDL Error: %sn", SDL_GetError() );
                }
                else {
                    // Initialise renderer colour
                    SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
                    // Initialise PNG loading
                    int imgFlags = IMG_INIT_PNG;
                    if ( !( IMG_Init( imgFlags ) & imgFlags ) ) {
                        printf( "SDL_image could not be initialised! SDL_image Error: %sn", IMG_GetError() );
                    }
                }
            }
        }
    }
}
Core::~Core() {
    SDL_DestroyRenderer( gRenderer );    gRenderer = NULL;
    SDL_DestroyWindow( gWindow );        gWindow = NULL;
    // Quit SDL subsystems
    IMG_Quit();
    SDL_Quit();
}
void Core::runGame() {
    // Main loop flag
    bool quit = false;
    // Event handler
    SDL_Event e;
    // p1 = new Paddle( gRenderer );
    while ( !quit ) {
        while( SDL_PollEvent( &e ) != 0 ) {
            //User requests quit
            if( e.type == SDL_QUIT ) {
                quit = true;
            }
        }
        // Clear screen
        SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
        SDL_RenderClear( gRenderer );
        // Render game assets
        render();
        // Update screen
        SDL_RenderPresent( gRenderer );
    }   
}
void Core::render() {
    // Set rendering space and render to screen
    SDL_Rect pRenderQuad = { p1->xPos, p1->yPos, p1->pWidth, p1->pHeight };
    // Render to screen
    SDL_RenderCopy( gRenderer, p1->pSprite, NULL, &pRenderQuad );
}

paddle.cpp

#include "SDL2/SDL.h"
#include "SDL2/SDL_image.h"
#include <stdio.h>
#include <string>
#include "paddle.h"
Paddle::Paddle(SDL_Renderer* gRenderer) {
    xPos =   300;  yPos =    400;
    pWidth =   0;  pHeight =   0;
    loadFromFile( gRenderer, "paddle.png" );
}
Paddle::~Paddle() {
    free();
}
bool Paddle::loadFromFile(SDL_Renderer* gRenderer, std::string path) {
    // Get rid of preexisting texture
    free();
    SDL_Texture* nTexture = NULL;
    SDL_Surface* lSurface = IMG_Load( path.c_str() );
    if ( lSurface == NULL ) { printf( "Unable to load image %s! SDL_image Error: %sn", path.c_str(), IMG_GetError() ); }
    else {
        nTexture = SDL_CreateTextureFromSurface( gRenderer, lSurface );
        if ( nTexture == NULL ) { printf( "Unable to load texture from %s! SDL Error: %sn", path.c_str(), SDL_GetError() ); }
        else {
            pWidth = lSurface->w;
            pHeight = lSurface->h;
        }
        SDL_FreeSurface( lSurface ); // Surface no longer needed
    }
    pSprite = nTexture;
    return pSprite != NULL;
}
void Paddle::free() {
    if ( pSprite != NULL ) {
        SDL_DestroyTexture( pSprite );
        pWidth = 0; pHeight = 0;
    }
}
// Getter methods
int Paddle::getXPos() { return xPos; }      int Paddle::getYPos() { return yPos; }
int Paddle::getWidth() { return pWidth; }   int Paddle::getHeight() { return pHeight; }

我也包括了makefile,因为那里也很容易出错。

makefile

OBJS = breakout.cpp
DEPS = paddle.h core.h
CC = g++
COMPILER_FLAGS = -w
LINKER_FLAGS = -lSDL2 -lSDL2_image
OBJ_NAME = breakout
%.o: %.cpp $(DEPS)
    $(CC) -c -o $@ $< $(COMPILER_FLAGS)
all : $(OBJS)
    $(CC) $(OBJS) $(COMPILER_FLAGS) $(LINKER_FLAGS) paddle.cpp core.cpp -o $(OBJ_NAME)

错误日志

g++ breakout.cpp -w -lSDL2 -lSDL2_image paddle.cpp core.cpp -o breakout
/tmp/cc0H2fKM.o: In function `Paddle::loadFromFile(SDL_Renderer*, std::basic_string<char, std::char_traits<char>, std::allocator<char> >)':
paddle.cpp:(.text+0x111): undefined reference to `IMG_Load'
paddle.cpp:(.text+0x121): undefined reference to `SDL_GetError'
paddle.cpp:(.text+0x15a): undefined reference to `SDL_CreateTextureFromSurface'
paddle.cpp:(.text+0x16a): undefined reference to `SDL_GetError'
paddle.cpp:(.text+0x1b8): undefined reference to `SDL_FreeSurface'
/tmp/cc0H2fKM.o: In function `Paddle::free()':
paddle.cpp:(.text+0x203): undefined reference to `SDL_DestroyTexture'
/tmp/ccDHGaLY.o: In function `Core::Core()':
core.cpp:(.text+0x12): undefined reference to `SDL_Init'
core.cpp:(.text+0x1e): undefined reference to `SDL_GetError'
core.cpp:(.text+0x44): undefined reference to `SDL_SetHint'
core.cpp:(.text+0x86): undefined reference to `SDL_CreateWindow'
core.cpp:(.text+0xa1): undefined reference to `SDL_GetError'
core.cpp:(.text+0xd1): undefined reference to `SDL_CreateRenderer'
core.cpp:(.text+0xee): undefined reference to `SDL_GetError'
core.cpp:(.text+0x127): undefined reference to `SDL_SetRenderDrawColor'
core.cpp:(.text+0x138): undefined reference to `IMG_Init'
core.cpp:(.text+0x149): undefined reference to `SDL_GetError'
/tmp/ccDHGaLY.o: In function `Core::~Core()':
core.cpp:(.text+0x17a): undefined reference to `SDL_DestroyRenderer'
core.cpp:(.text+0x195): undefined reference to `SDL_DestroyWindow'
core.cpp:(.text+0x1a5): undefined reference to `IMG_Quit'
core.cpp:(.text+0x1aa): undefined reference to `SDL_Quit'
/tmp/ccDHGaLY.o: In function `Core::runGame()':
core.cpp:(.text+0x1ea): undefined reference to `SDL_PollEvent'
core.cpp:(.text+0x218): undefined reference to `SDL_SetRenderDrawColor'
core.cpp:(.text+0x228): undefined reference to `SDL_RenderClear'
core.cpp:(.text+0x244): undefined reference to `SDL_RenderPresent'
/tmp/ccDHGaLY.o: In function `Core::render()':
core.cpp:(.text+0x2d1): undefined reference to `SDL_RenderCopy'
collect2: ld returned 1 exit status
make: *** [all] Error 1

我真的很感谢您对手头问题的支持。但是,如果可以提出有关我的代码的任何一般建议。

谢谢

编译器开关上标志的顺序很重要。

要将链接器传递给链接器的库应该是最后的。

使用-w通常没有任何意义,因为它通常是-W(Capital(,然后是某种指令,例如-werror -wall等。

建议:删除-w标志,然后将-l开关移至末端。