SDL2 Getting weird colors - c++

I'm creating a simple tile-based game using SDL2. I've drawn my tiles on two layers. The problem is the second layer which as you can see with the image below for some reason tiles with something already drawn underneath have a reddish tint. The corner and side tiles for the grass should be exactly the same color, for example.
Here's an image of my problem:
Here's my tilesheet:
And here is my code:
#include <iostream>
#include <string>
#include <SDL.h>
#include <SDL_image.h>
//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 640;
//The window we'll be rendering to
SDL_Window* window = NULL;
//The surface contained by the window
SDL_Surface* screenSurface = NULL;
//Holds built base layer of tilemap.
SDL_Surface* baseLayer = NULL;
//Map Data array
char mapLayerOne[20][20] = {
{4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 },
{4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 },
{4,4,4,6,6,6,6,6,6,4,4,4,4,4,4,4,4,4,4,4 },
{4,4,4,6,8,8,6,6,6,6,6,6,6,4,4,4,4,4,4,4 },
{4,4,4,6,8,8,6,6,6,6,6,6,6,4,4,4,4,4,4,4 },
{4,4,4,6,6,8,6,6,6,6,6,6,6,4,4,4,4,4,4,4 },
{4,4,4,6,6,8,8,8,8,6,6,6,6,6,4,4,4,4,4,4 },
{4,4,4,6,6,6,6,6,8,6,6,6,6,6,6,4,4,4,4,4 },
{4,4,4,6,6,14,6,6,8,8,6,6,6,6,6,4,4,4,4,4 },
{4,4,4,6,14,16,14,6,6,8,6,6,6,6,6,4,4,4,4,4 },
{4,4,4,14,16,16,16,12,8,8,8,8,6,6,6,4,4,4,4,4 },
{4,4,4,6,16,16,16,6,6,6,6,8,8,8,6,4,4,4,4,4 },
{4,4,4,6,6,16,6,6,6,6,6,6,6,8,6,4,4,4,4,4 },
{4,4,13,6,6,6,6,6,6,6,6,6,6,8,6,4,4,4,4,4 },
{4,4,4,14,14,14,14,14,14,14,14,14,14,14,14,15,4,4,4,4 },
{4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 },
{4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 },
{4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 },
{4,4,4,4,4,4,4,4,4,4,4,4,6,6,6,6,4,4,4,4 },
{4,4,4,4,4,4,4,4,4,4,4,6,6,6,6,6,4,4,4,4 }
};
char mapLayerTwo[20][20] = {
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,1,2,2,2,2,2,3,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,5,0,0,0,0,0,0,2,2,2,2,3,0,0,0,0,0,0 },
{ 0,0,5,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0 },
{ 0,0,5,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0 },
{ 0,0,5,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0 },
{ 0,0,5,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0 },
{ 0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0 },
{ 0,0,5,0,0,10,0,0,0,0,0,0,0,0,0,7,0,0,0,0 },
{ 0,0,5,0,11,18,9,0,0,0,0,0,0,0,0,7,0,0,0,0 },
{ 0,0,5,7,19,0,12,12,0,0,0,0,0,0,0,7,0,0,0,0 },
{ 0,0,5,0,3,0,1,0,0,0,0,0,0,0,0,7,0,0,0,0 },
{ 0,0,5,0,0,2,0,0,0,0,0,0,0,0,0,7,0,0,0,0 },
{ 0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0 },
{ 0,0,17,9,10,10,10,10,10,10,10,10,10,12,10,11,0,0,0,0 },
{ 0,0,0,17,18,18,18,18,18,18,18,18,18,12,18,19,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,1,2,12,2,3,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,5,0,8,0,0,3,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,1,0,0,8,0,0,7,0,0,0 }
};
bool init();
void DrawTiles(SDL_Surface *image, char mapLayer);
int main(int argc, char* args[])
{
//Main loop flag
bool quit = false;
//Event handler
SDL_Event e;
if(init())
{
//Load images
SDL_Surface *image = IMG_Load("Images/TileSheet_01.png");
if (!image)
std::cout << "Failed to load TileSheet_01.png!" << std::endl;
//Create BaseLayers of map
DrawTiles(image, 1);
DrawTiles(image, 2);
//While application is running
while (!quit)
{
//Handle events on queue
while (SDL_PollEvent(&e) != 0)
{
//User requests quit
if (e.type == SDL_QUIT)
quit = true;
}
//Get window surface
screenSurface = SDL_GetWindowSurface(window);
//Blit base layer of map to screenSurface
SDL_BlitSurface(baseLayer, NULL, screenSurface, NULL);
//Update the surface
SDL_UpdateWindowSurface(window);
//Delay in milliseconds to improve performance
SDL_Delay(1);
}
}
//Destroy window
SDL_DestroyWindow(window);
//Quit SDL subsystems
SDL_Quit();
return 0;
}
void DrawTiles(SDL_Surface *image, char mapLayer)
{
SDL_Rect baseTile[20];
int tileX = 0;
int tileY = 0;
for (int i = 1; i < 20; i++)
{
baseTile[i].h = 32;
baseTile[i].w = 32;
baseTile[i].x = tileX;
baseTile[i].y = tileY;
tileX += 32;
if (tileX == 128) { tileY += 32; tileX = 0; }
}
//Fill the surface
SDL_FillRect(screenSurface, NULL, SDL_MapRGB(screenSurface->format, 150, 50, 50));
SDL_Rect tileLoc;
tileLoc.x = 0;
tileLoc.y = 0;
// Draw tiles
for (int i = 0; i < 20; i++)
{
for (int j = 0; j < 20; j++)
{
if (mapLayer == 1 && mapLayerOne[i][j] != 0)
SDL_BlitSurface(image, &baseTile[mapLayerOne[i][j]], baseLayer, &tileLoc);
else if (mapLayer == 2 && mapLayerTwo[i][j] != 0)
SDL_BlitSurface(image, &baseTile[mapLayerTwo[i][j]], baseLayer, &tileLoc);
tileLoc.x += 32;
if (tileLoc.x == 640)
{
tileLoc.x = 0;
tileLoc.y += 32;
}
}
}
}
bool init()
{
//Initialization flag
bool success = true;
//Initialize SDL
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
std::cout << "SDL could not initialize!" << std::endl;
success = false;
}
else
{
//Create window
window = SDL_CreateWindow("My SDL TileMap", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
if (window == NULL)
{
std::cout << "Window could not be created!" << std::endl;
success = false;
}
else
{
//Initialize PNG loading
int imgFlags = IMG_INIT_PNG;
if (!(IMG_Init(imgFlags) & imgFlags))
{
//std::cout << "SDL_image could not initialize!" << std::endl;
printf("SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError());
success = false;
}
else
{
//Get window surface
screenSurface = SDL_GetWindowSurface(window);
//Surface to hold baselayer of map.
baseLayer = SDL_CreateRGBSurface(0, SCREEN_WIDTH, SCREEN_HEIGHT, 16, 0, 0, 0, 0);
}
}
}
SDL_Delay(300);
return success;
}
What's causing this?

baseLayer = SDL_CreateRGBSurface( 0, SCREEN_WIDTH, SCREEN_HEIGHT, 16, 0, 0, 0, 0 );
^^ ...but you're using 32bpp PNGs
Use a 32-bit surface instead of 16 and populate the masks:
// https://wiki.libsdl.org/SDL_CreateRGBSurface#Code_Examples
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
const Uint32 rmask = 0xff000000;
const Uint32 gmask = 0x00ff0000;
const Uint32 bmask = 0x0000ff00;
const Uint32 amask = 0x000000ff;
#else
const Uint32 rmask = 0x000000ff;
const Uint32 gmask = 0x0000ff00;
const Uint32 bmask = 0x00ff0000;
const Uint32 amask = 0xff000000;
#endif
baseLayer = SDL_CreateRGBSurface( 0, SCREEN_WIDTH, SCREEN_HEIGHT, 32, rmask, gmask, bmask, amask );

Related

Texture not displaying SDL2 [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 months ago.
Improve this question
I'm trying to make a game in C++ with SDL2, and I can't even get a texture displaying. SDL_GetError() returns nothing.
I'm on a windows 10 pro using Visual Studio.
Here are my 3 files:
main.cpp
#include "Classes.h"
int MouseX = 0;
int MouseY = 0;
int PlayerX = 0;
int PlayerY = 0;
SDL_Renderer* renderer;
Tile tile = Tile({10, 10, TileTypes::Tile_Grass}, renderer);
EventReturns HandleEvent(SDL_Event* event) {
switch (event->type) {
case SDL_QUIT:
return EventReturns::Event_QUIT;
case SDL_KEYDOWN:
switch (event->key.keysym.sym) {
case SDLK_ESCAPE:
return EventReturns::Event_TryQuit;
default:
return EventReturns::Event_None;
}
default:
return EventReturns::Event_None;
}
}
int mainLoop(EventReturns eventReturn) {
SDL_GetMouseState(&MouseX, &MouseY);
if (eventReturn == EventReturns::Event_QUIT || eventReturn == EventReturns::Event_TryQuit) {
return 1;
}
return 0;
}
void render() {
SDL_SetRenderDrawColor(renderer, 100, 200, 200, 255);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
tile.SetPos(0, 0);
if (tile.Draw(renderer) != 0) {
SDL_ShowSimpleMessageBox(0, "ERROR", "ERROR: Rect in tile has 0x0 size, Please close this with the task manager", NULL);
}
SDL_RenderPresent(renderer);
}
int main(int argc, char* argv[]) {
SDL_Window* window = SDL_CreateWindow("Game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 2880, 1600, SDL_WINDOW_SHOWN);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
bool running = true;
EventReturns eventReturn = EventReturns::Event_None;
SDL_Event event;
int quit = 0;
while (running) {
while (SDL_PollEvent(&event)) {
eventReturn = HandleEvent(&event);
}
quit = mainLoop(eventReturn);
render();
if (quit == 1) {
running = false;
}
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
Classes.h
#pragma once
#include <SDL.h>
#include <SDL_image.h>
#include <iostream>
#define SpriteSizeMult 1
enum class EventReturns {
Event_QUIT,
Event_None,
Event_TryQuit
};
enum class TileTypes {
Tile_Grass
};
struct TileStruct {
int x;
int y;
TileTypes type;
};
class Tile {
public:
Tile(int x, int y, char* TexturePath, SDL_Renderer* renderer);
Tile(TileStruct structure, SDL_Renderer* renderer);
Tile();
int Draw(SDL_Renderer* renderer);
void SetPos(int x, int y);
private:
int x = 0;
int y = 0;
int TextureWidth = 0;
int TextureHeight = 0;
SDL_Texture* texture;
SDL_Rect rect;
};
SDL_Point getsize(SDL_Texture* texture);
Classes.cpp
#include "Classes.h"
SDL_Point getsize(SDL_Texture* texture) {
SDL_Point size;
SDL_QueryTexture(texture, NULL, NULL, &size.x, &size.y);
return size;
}
Tile::Tile(int x, int y, char* TexturePath, SDL_Renderer* renderer)
{
this->x = x;
this->y = y;
this->texture = SDL_CreateTextureFromSurface(renderer, IMG_Load(TexturePath));
if (this->texture == nullptr) {
this->texture = SDL_CreateTextureFromSurface(renderer, IMG_Load("Assets/MissingTexture.png"));
std::cout << IMG_GetError();
}
SDL_Point point = getsize(this->texture);
this->TextureHeight = point.y;
this->TextureWidth = point.x;
this->rect = {this->x - ((this->TextureWidth * SpriteSizeMult) / 2), this->y - ((this->TextureHeight * SpriteSizeMult) / 2), this->TextureWidth * SpriteSizeMult, this->TextureHeight * SpriteSizeMult};
}
Tile::Tile(TileStruct structure, SDL_Renderer* renderer)
{
this->x = structure.x;
this->y = structure.y;
switch (structure.type) {
case TileTypes::Tile_Grass:
this->texture = SDL_CreateTextureFromSurface(renderer, IMG_Load("Assets/Tiles/Grass.png"));
default:
this->texture = SDL_CreateTextureFromSurface(renderer, IMG_Load("Assets/MissingTexture.png"));
}
if (this->texture == NULL) {
this->texture = SDL_CreateTextureFromSurface(renderer, IMG_Load("Assets/MissingTexture.png"));
if (this->texture == NULL) {
SDL_ShowSimpleMessageBox(0, "ERROR", "Failed to load texture", NULL);
SDL_ShowSimpleMessageBox(0, "ERROR", IMG_GetError(), NULL);
}
}
SDL_Point point = getsize(this->texture);
this->TextureHeight = point.y;
this->TextureWidth = point.x;
this->rect = { this->x - ((this->TextureWidth * SpriteSizeMult) / 2), this->y - ((this->TextureHeight * SpriteSizeMult) / 2), this->TextureWidth * SpriteSizeMult, this->TextureHeight * SpriteSizeMult };
}
Tile::Tile()
{
}
int Tile::Draw(SDL_Renderer* renderer)
{
if (rect.w == 0 || rect.h == 0) {
return -1;
}
this->rect.x = 0;
this->rect.y = 0;
SDL_RenderCopy(renderer, this->texture, NULL, &rect);
return 0;
}
void Tile::SetPos(int x, int y)
{
this->x = x;
this->y = y;
}
I'm sorry for the sheer amount of code that is, but I'd really appreciate the help. If there's any more info I need to put here, just let me know.
I'm fully aware that I should make a Minimal Reproducible Example, but as far as I'm aware, all the code listed here is necessary.
Finally, in case I've been unclear, when running the code the Missing Texture image that should appear isn't showing up.
I can't see SDL_INIT function in your code.
You should add this in the beginning of your main function.
if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
return 1;
You are initialising tile before creating a renderer so the constructor is trying to create a texture without a renderer.
SDL_Renderer* renderer;
Tile tile = Tile({10, 10, TileTypes::Tile_Grass}, renderer);
You should do something like this
#include "Classes.h"
int MouseX = 0;
int MouseY = 0;
int PlayerX = 0;
int PlayerY = 0;
SDL_Renderer* renderer;
EventReturns HandleEvent(SDL_Event* event) {
switch (event->type) {
case SDL_QUIT:
return EventReturns::Event_QUIT;
case SDL_KEYDOWN:
switch (event->key.keysym.sym) {
case SDLK_ESCAPE:
return EventReturns::Event_TryQuit;
default:
return EventReturns::Event_None;
}
default:
return EventReturns::Event_None;
}
}
int mainLoop(EventReturns eventReturn) {
SDL_GetMouseState(&MouseX, &MouseY);
if (eventReturn == EventReturns::Event_QUIT || eventReturn == EventReturns::Event_TryQuit) {
return 1;
}
return 0;
}
void render(Tile tile) {
SDL_SetRenderDrawColor(renderer, 100, 200, 200, 255);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
tile.SetPos(0, 0);
if (tile.Draw(renderer) != 0) {
SDL_ShowSimpleMessageBox(0, "ERROR", "ERROR: Rect in tile has 0x0 size, Please close this with the task manager", NULL);
}
SDL_RenderPresent(renderer);
}
int main(int argc, char* argv[]) {
if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
return 1;
SDL_Window* window = SDL_CreateWindow("Game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 2880, 1600, SDL_WINDOW_SHOWN);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
Tile tile = Tile({ 10, 10, TileTypes::Tile_Grass }, renderer);
bool running = true;
EventReturns eventReturn = EventReturns::Event_None;
SDL_Event event;
int quit = 0;
while (running) {
while (SDL_PollEvent(&event)) {
eventReturn = HandleEvent(&event);
}
quit = mainLoop(eventReturn);
render(tile);
if (quit == 1) {
running = false;
}
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}

Exception thrown: write access violation. this->**m_buffer** was 0x111011101110112

Im following this (https://www.udemy.com/course/free-learn-c-tutorial-beginners/learn/lecture/1838486#announcements ) tutorial and im stuck.
It seem that windows throws that exception and it cant be handled.
I think I try write something to some wrong place but cant see it.
Heres the line that causes the problem.
m_buffer[(y * SCREEN_WIDTH) + x] = color;
And here is everything else
//====================================main.cpp=======================================
#include<iostream>
#include "Screen.h"
#include<SDL.h>
using namespace std;
int main(int argc, char* argv[]) {
Screen screen;
if (!screen.init()) {
cout << "Error initialising SDL." << endl;
}
while (true) {
// update particles
// draw particles
for (int y = 0; y < Screen::SCREEN_HEIGHT; y++) {
for (int x = 0; x < Screen::SCREEN_WIDTH; x++ ){
screen.setPixel(x, y, 128, 0, 255);
}
}
//Draw the screen
screen.update();
// see for messages/events
if (!screen.processEvents()) {
break;
}
}
screen.close();
return 0;
}
//==========================================================================================
screen.h
#ifndef SCREEN_H_
#define SCREEN_H_
#include<SDL.h>
#include<iostream>
class Screen
{
public:
const static int SCREEN_WIDTH = 800;
const static int SCREEN_HEIGHT = 600;
private:
SDL_Window* m_window;
SDL_Renderer* m_renderer;
SDL_Texture* m_texture;
Uint32* m_buffer;
public:
Screen();
bool init();
void update();
void setPixel(int x, int y, Uint8 red, Uint8 green, Uint8 blue);
bool processEvents();
void close();
};
#endif // !SCREEN_H_
//=======================screen.cpp======================================================
#include "Screen.h"
Screen::Screen() : m_window(NULL), m_renderer(NULL), m_texture(NULL), m_buffer(NULL)
{
}
bool Screen::init() {
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
return false;
}
m_window = SDL_CreateWindow("Particle Fire Explosion",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); //-----------------SDL_WINDOW_HIDDEN SDL_WINDOW_SHOWN
if (m_window == 0) {
SDL_Quit();
return false;
}
m_renderer = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_PRESENTVSYNC);
m_texture = SDL_CreateTexture(m_renderer,
SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STATIC, SCREEN_WIDTH, SCREEN_HEIGHT);
if (m_renderer == NULL) {
SDL_DestroyWindow(m_window);
SDL_Quit();
return false;
}
if (m_texture == NULL) {
SDL_DestroyWindow(m_window);
SDL_DestroyRenderer(m_renderer);
SDL_Quit();
return false;
}
Uint32* buffer = new Uint32[SCREEN_WIDTH * SCREEN_HEIGHT];
memset(buffer, 0xFF, SCREEN_WIDTH * SCREEN_HEIGHT * sizeof(Uint32));
return true;
}
bool Screen::processEvents() {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT)
{
return false;
}
}
return true;
}
void Screen::setPixel(int x, int y, Uint8 red, Uint8 green, Uint8 blue) {
Uint32 color = 0;
color += red;
color <<= 8;
color += green;
color <<= 8;
color += blue;
color <<= 8;
color += 0xFF;
m_buffer[(y * SCREEN_WIDTH) + x] = color;
}
void Screen::update() {
SDL_UpdateTexture(m_texture, NULL, m_buffer, SCREEN_WIDTH * sizeof(Uint32));
SDL_RenderClear(m_renderer);
SDL_RenderCopy(m_renderer, m_texture, NULL, NULL);
SDL_RenderPresent(m_renderer);
}
void Screen::close() {
delete[] m_buffer;
SDL_DestroyRenderer(m_renderer);
SDL_DestroyTexture(m_texture);
SDL_DestroyWindow(m_window);
SDL_Quit();
}
//==========================================================================================
Maybe someone can see what is the broblem?
Your Screen::init() method never sets m_buffer, so when setPixel() tries to dereference it, it is dereferencing a NULL pointer, which invokes undefined behavior.
this line is wrong
Uint32* buffer = new Uint32[SCREEN_WIDTH * SCREEN_HEIGHT];
you mean
m_buffer = new Uint32[SCREEN_WIDTH * SCREEN_HEIGHT];

SDL Window won't change colors (C++)

Question:
First off, I'm very new to C++ so I'm just starting out. One of the exercises I'm currently on is having me create a "Particle Explosion" as you can see in the window title then have it flash different colors as you can see in the main.cpp.
My problem:
Whenever I run it in VS2015 I get my console to open, the window opens, but it doesn't flash any colors, it just stays white. Everything seems to be working just fine and it doesn't freeze or have any errors. Just. No. Colors.
Does anyone see an error I'm making? Once I created it I compared it to the exercise, but everything seems to be 100% exactly the same.
I'm on W7, VS2015 and using SDL2 lib.
main.cpp
#include <iostream>
#include <SDL.h>
#include "Screen.h"
#include <math.h>
#undef main
using namespace std;
using namespace caveofprogramming;
int main() {
Screen screen;
if (screen.init() == false) {
cout << "Error initialzing SDL." << endl;
}
while (true) {
// Update particles
// Draw Particles
int elapsed = SDL_GetTicks();
unsigned char green = (1 + sin(elapsed * 0.001)) * 128;
unsigned char red = (1 + sin(elapsed * 0.002)) * 128;
unsigned char blue = (1 + sin(elapsed * 0.003)) * 128;
for (int y = 0; y < Screen::SCREEN_HEIGHT; y++) {
for (int x = 0; x < Screen::SCREEN_WIDTH; x++) {
screen.setPixel(x, y, red, green, blue);
}
}
//Draw the screen
// Check for messages/events
if (screen.processEvents() == false) {
break;
}
}
screen.close();
return 0; // usually when your program runs ok it returns 0
}
Screen.cpp
#include "Screen.h"
#include <iostream>
namespace caveofprogramming {
Screen::Screen() :
m_window(NULL), m_renderer(NULL), m_texture(NULL), m_buffer(NULL) {
}
bool Screen::init() {
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
return false;
}
m_window = SDL_CreateWindow("Particle Fire Explosion",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH,
SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
if (m_window == NULL) {
SDL_Quit();
return false;
}
m_renderer = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_PRESENTVSYNC);
m_texture = SDL_CreateTexture(m_renderer, SDL_PIXELFORMAT_RGBA8888,
SDL_TEXTUREACCESS_STATIC, SCREEN_WIDTH, SCREEN_HEIGHT);
if (m_renderer == NULL) {
SDL_DestroyWindow(m_window);
SDL_Quit();
return false;
}
if (m_texture == NULL) {
SDL_DestroyRenderer(m_renderer);
SDL_DestroyWindow(m_window);
SDL_Quit();
return false;
}
m_buffer = new Uint32[SCREEN_WIDTH * SCREEN_HEIGHT];
memset(m_buffer, 0, SCREEN_WIDTH * SCREEN_HEIGHT * sizeof(Uint32));
return true;
}
void Screen::clear() {
memset(m_buffer, 0, SCREEN_WIDTH * SCREEN_HEIGHT * sizeof(Uint32));
}
void Screen::setPixel(int x, int y, Uint8 red, Uint8 green, Uint8 blue) {
if (x < 0 || x >= SCREEN_WIDTH || y < 0 || y >= SCREEN_HEIGHT) {
return;
}
Uint32 color = 0;
color += red;
color <<= 8;
color += green;
color <<= 8;
color += blue;
color <<= 8;
color += 0xFF;
m_buffer[(y * SCREEN_WIDTH) + x] = color;
}
void Screen::update() {
SDL_UpdateTexture(m_texture, NULL, m_buffer, SCREEN_WIDTH * sizeof(Uint32));
SDL_RenderClear(m_renderer);
SDL_RenderCopy(m_renderer, m_texture, NULL, NULL);
SDL_RenderPresent(m_renderer);
}
bool Screen::processEvents() {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
return false;
}
}
return true;
}
void Screen::close() {
delete[] m_buffer;
SDL_DestroyRenderer(m_renderer);
SDL_DestroyTexture(m_texture);
SDL_DestroyWindow(m_window);
SDL_Quit();
}
}
Screen.h
#pragma once
#include <SDL.h>
namespace caveofprogramming {
class Screen {
public:
const static int SCREEN_WIDTH = 800;
const static int SCREEN_HEIGHT = 600;
private:
SDL_Window *m_window;
SDL_Renderer *m_renderer;
SDL_Texture *m_texture;
Uint32 *m_buffer;
public:
Screen();
bool init();
bool processEvents();
void update();
void clear();
void setPixel(int x, int y, Uint8 red, Uint8 green, Uint8 blue);
void close();
};
}
As Elderbug said, I just had to add the function to my object to render.
//Draw the screen
screen.update();
thanks!

IMG_Load doesn't work

I was watching this series = https://www.youtube.com/watch?v=2NVgHrOFneg
and for some reason for the guy in the video the code works but for me it compiles fine but doesn't load an image. I really don't know what to do.
#include "SDL.h"
#include <iostream>
#include "SDL_image.h"
SDL_Texture *LoadTexture(std::string filePath, SDL_Renderer *renderTarget) //texture optimization function
{
SDL_Texture *texture = nullptr;
SDL_Surface *surface = IMG_Load(filePath.c_str());
if (surface == NULL)
std::cout << "Error 1" << std::endl;
else
{
texture = SDL_CreateTextureFromSurface(renderTarget, surface);
if (texture == NULL)
std::cout << "Error 2" << std::endl;
}
SDL_FreeSurface(surface);
return texture;
}
int main(int, char *argv[])
{
const int FPS = 144;
int frameTime = 0;
SDL_Window *window = nullptr;
SDL_Texture *currentImage= nullptr;
SDL_Renderer *renderTarget = nullptr;
SDL_Rect playerRect;
int frameWidth, frameHeight;
int textureWidth, textureHeight;
SDL_Init(SDL_INIT_VIDEO );
int imgFlags = IMG_INIT_PNG | IMG_INIT_JPG;
if (!(IMG_Init(imgFlags) != imgFlags))
{
std::cout << "Error: " << IMG_GetError() << std::endl;
}
window = SDL_CreateWindow("SDL Pong", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1024, 720, SDL_WINDOW_SHOWN);
renderTarget = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
currentImage = LoadTexture("Untitled.jpg", renderTarget);
SDL_QueryTexture(currentImage, NULL, NULL, &textureWidth, &textureHeight);
SDL_SetRenderDrawColor(renderTarget, 0xFF, 0, 0, 0xFF);
frameWidth = textureWidth / 3;
frameHeight = textureHeight / 4;
playerRect.x = playerRect.y = 0;
playerRect.y = frameWidth;
playerRect.h = frameHeight;
bool isRunning = true; //game loop
SDL_Event ev;
while (isRunning)
{
while (SDL_PollEvent(&ev) != 0)
{
if (ev.type == SDL_QUIT)
isRunning = false;
}
frameTime++;
if (FPS / frameTime == 4)
{
frameTime = 0;
playerRect.x += frameWidth;
if (playerRect.x >= textureWidth)
playerRect.x =0;
}
SDL_RenderClear(renderTarget);
SDL_RenderCopy(renderTarget, currentImage, &playerRect, NULL);
SDL_RenderPresent(renderTarget);
}
SDL_DestroyWindow(window);
SDL_DestroyTexture(currentImage);
SDL_DestroyRenderer(renderTarget);
window = nullptr;
renderTarget = nullptr;
currentImage = nullptr;
SDL_Quit();
return 0;
}
This is the error message: http://imgur.com/LHMdt5F
IMG_Init returns bitfield of formats that was initialised. If resulting bitfield doesn't contain every format that was requested in flags, something gone wrong.
if (!(IMG_Init(imgFlags) != imgFlags)) checks if there is no error. Then you're trying to get error message, but there were no errors. Remove negation operator.
When you create the .exe and run it from an IDE it often stores the executable in a ../bin/.. directory. If Untitled.jpg is in the same directory as your source files, it will not find it.
SDL_GetBasePath(); will return the base path to your files. Check it out docs for it.
The string from SDL_GetBasePath() + "Untitled.jpg" will find and open the file.

SDL2 'Bullet' movement not working?

I am attempting to make a simple scrolling shooter game with SDL2. I have a moving player on a screen, and I am trying to make the player shoot a bullet using an array (so they can shoot multiple bullets) however, when I press the space bar, nothing happens, and instead the bullet image sort of flashes in the top left corner.
Heres the same code in codepad: http://codepad.org/rOhE1AqY
#include <SDL.h>
#include <stdio.h> //use for things like printf, same as cout
#include <iostream>
#include <string>
#include <time.h>
using namespace std;
//screend dimensions& sprtie dimensions
const int SCREEN_HEIGHT = 600;
const int SCREEN_WIDTH = 400;
const int SPRITE_WIDTH = 60;
const int SPRITE_HEIGHT = 80;
const int MAX_BULLETS = 50;
SDL_Window* Window = NULL;//the window rendering to
SDL_Surface* ScreenSurface = NULL;//surface contained by window
SDL_Surface* Background = NULL;
SDL_Surface* Player = NULL;
SDL_Surface* Enemy = NULL;
SDL_Surface* Bullet = NULL;
SDL_Surface* newBullet = NULL;
SDL_Rect posPlayer, posEnemy, posBullet, posnewBullet;
const Uint8* keystate = SDL_GetKeyboardState(NULL);
SDL_Event event;
class thePlayer
{
public:
thePlayer();
void player_movement();
void show_player();
private:
};
class theBullet
{
public:
theBullet();
bool isActive;
int x_position;
int y_position;
void bullet_movement();
void add_new_bullet();
void show_bullet();
private:
};
theBullet arrayofBullets[MAX_BULLETS];
class theEnemy
{
public:
theEnemy();
void enemy_movement();
void show_enemy();
private:
};
thePlayer::thePlayer()
{
posPlayer.x = 170;
posPlayer.y = SCREEN_HEIGHT;
posPlayer.w = 20;
posPlayer.h = 30;
}
void thePlayer::player_movement()
{
if(keystate[SDL_SCANCODE_LEFT])
{
posPlayer.x -= 2;
}
if(keystate[SDL_SCANCODE_RIGHT])
{
posPlayer.x += 2;
}
if(keystate[SDL_SCANCODE_UP])
{
posPlayer.y -= 2;
}
if(keystate[SDL_SCANCODE_DOWN])
{
posPlayer.y += 2;
}
if ((posPlayer.x + SPRITE_WIDTH) > SCREEN_WIDTH)
{
posPlayer.x = (SCREEN_WIDTH - SPRITE_WIDTH);
}
if ((posPlayer.y + SPRITE_HEIGHT) > SCREEN_HEIGHT)
{
posPlayer.y = (SCREEN_HEIGHT - SPRITE_HEIGHT);
}
}
void thePlayer::show_player()
{
SDL_BlitSurface(Player, NULL, ScreenSurface, &posPlayer);
SDL_SetColorKey(Player, SDL_TRUE, SDL_MapRGB(Player->format, 255, 255, 255));
}
theBullet::theBullet()
{
/*posBullet.x;
posBullet.y;
posBullet.w = 10;
posBullet.h = 15;*/
}
void theBullet::bullet_movement()
{
/*if(keystate[SDL_SCANCODE_SPACE])
{
posBullet.x = posPlayer.x + 25;
posBullet.y = posPlayer.y + 10;
}
posBullet.y -= 2;
if(posBullet.y < 0)
{
posBullet.y = -50;
}*/
}
void theBullet::show_bullet()
{
//SDL_BlitSurface(Bullet, NULL, ScreenSurface, &posBullet);
//SDL_SetColorKey(Bullet, SDL_TRUE, SDL_MapRGB(Player->format, 255, 255, 255));//removes white background
}
theEnemy::theEnemy()
{
srand (time(NULL));
posEnemy.x = rand() % 300 + 50;
posEnemy.y =0;
posEnemy.w = 35;
posEnemy.h = 60;
}
void theEnemy::enemy_movement()
{
posEnemy.y += 1;
if(posEnemy.y > SCREEN_HEIGHT)
{
posEnemy.y = SCREEN_HEIGHT +50;
}
}
void theEnemy::show_enemy()
{
SDL_BlitSurface(Enemy, NULL, ScreenSurface, &posEnemy);
SDL_SetColorKey(Enemy, SDL_TRUE, SDL_MapRGB(Player->format, 255, 255, 255));
}
bool initialise()
{
bool success = true;
if (SDL_Init(SDL_INIT_EVERYTHING) !=0)
{
cout<<"SDL_Init Error."<<SDL_GetError()<<endl;
success = false;
}
else
{
//create the window for game
Window = SDL_CreateWindow("Scrolling Shooter Game", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
if (Window == NULL)
{
cout<<"Window Error"<<SDL_GetError()<<endl;
success = false;
}
else
{
//get window surface
ScreenSurface = SDL_GetWindowSurface(Window);
}
}
return success;
}
bool LoadingMedia()
{
bool success = true;
Background = SDL_LoadBMP("background.bmp");
if (Background == NULL)
{
cout<<"Error in loading background."<<SDL_GetError()<<endl;
success = false;
}
Player = SDL_LoadBMP("spaceship.bmp");
if (Player == NULL)
{
cout<<"Error in loading player."<<SDL_GetError()<<endl;
success = false;
}
Enemy = SDL_LoadBMP("enemy.bmp");
if (Enemy == NULL)
{
cout<<"Error in loading enemy."<<SDL_GetError()<<endl;
success = false;
}
Bullet = SDL_LoadBMP("bullet.bmp");
if (Bullet == NULL)
{
cout<<"Error in loading bullet."<<SDL_GetError()<<endl;
success = false;
}
return success;
}
void closedown()
{
SDL_FreeSurface(Background);
Background = NULL;
SDL_FreeSurface(Player);
Player = NULL;
SDL_FreeSurface(Enemy);
Enemy = NULL;
SDL_DestroyWindow(Window);
Window = NULL;
SDL_Quit();
}
int main(int argc, char** argv)
{
bool quit = false;
thePlayer myPlayer;
theEnemy myEnemy;
theBullet myBullet;
if (!initialise())
{
cout<<"Failed to initialise"<<SDL_GetError()<<endl;
}
else
{
if (!LoadingMedia())
{
cout<<"Error loading media"<<SDL_GetError()<<endl;
}
}
//makes all bullets false
for (int i=0; i<MAX_BULLETS; i++)
{
arrayofBullets[i].isActive = false;
}
//GAME LOOP
while (quit == false)
{
SDL_BlitSurface(Background, NULL, ScreenSurface, NULL);
myPlayer.show_player();
myPlayer.player_movement();
while (SDL_PollEvent(&event))
{
if( event.type == SDL_QUIT )
{
quit = true;
break;
}
if(keystate[SDL_SCANCODE_SPACE])
{
for (int i=0; i<MAX_BULLETS; i++)
{
if (arrayofBullets[i].isActive == false)
{
arrayofBullets[i].x_position = posPlayer.x + 25;
arrayofBullets[i].y_position = posPlayer.y + 10;
arrayofBullets[i].isActive = true;
break;
}
}
}
//update game objects
for (int i=0; i<MAX_BULLETS; i++)
{
if (arrayofBullets[i].isActive == true)
{
arrayofBullets[i].y_position -= 2;
if (arrayofBullets[i].y_position < 0)
{
arrayofBullets[i].isActive = false;
}
}
}
for (int i=0; i<MAX_BULLETS; i++)
{
if (arrayofBullets[i].isActive == true)
{
SDL_BlitSurface(Bullet, NULL, ScreenSurface, NULL);
}
}
}
//myPlayer.show_player();
//myBullet.show_bullet();
//myEnemy.show_enemy();
//myPlayer.player_movement();
//myBullet.bullet_movement();
//myEnemy.enemy_movement();
SDL_UpdateWindowSurface(Window); //updates screen
}
closedown();
return 0;
}
SDL_BlitSurface(Bullet, NULL, ScreenSurface, NULL);
You haven't specified destination rect, so it will blit on left-top corner.
It should be
SDL_Rect dstrect;
dstrect.x = arrayofBullets[i].x_position;
dstrect.y = arrayofBullets[i].y_position;
dstrect.w = Bullet->w;
dstrect.h = Bullet->h;
SDL_BlitSurface(Bullet, NULL, ScreenSurface, &dstrect);