0xC0000005: Access violation reading location 0x00000008 - c++

I have been struggling with this for a while and was wondering if anyone could help. I am trying to make a particle sample using C++ and SDL1.3 and I have had great success up until this point. The program compiles and the screen opens and nothing happens. When I run the debugger I get this error:
Unhandled exception at 0x0102414a in SDL 1.3 Space.exe: 0xC0000005: Access violation reading location 0x00000008.
The program '[7272] SDL 1.3 Space.exe: Native' has exited with code -1073741819 (0xc0000005).
and it points to this piece of the code:
bool particle::isDead()
{
return (SDL_GetTicks() >= endTime || x == 0 || y == 0 || x == SDL_GetVideoSurface()->w -1 || y == SDL_GetVideoSurface()->h - 1);
}
It would be greatly appreciated if someone would be so kind as to help me and /or point me in the right direction.
This is the entire program:
#include "SDL.h"
#include "common.h"
#include <stdio.h>
#include <string>
#include <cstdlib>
#include <vector>
#include <ctime>
/*static SDL_Texture *background = 0; //background
SDL_Renderer *renderer;
void render()
{
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, background, NULL, NULL); //Display background
SDL_RenderPresent(renderer);
endFrame = SDL_GetTicks();
};*/
class particle
{
float x, y, xvel, yvel;
Uint32 endTime;
Uint8 color;
public:
particle( float X, float Y, float Xvel, float Yvel, int life, Uint8 Color );
void move();
void show();
bool isDead();
};
particle::particle( float X, float Y, float Xvel, float Yvel, int life, Uint8 Color )
{
x = X;
y = Y;
xvel = Xvel;
yvel = Yvel;
endTime = SDL_GetTicks() + life;
color = Color;
}
void particle::move()
{
x += xvel;
y += yvel;
if ( x < 0 )
x = 0;
if ( y < 0 )
y = 0;
if ( x > SDL_GetVideoSurface() -> w)
x = SDL_GetVideoSurface() -> w - 1;
if ( y > SDL_GetVideoSurface() -> h)
y = SDL_GetVideoSurface() -> h -1;
}
void particle::show()
{
Uint8* pixels = (Uint8*) SDL_GetVideoSurface()->pixels;
Uint8* pixel = pixels + (int) y * SDL_GetVideoSurface()->pitch + (int) x;
*pixel = color;
}
bool particle::isDead()
{
return (SDL_GetTicks() >= endTime || x == 0 || y == 0 || x == SDL_GetVideoSurface()->w -1 || y == SDL_GetVideoSurface()->h - 1);
}
class particleEngine
{
std::vector <particle*> particles;
int x, y, maxparticle;
public:
particleEngine( int maxpart, int X, int Y );
~particleEngine();
void refresh();
};
particleEngine::particleEngine( int maxpart, int X, int Y )
{
x = X;
y = Y;
maxparticle = maxpart;
for ( int i = 0; i < maxparticle; i++ )
particles.push_back (new particle( x + rand()%6-3, y + rand()%6-3, rand()%10 + (float)rand()/(float)RAND_MAX - 5, rand()%10 + (float)rand()/(float)RAND_MAX - 5, 500 + rand()%1000, 0));
}
particleEngine::~particleEngine()
{
for ( int i = 0; i < maxparticle; i++)
delete particles[i];
}
void particleEngine::refresh()
{
for ( int i = 0; i < maxparticle; i++)
{
if ( particles[i]->isDead())
{
delete particles[i];
particles[i] = new particle( x + rand()%6-3, y + rand()%6-3, rand()%10 + (float)rand()/(float)RAND_MAX - 5, rand()%10 + (float)rand()/(float)RAND_MAX - 5, 500 + rand()%1000, 0);
}
else
{
particles[i]->move();
particles[i]->show();
}
}
}
int main( int argc, char* argv[] )
{
bool running = true;
const int FPS = 30;
Uint32 startFrame;
srand (time(0));
particleEngine ps(1000, SCREEN_WIDTH/2, SCREEN_HEIGHT/2);
SDL_Window *window; /* main window */
SDL_Renderer *renderer;
if (SDL_Init(SDL_INIT_EVERYTHING)!= 0)
{
printf("Could not initialize SDL");
}
window = SDL_CreateWindow("SDL 1.3 Particles", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT,
SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN );
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
// Body of the program goes here.
while (running)
{
startFrame = SDL_GetTicks();
SDL_Event event;
//render();
//While there's events to handle
while( SDL_PollEvent( &event ) )
{
//If the user has Xed out the window
if (event.type == SDL_QUIT)
{
running = false;
}
}
//SDL_FillRect(renderer, &renderer->clip_rect, SDL_MapRGB(renderer->format, 0x00,0x00, 0x00));
ps.refresh();
//SDL_RenderCopy(renderer, 0, 0, 0);
SDL_RenderPresent(renderer);
//SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
//SDL_RenderClear(renderer);
if (1000/FPS>SDL_GetTicks()-startFrame)
SDL_Delay(1000/FPS-(SDL_GetTicks()-startFrame));
}
SDL_Quit();
return 0;
}

Access violations mean you are dereferencing null pointers(or pointers to memory you don't have access to), so this would mean (assuming the debugger synced with the source correctly) that SDL_GetVideoSurface is returning null, so you'll probably wanna throw a few checks in isDead. Secondly, its probably a good idea to store the w/h of the surface minus 1 in your class at during the creation of the surface, should mean a little less computational overhead along with shorter code.

Related

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!

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++ possible constructor error violation writing location

I have added these functions to my code, and my program started crashing randomly showing
Unhandled exception at 0x6C7B52E7 (SDL2.dll) in SDL_2.exe: 0xC0000005: Access violation writing location 0xFF00000C. Debugger shows at completely random pieces of code, that worked perfectly before, which leads me to think, that these new functions mess up the memory.
void ObstacleSet::move()
{
Obstacles.push_back(Obstacle(mScreenWidth, mScreenHeight / 6 + 100, 10, 10, Coin, -29, 0));
Obstacles.push_back(Obstacle(mScreenWidth, mScreenHeight / 6 + 120, 10, 10, Coin, -29, 0));
Obstacles.push_back(Obstacle(mScreenWidth, mScreenHeight / 6 + 140, 10, 10, Coin, -29, 0));
Obstacles.push_back(Obstacle(mScreenWidth, mScreenHeight / 6 + 160, 10, 10, Coin, -29, 0));
Obstacles.push_back(Obstacle(mScreenWidth, mScreenHeight / 6 + 180, 10, 10, Coin, -29, 0));
for (auto &i : Obstacles)
{
i.move();
}
}
void ObstacleSet::outCheck(unsigned int &score)
{
for (unsigned int i = 0; i < getSize();)
{
if (getVelX(i) < 0 && (getX(i) + getW(i) <= 0))
{
eraseObstacle(i);
score++;
}
else if (getVelX(i) > 0 && (getX(i) >= mScreenWidth))
{
eraseObstacle(i);
score++;
}
else if (getVelY(i) > 0 && (getY(i) + getH(i) >= mScreenHeight))
{
eraseObstacle(i);
score++;
}
else if (getVelY(i) < 0 && (getY(i) <= 0))
{
eraseObstacle(i);
score++;
}
else
{
++i;
}
}
}
Apparently, i have some memory leak, or a dangling pointer somehow appears, but i just can not see where. Maybe i have a wrong constructor or something.
ObstacleSet is a class, that holds all Obstacles in a list.
#ifndef MOBSTSET_H
#define MOBSTSET_H
#include <SDL.h>
#include <cstdlib>
#include "my_OBSTACLES.h"
#include <list>
class ObstacleSet
{
public:
ObstacleSet(int ScreenWidth, int ScreenHeight);
int mScreenWidth;
int mScreenHeight;
void clear();
//Function, that moves the set depending on current time
void move();
//Render set on screen
void render(SDL_Renderer *Renderer);
unsigned int getSize();
float getX(int);
float getY(int);
int getW(int);
int getH(int);
float getVelX(int);
float getVelY(int);
Type GetType(int);
void eraseObstacle(int);
void outCheck(unsigned int &score);
std::list<Obstacle>::iterator getEnd();
private:
//Vector to hold all obstacles
std::list <Obstacle> Obstacles;
};
#endif
These appear in my main game loop one after another
Obstacle class header
#ifndef MYOBSTACLE_H
#define MYOBSTACLE_H
#include <SDL.h>
#include <cmath>
#include <vector>
#include <cstdlib>
enum Type
{
Wall,
Coin
};
class Obstacle
{
public:
Obstacle();
//Initializer with parameters
Obstacle(float x, float y, int w, int h, Type type, float VelocityX = 0, float VelocityY = 0);
float VelocityX = 0;
float VelocityY = 0;
float xPos;
float yPos;
int mWidth;
int mHeight;
//Type of obstacle
Type OBSType;
//Render obstacle on screen
void render(SDL_Renderer *Renderer);
//Move obstacle
void move();
int mRed = 200;
int mGreen = 200;
int mBlue = 20;
bool color_up = false;
};
#endif
These are my constructors for Obstacle
Obstacle::Obstacle() : xPos(10), yPos(10), mWidth(10), mHeight(10), VelocityX(0), VelocityY(0), OBSType(Coin), mRed(200), mGreen(200), mBlue(20), color_up(false)
{
printf("Obstacle created!");
}
Obstacle::Obstacle(float x, float y, int w, int h, Type type, float velocityX, float velocityY) : xPos(x), yPos(y), mWidth(w), mHeight(h), VelocityX(velocityX), VelocityY(velocityY), OBSType(type), mRed(200), mGreen(200), mBlue(20), color_up(false)
{
}
Here are some functions of ObstacleSet
void ObstacleSet::eraseObstacle(int number)
{
unsigned N = number;
std::list<Obstacle>::iterator i = Obstacles.begin();
if (Obstacles.size() > N)
{
std::advance(i, N);
}
Obstacles.erase(i);
}
unsigned int ObstacleSet::getSize()
{
return Obstacles.size();
}
float ObstacleSet::getX(int number)
{
unsigned N = number;
std::list<Obstacle>::iterator i = Obstacles.begin();
if (Obstacles.size() > N)
{
std::advance(i, N);
}
return i->xPos;
}
std::list<Obstacle>::iterator ObstacleSet::getEnd()
{
return Obstacles.end();
}
SDL Initialization code
bool init()
{
//Initialization flag
bool success = true;
//Initialize SDL
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO) < 0)
{
printf("SDL could not initialize! SDL Error: %s\n", SDL_GetError());
success = false;
}
else
//Set texture filtering to linear
if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1"))
{
printf("Warning: Linear texture filtering not enabled!");
}
//Initialize SDL_mixer
if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0)
{
printf("SDL_mixer could not initialize! SDL_mixer Error: %s\n", Mix_GetError());
success = false;
}
//Check for joysticks
if (SDL_NumJoysticks() < 1)
{
printf("Warning: No joysticks connected!\n");
}
else
{
//Load joystick
gGameController = SDL_JoystickOpen(0);
if (gGameController == NULL)
{
printf("Warning: Unable to open game controller! SDL Error: %s\n", SDL_GetError());
}
}
//Create window
gWindow = SDL_CreateWindow("Jello demo", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
if (gWindow == NULL)
{
printf("Window could not be created! SDL Error: %s\n", SDL_GetError());
success = false;
}
else
{
//Create vsynced renderer for window
gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (gRenderer == NULL)
{
printf("Renderer could not be created! SDL Error: %s\n", SDL_GetError());
success = false;
}
else
//Initialize renderer color
SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
//Initialize PNG loading
int imgFlags = IMG_INIT_PNG;
if (!(IMG_Init(imgFlags) & imgFlags))
{
printf("SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError());
success = false;
}
//Initialize SDL_ttf
if (TTF_Init() == -1)
{
printf("SSDL_ttf could not initialize! SDL_ttf Error: %s\n", TTF_GetError());
success = false;
}
}
return success;
}
Maybe I have got a memory leak or a dangling pointer, but I can't find where the mistake is. I will be VERY glad if anyone could find where i am wrong. Write me if you need any additional code pieces
Unless you have an invariant somewhere that guarantees that ObstacleSet never calls anything on an empty Obstacles list there is a potential problem.
This code has undefined behaviour on an empty list
float ObstacleSet::getX(int number)
{
unsigned N = number;
std::list<Obstacle>::iterator i = Obstacles.begin();
if (Obstacles.size() > N)
{
std::advance(i, N);
}
return i->xPos;
}
Trying to fix it
float ObstacleSet::getX(int number)
{
unsigned N = number;
std::list<Obstacle>::iterator i = Obstacles.begin();
if (Obstacles.size() > N)
{
std::advance(i, N);
}
if (i != Obstacles.end())
return i->xPos;
// handle empty
return ERRORPOS; // or throw or assert or ...
}
Same with all other functions that access the list.
Some issues I see in the code:
In ObstacleSet::move() you add five obstacles to the list. It looks like the list can grow indefinitely, resulting in memory overflow.
You don't check if Obstacles are empty in eraseObstacle(), getX() and perhaps in other functions which you haven't shown.
So apparently, there error was not in the code i provided. I initialized SDL_mixer wrongly. I loaded audio like this
if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0), but sampling rate of wav file i provided was not MIX_DEFAULT_FORMAT, which is 22050.
Anyway, thanks to everybody, who tried to help me with my code. It was a pleasant experience to use stackoverflow for the fisrt time.

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.

SDL software rendering faster than hardware rendering

I've just found out a strange behavior of SDL.
I've written a simple particle renderer, and for some reason it runs about 6 times faster with the software renderer than with the hardware renderer.
Here's the source code:
main.cpp
#define _USE_MATH_DEFINES
#include <iostream>
#include <cstdlib>
#include <Windows.h>
#include <vector>
#include <math.h>
#include <time.h>
#include <SDL.h>
#include "Particle.h"
const int SCREEN_WIDTH = 1024;
const int SCREEN_HEIGHT = 600;
const int PARTICLE_NUMBER = 50000;
const int MAX_SPEED = 200;
const int MIN_SPEED = 5;
long long getMs (void) {
SYSTEMTIME stime;
GetLocalTime(&stime);
long long ms = stime.wMilliseconds +
stime.wSecond * 1000 +
stime.wMinute * 60000 +
stime.wHour * 3600000 +
stime.wDay * 86400000 +
stime.wMonth * 2592000000 +
(stime.wYear - 1970) * 31104000000;
return ms;
}
int main(int argc, char *argv[])
{
bool hardwareAccelerated = true;
if (argc == 2)
{
if (strncmp(argv[1], "-software", 9) == 0)
{
hardwareAccelerated = false;
}
}
char title [100];
sprintf(title, "Particles: %d - (%s)", PARTICLE_NUMBER, (hardwareAccelerated ? "HARDWARE ACCELERATED" : "SOFTWARE RENDERING"));
Particle<double> *particles = (Particle<double>*) malloc(sizeof(Particle<double>) * PARTICLE_NUMBER);
for (int i = 0; i < PARTICLE_NUMBER; i++)
{
double x = rand() % SCREEN_WIDTH;
double y = rand() % SCREEN_HEIGHT;
double direction = (((double) rand() / (double) RAND_MAX) - 0.5f) * 2 * M_PI;
double speed = rand() % (MAX_SPEED - MIN_SPEED) + MIN_SPEED;
(particles+i)->setPos(x, y);
(particles+i)->setDirection(direction);
(particles+i)->setSpeed(speed);
// std::cout << (particles+i) << std::endl;
}
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
return 1;
}
SDL_Window *window = SDL_CreateWindow(title,
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
if (window == nullptr) {
return 2;
}
SDL_RendererFlags flags = (hardwareAccelerated ? SDL_RENDERER_ACCELERATED : SDL_RENDERER_SOFTWARE);
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1,
flags);
if (renderer == nullptr) {
return 3;
}
bool quit = false;
SDL_Event evt;
long long lastFrame = getMs();
double delta = 0.f;
while (!quit)
{
long long currentTime = getMs();
delta = currentTime - lastFrame;
lastFrame = currentTime;
std::cout << "delta: " << delta << std::endl;
while(SDL_PollEvent(&evt) != 0)
{
if (evt.type == SDL_QUIT)
{
quit = true;
}
}
SDL_SetRenderDrawColor(renderer, 0,0,0,1);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 255,0,0,255);
for (int i = 0; i < PARTICLE_NUMBER; i++)
{
(particles+i)->tick(delta);
double *pos = (particles+i)->getPos();
SDL_RenderDrawPoint(renderer, pos[0], pos[1]);
}
SDL_RenderPresent(renderer);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
particle.h
#ifndef _H_PARTICLE
#define _H_PARTICLE
#include <math.h>
template <class T>
class Particle
{
public:
Particle(void);
void tick(double);
void setPos(T, T);
T* getPos(void);
void setDirection(double);
double getDirection(void);
void setSpeed(T);
T getSpeed(void);
~Particle(void);
private:
T x;
T y;
T speed;
double direction;
};
template <class T>
Particle<T>::Particle(void)
{
}
template <class T>
void Particle<T>::tick(double delta)
{
double dt = delta / 1000;
T d_speed = this->speed * dt;
// std::cout << d_speed << std::endl;
this->x += cos(this->direction) * d_speed;
this->y += sin(this->direction) * d_speed;
if (this->x > SCREEN_WIDTH) this->x = 0;
if (this->y > SCREEN_HEIGHT) this->y = 0;
if (this->x < 0) this->x = SCREEN_WIDTH;
if (this->y < 0) this->y = SCREEN_HEIGHT;
}
template <class T>
void Particle<T>::setPos(T x, T y)
{
this->x = x;
this->y = y;
}
template <class T>
T* Particle<T>::getPos(void)
{
T pos[2];
pos[0] = this->x;
pos[1] = this->y;
return pos;
}
template <class T>
void Particle<T>::setDirection(double direction)
{
this->direction = direction;
}
template <class T>
double Particle<T>::getDirection(void)
{
return this->direction;
}
template <class T>
void Particle<T>::setSpeed(T speed)
{
this->speed = speed;
}
template <class T>
T Particle<T>::getSpeed(void)
{
return this->speed;
}
template <class T>
Particle<T>::~Particle(void)
{
}
#endif
Why is this happening? Shouldn't the hardware renderer be a lot faster than the software one?
SDL_RenderDrawPoint() calls SDL_RenderDrawPoints() but wiht a count of 1.
SDL_RenderDrawPoints() calls SDL_stack_alloc() before rendering the number of points it needs to, and SDL_stack_free() when it's finished. That's probably your problem. You're doing a malloc and free for every single particle in your system, each frame.
I reckon Retired Ninja has the right idea - use SDL_RenderDrawPoints() instead and just do the malloc and free once each frame.
Alternatively - use a different paradigm. Create an SDL_Surface once. Each frame, you blit all the pixels you need to ( by directly manipulating the pixel memory of the SDL_Surface by doing SDL_MapRGB() on a particular pixel ) and then when it comes to rendering, convert the SDL_Surface to a an SDL_Texture and present that to the renderer.
Some example code - if a Particle is a class and contains a pointer to an SDL_Surface, then you could have a draw function that looks like this:
void Particle::draw()
{
Uint32 x = m_position.getX();
Uint32 y = m_position.getY();
Uint32 * pixel = (Uint32*)m_screen->pixels+(y*(m_pitch/4))+x;
Uint8 r1 = 0;
Uint8 g1 = 0;
Uint8 b1 = 0;
Uint8 a1 = 0;
GFX_RGBA_FROM_PIXEL(*pixel, m_screen->format, &r1, &g1, &b1, &a1);
Uint32 * p = (Uint32*)m_screen->pixels+(y*(m_pitch/4))+x;
*p = SDL_MapRGB(m_screen->format, m_r, m_g, m_b);
}
Where GFX_RGBA_FROM_PIXEL is (stolen from Andreas Schiffler's SDL2_gfx library) and is defined as:
///////////////////////////////////////////////////////////////////
void GFX_RGBA_FROM_PIXEL(Uint32 pixel, SDL_PixelFormat * fmt, Uint8* r, Uint8* g, Uint8* b, Uint8* a)
{
*r = ((pixel&fmt->Rmask)>>fmt->Rshift)<<fmt->Rloss;
*g = ((pixel&fmt->Gmask)>>fmt->Gshift)<<fmt->Gloss;
*b = ((pixel&fmt->Bmask)>>fmt->Bshift)<<fmt->Bloss;
*a = ((pixel&fmt->Amask)>>fmt->Ashift)<<fmt->Aloss;
}
It might work faster. I haven't done any time tests but it might be worth it, as you're directly manipulating the colour of pixel memory, and then simply blitting it each frame. You're not doing any mallocs or frees.