I have been trying to make a pong clone as a first c++ "big" project, and I am encountering several problems.
First of all, this is my code so far:
game.hpp:
#pragma once
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
#include <iostream>
class Game
{
public:
Game();
~Game();
// GAME VARIABLES
const int WIDTH=720, HEIGHT=720, FONT_SIZE=32;
int running, lastTime;
int frameCount, timerFPS, lastFrame, fps;
// GAME TOOLS
SDL_Window *window;
SDL_Renderer *renderer;
TTF_Font *font;
SDL_Color color;
// GAME OBJECTS:
SDL_Rect rPaddle, lPaddle, Ball, scoreBoard;
// GAME FUNCTIONS:
void initRects(); // AFTER YOU HAVE A WORKING VERSION, TRY TO MOVE TO CONSTRUCTOR
void render();
void run();
};
game.cpp:
#include "game.hpp"
Game::Game()
{
running = 1;
if(SDL_Init(SDL_INIT_EVERYTHING)<0)
std::cerr << "SDL FAILED: SDL_INIT_EVERYTHING: " << SDL_GetError() << std::endl;
if(SDL_CreateWindowAndRenderer(WIDTH, HEIGHT, 0, &window, &renderer)<0)
std::cerr << "SDL FAILED: SDL_CreateWindowAndRenderer: " << SDL_GetError() << std::endl;
TTF_Init();
font = TTF_OpenFont("PreschoolBits.ttf", FONT_SIZE);
color.r=color.g=color.b=255;
}
Game::~Game()
{
TTF_CloseFont(font);
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
}
void Game::initRects()
{
lPaddle.x=32; lPaddle.h=HEIGHT/5;
lPaddle.y=(HEIGHT/2)-(lPaddle.h/2);
lPaddle.w=12;
rPaddle=lPaddle;
rPaddle.x=WIDTH-rPaddle.w-32;
Ball.w=Ball.h=16;
}
void Game::render()
{
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
frameCount++;
timerFPS=SDL_GetTicks()-lastFrame;
if(timerFPS<(1000/60))
SDL_Delay(timerFPS<((1000/60)-timerFPS));
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, 0);
SDL_RenderFillRect(renderer, &lPaddle);
SDL_RenderFillRect(renderer, &rPaddle);
SDL_RenderFillRect(renderer, &Ball);
SDL_RenderPresent(renderer);
}
void Game::run()
{
initRects();
while(running)
{
lastFrame=SDL_GetTicks();
if(lastFrame>=(lastTime+1000))
{
lastTime=lastFrame;
fps=frameCount;
frameCount=0;
}
render();
SDL_Delay(2000);
running=0;
}
}
pong.cpp:
#include "game.hpp"
int main()
{
Game game;
game.run();
return 0;
}
Now, when I try to render the render the rectangles, they don't show up. So I tried to remove them and just render colors on screen.
Both before and after the SDL_RenderClear I wrote:
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
But the window still showed up black, no matter what I tried.
What could I be doing wrong?
To make a filled Rect you must create a rect object:SDL_Rect MyRectName, Set its values to whatever you want:MyRectName.(w,h,x,y) = MyValue, and then to render, run SDL_RenderFillRect(MyRenderer, MyRectName);.
Related
I am trying to make a simple racing game with C++ using SDL2. When i tried rendering my car asset(PNG Image) it simply did not render saying in the console that it couldn't access the file. Note that the source files are located in an exclusive directory (src/), the headers are in /include and the images are located in /assets. Here is my code:
main.cpp
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <iostream>
#include <Headers/RenderWindow.hpp>
int main(int argc, char *args[])
{
if (SDL_Init(SDL_INIT_VIDEO) > 0)
{
std::cout << "SDL_Init has failed..." << std::endl;
}
if (!(IMG_Init(IMG_INIT_PNG)))
{
std::cout << "IMG_Init has failed" << std::endl;
}
RenderWindow window("Untitled Racing Game", 1280, 720);
SDL_Texture *blueCar = window.LoadTexture("../assets/blue_car.png");
bool run = true;
SDL_Event event;
while (run)
{
while (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT)
{
run = false;
}
}
window.Clear();
window.Render(blueCar);
window.Display();
}
window.CleanUp();
SDL_Quit();
return 0;
}
RenderWindow.hpp
#pragma once
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
class RenderWindow
{
public:
RenderWindow(const char *title, int width, int height);
SDL_Texture *LoadTexture(const char *filePath);
void CleanUp();
void Clear();
void Render(SDL_Texture *texture);
void Display();
private:
SDL_Window *window;
SDL_Renderer *renderer;
};
RenderWindow.cpp
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <iostream>
#include "Headers/RenderWindow.hpp"
RenderWindow::RenderWindow(const char *title, int width, int height)
: window(NULL), renderer(NULL)
{
window = (SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN));
if (window == NULL)
{
std::cout << "Window Failed to Load. Error " << SDL_GetError() << std::endl;
}
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
}
SDL_Texture *RenderWindow::LoadTexture(const char *filePath)
{
SDL_Texture *texture = NULL;
texture = IMG_LoadTexture(renderer, filePath);
if (texture == NULL)
{
std::cout << "Failed to load texture, " << SDL_GetError() << std::endl;
}
return texture;
}
void RenderWindow::CleanUp()
{
SDL_DestroyWindow(window);
}
void RenderWindow::Clear()
{
SDL_RenderClear(renderer);
}
void RenderWindow::Render(SDL_Texture *texture)
{
SDL_RenderCopy(renderer, texture, NULL, NULL);
}
void RenderWindow::Display()
{
SDL_RenderPresent(renderer);
}
I have a C++ project where I'm initially trying to display a PNG image to the screen.
This is my code.
RenderWindow.hpp
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
class RenderWindow
{
public:
RenderWindow(const char *p_title, int p_width, int p_height);
void render();
void cleanUp();
private:
SDL_Window *window;
SDL_Renderer *renderer;
SDL_Surface *image = IMG_Load("~/SDL2_Game/images/Green_Tile.png");
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, image);
};
RenderWindow.cpp
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <iostream>
#include "RenderWindow.hpp"
RenderWindow::RenderWindow(const char* p_title, int p_w, int p_h):window(NULL), renderer(NULL)
{
window = SDL_CreateWindow(p_title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, p_w, p_h, SDL_WINDOW_SHOWN);
if (window == NULL) std::cout << "Window failed to init: " << SDL_GetError() << std::endl;
renderer = SDL_CreateRenderer(window,-1,SDL_RENDERER_ACCELERATED);
}
void RenderWindow::render(){
SDL_RenderClear(renderer);
//SDL_Rect dstrect = { 5, 5, 320, 240 };
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
}
void RenderWindow::cleanUp(){
SDL_DestroyTexture(texture);
SDL_FreeSurface(image);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
}
main.cpp
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <iostream>
#include "RenderWindow.hpp"
int main(int argc, char** argv){
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
std::cout << "Problem with initialization. " << SDL_GetError() << std::endl;
}
else {
std::cout << "Initialization success!" <<std::endl;
}
if (!IMG_Init(IMG_INIT_PNG)){
std::cout << "Problem with Image initialization " <<SDL_GetError() << std::endl;
}
RenderWindow win("RPG_Game_v_1.0", 800, 600);
win.render();
bool gameRunning = true;
SDL_Event event;
while(gameRunning){
while(SDL_PollEvent(&event)){
if (event.type == SDL_QUIT) gameRunning = false;
}
}
win.cleanUp();
IMG_Quit();
SDL_Quit();
return 0;
}
I'm on a Linux machine.
I compile this with
g++ -g -o game ./*.cpp -lSDL2main -lSDL2 -lSDL2_image
Only a window is displaying. There is no image. I've tried refactoring my code with SDL_BlitSurface() and it does indeed display the PNG image. But why is this code not working? is it due to the fact that I'm using SDL_Texture* and my current system does not have a discrete graphics card?
I think that the call to SDL_CreateTextureFromSurface fails because it is called before SDL_CreateWindow and SDL_CreateRenderer, thereby initializing texture to NULL.
Please move the initizalization of texture (and image) to after window and renderer are initialized.
To further help with such issues, please check if the result of SDL functions != NULL and print SDL_GetError() to get more information about what went wrong.
I'm learning the basics of creating a window using SDL2 by following a tutorial. The code works just fine, and even compiles correctly, however on runtime it gives the error message 'Assertion failure at SDL_RenderClear_REAL'.
I've tried reinstalling SDL2, as well as moving it to the user library folder on my mac, but neither of these fixed the issue
main.cpp
#include "game.hpp"
Game *game = nullptr;
int main() {
game = new Game();
game->init("GUI", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, false);
while (game->running()) {
game->handleEvents();
game->update();
game->render();
}
game->clean();
return 0;
}
game.cpp
#include "game.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 == true) {
flags = SDL_WINDOW_FULLSCREEN;
}
if (SDL_Init(SDL_INIT_EVERYTHING) == 0) {
std::cout << "Sub-systems initialized\n";
window = SDL_CreateWindow(title, xpos, ypos, width, height, flags);
if (window) {
std::cout << "Window created.\n";
}
renderer = SDL_CreateRenderer(window, -1, 0);
if (renderer) {
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
std::cout << "Renderer created\n";
}
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() {
cnt++;
std::cout << cnt << "\n";
}
void Game::render() {
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
}
void Game::clean() {
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
std::cout << "Game cleaned\n";
}
game.hpp
#ifndef game_hpp
#define game_hpp
#include "SDL2/SDL.h"
#include <iostream>
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 cnt = 0;
bool isRunning;
SDL_Window *window;
SDL_Renderer *renderer;
};
#endif
After narrowing down the code, it seems that the issue is limited to SL_RenderClear. Here's the exact message it produces in the console:
2019-08-20 15:26:15.508900-0500 GUI[26436:7287503] WARN:
Assertion failure at SDL_RenderClear_REAL (/Users/valve/release/SDL/SDL2-2.0.10-source/src/render/SDL_render.c:2235), triggered 1 time:
'renderer && renderer->magic == &renderer_magic'
Program ended with exit code: 42
How can I fix this issue?
EDIT: Added full code to help identify the problem.
A basic "hello world" of creating a window and clearing the color on the screen for SDL requires a few boilerplate initialization steps
Initialize SDL
Create a SDL_Window
Create a SDL_Renderer
After which you can do
SDL_RenderClear and use SDL_RenderDrawColor to set a custom color to make it more obvious that it is properly clearing the Renderer.
Without error checking this would look something like:
SDL_Init(flags);
SDL_Window* window = SDL_CreateWindow("window title", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, more_flags);
SDL_SetRenderDrawColor(renderer, red, green, blue, alpha);
SDL_RenderClear(renderer);
Also remember to call SDL_Delay(ms) if you want the program to not immediately close before you get a chance to see the window.
I'm trying to render a SDL_Rect in a class, I send the renderer to the "draw" function of my class, and then render it from there.
void Tray::draw(SDL_Renderer *renderer){
SDL_RenderFillRect(renderer, &bckRect);
}
When I put the same code on my main loop. All goes fine, but when I do this from my tray class, It compiles, but doesn't run.
Simplified code:
main.cpp
#include <iostream>
#include <SDL2/SDL.h>
// local includes
#include "editor.h"
using namespace std;
int main(int argc, const char * argv[]) {
Editor *editor = new Editor();
while (editor->running){
editor->render();
}
editor->clean();
return 0;
}
editor.h
#ifndef EDITOR_H
#define EDITOR_H
#include <iostream>
#include <SDL2/SDL.h>
#include "Gui-classes/tray.h"
#include "properties.h"
class Editor{
private:
// Window variables
SDL_Window *window;
SDL_Renderer *renderer;
Tray *tray;
public:
Editor();
~Editor();
void render();
};
#endif
editor.cpp
#include "editor.h"
Editor::Editor(){
props = new Properties();
if (SDL_Init(SDL_INIT_EVERYTHING) == 0) {
window = SDL_CreateWindow("Great Editor", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1000, 600, SDL_WINDOW_RESIZABLE);
running = true;
if (window) {
std::cout << "Window created!" << std::endl;
}
renderer = SDL_CreateRenderer(window, -1, 0);
}
}
void Editor::render(){
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 12, 12, 55, 255);
tray->draw(renderer);
SDL_RenderPresent(renderer);
}
void Editor::clean(){
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
std::cout << "Window ended" << std::endl;
}
tray.h
#ifndef TRAY_H
#define TRAY_H
#include <iostream>
#include <SDL2/SDL.h>
class Tray{
private:
// Position variables
int x;
int y;
int w;
int h;
//Display variables
SDL_Color color;
SDL_Rect bckRect;
public:
Tray();
~Tray();
void draw(SDL_Renderer *renderer);
};
#endif
Tray.cpp
#include "tray.h"
Tray::Tray(){
bckRect.x = x;
bckRect.x = y;
bckRect.w = w;
bckRect.h = h;
}
Tray::~Tray(){
}
void Tray::draw(SDL_Renderer *renderer){
SDL_RenderFillRect(renderer, &bckRect);
//std::cout << "teeest" << std::endl;
}
Thanks for the help.
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...