I am trying to build my first program in SDL 1.2 simply to get familiar with SDL.
I have a headache trying to understand why my program immediately closes.
Does this have to do with the way I'm compiling it?
Here is all of my code and don't worry about trying to find logical errors that don't have to do with the error at hand. I simply want to find out why the program is immediately closing upon starting it.
Guy.h:
#ifndef GUY_H
#define GUY_H
class Guy{
public:
Guy(int, int);
void move();
void adjustVelocity(int, int);
int getX();
int getY();
int getXVel();
int getYVel();
private:
int xPos, yPos, xVel, yVel;
};
#endif
Guy.cpp:
#include "Guy.h"
Guy::Guy(int x, int y){
xPos = x;
yPos = y;
}
void Guy::move(){
xPos += xVel;
yPos += yVel;
}
void Guy::adjustVelocity(int x, int y){
xVel += x;
yVel += y;
}
int Guy::getX(){
return xPos;
}
int Guy::getY(){
return yPos;
}
int Guy::getXVel(){
return xVel;
}
int Guy::getYVel(){
return yVel;
}
main.cpp:
#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include "Guy.h"
#include <string>
#include <iostream>
bool init();
bool loadAllFiles();
void paintScreen();
void update();
bool handle();
void cleanUp();
void addSurface(int, int, SDL_Surface*, SDL_Surface*, SDL_Rect* clip = NULL);
SDL_Surface* loadFile(std::string);
SDL_Surface* Screen;
SDL_Surface* BackgroundIMG;
SDL_Surface* GuyIMG;
Guy* Hunter;
int main(int argc, char* args[]){
std::cout << "Why won't it even cout this?? :(" << endl;
if(!init()){
return 1;
}
if(!loadAllFiles()){
return 2;
}
Hunter = new Guy(0,0);
paintScreen();
while(handle()){
update();
}
cleanUp();
return 0;
SDL_Init(SDL_INIT_EVERYTHING);
Screen = SDL_SetDisplayMode(640, 480, 32, SDL_SWSURFACE);
SDL_Flip(Screen);
SDL_Delay(1000);
}
bool init(){
if(SDL_Init(SDL_INIT_EVERYTHING)==-1){
return false;
}
Screen = SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE);
if(Screen==NULL){
return false;
}
SDL_WM_SetCaption("First SDL Test On Own", NULL);
return true;
}
bool loadAllFiles(){
BackgroundIMG = loadFile("Background.png");
GuyIMG = loadFile("Guy.png");
if(BackgroundIMG==NULL || GuyIMG==NULL){
return false;
}
else{
return true;
}
}
void paintScreen(){
addSurface(0, 0, BackgroundIMG, Screen);
addSurface(Hunter->getX(), Hunter->getY(), GuyIMG, Screen);
SDL_Flip(Screen);
}
void update(){
Hunter->move();
addSurface(Hunter->getX(), Hunter->getY(), GuyIMG, Screen);
SDL_Flip(Screen);
}
bool handle(){
SDL_Event event;
while(SDL_PollEvent(&event)){
if(event.type==SDL_QUIT){
return false;
}
else if(event.type==SDL_KEYDOWN){
switch(event.key.keysym.sym){
case SDLK_UP:
Hunter->adjustVelocity(0, -1);
break;
case SDLK_DOWN:
Hunter->adjustVelocity(0, 1);
break;
case SDLK_RIGHT:
Hunter->adjustVelocity(1, 0);
break;
case SDLK_LEFT:
Hunter->adjustVelocity(-1, 0);
break;
}
}
}
return true;
}
void cleanUp(){
SDL_FreeSurface(GuyIMG);
SDL_FreeSurface(BackgroundIMG);
SDL_Quit();
delete Hunter;
}
void addSurface(int x, int y, SDL_Surface* source, SDL_Surface* destination, SDL_Rect* clip){
SDL_Rect offset;
offset.x = x;
offset.y = y;
SDL_BlitSurface(source, clip, destination, &offset);
}
SDL_Surface* loadFile(std::string s){
SDL_Surface* surface = IMG_Load(s.c_str());
if(surface==NULL){
return NULL;
}
else{
SDL_Surface* opsurface = SDL_DisplayFormat(surface);
SDL_FreeSurface(surface);
return opsurface;
}
}
My makefile:
all: main.o
g++ -o run main.o Guy.o -lSDL -lSDL_image
main.o: Guy.o
g++ -c main.cpp
Guy.o:
g++ -c Guy.cpp
Whenever I compile it with this makefile, I get no errors.
Your program immediately closes because you are using SDL_PollEvent(&event). This function will return false if there is no event to process, which in your case is happening when the program starts. If a user has to provide window inputs, the fact that there is no event to process is the rule and not the exception.
You have 2 alternatives :
Switch to SDL_WaitEvent. It is really similar to SDL_PollEvent, but the difference is that it is a blocking call.It has the advantage of being simple to obtain the behavior you expect from your app.
Stay with SDL_PollEvent, and add a mechanism to defer execution when there is no event to process. In general people use a SDL_Delay with a delay of 0 or 10. The advantage is that you have control of what the app does when there is no events.
Example of process loop scenario.
SDL_Event event;
bool stop = false;
while(!stop){
bool got_event = SDL_PollEvent(&event) > 0;
if(got_event){
stop = processEvent(event);
}
else {
if(backGroundWorkTodo()){
doBackGroundWork();
}
else{
//may defer execution
SDL_Delay(0);
}
}
}
Related
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;
}
I'm currently using this tutorial: https://www.youtube.com/watch?v=44tO977slsU&list=PLhfAbcv9cehhkG7ZQK0nfIGJC_C-wSLrx&index=3
But I've been getting this error on the first line that I don't know how to address as a beginner.
It says it's unresolved externals
I've been trying to look at some of the windows config advice, but I don't know how to apply it to this tutorial.
here's the code:
#include "Header.hpp"
Game::Game(){}
Game::~Game(){}
void Game::init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen)
{
int flags = 0;
if (fullscreen) { flags = SDL_WINDOW_FULLSCREEN; }
if (SDL_Init(SDL_INIT_EVERYTHING) == 0) {
std::cout << "Subsystems initialized" << std::endl;
window = SDL_CreateWindow(title, xpos, ypos, width, height, flags);
if (window) { std::cout << "Windows created" << std::endl; }
renderer = SDL_CreateRenderer(window, -1, 0);
if (renderer) {
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
std::cout << "renderer created" << std::endl;
}
isRunning == true; } else { isRunning == false; }
}
void Game::handleEvents() {
SDL_Event event;
SDL_PollEvent(&event);
switch (event.type) {
case SDL_QUIT:
isRunning = false;
break;
default:
break;
}
}
void Game::update() { count++; std::cout << count << std::endl; }
void Game::render() {
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
}
void Game::clean() {
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
std::cout << "Game cleaned" << std::endl;
}
this is is the header file, if it'll help:
#ifndef Header_hpp
#define Header_hpp
#include <iostream>
#include "SDL.h"
class Game {
public:
Game();
~Game();
void init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen);
void handleEvents();
void update();
void render();
void clean();
bool running(){ return isRunning; }
private:
int count = 0;
bool isRunning;
SDL_Window *window;
SDL_Renderer *renderer;
};
#endif / * Header_hpp */
I'm genuinely clueless on what could be causing this so I guess I'll include the main.cpp as well if something can be found there:
#include "Header.hpp"
Game* game = nullptr;
int main(int argc, const char * argv[]) {
game = new Game();
game->init("Birchengine", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, false);
while (game->running()) {
game->handleEvents();
game->update();
game->render();
}
game->clean();
return 0;
}
What could be the cause of this error, and how do I prevent it in the future?
I have recently started a game project in C++ using SDL2. I have created a class for the Game and included an init function which initializes SDL and creates a window. My code complies normally with 0 errors and warnings. However, when I run the executable file, I am not able to terminate the program nor a window appears.
My Code:
game.cc
#include "Game.hh"
#include <iostream>
using namespace std;
// Constructing Funtions
Game::Game()
{}
Game::~Game()
{}
// Initializing Function
void Game::init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen)
{
int flags = 0;
// Check to see if Fullscreen Mode has been called
if(fullscreen)
flags = SDL_WINDOW_FULLSCREEN;
if(SDL_Init(SDL_INIT_EVERYTHING) == 1) {
cout << "Initialization Complete" << endl;
// Create the Window
window = SDL_CreateWindow(title, xpos, ypos, width, height, flags);
// Create the Renderer
renderer = SDL_CreateRenderer(window, -1, 0);
if (renderer) {
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
}
// Set Is Running to True
isRunning = true;
} else {
isRunning = false;
}
}
// Looping Funtions
void Game::eventHandler()
{
// Initialize EventHandler & Get Event Type
SDL_Event event;
SDL_PollEvent(&event);
// Process Events
switch (event.type) {
case SDL_QUIT:
isRunning = false;
break;
default:
break;
}
}
void Game::update()
{}
void Game::render()
{
// Clear Renderer
SDL_RenderClear(renderer);
// Render Shit
SDL_RenderPresent(renderer);
}
void Game::clean()
{
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
cout << "Game Quit Successfuly" << endl;
}
bool Game::running()
{
return isRunning;
}
Game.hh
#ifndef GAME_HH
#define GAME_HH
#include "SDL.h"
class Game {
public:
// Constructor and Deconstructor
Game();
~Game();
// Initializing Functions
void init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen);
// Looping Commands
void eventHandler();
void update();
void render();
void clean();
// Application Running Checker
bool running();
private:
bool isRunning;
SDL_Window* window;
SDL_Renderer* renderer;
};
#endif
And finally main.cc
#include <iostream>
#include "Game.hh"
Game *game = nullptr;
int main()
{
game = new Game;
game->init("Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, false);
do {
game->eventHandler();
game->update();
game->render();
} while(game->running());
game->clean();
}
Any Ideas?
EDIT: found a fix to the issue, I made the public function running return the private isRunning variable. However, now the issue is that the code returns "Game Quit Successfully" w/out initiating anything...
So I'm basically following a book called SDL Game Development by Shaun Mitchell.
I'm current on page 58, where it tells us how to implement polymorphism.
So far what I have down are:
- Create the main code where we do all our rendering updating etc. (Game.cpp and Game.h)
- Create a Texture manager as a singleton (TextureManager.h and TextureManager.cpp)
- Create a GameObject (GameObject.h and GameObject.cpp)
- Create a Player that inherits GameObject (Player.h and Player.cpp)
So my GameObject class basically has 3 methods: load, draw and update.
Load basically loads an image, and I use my TextureManager to do so.
Draw draws it and update just changes it positions and current frame.
I pass the name of the image which is basically the directory, the renderer and the textureID from the Game class where I call them.
Essentially the problem is that I pass in two different directories into a GameObject
and a Player, but it only loads up the last directory I pass in. As in both GameObject and Player becomes the same image.
So I think the problem lies in Game class, Player class or GameObject class.
I create the objects in Game class, and push them in vector at Game.cpp in init function
Where it says
m_go->load(100, 100, 96, 60, "assets/simba.bmp", "animate",m_pRenderer);
m_player->load(300, 300, 96, 60, "assets/download.bmp", "animate",m_pRenderer);
GameObject.h
#ifndef GAMEOBJECT_H
#define GAMEOBJECT_H
#include <string>
#include <iostream>
#include "SDL_image.h"
#include "TextureManager.h"
class GameObject
{
public:
virtual bool load(int x, int y, int width, int height, std::string name, std::string textureID, SDL_Renderer* pRenderer);
virtual void draw(SDL_Renderer* pRenderer);
virtual void update();
virtual void clean();
protected:
std::string m_textureID;
int m_currentFrame;
int m_currentRow;
int m_x;
int m_y;
int m_width;
int m_height;
};
#endif // GAMEOBJECT_H
GameObject.cpp
#include "GameObject.h"
bool GameObject::load(int x, int y, int width, int height, std::string name, std::string textureID, SDL_Renderer* pRenderer)
{
m_x = x;
m_y = y;
m_width = width;
m_height = height;
m_textureID = textureID;
m_currentRow = 1;
m_currentFrame = 1;
if(!TextureManager::Instance()->load(name, textureID, pRenderer))
{
return false;
}
return true;
}
void GameObject::draw(SDL_Renderer* pRenderer)
{
TextureManager::Instance()->drawFrame(m_textureID, m_x, m_y,m_width, m_height, m_currentRow, m_currentFrame, pRenderer);
}
void GameObject::update()
{
m_x += 1;
m_currentFrame = int(((SDL_GetTicks() / 100) % 6));
}
void GameObject::clean()
{
}
In my Player class, I do the same thing except I use the methods that are already made in GameObject
Player.h
#ifndef PLAYER_H
#define PLAYER_H
#include "GameObject.h"
class Player : public GameObject
{
public:
bool load(int x, int y, int width, int height, std::string name, std::string textureID, SDL_Renderer* pRenderer);
void draw(SDL_Renderer* pRenderer);
void update();
void clean();
};
#endif // PLAYER_H
Player.cpp
#include "Player.h"
bool Player::load(int x, int y, int width, int height, std::string name, std::string textureID, SDL_Renderer* pRenderer)
{
if(!GameObject::load(x, y, width, height, name, textureID, pRenderer))
{
return false;
}
return true;
}
void Player::draw(SDL_Renderer* pRenderer)
{
GameObject::draw(pRenderer);
}
void Player::update()
{
m_currentFrame = int(((SDL_GetTicks() / 100) % 6));
m_x -= 1;
}
void Player::clean()
{
}
This is the part where the images doesn't load the same thing happens in Game.cpp
So I basically created a vector that holds GameObjects, it told me to use it so that I could just for loop through it whenever I want to draw objects
Game.h
#ifndef GAME_H
#define GAME_H
#include <SDL.h>
#include <SDL_image.h>
#include <string.h>
#include <iostream>
#include <vector>
#include "TextureManager.h"
#include "Player.h"
class Game
{
public:
Game() {}
~Game() {}
bool init(const char* title, int xpos, int ypos, int width, int height, int flags);
void render();
void update();
void handleEvents();
void clean();
// a function to access the private running variable
bool running() { return m_bRunning; }
private:
SDL_Window* m_pWindow;
SDL_Renderer* m_pRenderer;
int m_currentFrame;
bool m_bRunning;
GameObject* m_go;
GameObject* m_player;
std::vector<GameObject*> m_gameObjects;
};
#endif
Game.cpp
#include "Game.h"
typedef TextureManager TheTextureManager; // Singleton TextureManager
Game* g_game = 0; // Game Object
bool Game::init(const char* title, int xpos, int ypos, int width,int height, int flags)
{
// attempt to initialize SDL
if(SDL_Init(SDL_INIT_EVERYTHING) == 0)
{
std::cout << "SDL init success\n";
// init the window
m_pWindow = SDL_CreateWindow(title, xpos, ypos,width, height, flags);
if(m_pWindow != 0) // window init success
{
std::cout << "window creation success\n";
m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, 0);
if(m_pRenderer != 0) // renderer init success
{
std::cout << "renderer creation success\n";
SDL_SetRenderDrawColor(m_pRenderer,255,255,255,255);
}
else
{
std::cout << "renderer init fail\n";
return false; // renderer init fail
}
}
else
{
std::cout << "window init fail\n";
return false; // window init fail
}
}
else
{
std::cout << "SDL init fail\n";
return false; // SDL init fail
}
std::cout << "init success\n";
m_go = new GameObject();
m_player = new Player();
m_go->load(100, 100, 96, 60, "assets/simba.bmp", "animate",m_pRenderer);
m_player->load(300, 300, 96, 60, "assets/download.bmp", "animate",m_pRenderer);
m_gameObjects.push_back(m_go);
m_gameObjects.push_back(m_player);
m_bRunning = true; // everything inited successfully, start the main loop
return true;
}
void Game::render()
{
SDL_RenderClear(m_pRenderer); // clear the renderer to the draw color
//m_go.draw(m_pRenderer);
//m_player.draw(m_pRenderer);
for(std::vector<GameObject*>::size_type i = 0; i != m_gameObjects.size(); i++)
{
m_gameObjects[i]->draw(m_pRenderer);
}
SDL_RenderPresent(m_pRenderer); // draw to the screen
}
void Game::clean()
{
std::cout << "cleaning game\n";
SDL_DestroyWindow(m_pWindow);
SDL_DestroyRenderer(m_pRenderer);
SDL_Quit();
}
void Game::handleEvents()
{
SDL_Event event;
if(SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
m_bRunning = false;
break;
default:
break;
}
}
}
void Game::update()
{
//m_currentFrame = int(((SDL_GetTicks() / 100) % 6));
//m_go.update();
//m_player.update();
for(std::vector<GameObject*>::size_type i = 0; i != m_gameObjects.size(); i++)
{
m_gameObjects[i]->update();
}
}
int main(int argc, char* argv[])
{
g_game = new Game();
g_game->init("Chapter 1", 100, 100, 640, 480, 0);
while(g_game->running())
{
g_game->render();
g_game->handleEvents();
g_game->update();
SDL_Delay(10); // add the delay
}
g_game->clean();
return 0;
}
As you can see at the end of the init function, I have m_go load up simba, and m_player load up download. Even though they move in different directions (GameObject moves to the right and Player moves to the left as you can see in the classes in update method).
My program only loads download for both.
I'm not sure if the TextureManager class is related but I'll post it anyway
TextureManager.h
#ifndef TEXTUREMANAGER_H
#define TEXTUREMANAGER_H
#include <SDL.h>
#include <SDL_image.h>
#include <string.h>
#include <iostream>
#include <map>
class TextureManager
{
public:
bool load(std::string fileName,std::string id,SDL_Renderer* pRenderer);
void draw(std::string id, int x, int y, int width, int height, SDL_Renderer* pRenderer, SDL_RendererFlip flip = SDL_FLIP_NONE);
void drawFrame(std::string id, int x, int y, int width, int height, int currentRow, int currentFrame, SDL_Renderer* pRenderer, SDL_RendererFlip flip = SDL_FLIP_NONE);
std::map <std::string, SDL_Texture*> m_textureMap;
static TextureManager* Instance()
{
if(s_pInstance == 0)
{
s_pInstance = new TextureManager();
return s_pInstance;
}
return s_pInstance;
}
//typedef TextureManager TheTextureManager;
protected:
private:
TextureManager(){}
static TextureManager* s_pInstance;
};
#endif // TEXTUREMANAGER_H
TextureManager.cpp
#include "TextureManager.h"
TextureManager* TextureManager::s_pInstance = 0;
bool TextureManager::load(std::string fileName, std::string id, SDL_Renderer* pRenderer)
{
SDL_Surface* pTempSurface = IMG_Load(fileName.c_str());
if(pTempSurface == 0)
{
return false;
}
SDL_Texture* pTexture =
SDL_CreateTextureFromSurface(pRenderer, pTempSurface);
SDL_FreeSurface(pTempSurface);
// everything went ok, add the texture to our list
if(pTexture != 0)
{
m_textureMap[id] = pTexture;
return true;
}
// reaching here means something went wrong
return false;
}
void TextureManager::draw(std::string id, int x, int y, int width, int height, SDL_Renderer* pRenderer, SDL_RendererFlip flip)
{
SDL_Rect srcRect;
SDL_Rect destRect;
srcRect.x = 0;
srcRect.y = 0;
srcRect.w = destRect.w = width;
srcRect.h = destRect.h = height;
destRect.x = x;
destRect.y = y;
SDL_RenderCopyEx(pRenderer, m_textureMap[id], &srcRect,
&destRect, 0, 0, flip);
}
void TextureManager::drawFrame(std::string id, int x, int y, int width, int height, int currentRow, int currentFrame, SDL_Renderer *pRenderer, SDL_RendererFlip flip)
{
SDL_Rect srcRect;
SDL_Rect destRect;
srcRect.x = width * currentFrame;
srcRect.y = height * (currentRow - 1);
srcRect.w = destRect.w = width;
srcRect.h = destRect.h = height;
destRect.x = x;
destRect.y = y;
SDL_RenderCopyEx(pRenderer, m_textureMap[id], &srcRect,
&destRect, 0, 0, flip);
}
You are using "animate" more than once for the textureID - this needs to be unique
Your Code:
m_go->load(100, 100, 96, 60, "assets/simba.bmp", "animate", m_pRenderer);
m_player->load(300, 300, 96, 60, "assets/download.bmp", "animate", m_pRenderer)
What happens is the texture is loaded but it overwrites the existing texture which has the "animate" key in the map. Make them unique and this should resolve your issue.
I am working on building a game, and I get a compiling error apply_surface was not declared in this scope. the error is in line 95, in the function User::show().
EDIT: Now that it is fized, the image "baz", is not showing up on the screen. sorry for the edit.
/*This source code copyrighted by Lazy Foo' Productions (2004-2013)
and may not be redistributed without written permission.*/
//The headers
#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include <string>
SDL_Surface *background = NULL;
SDL_Surface *screen = NULL;
SDL_Surface *baz = NULL;
SDL_Event event;
void cleanup()
{
SDL_FreeSurface(background);
SDL_FreeSurface(screen);
SDL_FreeSurface(baz);
SDL_Quit;
}
bool quit = false;
class User
{
private:
SDL_Surface *baz = NULL;
SDL_Surface *screen = NULL;
int x;
int y;
int xVel;
int yVel;
public:
void keys();
void move();
void show();
void user();
};
void User::keys()
{
while(quit == false)
if(SDL_PollEvent(&event))
{
if( event.type == SDL_QUIT )
quit = true;
}
Uint8 *keystates = SDL_GetKeyState(NULL);
if(keystates[SDLK_d] )
{
User::xVel+=50;
}
if(keystates[SDLK_a])
{
User::xVel-=50;
}
if(keystates[SDLK_s])
{
User::yVel+=50;
}
if(keystates[SDLK_w])
{
User::yVel-=50;
}
if(keystates[SDLK_ESCAPE])
{
cleanup();
}
}
void User::user()
{
x = 0;
y = 0;
xVel = 0;
yVel = 0;
}
void User::move()
{
x+=xVel;
y+=yVel;
x-=xVel;
}
void User::show()
{
apply_surface(x,y,baz,screen);
SDL_Flip( screen );
}
void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination )
{ //Temporary rectangle to hold the offsets
SDL_Rect offset;
//Get the offsets
offset.x = x;
offset.y = y; //Blit the surface
SDL_BlitSurface( source, NULL, destination, &offset );
}
int main( int argc, char* argv[])
{
SDL_Init(SDL_INIT_EVERYTHING);
screen = SDL_SetVideoMode(640,400,32,SDL_SWSURFACE);
background = IMG_Load("background.png");
baz = IMG_Load("baz.png");
apply_surface(0,0,background,screen);
SDL_Flip(screen);
while( quit == false )
{
User Baz;
Baz.user();
Baz.keys();
Baz.move();
Baz.show();
if(quit == true)
{
cleanup();
}
}
return 0;
}
your apply_surface() function is not declared within the scope
So move your code :
void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination )
{ //Temporary rectangle to hold the offsets
SDL_Rect offset;
//Get the offsets
offset.x = x;
offset.y = y; //Blit the surface
SDL_BlitSurface( source, NULL, destination, &offset );
}
to the top ( before you use it )
Or else
Add a function prototype at the top like this :
void apply_surface( int, int, SDL_Surface*, SDL_Surface*);