SDL_RenderCopy不呈现(不是NULL,也没有SDL / IMG错误)

时间:2018-11-28 02:29:55

标签: c++ textures sdl-2 renderer

我正在尝试制作一个简单的Snake游戏。自我碰撞和很多事情还没有准备好。问题是:即使没有错误,运行也很好,将“ close()”更改为“ endGame()”,并还原,重建整个程序,我无法使用SDL_RenderCopy渲染任何内容。您会在我的代码中看到许多不必要的内容,并看到一些巴西葡萄牙语的注释,请做好准备。

图片是16x16 png的s​​pritesheet,使用颜色#ff00ff作为ColorKey。此Spritesheet中分别只有4个Sprite:Apple,Snake的主体,Snake的头部和Snake的尾巴(仍未使用)。

整个代码:

#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>

using namespace std;

const int CELL_SIZE = 16;
const int CELL_WIDTH = 16;
const int CELL_HEIGHT = 16;
const int SCREEN_WIDTH = CELL_SIZE * (CELL_WIDTH-1);
const int SCREEN_HEIGHT = CELL_SIZE * (CELL_HEIGHT-1);

SDL_Window* gWindow = NULL;
SDL_Renderer* gRenderer = NULL;

void loadTexture(string path);

SDL_Texture* spriteSheet = NULL;

void loadMedia();
void init();


class Snake {
    int initialLength = 3; //from body (head incluse)
    int length = initialLength;
    int facing = DIR_UP;

    //Head position in CELLS (multiplied for CELL_SIZE when drawed)
    int x = 5;
    int y = 5;

    //UNUSED TEMPORARY COLORS - IGNORE
    Uint8 color[3] = {0x22,0x88,0x44}; //Snake Color, em RGB
    Uint8 headColor[3] = {0x11,0x44,0x44}; //Color for the Head of the Snek

    int stepDelay = 60; //time in frames that the Snakes waits till move
    int stepFramesRemaining = stepDelay;
    int stepDelayReduction = 1; //reduces stepDelay every time the Snakes eats the apple
    const int minStepDelay = 15; //the minimum delay

    //For clipping the image (its an 16x16 png image)
    const SDL_Rect clipHead = {0,8,8,8};
    const SDL_Rect clipBody = {8,0,8,8};
    const SDL_Rect clipTail = {8,8,8,8};

    public:
        enum direction { //direções nas quais a cobra pode se mover
            DIR_UP,
            DIR_RIGHT,
            DIR_DOWN,
            DIR_LEFT
        };

        /* The following var stores the entire Snake's body in an 2D Array. The number stored means how much "steps" it will survive.
            When the value is zero, it means that there is no body in the place. The bodypart with value equivalent to "length" is the Head.
         */
        int body[CELL_WIDTH][CELL_HEIGHT];

        void init(); //initializes some vars
        void tick(); //tick function
        void stepFoward(); //moves Snake foward
        void faceTo(int dir); //alters which direction Snake is faced
        void eat(); //eats the apple
        void draw(); //renders (or at least tries) to render the snake

        int getLength(){
            return length;
        };

        int getFacing(){
            return facing;
        };
} Snake;

class Food {
    Uint8 color[3] = {0x85,0x22,0x10}; //RGB color of the Apple
    bool visible = true;

    public:
        int x = 2;
        int y = 2;

        void respawn();
        void destroy();
        void draw();
} Food;

void Food::respawn(){
    //teleports the apple to a random spot
    x = rand() % (CELL_WIDTH-2);
    y = rand() % (CELL_HEIGHT-2);
    visible = true;
}

void Food::destroy(){
    //Reset values
    x = 0;
    y = 0;
    visible = false;

    //resets
    respawn();
}

void Food::draw(){
    if(visible){
        SDL_Rect rect = {x*CELL_SIZE,y*CELL_SIZE,CELL_SIZE,CELL_SIZE};

        SDL_SetRenderDrawColor(gRenderer,color[0],color[1],color[2],0xff);
        SDL_RenderFillRect(gRenderer, &rect);
    }
}

void Snake::init(){
    //Spawns in a vertical line
    for(int i=0; i<length; i++){
        body[x][y+i] = length-i;
    }
}

void Snake::tick(){
    if(stepFramesRemaining > 0){
        stepFramesRemaining--;
    } else {
        //when 0, moves the snake
        stepFramesRemaining = stepDelay;

        stepFoward();
    }
}

void Snake::eat(){

    //increases the body size by 1
    for(int i=0; i<CELL_HEIGHT; i++){
        for(int j=0; j<CELL_WIDTH; j++){
            if(body[j][i] > 0){
                body[j][i]++;
            }
        }
    }
    length++;

    if(stepDelay > minStepDelay){
        stepDelay -= stepDelayReduction;
    }

    Food.destroy();
}

void Snake::draw(){
    //SDL_SetRenderDrawColor(gRenderer,color[0],color[1],color[2],0xff);
    SDL_Rect rect = {0,0,0,0}; //for later use

    //Draws the body and head
    for(int i=0; i<CELL_HEIGHT; i++){
        for(int j=0; j<CELL_WIDTH; j++){
            if(body[j][i] == length){
                rect = {j*CELL_SIZE,i*CELL_SIZE,CELL_SIZE,CELL_SIZE};

                SDL_SetRenderDrawColor(gRenderer,0x33,0xff,0x22,0xff);
                SDL_RenderFillRect(gRenderer,&rect);

                SDL_RenderCopy(gRenderer, spriteSheet, &clipHead, &rect);

            } else if (body[j][i] > 0){
                rect = {j*CELL_SIZE,i*CELL_SIZE,CELL_SIZE,CELL_SIZE};
                //SDL_SetRenderDrawColor(gRenderer,color[0],color[1],color[2],0xff);

                SDL_RenderCopyEx(gRenderer, spriteSheet, &clipBody, &rect, 0, NULL, SDL_FLIP_NONE);

                SDL_SetRenderDrawColor(gRenderer,0x66,0xee,0x22,0xff);
                SDL_RenderFillRect(gRenderer,&rect);
            }

            SDL_RenderFillRect(gRenderer,&rect);
        }
    }

    //SDL_RenderFillRect(gRenderer,&rect);
}

void Snake::stepFoward(){
    int headMoved = 0; //informs if the head already moved

    //decreases the "body" lifespan and moves head
    for(int i=0; i<CELL_HEIGHT; i++){
        for(int j=0; j<CELL_WIDTH; j++){
            if(body[j][i] > 0){
                //Verifica se é a cabeça, para movê-la logo em seguida
                if(body[j][i] == length && headMoved < 2){
                    //moves head position, looping if needed
                    switch(facing){
                    case DIR_UP:
                        if(y == 0){
                            body[x][CELL_HEIGHT-1] = length;
                            y = CELL_HEIGHT-1;
                        } else {
                            body[x][y-1] = length;
                            y--;
                        }
                        break;
                    case DIR_DOWN:
                        if(y == CELL_HEIGHT-2){
                            body[x][0] = length+1; //(+1 to avoid being subtracted twice)
                            y = 0;
                        } else {
                            body[x][y+1] = length+1;
                            y++;
                        }
                        break;
                    case DIR_LEFT:
                        if(x == 0){
                            body[CELL_WIDTH-1][y] = length;
                            x = CELL_WIDTH-1;
                        } else {
                            body[x-1][y] = length;
                            x--;
                        }
                        break;
                    case DIR_RIGHT:
                        if(x == CELL_WIDTH-2){
                            body[0][y] = length+1; //avoiding again the "-2" subtraction.
                            x = 0;
                        } else {
                            body[x+1][y] = length+1;
                            x++;
                        }
                        break;
                    }

                    headMoved++;
                }
                body[j][i]--; //decreases the "body" lifespan
            }
        }
    }

    //verifies if can eat (head in the same position as the apple)
    if(x == Food.x && y == Food.y){
        eat();
    }
}

void Snake::faceTo(int dir){
    facing = dir;
}

void init();

void close();

void init(){ //Initializes the game
    gWindow = SDL_CreateWindow("· Snake ·", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
    gRenderer = SDL_CreateRenderer( gWindow, -1, SDL_RENDERER_ACCELERATED );
    if( gRenderer == NULL ){
        printf( "Renderer could not be created! SDL Error: %s\n", SDL_GetError() );
    }

    int imgFlags = IMG_INIT_PNG;
    if(!(IMG_Init(imgFlags) & imgFlags)){
        cout << "IMG INIT error!" << endl;
    }

    loadMedia();
    Snake.init();
}

void close(){ //Closes the program
    SDL_DestroyTexture(spriteSheet);
    spriteSheet = NULL;
    SDL_DestroyRenderer(gRenderer);
    gRenderer = NULL;

    IMG_Quit();
    SDL_Quit();
}

void loadTexture(string path){ //Almost the same function from LazyFoo tutorial
    //The final texture
    SDL_Texture* newTexture = NULL;

    //Load image at specified path
    SDL_Surface* loadedSurface = IMG_Load( path.c_str() );
    if( loadedSurface == NULL )
    {
        printf( "Unable to load image %s! SDL_image Error: %s\n", path.c_str(), IMG_GetError() );
    }
    else
    {
        //Color key image
        SDL_SetColorKey( loadedSurface, SDL_TRUE, SDL_MapRGB( loadedSurface->format, 0xff, 0x00, 0xff));

        //Create texture from surface pixels
        newTexture = SDL_CreateTextureFromSurface( gRenderer, loadedSurface);
        if( newTexture == NULL ){
            printf( "Unable to create texture from %s! SDL Error: %s\n", path.c_str(), SDL_GetError() );
        }

        //Get rid of old loaded surface
        SDL_FreeSurface( loadedSurface );
    }

    spriteSheet = newTexture;
}

void loadMedia(){ //loads everything (it will load sound too, when i make the sounds of course)
    loadTexture("spritesheet.png");
    if(spriteSheet == NULL){
        cout << "ERRO" << endl;
    }
}

void tick(){ 
    Snake.tick();
}

void draw(){ //Render Function
    //Background
    SDL_SetRenderDrawColor(gRenderer, 0xee, 0xf2, 0xf0, 0xff);
    SDL_RenderClear(gRenderer);

    Snake.draw();
    Food.draw();

    //Aplica as alterações
    SDL_RenderPresent(gRenderer);
}

int main(){
    srand (time (NULL));
    init();

    bool quit = false;
    SDL_Event e; //Event Handling
    while(!quit){
        while(SDL_PollEvent(&e) != 0){
            if(e.type == SDL_QUIT){
                quit = true;
            } else if(e.type == SDL_KEYDOWN){
                switch(e.key.keysym.sym){
                case SDLK_UP:
                    Snake.faceTo(Snake.DIR_UP);
                    break;
                case SDLK_DOWN:
                    Snake.faceTo(Snake.DIR_DOWN);
                    break;
                case SDLK_LEFT:
                    Snake.faceTo(Snake.DIR_LEFT);
                    break;
                case SDLK_RIGHT:
                    Snake.faceTo(Snake.DIR_RIGHT);
                    break;
                }
            }
        }

        //Tick function
        tick();

        //Renders everything
        draw();

        SDL_RenderCopy(gRenderer, spriteSheet, NULL, NULL);

        //Slows down the program just a bit (its not a time based frame system... yet)
        SDL_Delay(3);
    }

    close(); //ends
    return 0;
}

应该工作的代码部分,但不是:

//Draws the body and head
    for(int i=0; i<CELL_HEIGHT; i++){
        for(int j=0; j<CELL_WIDTH; j++){
            if(body[j][i] == length){
                rect = {j*CELL_SIZE,i*CELL_SIZE,CELL_SIZE,CELL_SIZE};

                SDL_SetRenderDrawColor(gRenderer,0x33,0xff,0x22,0xff);
                SDL_RenderFillRect(gRenderer,&rect);

                SDL_RenderCopy(gRenderer, spriteSheet, &clipHead, &rect);

            } else if (body[j][i] > 0){
                rect = {j*CELL_SIZE,i*CELL_SIZE,CELL_SIZE,CELL_SIZE};
                //SDL_SetRenderDrawColor(gRenderer,color[0],color[1],color[2],0xff);

                SDL_RenderCopyEx(gRenderer, spriteSheet, &clipBody, &rect, 0, NULL, SDL_FLIP_NONE);

                SDL_SetRenderDrawColor(gRenderer,0x66,0xee,0x22,0xff);
                SDL_RenderFillRect(gRenderer,&rect);
            }

            SDL_RenderFillRect(gRenderer,&rect);
        }
    }

    //SDL_RenderFillRect(gRenderer,&rect);
}

0 个答案:

没有答案