i can't show text on the window using SDL2 TTF library - c++

I make a SDL_ttf test code:
#include <SDL.h>
#include <stdbool.h>
#include <iostream>
#include "SDLwindow.h"
#include <SDL_ttf.h>
#include "GraphLib.h"
#undef main
using namespace std;
int main() {
bool running = 1;
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
TTF_Init();
WindowSDL window1;
TTF_Font* font = TTF_OpenFont("./acme.ttf", 10);
SDL_Surface* textSurf = TTF_RenderText_Solid(font, "Hola mundo", {255,0,0});
SDL_Texture* textTexture = SDL_CreateTextureFromSurface(window1.renderer, textSurf);
SDL_FreeSurface(textSurf);
SDL_Rect textRect;
textRect.x = 10;
textRect.y = 10;
textRect.w = 400;
textRect.h = 100;
//TTF_CloseFont(font);
window1.CreateWindow("Pix", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 600, 600, SDL_WINDOW_BORDERLESS);
window1.CreateRenderer(window1.window, -1, 0);
window1.ChangeBackgroundColor(0xe0e0e0);
drawLine(window1, 3, 3, 40, 50, 0x0aaf88, 0);
drawLine(window1, 40, 50, 80, 3, 0x0aaf88, 0);
drawLine(window1, 80, 3, 3, 3, 0x0aaf88, 0);
SDL_RenderCopy(window1.renderer, textTexture, NULL, &textRect);
SDL_RenderPresent(window1.renderer);
while (running) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
running = 0;
}
}
}
window1.Shutdown();
TTF_Quit();
return 0;
}
...and... boom it doesn't appear, heres my screen:
I tried to change the order of certain lines like TTF_Init(); and so on, the results were the same, it does not appear on the screen

Related

X11 won't open a window

I am trying to open an X11 window, print out one pixel, and then later add code to make Terminate() return true. But it won't make a window. Here is my code:
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <iostream>
int x = 0;
int y = 0;
bool Termination() {
return true;
}
int main() {
Display *dspl = XOpenDisplay(NULL);
if (!dspl) return 1;
int screenNumber = DefaultScreen(dspl);
unsigned long white = WhitePixel(dspl, screenNumber);
unsigned long black = BlackPixel(dspl, screenNumber);
Window win = XCreateSimpleWindow(dspl, DefaultRootWindow(dspl), 50, 50, 1280, 720, 0, black, white);
XSetStandardProperties(dspl, win, "Lel", "Gaem", None, NULL, 0, NULL);
GC gc = XCreateGC(dspl, win, 0,0);
XSetBackground(dspl, gc, black);
XSetForeground(dspl, gc, white);
XClearWindow(dspl, win);
XMapRaised(dspl, win);
XDrawPoint(dspl, win, gc, x, y);
while (Termination())
{
}
XFreeGC(dspl, gc);
XDestroyWindow(dspl, win);
XCloseDisplay(dspl);
printf("Job's done!\n");
return 0;
}
What's keeping X11 from making my window appear?
add this before the while
XMapWindow(dspl, win);
XInternAtom(dspl, "WM_DELETE_WINDOW", False);

Full frame-rate across multiple OpenGL windows?

I'm trying to make an OpenGL program with as many windows as I want. I know it's possible. I don't care if I have to use something other than SDL2, but I've tried GLFW3 and get the same results.
The problem is not that I can't create multiple windows or can't render to both of them. I can. The problem is no matter how I try to do it, whether I use a single thread or multiple, the frame rate is locked to a divisor of my monitor's refresh rate. What I mean is, if I have two windows rendering on the main thread and updated using SDL_GL_SwapWindow(window) I get 72fps for both of them (My monitor has a refresh rate of 144hz and 144/2=72hz). This is expected for a single thread because of v-sync. Each call to SDL_GL_SwapWindow is syncing the window to the refresh rate and 1/144 + 1/144 is 1/72. That's not the problem. The problem is I have tried using separate threads for each window and even then it runs at 72fps even though they should be rendering/swapping the buffers at the same time.
Example 1:
In this example, I have both windows rendering and swapping buffers on the main thread. This does what you would expect on a monitor with a refresh rate of 144hz. They render at 72fps.
#include <iostream>
#include <SDL2/SDL.h>
#undef main
#include <glad/glad.h>
int main() {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* w1 = SDL_CreateWindow("w1", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_OPENGL);
SDL_Window* w2 = SDL_CreateWindow("w2", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 700, 700, SDL_WINDOW_OPENGL);
SDL_GLContext c1 = SDL_GL_CreateContext(w1);
SDL_GLContext c2 = SDL_GL_CreateContext(w2);
SDL_GL_MakeCurrent(w1, c1);
gladLoadGL();
int r = 0, b = 0;
bool running = true;
while (running) {
uint64_t startTime = SDL_GetPerformanceCounter();
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
running = false;
} else if (event.type == SDL_WINDOWEVENT) {
if (event.window.event == SDL_WINDOWEVENT_CLOSE) {
SDL_GL_DeleteContext(c2);
SDL_DestroyWindow(w2);
}
}
}
SDL_GL_MakeCurrent(w1, c1);
glClearColor(r / 255.0f, 0, 0, 1);
r = (r + 1) % 256;
glClear(GL_COLOR_BUFFER_BIT);
SDL_GL_SwapWindow(w1);
SDL_GL_MakeCurrent(w2, c2);
glClearColor(0, 0, b / 255.0f, 1);
b = (b + 1) % 256;
glClear(GL_COLOR_BUFFER_BIT);
SDL_GL_SwapWindow(w2);
double deltaTime = (SDL_GetPerformanceCounter() - startTime) / (double)SDL_GetPerformanceFrequency();
std::cout << 1.0 / deltaTime << " fps" << std::endl;
}
SDL_GL_DeleteContext(c1);
SDL_DestroyWindow(w1);
SDL_Quit();
return 0;
}
Example 2:
In this example, I have both windows rendering and swapping buffers on their own threads. This doesn't do what I expect because it behaves the exact same as having them both on the same thread like in example 1.
#include <iostream>
#include <thread>
#include <SDL2/SDL.h>
#undef main
#include <glad/glad.h>
void RenderThread(bool& running, SDL_Window* window) {
SDL_GLContext context = SDL_GL_CreateContext(window);
SDL_GL_MakeCurrent(window, context);
gladLoadGL();
int r = 0;
while (running) {
uint64_t startTime = SDL_GetPerformanceCounter();
glClearColor(r / 255.0f, 0, 0, 1);
r = (r + 1) % 256;
glClear(GL_COLOR_BUFFER_BIT);
SDL_GL_SwapWindow(window);
double deltaTime = (SDL_GetPerformanceCounter() - startTime) / (double)SDL_GetPerformanceFrequency();
std::cout << 1.0 / deltaTime << " fps" << std::endl;
}
SDL_GL_DeleteContext(context);
}
int main() {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* w1 = SDL_CreateWindow("w1", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_OPENGL);
SDL_Window* w2 = SDL_CreateWindow("w2", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 700, 700, SDL_WINDOW_OPENGL);
bool running = true, r1 = true, r2 = true;
std::thread t1(RenderThread, std::ref(r1), w1);
std::thread t2(RenderThread, std::ref(r2), w2);
while (running) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
running = false;
r1 = false;
t1.join();
} else if (event.type == SDL_WINDOWEVENT) {
if (event.window.event == SDL_WINDOWEVENT_CLOSE) {
r2 = false;
t2.join();
SDL_DestroyWindow(w2);
}
}
}
}
SDL_DestroyWindow(w1);
SDL_Quit();
return 0;
}
I'm fine with using another library for the windows. If my problem can be fixed with a different library please tell me which one.

Mouse handling SDL2 very slow and sluggish in linux when VSYNC is turned ON

In the event handling loop of SDL2, calling the method SDL_GetMouseState(&x,&y); or using event.motion.x and event.motion.y for the relative mouse coordinates makes SDL2 responsiveness VERY SLUGGISH. Whats weird is SDL_GetMouseState()is alot faster than event.motion.x and y, however they are both unbearably bad. Is there any other way of getting the mouse pos? You can even try this. I setup a simple text program in SDL2 to test something responsive such as scrolling, where you offset the y values. Try with and without vsync and with and without getting the mouse pos this way. I am currently using linux mint.
Code: (You will need arial.ttf in your folder where the project is if using codeblocks like i am)
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
#include <SDL2/SDL_image.h>
#include <string>
using std::string;
using std::to_string;
int main(int argc, char* argv[])
{
SDL_Init(SDL_INIT_VIDEO);
TTF_Init();
SDL_Window *window = SDL_CreateWindow("Test Program", 0, 30, 1280, 720, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);// | SDL_WINDOW_SHOWN);
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC );
SDL_Event event;
SDL_Point mousePos = {0,0};
///Fps vars
int fpsCounter, fpsStart, fpsEnd;
fpsStart = SDL_GetTicks();
fpsEnd = SDL_GetTicks();
fpsCounter = 0;
TTF_Font *fpsFont = TTF_OpenFont("arial.ttf", 30);
SDL_Surface *fpsSurface = TTF_RenderText_Blended(fpsFont, "FPS: ", {0,0,0});
SDL_Texture *fpsTexture = SDL_CreateTextureFromSurface(renderer, fpsSurface);
SDL_FreeSurface(fpsSurface);
int textW, textH, yVal;
yVal = 50;
SDL_QueryTexture(fpsTexture, NULL, NULL, &textW, &textH);
SDL_Rect fpsRect = {1000, yVal, textW, textH};
bool running = true;
while (running)
{
while ( SDL_PollEvent(&event) )
{
if (event.type == SDL_QUIT)
{
running = false;
break;
}
else if (event.type == SDL_MOUSEMOTION){
int x,y;
SDL_GetMouseState(&x,&y);
mousePos = {x,y};
break;
}
else if (event.type == SDL_MOUSEWHEEL){
if (event.wheel.y > 0){ ///Scrolling up here
yVal -= 50;
fpsRect.y = yVal;
break;
}
if (event.wheel.y < 0){ ///Scrolling down here
yVal += 50;
fpsRect.y = yVal;
break;
}
}
}
SDL_SetRenderDrawColor(renderer, 255,255,255,255);
SDL_RenderClear(renderer);
//Update every 0.5s (500ms)
fpsEnd = SDL_GetTicks();
fpsCounter += 2;
if ( (fpsEnd-fpsStart) > 500 ){
fpsStart = SDL_GetTicks();
SDL_DestroyTexture(fpsTexture);
///Change text
string newText = ("FPS: " + to_string(fpsCounter));
fpsSurface = TTF_RenderText_Blended(fpsFont, newText.c_str(), {0,0,0});
fpsTexture = SDL_CreateTextureFromSurface(renderer, fpsSurface);
SDL_FreeSurface(fpsSurface);
SDL_QueryTexture(fpsTexture, NULL, NULL, &textW, &textH);
fpsRect = {1000, yVal, textW, textH};
fpsCounter = 0;
}
SDL_RenderCopy(renderer, fpsTexture, NULL, &fpsRect);
SDL_RenderPresent(renderer);
}
SDL_DestroyTexture(fpsTexture);
TTF_CloseFont(fpsFont);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
TTF_Quit();
SDL_Quit();
return 0;
}
I don't agree that turning off VSYNC is a solution. It shouldn't be like this with VSYNC on regardless. It isn't like this in windows for some reason, it works fine there. Capping the FPS with SDL_Delay() to the refresh rate of the display also gives me the same problem.
The problem is that you "break" every time you get an event. So, your event queue is full all the time as you only process one event per draw.
Replace "break" with "continue" and process all events.

Allegro Throws errors when trying to draw lines

For some reason allegro (C++ Game Engine), throws errors when i try to run... So first this code works fine ! :
#include <allegro5/allegro.h>
#include <allegro5/allegro_primitives.h>
int main(void)
{
int width = 640, height = 480;
ALLEGRO_DISPLAY *display = NULL;
if (!al_init())
return -1;
display = al_create_display(width, height);
if (!display)
return -1;
al_flip_display();
//al_draw_line(100, 100, width - 100, 100, al_map_rgb(255, 0, 0), 1);
al_rest(3);
al_destroy_display(display);
return 0;
}
But all the sudden when i try to uncomment that line above i get this "error".
More Closer Up:
As you can see above this is some type of assertion failling... Im Confused?! Help would be appreciated!
Before you can use the primitives add-on you need to initialize it by calling al_init_primitives_addon.
#include <allegro5/allegro.h>
#include <allegro5/allegro_primitives.h>
int main(void)
{
int width = 640, height = 480;
ALLEGRO_DISPLAY *display = NULL;
if (!al_init())
return -1;
display = al_create_display(width, height);
if (!display)
return -1;
al_init_primitives_addon();
if (!al_init_primitives_addon())
return -1;
al_draw_line(0, 50, 300, 100, al_map_rgb(255, 0, 4), 1.0f);
al_flip_display();
al_rest(13);
al_shutdown_primitives_addon();
al_destroy_display(display);
return 0;
}
The full documentation can be found here: https://www.allegro.cc/manual/5/al_init_primitives_addon.
Don't forget to call al_shutdown_primitives_addon when you're done.

exc_bad_access error xcode5 c++ sdl2

I've been toying with this code a guy on youtube attached to one of his tutorial videos... I've run into a few problems that I cant seem to get past... The current one is this 'EXC_BAD_ACCESS' error... From what I've researched briefly online these errors occur when you improperly use the stack and allocate memory to things that no longer exist or something like that... I just can't pinpoint what I'm doing wrong exactly... I've seen some troubleshooting done -- but nothing for xcode 5 yet
The error shows up in a class called 'cSprite.cpp':
// ~~~~~~~~~~~~~~~~~~~ cSprite.cpp ~~~~~~~~~~~~~~~~~~~~~~~~~~~
#include "stdafx.h"
#include "cSprite.h"
//#include "gMain.h"
//#include <SDL2/SDL_main.h>
//#include <SDL2/SDL.h>
//#include "cSDL_Setup.h"
using namespace std;
void draw(SDL_Renderer, SDL_Texture, SDL_Rect);
cSprite::cSprite(SDL_Renderer* passed_renderer, string filePath, int x, int y, int w, int h)
{
renderer = passed_renderer;
//... image
image = NULL;
image = IMG_LoadTexture(renderer,filePath.c_str());
// image error message
if (image == NULL)
{
cout<<"Couldnt load image..."<<filePath.c_str()<<endl;
}
//image dimensions
rect->x = x; // ***** Error: Thread 1:EXC_BAD_ACCESS(code=EXC_1386_GPFLT)
rect->y = y;
rect->w = w;
rect->h = h;
};
cSprite::~cSprite(void)
{
SDL_DestroyTexture(image);
}
//get methods
//SDL_Rect* cSprite::getRect()
//{
// return rect;
//}
//get methods
//SDL_Texture* cSprite::getImage()
//{
// return image;
//}
void cSprite::draw()
{
SDL_RenderCopy(renderer, image, NULL, rect);
}
... the line 'rect->x = x;'
gets the error I put beside it...but idk what else could be causing it... I was hoping someone could explain why EXC_BAD_ACCESS errors even occur... and/or where in the rest of my code it could be coming from...
here's my 3 other .cpp files
....
// ~~~~~~~~~~~~~~~~~~~~~~~~ gMain.cpp ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#include <iostream>
#include "stdafx.h"
#include "gMain.h"
using namespace std;
gMain::gMain(int passed_screenWidth, int passed_screenHeight)
{
screenWidth = passed_screenWidth;
screenHeight = passed_screenHeight;
// quit boolean
quit = false;
// create instance of cSDL class
csdl_setup = new cSDL_Setup(&quit, screenWidth, screenHeight);
grass = new cSprite(csdl_setup->getRenderer(), "/Users/jamesbryant/Desktop/nuGame/nuGame/images.jpeg", screenWidth, screenHeight, screenWidth, screenHeight);
bruce_Lee = new cSprite(csdl_setup->getRenderer(), "/Users/jamesbryant/Desktop/nuGame/nuGame/lee.bmp", 300, 300, 200, 200);
}
gMain::~gMain(void)
{
}
void gMain::gameLoop(void)
{
// game loop logic
while (!&quit && csdl_setup->getMainEvent() ->type != SDL_QUIT)
{
csdl_setup->begin();
grass->draw();
bruce_Lee->draw();
csdl_setup->end();
}
}
....
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cSDL_Setup.cpp ~~~~~~~~~~~~~~~~~~~~~~~~~~~
#include "stdafx.h"
#include "cSDL_Setup.h"
//#include "gMain.h"
using namespace std;
cSDL_Setup::cSDL_Setup(bool* quit, int screenWidth, int screenHeight)
{
// create window
window = NULL;
window = SDL_CreateWindow("rWDY_pWDR", 400, 400, screenWidth, screenHeight, SDL_WINDOW_RESIZABLE);
// if window couldnt be created...
if (window == NULL)
{
cout<<"Window couldnt be created..."<<endl;
*quit = true;
//exit(0);
}
//create renderer
renderer = NULL;
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
// initialize images
mainEvent = new SDL_Event();
}
cSDL_Setup::~cSDL_Setup(void)
{
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
delete mainEvent;
}
//get methods
SDL_Renderer* cSDL_Setup::getRenderer()
{
return renderer;
}
SDL_Event* cSDL_Setup::getMainEvent()
{
return mainEvent;
}
void cSDL_Setup::begin()
{
SDL_PollEvent(mainEvent);
SDL_RenderClear(renderer);
}
void cSDL_Setup::end()
{
SDL_RenderPresent(renderer);
}
....
// ~~~~~~~~~~~~~~~~~~~~~~~~~~ firstGame.cpp ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#include "stdafx.h"
#include "cSDL_Setup.h"
//#include "gMain.h"
using namespace std;
cSDL_Setup::cSDL_Setup(bool* quit, int screenWidth, int screenHeight)
{
// create window
window = NULL;
window = SDL_CreateWindow("rWDY_pWDR", 400, 400, screenWidth, screenHeight, SDL_WINDOW_RESIZABLE);
// if window couldnt be created...
if (window == NULL)
{
cout<<"Window couldnt be created..."<<endl;
*quit = true;
//exit(0);
}
//create renderer
renderer = NULL;
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
// initialize images
mainEvent = new SDL_Event();
}
cSDL_Setup::~cSDL_Setup(void)
{
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
delete mainEvent;
}
//get methods
SDL_Renderer* cSDL_Setup::getRenderer()
{
return renderer;
}
SDL_Event* cSDL_Setup::getMainEvent()
{
return mainEvent;
}
void cSDL_Setup::begin()
{
SDL_PollEvent(mainEvent);
SDL_RenderClear(renderer);
}
void cSDL_Setup::end()
{
SDL_RenderPresent(renderer);
}
... here's what my cSprite.h file looks like right now:
#ifndef __game__cSprite__
#define __game__cSprite__
#pragma once
#include <iostream>
#include <SDL2/SDL_main.h>
#include <SDL2/SDL.h>
using namespace std;
class cSprite
{
public:
cSprite(SDL_Renderer* passed_renderer, string filePath, int x, int y, int w, int h);
~cSprite(void);
void draw();
private:
SDL_Texture* image = NULL;
SDL_Rect* rect = NULL;
SDL_Renderer* renderer = NULL;
};
#endif /* defined(__game__cSprite__) */
You didn't post your header for cSprite. However, I imagine that rect is an SDL_Rect*.
The function getting the error is cSprite::cSprite(), ie. the constructor. One of its duties is to initialize all of the class members to reasonable values.
However, I do not see any code that initializes rect to point to anything. The error you're currently getting suggests you're dereferencing a bum pointer, and that's consistent with this observation.
You either need to allocate an SDL_Rect to assign to rect, or you should change rect to just be SDL_Rect, not SDL_Rect*. If you make the latter change, then you will also need to change all of your rect-> to rect., and pass a pointer to rect in the SDL calls that require it (ie. SDL_RenderCopy(renderer, image, NULL, &rect);)