Create space between characters blitted on screen - SDL - c++

I have a bmp-file of numbers and characters. My program reads keypresses and blits the appropriate character/number from the bitmap onto the screen. The only problem is if i press 'A' - 'A' will show on screen, but if I press 'B', it will take 'A's place. So I will never have more than one character on screen.
Here's my code:
#include <SDL/SDL.h>
#include <iostream>
#include <string>
#include <vector>
#include <SDL_image/SDL_image.h>
using namespace std;
const Uint32 FRAMES_PER_SECOND = 60;
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int WIDTH = 21;
const int HEIGHT = 25;
SDL_Event sdlEvent;
char getAsciiKey(const SDL_Event &sdlEvent);
int main( int argc, char* args[] )
{
//The surfaces
SDL_Surface* image[2] = {NULL};
SDL_Surface* screen = NULL;
//Start SDL
SDL_Init( SDL_INIT_EVERYTHING );
//Set up screen
screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, 32, SDL_SWSURFACE | SDL_DOUBLEBUF );
char filename[256]; //create a large enough C-string
for(int index = 0; index < 2; index++)
{
sprintf(filename, "Text-types/Arial%d.bmp", index); //Arial0 and Arial1
//Load the image
image[index] = IMG_Load( filename );
if(image == NULL)
{
cout << "Error loading image: " << filename << endl;
exit(1);
}
}
Uint32 color = SDL_MapRGB(screen->format, 0xff,0xff,0xff); //White
SDL_FillRect(screen, &screen->clip_rect, color); //Backgroundcolor -> White
bool quit = false;
//Main program loop
while(quit == false)
{
//Process any events from the event queue - such as key presses or mouse movements
while(SDL_PollEvent(&sdlEvent))
{
if(sdlEvent.type == SDL_QUIT)
{
quit = true;
}
if (sdlEvent.type == SDL_KEYDOWN) //A key has just pressed
{
int x, y, temp;
SDL_Rect srcRect;
SDL_Rect dstRect;
//char letter = getAsciiKey(sdlEvent); //Getting keypress
temp = (static_cast<int>(getAsciiKey(sdlEvent)) - 12);
x = (temp % 20); //X-axis postion
y = (temp / 20); //Y-axis position
srcRect.x = (x - 1) * WIDTH;
srcRect.y = (y - 1) * HEIGHT;
//PIXELSIZE
srcRect.w = WIDTH;
srcRect.h = HEIGHT;
dstRect.x = 0;
dstRect.y = 0;
dstRect.w = WIDTH;
dstRect.h = HEIGHT;
SDL_BlitSurface(image[1] , &srcRect, screen, &dstRect ); //Putting image up on screen
//Update Screen
SDL_Flip( screen );
//Pause
SDL_Delay( 2000 );
}
}
}
//Free any loaded images
for(int index = 0; index < 2; index++)
{
SDL_FreeSurface( image[index] );
}
//Quit SDL
SDL_Quit();
return 0;
}
char getAsciiKey(const SDL_Event &sdlEvent)
{
char key = 0;
if(sdlEvent.key.keysym.sym >= SDLK_a && sdlEvent.key.keysym.sym <= SDLK_z)
{
if(sdlEvent.key.keysym.mod & KMOD_SHIFT)
{
key = 'A' + char(sdlEvent.key.keysym.sym - SDLK_a);
}
else
{
key = 'a' + char(sdlEvent.key.keysym.sym - SDLK_a);
}
}
else if(sdlEvent.key.keysym.sym >= SDLK_0 && sdlEvent.key.keysym.sym <= SDLK_9)
{
key = '0' + char(sdlEvent.key.keysym.sym - SDLK_0);
}
return key;
}

dstRect.x = 0;
dstRect.y = 0;
This is the position you're blitting to, and I don't see you changing it anywhere. Update it for each new character.
Also, this:
dstRect.w = WIDTH;
dstRect.h = HEIGHT;
is redundant, width and height of destination are ignored when blitting (at least the reference for SDL_BlitSurface says so).

Related

Fixing code that uses enums to organize event handling

When I ran the following code, I expected a result where pressing one of three buttons would each trigger a matching state that would render a matching image adjacent to those buttons, allowing me to rotate through fresh images at leisure with each successive button press.
Instead of that happy scenario, any initial button press skips right to the last image...or does nothing...or renders a blank white screen depending on how I fiddle with my placement of the initial state declaration and whether I place the state switch within or without the event handling switch. The whole system breaks and stops dead in its tracks. What is going on, and how do I fix it?
#include <string>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include "cleanup.h"
SDL_Window* window = NULL;
SDL_Renderer* renderer = NULL;
SDL_Rect* clip = NULL;
const int LONGBUTTON_HEIGHT = 128;
const int LONGBUTTON_WIDTH = 256;
int Screen_Width = 640;
int Screen_Height = 480;
int mouse_x;
int mouse_y;
int alphabutton_x = 0;
int alphabutton_y = 5;
int alphabutton_h = Screen_Width / 10;
int alphabutton_w = Screen_Width / 5;
int betabutton_x = 0;
int betabutton_y = 0.5 * (Screen_Width / 5) + 5;
int betabutton_h = Screen_Width / 10;
int betabutton_w = Screen_Width / 5;
int gammabutton_x = 0;
int gammabutton_y = 1 * (Screen_Width / 5) + 5;
int gammabutton_h = Screen_Width / 10;
int gammabutton_w = Screen_Width / 5;
int alpha_x = Screen_Width / 5;
int alpha_y = 0;
int alpha_h = Screen_Height;
int alpha_w = (4* Screen_Width)/5;
int beta_x = Screen_Width / 5;
int beta_y = 0;
int beta_h = Screen_Height;
int beta_w = (4* Screen_Width)/5;
int gamma_x = Screen_Width / 5;
int gamma_y = 0;
int gamma_h = Screen_Height;
int gamma_w = (4* Screen_Width)/5;
enum alphaButtonSprite {ALPHA_DEFAULT, ALPHA_HOVER, ALPHA_INACTIVE, ALPHA_PRESSED, ALPHA_TOTAL};
enum betaButtonSprite {BETA_DEFAULT, BETA_HOVER, BETA_INACTIVE, BETA_PRESSED, BETA_TOTAL};
enum gammaButtonSprite {GAMMA_DEFAULT, GAMMA_HOVER, GAMMA_INACTIVE, GAMMA_PRESSED, GAMMA_TOTAL};
enum State {ALPHA_STATE, BETA_STATE, GAMMA_STATE};
State state;
SDL_Texture* loadTexture(const std::string& file, SDL_Renderer* renderer)
{
SDL_Texture* texture = IMG_LoadTexture(renderer, file.c_str());
return texture;
}
void renderTexture(SDL_Texture* texture, SDL_Renderer* renderer, SDL_Rect dest,
SDL_Rect* clip = nullptr)
{
SDL_RenderCopy(renderer, texture, clip, &dest);
}
void renderTexture(SDL_Texture* texture, SDL_Renderer* renderer, int x, int y, int h, int w,
SDL_Rect* clip = nullptr)
{
SDL_Rect dest;
dest.x = x;
dest.y = y;
dest.h = h;
dest.w = w;
renderTexture(texture, renderer, dest, clip);
}
// Main Function
int main(int, char**)
{
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow("New Window", SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, Screen_Width, Screen_Height, SDL_WINDOW_RESIZABLE);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
SDL_Texture* longbutton_image = loadTexture("longbuttonSpriteSheet.png", renderer);
SDL_Texture* alpha_image = loadTexture("alphaImage.png", renderer);
SDL_Texture* beta_image = loadTexture("betaImage.png", renderer);
SDL_Texture* gamma_image = loadTexture("gammaImage.png", renderer);
state = BETA_STATE;
SDL_Rect alpha_clips[alphaButtonSprite::ALPHA_TOTAL];
for (int i = 0; i < alphaButtonSprite::ALPHA_TOTAL; i++)
{
alpha_clips[i].x = i * LONGBUTTON_WIDTH;
alpha_clips[i].y = 0;
alpha_clips[i].w = LONGBUTTON_WIDTH;
alpha_clips[i].h = LONGBUTTON_HEIGHT;
}
int usealpha_Clip = ALPHA_DEFAULT;
SDL_Rect beta_clips[betaButtonSprite::BETA_TOTAL];
for (int i = 0; i < betaButtonSprite::BETA_TOTAL; i++)
{
beta_clips[i].x = i * LONGBUTTON_WIDTH;
beta_clips[i].y = 4 * LONGBUTTON_HEIGHT;
beta_clips[i].w = LONGBUTTON_WIDTH;
beta_clips[i].h = LONGBUTTON_HEIGHT;
}
int usebeta_Clip = BETA_DEFAULT;
SDL_Rect gamma_clips[gammaButtonSprite::GAMMA_TOTAL];
for (int i = 0; i < gammaButtonSprite::GAMMA_TOTAL; i++)
{
gamma_clips[i].x = i * LONGBUTTON_WIDTH;
gamma_clips[i].y = 5 * LONGBUTTON_HEIGHT;
gamma_clips[i].w = LONGBUTTON_WIDTH;
gamma_clips[i].h = LONGBUTTON_HEIGHT;
}
int usegamma_Clip = GAMMA_DEFAULT;
SDL_Event e;
bool quit = false;
while (!quit)
{
while (SDL_PollEvent(&e))
{
switch (e.type)
{
case SDL_MOUSEBUTTONDOWN:
mouse_x = e.button.x;
mouse_y = e.button.y;
if ((mouse_x <= (alphabutton_x + alphabutton_w)) && (mouse_x > alphabutton_x) &&
(mouse_y <= (alphabutton_y + alphabutton_h)) && (mouse_y > alphabutton_y))
usealpha_Clip = ALPHA_PRESSED;
state = ALPHA_STATE;
if ((mouse_x <= (betabutton_x + betabutton_w)) && (mouse_x > betabutton_x) &&
(mouse_y <= (betabutton_y + betabutton_h)) && (mouse_y > betabutton_y))
usebeta_Clip = BETA_PRESSED;
state = BETA_STATE;
if ((mouse_x <= (gammabutton_x + gammabutton_w)) && (mouse_x > gammabutton_x) &&
(mouse_y <= (gammabutton_y + gammabutton_h)) && (mouse_y > gammabutton_y))
usegamma_Clip = GAMMA_PRESSED;
state = GAMMA_STATE;
break;
}
}
switch (state)
{
case ALPHA_STATE:
SDL_RenderClear(renderer);
renderTexture(longbutton_image, renderer, alphabutton_x, alphabutton_y, alphabutton_h, alphabutton_w, &alpha_clips[usealpha_Clip]);
renderTexture(longbutton_image, renderer, betabutton_x, betabutton_y, betabutton_h, betabutton_w, &beta_clips[usebeta_Clip]);
renderTexture(longbutton_image, renderer, gammabutton_x, gammabutton_y, gammabutton_h, gammabutton_w, &gamma_clips[usegamma_Clip]);
renderTexture(alpha_image, renderer, alpha_x, alpha_y, alpha_h, alpha_w, nullptr);
SDL_RenderPresent(renderer);
break;
case BETA_STATE:
SDL_RenderClear(renderer);
renderTexture(longbutton_image, renderer, alphabutton_x, alphabutton_y, alphabutton_h, alphabutton_w, &alpha_clips[usealpha_Clip]);
renderTexture(longbutton_image, renderer, betabutton_x, betabutton_y, betabutton_h, betabutton_w, &beta_clips[usebeta_Clip]);
renderTexture(longbutton_image, renderer, gammabutton_x, gammabutton_y, gammabutton_h, gammabutton_w, &gamma_clips[usegamma_Clip]);
renderTexture(beta_image, renderer, beta_x, beta_y, beta_h, beta_w, nullptr);
SDL_RenderPresent(renderer);
break;
case GAMMA_STATE:
SDL_RenderClear(renderer);
renderTexture(longbutton_image, renderer, alphabutton_x, alphabutton_y, alphabutton_h, alphabutton_w, &alpha_clips[usealpha_Clip]);
renderTexture(longbutton_image, renderer, betabutton_x, betabutton_y, betabutton_h, betabutton_w, &beta_clips[usebeta_Clip]);
renderTexture(longbutton_image, renderer, gammabutton_x, gammabutton_y, gammabutton_h, gammabutton_w, &gamma_clips[usegamma_Clip]);
renderTexture(gamma_image, renderer, gamma_x, gamma_y, gamma_h, gamma_w, nullptr);
SDL_RenderPresent(renderer);
break;
}
}
//Destroy the various items
cleanup(longbutton_image, alpha_image, beta_image, gamma_image, renderer, window);
IMG_Quit();
SDL_Quit();
return 0;
}
Found the answer to this one. In the mousebuttondown event switch cases, just put the state code before the useclip code. Why it makes a difference, I don't know, but it works. Cough...Also, doing it in the mousebuttonup switch cases instead of mousebuttondown works even better.

SDL_RenderCopy not rendering (Isn't NULL, none SDL/IMG Error too)

I'm trying to make a simple Snake game. The self collision and a lot of things aren't ready. The problem is: Even with no errors, running just fine, changing "close()" to "endGame()" and reverting, rebuilding the entire program, i could not render anything with SDL_RenderCopy. You will see many unnecessary things in my code and some Brazilian-Portuguese comments, prepare yourself.
The image is a 16x16 png spritesheet, using the color #ff00ff as ColorKey. There are only 4 sprites in this spritesheet, respectively: Apple, Snake's Body, Snake's Head and Snake's Tail (still unused).
Whole code:
#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;
}
The portion of code who should be working, but isn't:
//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);
}

C++ SDL image gets black and disappears

I started writing a little game but something with the image is not working. They're working fine at the beginning but after some moments there become black and then they disappear.
Don't be worried about the long code the relevant things with the images happen mostly in the following methods: build_mode_draw() and play_mode_draw().
I tested the program with a blue cube instead of a image and it worked fine
Probably I don't really understand how the image gets loaded
#include <SDL2/SDL.h>
#define WindowWidth 1500
#define WindowHight 800
#define ArrayGrosseBuildMode 100
#define StartFensterBlockmenge 10 // in Plockgröße bezüglich der kleineren Achse
bool end = false;
bool programm_part_run = true;
unsigned int play_mode_speed = 0;
unsigned int counter;
unsigned int counter_2;
unsigned int counter_3;
unsigned int blocksize;
unsigned int blocks_fit_in_X;
unsigned int blocks_fit_in_Y;
unsigned int play_mode_blockamount;
//unsigned int blockamount = 0;
bool build_mode_block_pos[ArrayGrosseBuildMode][ArrayGrosseBuildMode];
unsigned int play_mode_block_pos_X[WindowWidth]; // Fächer beschreiben
unsigned int play_mode_block_pos_Y[WindowHight]; // ||
//mouse variables
unsigned short int pressed_mouse_button = 0; // 0 = no , 1 = left , mouse Button pressed
unsigned int MouseX;
unsigned int MouseY;
//keyboard variables
//set window
SDL_Window* window = NULL;
//set renderer
SDL_Renderer* renderer = NULL;
//set event
SDL_Event event;
void input()
{
SDL_PollEvent(&event);
// reset variables
pressed_mouse_button = 0; // set to no mouse button pressed
switch(event.type)
{
case SDL_QUIT:
end = true;
programm_part_run = false;
break;
case SDL_MOUSEMOTION:
MouseX = event.motion.x;
MouseY = event.motion.y;
break;
case SDL_MOUSEBUTTONDOWN:
switch(event.button.button)
{
case SDL_BUTTON_LEFT:
pressed_mouse_button = 1;
break;
}
break;
case SDL_KEYDOWN:
switch(event.key.keysym.sym)
{
case SDLK_SPACE:
programm_part_run = false;
break;
}
}
}
void put_build_mode_grid_in_renderer()
{
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
for(counter = 0; counter <= blocks_fit_in_Y; counter = counter + 1)
{
SDL_RenderDrawLine(renderer,0,counter * blocksize,blocks_fit_in_X*blocksize,counter * blocksize);
}
for(counter = 0; counter <= blocks_fit_in_X; counter = counter + 1)
{
SDL_RenderDrawLine(renderer,counter * blocksize,0,counter * blocksize,blocks_fit_in_Y*blocksize);
}
}
void build_mode_draw()
{
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 0);
SDL_RenderClear(renderer);
put_build_mode_grid_in_renderer();
SDL_Surface * image = SDL_LoadBMP("stealcube.bmp");
SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer,image);
SDL_FreeSurface(image);
for(counter = 0; counter <= blocks_fit_in_X; counter = counter + 1)
{
for(counter_2 = 0; counter_2 <= blocks_fit_in_Y; counter_2 = counter_2 + 1)
{
if(build_mode_block_pos[counter][counter_2] == true)
{
SDL_Rect dstrect = { counter * blocksize, counter_2 * blocksize, blocksize, blocksize};
SDL_RenderCopy(renderer, texture, NULL, &dstrect);
}
}
}
SDL_RenderPresent(renderer);
}
void build_mode()
{
while(programm_part_run)
{
input();
if(pressed_mouse_button == 1)
{
build_mode_block_pos[MouseX/blocksize][MouseY/blocksize] = true;
}
build_mode_draw();
}
}
void play_mode_draw()
{
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 0);
SDL_RenderClear(renderer);
SDL_Surface * image = SDL_LoadBMP("stealcube.bmp");
SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer,image);
SDL_FreeSurface(image);
for(counter = 0; counter < play_mode_blockamount; counter = counter + 1)
{
SDL_Rect dstrect = { play_mode_block_pos_X[counter], play_mode_block_pos_Y[counter], blocksize, blocksize};
SDL_RenderCopy(renderer, texture, NULL, &dstrect);
}
SDL_RenderPresent(renderer);
}
void play_mode()
{
counter_3 = 0;
for(counter = 0; counter <= blocks_fit_in_X; counter = counter + 1)
{
for(counter_2 = 0; counter_2 <= blocks_fit_in_Y; counter_2 = counter_2 + 1)
{
if(build_mode_block_pos[counter][counter_2] == true)
{
play_mode_block_pos_X[counter_3] = counter*blocksize;
play_mode_block_pos_Y[counter_3] = counter_2*blocksize;
counter_3 = counter_3 + 1;
}
}
}
play_mode_blockamount = counter_3;
while(programm_part_run)
{
for(counter = 0; counter < play_mode_speed; counter = counter + 1)
{
input();
SDL_Delay(1);
}
for(counter = 0; counter <= play_mode_blockamount; counter = counter + 1)
{
if(play_mode_block_pos_Y[counter] < blocks_fit_in_Y * blocksize - blocksize)
{
play_mode_block_pos_Y[counter] = play_mode_block_pos_Y[counter] + 1;
}
}
play_mode_draw();
}
}
int main (int argc, char** argv)
{
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow
(
"Test Fenster :)", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
WindowWidth,
WindowHight,
SDL_WINDOW_SHOWN
);
renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED);
//setup
if(WindowWidth < WindowHight)
{
blocksize = WindowWidth/StartFensterBlockmenge;
}
else
{
blocksize = WindowHight/StartFensterBlockmenge;
}
blocks_fit_in_X = WindowWidth/blocksize;
blocks_fit_in_Y = WindowHight/blocksize;
while(!end)
{
programm_part_run = true;
build_mode();
programm_part_run = true;
play_mode();
}
}

Collision with more than 1 Object SDL 2.0-C++

I'am new there. I've been learning classes and tried to make a very simple platform game. But I have problem now. I've wanted to set Class "Player" to collide with 2 objects of Class "Block" But Collision do not work for one of them.
Here is my code:
#include <iostream>
#include <SDL.h>
#include <SDL_image.h>
#undef main
class Block
{
private:
SDL_Texture *BlockTexture;
public:
Block(SDL_Renderer *renderTarget, std::string filePath, int xPos, int yPos, int Width, int Height);
~Block();
void Draw(SDL_Renderer *renderTarget);
SDL_Rect BlockPos;
};
Block::Block(SDL_Renderer *renderTarget, std::string filePath, int xPos, int yPos, int Width, int Height)
{
SDL_Surface *surface = IMG_Load(filePath.c_str());
{
BlockTexture = SDL_CreateTextureFromSurface(renderTarget, surface);
}
SDL_FreeSurface(surface);
BlockPos.x = xPos;
BlockPos.y = yPos;
BlockPos.w = Width;
BlockPos.h = Height;
}
Block::~Block()
{
SDL_DestroyTexture(BlockTexture);
}
void Block::Draw(SDL_Renderer *renderTarget)
{
SDL_RenderCopy(renderTarget, BlockTexture, NULL, &BlockPos);
}
class Player
{
private:
SDL_Texture *Texture;
float moveSpeed;
float jumpSpeed;
int falling = 0;
SDL_Scancode keys [3];
public:
SDL_Rect PlayerPos;
Player(SDL_Renderer *renderTarget, std::string filePath, int PosX, int PosY, int Width, int Height);
~Player();
void Update(float delta, const Uint8 *Keystate);
void Draw(SDL_Renderer *renderTarget);
bool Collision(Block &p);
};
Player::Player(SDL_Renderer *renderTarget, std::string filePath, int PosX, int PosY, int Width, int Height)
{
SDL_Surface *surface = IMG_Load(filePath.c_str());
{
Texture = SDL_CreateTextureFromSurface(renderTarget, surface);
}
SDL_FreeSurface(surface);
PlayerPos.x = PosX;
PlayerPos.y = PosY;
PlayerPos.w = Width;
PlayerPos.h = Height;
keys[0] = SDL_SCANCODE_UP;
keys[1] = SDL_SCANCODE_LEFT;
keys[2] = SDL_SCANCODE_RIGHT;
moveSpeed = 200.f;
jumpSpeed = 100.f;
}
Player::~Player()
{
SDL_DestroyTexture(Texture);
}
void Player::Update(float delta, const Uint8 *KeyState)
{
if(KeyState[keys[0]])
{
PlayerPos.y -= moveSpeed * delta;
}
if(KeyState[keys[1]])
{
PlayerPos.x -= (moveSpeed / 2) * delta;
}
if(KeyState[keys[2]])
{
PlayerPos.x += moveSpeed * delta;
}
if(falling == 0)
{
PlayerPos.y += jumpSpeed * delta;
}
}
void Player::Draw(SDL_Renderer *renderTarget)
{
SDL_RenderCopy(renderTarget, Texture, NULL, &PlayerPos);
}
bool Player::Collision(Block &p)
{
if(PlayerPos.x + PlayerPos.w <= p.BlockPos.x || PlayerPos.x >= p.BlockPos.x + p.BlockPos.w ||
PlayerPos.y + PlayerPos.h <= p.BlockPos.y || PlayerPos.y >= p.BlockPos.y + p.BlockPos.h)
{
falling = 0;
return true;
}
else
falling = 1;
return false;
}
SDL_Texture *LoadTexture(std::string filePath, SDL_Renderer *Renderer)
{
SDL_Texture *texture = NULL;
SDL_Surface *surface = IMG_Load(filePath.c_str());
{
texture = SDL_CreateTextureFromSurface(Renderer, surface);
}
SDL_FreeSurface(surface);
return texture;
}
int main(int argc, char *argv[])
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window *window = SDL_CreateWindow("Platform", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_SHOWN);
SDL_Renderer *renderTarget = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
int imgFlags = IMG_INIT_PNG;
int currentTime = 0;
int previousTime = 0;
float delta = 0;
const Uint8 *Keystate;
Player Player(renderTarget, "BlockP.png", 100, 100, 50, 50);
Block Block1(renderTarget, "Block.png", 0, 500, 800, 100);
Block Block2(renderTarget, "Block.png", 100, 300, 300, 50);
bool isRunning = true;
SDL_Event ev;
while(isRunning)
{
Keystate = SDL_GetKeyboardState(NULL);
Player.Collision(Block1);
Player.Collision(Block2);
previousTime = currentTime;
currentTime = SDL_GetTicks();
delta = (currentTime - previousTime) / 1000.0f;
Player.Update(delta, Keystate);
while(SDL_PollEvent(&ev) != 0)
{
if(ev.type == SDL_QUIT)
isRunning = false;
}
SDL_RenderClear(renderTarget);
Player.Draw(renderTarget);
Block1.Draw(renderTarget);
Block2.Draw(renderTarget);
SDL_RenderPresent(renderTarget);
}
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderTarget);
window = NULL;
renderTarget = NULL;
SDL_Quit();
return 0;
}
The problem with your code is that each call to Player.Collision overwrites the "falling" variable.
Player.Collision(Block1); //this call calculates a falling value
Player.Collision(Block2); //...then this call overwrites falling with a new value
So effectively your code is only testing if the player is colliding with Block2, so collisions with Block1 are ignored.
Currently your Collision function is:
bool Player::Collision(Block &p)
{
if(PlayerPos.x + PlayerPos.w <= p.BlockPos.x || PlayerPos.x >= p.BlockPos.x + p.BlockPos.w ||
PlayerPos.y + PlayerPos.h <= p.BlockPos.y || PlayerPos.y >= p.BlockPos.y + p.BlockPos.h)
{
falling = 0;
return true;
}
else
falling = 1;
return false;
}
Firstly, your "return false;" is not actually part of the else, as you don't have {}. In this particular case it makes no difference as the else is exited and then the return happens but your indentation would suggest you expect the "return false;" line to be executed as part of the else block so you should put:
else
{
falling = 1;
return false;
}
Next you want to say if you have already detected a collision (eg, with Block1) then don't set falling to 1, to do this add an if statement.
else
{
if(falling != 0) //if we haven't already detected a collision this frame
{
falling = 1;
}
return false;
}
You will however need to set falling back to 1 at the start of each frame, otherwise if a collision is detected on one frame then the player will never fall on subsequent frames, even if they are not colliding with a block.
As a side note, your Player.Update code modifies the player's y position if falling == 0, this seems counter intuitive as usually 0 is false and 1 is true, hence you seem to be saying if not falling then update y, where as it should be if falling update y. Personally I would use a bool rather than an int to hold the value of falling, and then say if(falling) update y, this would make your code clearer.

C++, SDL, function doesnt seem to change main surface after first launch

Here is the code of draw()
My problem is that it draws things only once, then it draws the same.
I am using SLD_Flip(surface) after it.
sqrbmp, applebmp, blank are surfaces with BMP loaded
des is a rectangle
screen is main surface
It is supposed to draw a game map.
Where is my bad?
// includes, defines etc.
const int mapx = 32; // 640 / 20(bmp size)
const int mapy = 24; // 480 / 20
//nothing important
SDL_Event keys;
SDL_Surface * screen = NULL;
SDL_Surface * blank = NULL;
SDL_Surface * sqrbmp = NULL;
SDL_Surface * applebmp = NULL;
SDL_Rect des;
int map[mapy][mapx];
// nothing important
// nothing important
struct square
{
square(int xt, int yt, int dirt);
int x;
int y;
int dir;
};
std::vector <square> snake;
square::square(int xt, int yt, int dirt)
{
x = xt;
y = yt;
dir = dirt;
snake.push_back(*this);
}
bool squareontile(int x, int y)
{
// returns true if there is square on that tile
}
void draw()
{
for(int yt = 0 ; yt < mapy; yt++)
{
for(int xt = 0 ; xt < mapx; xt++)
{
des.y = yt * 20;
des.x = xt * 20;
if(squareontile(xt,yt) == 1)
{
SDL_BlitSurface(sqrbmp, NULL, screen, &des);
}
else
{
switch(map[yt][xt])
{
case 5:
SDL_BlitSurface(applebmp, NULL, screen, &des);
break;
default:
SDL_BlitSurface(blank, NULL, screen, &des);
break;
}
}
}
}
}
// nothing important
void checkmap()
{
for(int yt = 0 ; yt < mapy; yt++)
{
for(int xt = 0 ; xt < mapx; xt++)
{
if(squareontile(xt,yt) == 0 && map[yt][xt] != 5)
{
map[yt][xt] = 0;
}
}
}
}
bool checksnake()
{
for(int a = 0; a < snake.size() ; a++)
{
for(int b = 0; b < snake.size() ; b++)
{
if(snake[a].y == snake[b].y && snake[a].x == snake[b].x && a != b)
{
return true;
}
}
}
}
// nothing important
void apple()
{
if(!appleisonmap())
{
int y;
int x;
do
{
y = rand() % mapy;
x = rand() % mapx;
} while(squareontile(x,y));
map[y][x] = 5;
}
}
// nothing important
int main( int argc, char * args[] )
{
// nothing important
SDL_Init( SDL_INIT_EVERYTHING );
screen = SDL_SetVideoMode( 640, 480, 24, SDL_SWSURFACE );
applebmp = SDL_LoadBMP("apple.bmp"); // 20x20
blank = SDL_LoadBMP("blank.bmp"); // 20x20
sqrbmp = SDL_LoadBMP( "sqr.bmp" ); // 20x20
for(int b = 7 ; b > 0 ; b--)
{
square(5,b,1);
}
while(!exitv && !game_over)
{
draw();
game_over = checksnake();
SDL_Flip( screen );
SDL_Delay(100);
while( SDL_PollEvent( & keys ) )
{
if( keys.type == SDL_QUIT )
{
exitv = true;
}
// detecting other keys, input for moving, ya know
}
checkmap();
apple();
checksquare();
}
SDL_FreeSurface( sqrbmp );
SDL_FreeSurface( applebmp );
SDL_FreeSurface( blank );
SDL_Quit();
return 0;
}
Ahh found the error. I just forgot 1 function and the snake wasnt moving.