I'm a new person to C++, but i have learned a little Java and I/m working with SDL for the first time at the same time but my problem is I'm trying to create an object (paddle) p1 and p2.
this
#ifndef PONG_H_
#define PONG_H_
#undef main
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <SDL/SDL_ttf.h>
class paddle{
private:
int y;
int yv;
int x;
public:
paddle(){
y = 0;
yv = 0;
x = 0;
}
paddle(int ex, int why, int vel){
y = why;
yv = vel;
x = ex;
}
void setY(int ycoord) {y = ycoord;}
void setV(int velocity){ yv = velocity;}
void setX(int xcoord) {x = xcoord;}
int getX() {return x;}
int getY() {return y;}
int update(){y += yv; return y;}
};
class Pong { //pong class where everythin gets its name and a purpose.
private:
SDL_Surface * Paddle;
SDL_Surface * Ball; //SDL_Surface pointer for Ball
SDL_Surface * screen; //SDL_Surface pointer to backbuffer
public:
int Running;
Pong(); //eh..
int OnExecute(); //another function returning a value.
int w; //width of screen
int h; //height of screen
bool OnInit();
void OnEvent(SDL_Event* Event);
void OnLoop();
void OnRender();
void OnCleanup();
void redraw( int x, int y, SDL_Surface* source, SDL_Surface* destination ) { //Make a temporary rectangle to hold the offsets
SDL_Rect offset; //Give the offsets to the rectangle
offset.x = x; offset.y = y;
SDL_BlitSurface( source, NULL, destination, &offset );//Blit the surface
offset.x =0; offset.y=0; //resets the offsets sicne they apaprently dont reset per use.
};
};
#endif /* PONG_H_ */
is my header file, it contains the main functions of pong class also but I omitted those to make things less convoluted. Let me know if those are needed for a good answer.
and i declare the objects here...
#include <iostream>
#include <SDL/SDL.h>
#include "Pong.h"
paddle p1;
paddle p2;
Pong::Pong(){
h = 768;
w = 1024;
screen = NULL;
Paddle = NULL;
Ball = NULL;
Running = true;
atexit(SDL_Quit);
}
int Pong::OnExecute() {
if(OnInit() == false)
return-1;
SDL_Event Event;
while(Running) {
while(SDL_PollEvent(&Event)) {
OnEvent(&Event);
}
OnLoop();
OnRender();
}
OnCleanup();
return 0;
}
int main( int argc, char* args[]) {
Pong theApp;
return theApp.OnExecute();
}
but what sort of makes it difficult is i use it in...here:
#include "Pong.h"
void Pong::OnEvent(SDL_Event* Event) {
if(Event->type == SDL_QUIT)
Running = false;
switch(Event->type)
{
case SDL_KEYDOWN: //look for key holds
switch(Event->key.keysym.sym) //check key values and changes coords respectiely
{
default:
break;
case SDLK_UP:
p2.setV(-2);
break;
case SDLK_DOWN:
p2.setV(2);
break;
case SDLK_w:
p1.setV(-2);
break;
case SDLK_s:
p1.setV(2);
break;
case SDLK_ESCAPE:
Running = false;
break;
}
break;
case SDL_KEYUP:
switch(Event->key.keysym.sym)
{
default:
break;
case SDLK_UP:
p2.setV(0);
break;
case SDLK_DOWN:
p2.setV(0);
break;
case SDLK_w:
p1.setV(0);
break;
case SDLK_s:
p1.setV(0);
break;
}
break;
break;//break of Key holding event check
}
}
Its hard for me to ask the question because I don't know where to begin. I tried many different weird things and I'm just lost now. If you need any more info I'll be happy to provide.
void Pong::OnLoop(){
if(p1.getY()<=0){
p1.setV(0);
p1.setY(0);
}
if(p2.getY()<=0){
p2.setV(0);
p2.setY(0);
}
if(p1.getY()>=h - Paddle->h){
p1.setV(0);
p1.setY(h - Paddle->h);
}
if(p2.getY()>=h - Paddle->h){
p2.setV(0);
p2.setY(h - Paddle->h);
}
}
..\src\Pong_OnLoop.cpp:11:5: error: 'p1' was not declared in this scope
..\src\Pong_OnLoop.cpp:15:5: error: 'p2' was not declared in this scope
..\src\Pong_OnLoop.cpp:19:5: error: 'p1' was not declared in this scope
..\src\Pong_OnLoop.cpp:23:5: error: 'p2' was not declared in this scope
Since you haven't provided a clear question, it's difficult to provide the right answer, but my guess is that you can't access p1 and p2 in the OnEvent-/OnLoop-Method.
Is it absolutely necessary to let the two paddle-objects live in the global namespace? Because in this scenario I think it would be best to have 2 paddle-members as part of the Pong class, also I would use initialization lists like so:
class Pong {
private:
SDL_Surface * Paddle;
SDL_Surface * Ball; //SDL_Surface pointer for Ball
SDL_Surface * screen; //SDL_Surface pointer to backbuffer
paddle p1;
paddle p2;
public:
Pong() :
h(768),
w(1024),
screen(NULL),
Paddle(NULL),
Ball(NULL),
Running(true),
p1(10, 384, 0),
p2(1014, 384, 0) {
atexit(SDL_Quit);
};
// ...
};
You might not even need all initializers depending on the optimization settings and the default memory initialization but that's not the point. This way you should have access to p1 and p2 in all of Pongs own methods. Bo Perssons answer may work as well, but I think this is a more object- and thus C++-oriented approach.
On a side note: You said that the header file contains some more methods - seeing that your constructor is implemented in the cpp-file and the redraw-Method in the header-file you might want to learn a bit more about inlining. It won't be much of an issue in this example but it's usually best practice to move the more complex methods to the translation units (cpp-files), especially when creating libraries.
If you want the paddles visible in more than the file they are defined in, you have to add a declaration to the header file
extern paddle p1;
extern paddle p2;
so the other .cpp files will know that they exist.
Related
I have a Game class that through its constructor initializes the window and the SDL renderer. I understand from what I read so far (not much) that there should only be one renderer for each window.
Then I have a Player class where through the constructor I want to load a texture with an image, for which I need the renderer, therefore, I put the renderer as the constructor parameter and in this way I am forced to pass from the constructor from Game the renderer to the Player constructor (since it instantiated the Player class in The Game class).
The fact is that the renderer is passed before being created, and I don't know if there is another way to invoke the constructor of the Player from Game, since it forces me to put it that way. I leave the code for you to see:
Game class:
#pragma once
#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include "player.hpp"
//#include "helpers.hpp"
using namespace std;
#define WINDOW_WIDHT 640
#define WINDOW_HEIGTH 480
class Game
{
public:
Game();
~Game();
void loop();
void update() {}
void input();
void render();
void draw() {}
private:
SDL_Window *window;
SDL_Renderer *renderer = nullptr;
SDL_Event event;
SDL_Texture *gTexture;
bool running;
Player player;
};
Game::Game() : player(renderer)
{
SDL_Init(0);
SDL_CreateWindowAndRenderer(WINDOW_WIDHT, WINDOW_HEIGTH, 0, &window, &renderer);
SDL_SetWindowTitle(window, "Intento...");
//inicializa la carga de pngs
int imgFlags = IMG_INIT_PNG;
if (!IMG_Init(imgFlags) & imgFlags)
{
cout << "No se puede inicializar SDL_Img" << endl;
}
running = true;
loop();
}
Game::~Game()
{
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
IMG_Quit();
SDL_Quit();
}
void Game::loop()
{
while (running)
{
input();
render();
update();
}
}
void Game::render()
{
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
SDL_Rect rect;
rect.x = rect.y = 0;
rect.w = WINDOW_WIDHT;
rect.h = WINDOW_HEIGTH;
SDL_RenderFillRect(renderer, &rect);
SDL_RenderPresent(renderer);
}
void Game::input()
{
while (SDL_PollEvent(&event) > 0)
{
switch (event.type)
{
case SDL_QUIT:
running = false;
break;
}
}
}
Clase Player:
#pragma once
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <iostream>
//#include "helpers.hpp"
using namespace std;
class Player
{
public:
Player(SDL_Renderer *renderer);
~Player() = default;
const SDL_Rect getDest() { return dest; }
const SDL_Rect getSrc() { return src; }
void setDest(int x, int y, int w, int h);
void setSrc(int x, int y, int w, int h);
SDL_Texture *loadTexture(std::string path, SDL_Renderer *renderer);
private:
SDL_Rect dest;
SDL_Rect src;
};
Player::Player(SDL_Renderer *renderer){
loadTexture("mario.png", renderer);
/* setSrc(48, 48, 48, 48);
setDest(100, 100, 48, 48);
SDL_Rect playerRectSrc = getSrc();
SDL_Rect playerRectDest = getDest(); */
}
void Player::setDest(int x, int y, int w, int h){
dest.x = x;
dest.y = y;
dest.w = w;
dest.h = h;
}
void Player::setSrc(int x, int y, int w, int h){
src.x = x;
src.y = y;
src.w = w;
src.h = h;
}
SDL_Texture* Player::loadTexture(std::string path, SDL_Renderer *renderer)
{
SDL_Texture *newTexture = NULL;
SDL_Surface *loadedSurface = IMG_Load(path.c_str());
if (loadedSurface == NULL)
{
cout << "No se pudo cargar la imagen" << endl;
}
else
{
newTexture = SDL_CreateTextureFromSurface(renderer, loadedSurface);
if (newTexture == NULL)
{
cout << "No se pudo generar la textura para player" << endl;
}
SDL_FreeSurface(loadedSurface);
}
return newTexture;
}
The question is how to call the Player constructor after the renderer has been created? The only thing I can think of is not to create the texture through the constructor, but through a function, but it wouldn't be the right thing to do, right? that's what the constructor is for
The only thing I can think of is not to create the texture through the constructor, but through a function, but it wouldn't be the right thing to do, right? that's what the constructor is for
Right. However, SDL is a C library so it doesn't use C++ RAII, which is responsible for construction/destruction. First, we call constructors in the member initializer list (: foo{}, bar{foo}), which provides us with fully constructed member objects. Then, we do whatever we want in the constructor body ({ use(foo); }). However, in your case the constructor body ({ SDL_CreateWindowAndRenderer(...); } ) is needed before member initialization (: player{renderer}).
The question is how to call the Player constructor after the renderer has been created?
Construct all that SDL_ stuff before constructing the Player:
class RenderWindow {
SDL_Window* window;
SDL_Renderer* renderer;
public:
RenderWindow() {
SDL_Init(0);
SDL_CreateWindowAndRenderer(WINDOW_WIDHT, WINDOW_HEIGTH, 0, &window, &renderer);
SDL_SetWindowTitle(window, "Intento...");
}
// an easy double-free protection, you can use anything else
RenderWindow(RenderWindow&&) = delete;
~RenderWindow() {
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
}
// lvalue-only to forbid dangling like RenderWindow{}.raw_renderer()
auto raw_renderer() & { return renderer; }
};
Now, your Player and Game can be implemented in a natural RAII construct-then-use way:
class Player {
public:
Player(SDL_Renderer*); // TODO implement
};
class Game {
// note the declaration order: construction goes from top to bottom
RenderWindow render_window;
Player player;
public:
// SDL_* happens in render_window{},
// so player{render_window.raw_renderer()} gets an initialized SDL_Renderer
Game(): /*render_window{},*/ player{render_window.raw_renderer()} {}
};
Im am trying to make a clean and organized way of making sprites. The problem is that the position of the sprites are being read as zero and they are just being drawn in the top left corner.
Sprite.h
#ifndef Sprite_h
#define Sprite_h
#endif /* Sprite_h */
using namespace std;
bool show = true;
class Sprite{
public:
int Spritex;
int Spritey;
string name;
sf::Texture texture;
Sprite(string image, int x, int y){
x = Spritex;
y = Spritey;
texture.loadFromFile(image);
}
sf::Sprite getSprite() {
sf::Sprite sprite;
sprite.setTexture(texture);
sprite.setPosition(Spritex, Spritey);
return sprite;
}
void changeimage(string image);
};
void Sprite:: changeimage(string image){
texture.loadFromFile(image);
}
main.cpp
#include <iostream>
#include <SFML/Graphics.hpp>
#include "Character.h"
#include "Projectile.h"
#include "Sprite.h"
//Use std
using namespace std;
//Boolean to determine if screen will scroll
bool scroll = false;
//player that is part of Character class and computer that is part of Sprite class
Character player("/Users/danielrailic/Desktop/Xcode /NewGame/ExternalLibs/Sprites/Player.png");
Sprite computer("/Users/danielrailic/Desktop/Xcode /NewGame/ExternalLibs/Sprites/CompSprite.png", 1200, 100);
Sprite battery("/Users/danielrailic/Desktop/Xcode /NewGame/ExternalLibs/Sprites/battery4.png", 0, 0);
//boolean for whether to show weapon or not
bool showweapon;
//main loop
int main() {
int windowWidth = 5000;//width of window
int windowHeight = 5000;//height of window
sf::RenderWindow window(sf::VideoMode(windowWidth, windowHeight ), "Awesome Game" );//Make the window
//Setting up the dungeon back-round
sf::Texture dungeon;
dungeon.loadFromFile("/Users/danielrailic/Desktop/Xcode /NewGame/ExternalLibs/Sprites/DungeonBack.png");
sf::Sprite backround;
backround.setTexture(dungeon);
while (window.isOpen()){
// check all the window's events that were triggered since the last iteration of the loop
sf::Event event;
while (window.pollEvent(event)){
// "close requested" event: we close the window
if (event.type == sf::Event::Closed)
window.close();
}
//Movement
if (moveChar == true){
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)){
player.left();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)){
player.right();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)){
player.forward();
}
if (sf:: Keyboard::isKeyPressed(sf::Keyboard::Down)){
player.backward();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::LShift))
{
player.Highspeed();
}
else{
player.Lowspeed();
}
}
//If player intersects with comp sprite, pick up comp sprite
if (player.getSprite().getGlobalBounds().intersects(computer.getSprite().getGlobalBounds())){
show = false;
player.hascomp = true;
}
//draw and window stuff
window.clear(sf::Color(255, 255, 255));
window.draw(backround);
if (show == true){
window.draw(computer.getSprite());
}
if (show == false){
window.draw(battery.getSprite());
}
window.draw(player.getSprite());
window.display();
window.setFramerateLimit(70);
}
}
If you have a question I will do my best to answer. Everything works except the spritex and spritey are being read as 0 for some reason. Thanks for any help.
You are writing to variables x and y here, which you never read from:
Sprite(string image, int x, int y){
x = Spritex;
y = Spritey;
texture.loadFromFile(image);
}
I assume you flipped the assignments, and should write
Sprite(string image, int x, int y){
Spritex = x;
Spritey = y;
}
or
Sprite(string image, int x, int y) : Spritex(x), Spritey(y) {
texture.loadFromFile(image);
}
If you turn up your warning levels, you will be warned about things like this, and also the non-initialized member you still have (name)
I use Visual Studio Community as an IDE.
My main problem is that my code simply doesn't present the information produced by the renderer onto the window. It opens a blank white window with nothing on it. However, it is strange as there are no build errors and every line of code runs, just nothing is presented.
After searching around for the issue i found that many, if not all, code examples aren't split into more than one function so i couldn't compare the issue.
After thinking this, i changed my code to another version which basically had all the rendering and production (Same base code as below) in one function with a 'SDL_RenderPresent' at the end of that function.
This worked for one part of the code, the part that produced a tiled grass background, but not for the randomly placed Rabbit sprite.
I searched for this issue as well but equally found nothing as all just had once section they wanted to render.
I know my issue contains a few issues that should probably be in separate questions but it seemed to go from problem to problem so i've reached out for higher knowledge on all grounds.
This is my Display.cpp file where the problem, i suspect, lies.
#include "Display.h"
Display::Display(){
}
Display::~Display(){
}
void Display::World() {
//Gets display size to scale from :)
SDL_DisplayMode screen;
SDL_GetDesktopDisplayMode(0, &screen);
int screenW = screen.w; //These produce 0 for some reason??
int screenH = screen.h; // ^^
//Fin
SDL_Window * window = SDL_CreateWindow("SDL2 Displaying Image", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, screenW, screenH - 20, SDL_WINDOW_SHOWN);
SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_TARGETTEXTURE || SDL_RENDERER_ACCELERATED);
SDL_Surface * surfaceGrass = IMG_Load("Grass.jpg"); //Grass Sprite is 200 by 200 px
SDL_Texture * grass = SDL_CreateTextureFromSurface(renderer, surfaceGrass);
SDL_FreeSurface(surfaceGrass);
//Start of grass make things
int grassW = screenW * 0.25;
int grassH = grassW;
int vertical;
for (int i = 0; i <= 3; i++) {
switch (i) {
case(0):
vertical = 0;
break;
case(1):
vertical = grassW;
break;
case(2):
vertical = 2 * grassW;
break;
}
for (int j = 0; j < screenW; j = j + grassW) {
SDL_Rect screenRectForGrass = { j, vertical, grassW, grassH };
SDL_RenderCopy(renderer, grass, NULL, &screenRectForGrass);
}
}
//End of grass make things
MakeRabbit();
}
void Display::MakeRabbit() {
int colour = rand() % 10;
if (colour <= 3) {
std::cout << "Colour statement" << std::endl;
SDL_Surface * surfaceRabbit = IMG_Load("Brown Rabbit.jpg"); //Produces a square 50 by 50 pixels
SDL_Texture * rabbit = SDL_CreateTextureFromSurface(renderer, surfaceRabbit);
}
else {
std::cout << "Colour statement" << std::endl;
SDL_Surface * surfaceRabbit = IMG_Load("Black Rabbit.jpg");
SDL_Texture * rabbit = SDL_CreateTextureFromSurface(renderer, surfaceRabbit);
}
int randomX = rand() % 50;
int randomY = rand() % 50;
SDL_Rect screenRectForRabbit = { randomX, randomY, 50, 50 };
SDL_RenderCopy(renderer, rabbit, NULL, &screenRectForRabbit);
DisplayRenderer();
}
void Display::DisplayRenderer() {
SDL_RenderPresent(renderer);
Quit();
}
void Display::Quit() {
bool quit = false;
SDL_Event event;
while (!quit) {
SDL_WaitEvent(&event);
switch (event.type)
{
case SDL_QUIT:
quit = true;
break;
}
}
SDL_DestroyTexture(grass);
SDL_DestroyTexture(rabbit);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_FreeSurface(surfaceRabbit);
}
Display.h file
#include <iostream>
#include <SDL.h>
#include <SDL_image.h>
#include <time.h>
#include <stdlib.h>
using namespace std;
class Display{
private:
SDL_Window * window;
SDL_Renderer * renderer;
SDL_Surface * surfaceGrass;
SDL_Surface * surfaceRabbit;
SDL_Texture * rabbit;
SDL_Texture * grass;
private:
int screenW;
int screenH;
public:
Display();
~Display();
void MakeRabbit();
void World();
void DisplayRenderer();
void Quit();
};
and Main.cpp
#include "Display.h"
int main(int argc, char ** argv){
srand(time(NULL));
SDL_Init(SDL_INIT_EVERYTHING);
IMG_Init(IMG_INIT_JPG);
Display Main;
Main.World();
SDL_Quit();
IMG_Quit();
return 0;
}
You are redefining several of your variables each time you assign to them.
Instead of
SDL_Texture * rabbit = ...
use
rabbit = ...
This will use the SDL_Texture * rabbit variable that you already have defined in the class. The way you are doing it creates two different pointers, both called rabbit, but in different scopes.
I made a character class for the player, and I want to add a player member to the class then draw the player. I am using sfml and xcode. The error I am getting is: No matching member function for call to 'draw' on the: window.draw(player); line. It looks like I need to put a sprite object into .draw() so how do I make player sprite that is part of the class and draw it onto the window? I am new to c++ and sfml so any help is very much appreciated thanks.
#include <iostream>
#include <SFML/Graphics.hpp>
using namespace std;
class Character{
public:
string sprite;
int health;
int defense;
int speed;
int experience;
bool move;
int x_pos;
int y_pos;
sf::Texture texture;
//Constructor - Ran everytime a new instance of the class is created
Character(string image){
health = 100;
defense = 100;
speed = 100;
experience = 0;
x_pos = 0;
y_pos = 0;
texture.loadFromFile(image);
sf::Sprite sprite;
sprite.setTexture(texture);
sprite.setTextureRect(sf::IntRect(0, 0, 100, 100));
sprite.setPosition(x_pos, y_pos);
}
//Destructor - Ran when the object is destroyed
~Character(){
}
//Methods
void forward();
void backward();
void left();
void right();
void attack();
};
void Character::forward(){
cout << "Go Forward";
}
void Character::backward(){
cout << "Go Backward";
}
void Character::left(){
cout << "Go Left";
}
void Character::right(){
cout << "Go Right";
}
Character player("/Users/danielrailic/Desktop/Xcode /NewGame/ExternalLibs/Player.png");
int main() {
// insert code here...
int windowWidth = 1150;
int windowHeight = 750;
sf::RenderWindow window(sf::VideoMode(windowWidth, windowHeight ), "Awesome Game" );
while(window.isOpen()){
window.draw(player);
window.display();
window.setFramerateLimit(60);
}
}
You could simply add a member function that would return your player's sprite:
sf::Sprite Character::getSprite() {
sf::Sprite sprite;
sprite.setTexture(texture);
sprite.setTextureRect(sf::IntRect(0, 0, 100, 100));
sprite.setPosition(x_pos, y_pos);
return sprite;
}
Then pass the result to window.draw:
window.draw(player.getSprite());
Alternatively, you could invert the dependency and make the player responsible for all the drawing:
void Character::draw(sf::RenderWindow& w) {
w.draw(...);
}
There are other approaches, and the choice depends largely on a lot of external factors. This should get you started, though.
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);
}
}
}