SDL_RenderCopy не рендерится (не NULL, нет ошибки SDL / IMG тоже) - PullRequest
0 голосов
/ 28 ноября 2018

Я пытаюсь сделать простую игру Snake.Самостоятельное столкновение и многое еще не готовы.Проблема в том, что даже без ошибок, просто отлично работает, меняя «close ()» на «endGame ()» и возвращая, перестраивая всю программу, я не смог ничего отрендерить с помощью SDL_RenderCopy.Вы увидите много ненужных вещей в моем коде и некоторые бразильско-португальские комментарии, подготовьтесь сами.

Изображение - это spritesheet размером 16x16 png, использующее цвет # ff00ff в качестве ColorKey.В этом спрайте есть только 4 спрайта, соответственно: Apple, тело Змеи, голова змеи и хвост змеи (все еще не используется).

Весь код:

#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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...