I tried to use event management in C + +,
I joined the SDL library in VS and in my example,
here is my code:
#include "SDL/SDL.h"
int main(int argc, char *argv[])
{
SDL_Surface *ecran = NULL;
SDL_Event event; /* La variable contenant l'événement */
int continuer = 1; /* Notre booléen pour la boucle */
SDL_Init(SDL_INIT_VIDEO);
ecran = SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE);
SDL_WM_SetCaption("Gestion des événements en SDL", NULL);
while (continuer) /* TANT QUE la variable ne vaut pas 0 */
{
SDL_WaitEvent(&event); /* On attend un événement qu'on récupère dans event */
switch(event.type) /* On teste le type d'événement */
{
case SDL_QUIT: /* Si c'est un événement QUITTER */
continuer = 0; /* On met le booléen à 0, donc la boucle va s'arrêter */
break;
}
}
SDL_Quit();
return EXIT_SUCCESS;
}
No error in the code but after compiling I got an error:
LINK: fatal error LNK1561: entry point must be defined
Not sure if this is the same issue that you have, but I recall looking at this just a day or two ago!:
Quote:
There's something wrong with your project's settings. Did you actually create a Console Application? I think that you have created a Win32 Project instead of a Console. Do this:
Right click on project name -> Properties -> Expand Linker tab -> System -> SubSystem: make sure that it is Console (/SUBSYSTEM:CONSOLE).
Otherwise, re-create the project, but when you create it, make sure that you select Win32 Console Application.
link
Looks like you have the same issue here...
If I remember correctly, there was something in the SDL which wraps your main() function: In the SDL-header, there is a line
#define main some_other_name
and then, somewhere in the library, there is a main() implementation, which calls some_other_name().
If I read the symptoms correctly, you are not statically linking the sdl library, so that the linker does not see the main() definition inside SDL, only the function some_other_name() which you have defined.
Related
This is my code:
#include <iostream>
#include <SDL2/SDL.h>
int main(int argc, const char * argv[]) {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *_window;
_window = SDL_CreateWindow("Game Engine", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 700, 500, SDL_WINDOW_RESIZABLE);
SDL_Delay(20000);
SDL_DestroyWindow(_window);
SDL_Quit();
return 0;
}
Im working in Xcode. I've downloaded SDL2 and imported the library to the projects build phases. I've tested that the SDL2 works correctly.
The problem is that window never shows up. I just get a "spinning-mac-wheel" and then the program quits after the delay. I've made sure that the window is not hidden behind somewhere.
Ideas?
You have to give the system a chance to have it's event loop run.
easiest is to poll for events yourself:
SDL_Event e;
bool quit = false;
while (!quit){
while (SDL_PollEvent(&e)){
if (e.type == SDL_QUIT){
quit = true;
}
if (e.type == SDL_KEYDOWN){
quit = true;
}
if (e.type == SDL_MOUSEBUTTONDOWN){
quit = true;
}
}
}
instead of the wait loop
--- Addendum
Since this answer is still helping people maybe it's nice if I also add a bit more info on why this works instead of just posting the solution.
When on the Mac (same for Windows actually) a program starts, it starts with just the 'main thread'. This is the thread which is used to set up UI stuff. The 'main thead' differs from other threads in that it comes with an event handling system. This system catches events like mouse moves, key presses, button clicks and then queues these and lets your code respond to it. All the UI things on Mac (and Windows) rely on this event pump being there and running. This is the reason why if you do anything UI related in your code you need to make sure you are not on a different thread.
Now, in your code you initialise the window and the UI, but then you do a SDL_Delay. This just blocks the thread and halts it for 20 seconds so nothing is done. And since you do that on the main thread, even the handling of the queue with the events is blocked. So on the Mac that shows as the spinning macwheel.
So the solution I posted actually keeps on polling for events and handles them. This way you are effectively also 'idling', but the moment events are posted (like mouse clicks and keys) the thread will wake up again and stuff will be processed.
You have to load a bitmap image, or display something on the window, for Xcode to start displaying the window.
#include <SDL2/SDL.h>
#include <iostream>
using namespace std;
int main() {
SDL_Window * window = nullptr;
SDL_Surface * window_surface = nullptr;
SDL_Surface * image_surface = nullptr;
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow("Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_SHOWN);
window_surface = SDL_GetWindowSurface(window);
image_surface = SDL_LoadBMP("image.bmp");
SDL_BlitSurface(image_surface, NULL, window_surface, NULL);
SDL_UpdateWindowSurface(window);
SDL_Delay(5000);
SDL_DestroyWindow(window);
SDL_FreeSurface(image_surface);
SDL_Quit();
}
You need to initialize SDL with SDL_Init(SDL_INIT_VIDEO) before creating the window.
Please remove the sdl_delay() and replace it with the below mentioned code. I don't have any reason for it but I tried on my own and it works
bool isquit = false;
SDL_Event event;
while (!isquit) {
if (SDL_PollEvent( & event)) {
if (event.type == SDL_QUIT) {
isquit = true;
}
}
}
This test program should create a blank window that stays open until you x-it-out. I copied it from SDL's documentation to make sure it is correct. It can be found here.
// Example program:
// Using SDL2 to create an application window
#include "SDL.h"
#include <stdio.h>
int main(int argc, char* argv[]) {
SDL_Window *window; // Declare a pointer
SDL_Init(SDL_INIT_VIDEO); // Initialize SDL2
// Create an application window with the following settings:
window = SDL_CreateWindow(
"An SDL2 window", // window title
SDL_WINDOWPOS_UNDEFINED, // initial x position
SDL_WINDOWPOS_UNDEFINED, // initial y position
640, // width, in pixels
480, // height, in pixels
SDL_WINDOW_OPENGL // flags - see below
);
// Check that the window was successfully created
if (window == NULL) {
// In the case that the window could not be made...
printf("Could not create window: %s\n", SDL_GetError());
return 1;
}
//game loop, quitGame to quit
bool quitGame = false;
//var for checking events
SDL_Event event;
while(!quitGame) {
//Update particles
//Draw particles
//Check for events
while(SDL_PollEvent(&event)) {
if(event.type == SDL_QUIT)
quitGame = true;
}
}
// Close and destroy the window
SDL_DestroyWindow(window);
// Clean up
SDL_Quit();
return 0;
}
It doesn't create a window and terminates immediately, but gives no errors.
I'm using Eclipse, mingw32, and the latest stable release of SDL2. SDL2's libraries and headers are within a file in my C drive. I am using a 64 bit system. I include the entire folder of SDL2's header files. The only library folder I have linked is the one within the 64 bit part of the SDL2 folder. The libraries I have linked are the ones suggested by HolyBlackCat, (in this order) mingw32, SDL2main, and SDL2. Any help is greatly appreciated. Thanks!
I've been writing some rudimentary code in C++ with the SDL2 library. It was working flawlessly, but I needed to print some text on screen, and to do that, I had to download the SDL2 TTF library. I installed it just like I did with SDL2. I tried to simply print a word, but once I compile the code, Visual Studio says the following:
Unhandled exception at 0x71002A95 (SDL2_ttf.dll) in nuevo proyecto.exe:
0xC0000005: Access violation reading location 0x00000000.
And the program just doesn't work, it's frozen in a white screen (it worked with no problems before I tried to use the TTF library). What can I do? Thanks in advance. Here's my code:
#include "stdafx.h"
#include <SDL.h>
#include <SDL_ttf.h>
#include <string>
SDL_Window * ventana;
SDL_Surface * superficie;
SDL_Surface * alpha;
SDL_Surface * renderizar;
SDL_Surface * texto;
bool inicia = false, cierra=false;
SDL_Point mouse;
TTF_Font *fuente = TTF_OpenFont("arial.ttf", 20);
char* palabras="hola";
SDL_Color color = { 0, 0, 0, 0 };
int controles(){
SDL_GetMouseState(&mouse.x,&mouse.y);
return 0;
}
int graficos(char *archivo){ //la primera vez inicia ventana
//el argumento es el nombre del bmp a renderizar
if (inicia == false){ ventana = SDL_CreateWindow("ventana", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0); } //abre ventana solo una vez
inicia = true; // no permite que se abra mas de una vez la ventana
superficie = SDL_GetWindowSurface(ventana);
alpha = SDL_LoadBMP("alpha.bmp");
texto = TTF_RenderText_Solid(fuente, palabras, color);
renderizar = SDL_LoadBMP(archivo);
SDL_Rect rectangulo = { 0, 0, 640, 480 };
SDL_Rect rrenderizar = { mouse.x, mouse.y, 4, 4 };
SDL_Rect rtexto = { 0, 0, 60, 60 };
SDL_BlitSurface(alpha, NULL, superficie, &rectangulo);
SDL_BlitSurface(renderizar, NULL, superficie, &rrenderizar);
SDL_BlitSurface(texto, NULL, superficie, &rtexto);
SDL_UpdateWindowSurface(ventana);
return 0;
}
int main(int argc, char **argv)
{
TTF_Init();
SDL_Init(SDL_INIT_VIDEO);
SDL_Event evento;
while (!cierra){
SDL_PollEvent(&evento);
switch (evento.type){
case SDL_QUIT:cierra = true; break;
}
//programa aqui abajo
controles();
graficos("hw.bmp");
}
TTF_Quit();
SDL_Quit();
return 0;
}
PS: I do have the DLL's, fonts and other files in the Debug folder.
According to SDL_TTF Documentation:
int TTF_Init()
Initialize the truetype font API. This must be called
before using other functions in this library, except TTF_WasInit. SDL
does not have to be initialized before this call.
You call TTF_OpenFont before calling TTF_Init when declaring your font variable. Instead you should do:
TTF_Font* fuente = NULL;
int main()
{
TTF_Init();
fuente = TTF_OpenFont("arial.ttf", 20);
...
}
I'm fairly new to programming, so this question will probably be basic. I'm writing a very basic program in C++ with the SDL2 library (in Visual Studio 2013). When I was writing it, I came across a problem. I wrote the following:
int controles(){
//declare actions that will happen when a key is pressed
const Uint8 * estado = SDL_GetKeyboardState(NULL);
if (estado[SDL_SCANCODE_UP]){ y--; SDL_UpdateWindowSurface(ventana); }
if (estado[SDL_SCANCODE_DOWN]){ y++; SDL_UpdateWindowSurface(ventana); }
return 0;
}
The problem is that I need to update the window surface after the value of y is modified, but I get an error because ventana, the name of the window, is defined in another function. I tried to define ventana globally, but the program won't work then. I then thought the following; write a goto statement in graficos, the function where ventana is defined, in order to skip every other statement in that function, except for the one that updates the window surface. However, when I did that, the program doesn't even compile:
int graficos(int caso){
if (caso == 1) {goto reload;} //skip to reload if (1)
SDL_Init(SDL_INIT_VIDEO); //load SDL
//load graphics in memory
SDL_Window * ventana = SDL_CreateWindow("ventana", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0);
SDL_Surface * superficie = SDL_GetWindowSurface(ventana);
SDL_Surface * pantallainicio = SDL_LoadBMP("pantallainicio.bmp");
SDL_Surface * paleta = SDL_LoadBMP("paleta.bmp");
SDL_Rect rpantallainicio = { 0, 0, 640, 480 };
SDL_Rect rpaleta = { x, y, 16, 16 };
//render graphics
SDL_BlitSurface(pantallainicio, NULL, superficie, &rpantallainicio);
SDL_BlitSurface(paleta, NULL, superficie, &rpaleta);
SDL_UpdateWindowSurface(ventana);
reload:SDL_UpdateWindowSurface(ventana);
return 0;
}
I get the following errors:
error C4533: initialization of 'rpaleta' is skipped by 'goto reload'
error C4533: initialization of 'rpantallainicio' is skipped by 'goto reload'
I hope I explained my issue well enough. What can I do? Is there a way to fix this? Or can I reference ventana in some other way? This issue might be very basic, sorry for that, and thanks in advance!
You can fix this issue by simply not using goto at all - use a sub-function instead. Also, extract the variable ventana, as you need it to be stored and usable by graficos whenever.
void init()
{
SDL_Init(SDL_INIT_VIDEO); //load SDL
//load graphics in memory
ventana = SDL_CreateWindow("ventana", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0);
SDL_Surface * superficie = SDL_GetWindowSurface(ventana);
SDL_Surface * pantallainicio = SDL_LoadBMP("pantallainicio.bmp");
SDL_Surface * paleta = SDL_LoadBMP("paleta.bmp");
SDL_Rect rpantallainicio = { 0, 0, 640, 480 };
SDL_Rect rpaleta = { x, y, 16, 16 };
//render graphics
SDL_BlitSurface(pantallainicio, NULL, superficie, &rpantallainicio);
SDL_BlitSurface(paleta, NULL, superficie, &rpaleta);
}
int graficos(int caso)
{
if (caso != 1) { init(); } //skip to reload if (1)
SDL_UpdateWindowSurface(ventana);
return 0;
}
SDL_Window * ventana;
Use of goto should generally be avoided. Use subroutines or other alternatives where possible. Here, the code does exactly the same thing as originally intended, but the "extra" flow that occurs when caso is not 1 is wrapped in its own subroutine named 'init'.
I would like to display text in my Windows thanks to sfml. But I don't arrived to do it, the texte just don't appear in the windows, that's really strange because I can display lines without difficulties !
Can you check my code and tell me what I need to change please ? :)
My main.cpp
int main()
{
bool sortir = false;
// Création de la pile de double
Pile<double> pile_double;
// Création de la pile de string
Pile<string> pile_string;
// Création du map
map<string, function<void()>> _map;
int largeur_fenetre = 300;
int hauteur_fenetre = 400;
// Création de la fenetre
sf::RenderWindow window(sf::VideoMode(largeur_fenetre, hauteur_fenetre), "Interpreteur NPI");
//copie largeur / longueur
push(pile_double, (double) largeur_fenetre);
push(pile_double, (double) hauteur_fenetre);
// on fait tourner le programme tant que la fenêtre n'a pas été fermée
while (window.isOpen())
{
// on traite tous les évènements de la fenêtre qui ont été générés depuis la dernière itération de la boucle
sf::Event event;
while (window.pollEvent(event))
{
cout << "passage 1er while" << endl;
// fermeture de la fenêtre lorsque l'utilisateur le souhaite
if (event.type == sf::Event::Closed)
window.close();
}
// effacement de la fenêtre en noir
window.clear(sf::Color::Black);
window.display();
cout << "coucou" << endl;
while (sortir == false)
{
cout << "Entrez la commande souhaité >";
string carac;
cin >> carac;
// Recherche du string dans le map
for (map<string, function<void()>>::iterator it = _map.begin(); it != _map.end(); ++it) // Debut recherche de la relation
{
// S'il est trouvé on demarre sa fonction associé
if (carac == it->first)
{
(it->second)();
pile_double.display();
pile_string.display();
window.display();
}
} // Fin de la recherche de la relation string -> fonction | Fin du For
if (carac == "exit")
{
sortir = true;
}
}
}
return 0;
}
fonction.cpp
void drawstr(Pile<double>& nomDeLaPile, sf::RenderWindow& window, Pile<string>& nomDeLaPile2)
{
sf::Text text;
sf::Font font;
text.setFont(font);
text.setString("Hello world");
text.setCharacterSize(24);
text.setColor(sf::Color::Red);
text.setStyle(sf::Text::Bold | sf::Text::Underlined);
window.draw(text);
}
My apologies for very bad English, I hope you understand anyways!
You do:
sf::Font font;
text.setFont(font);
But you don't load any font, you "set" an empty font...
Try something like that before:
if (!font.loadFromFile("arial.ttf"))
{
// error
}
But you shouldn't do that in the drawing function.
Font has to be loaded once when starting the application.
From the SFML tutorial:
Note that SFML won't load your system fonts automatically, i.e.
font.loadFromFile("Courier New") won't work. First because SFML
requires file names, not font names, and secondly because SFML doesn't
have a magic access to your system's font folder. So, if you want to
load a font, you need to have the font file with your application,
like other resources (images, sounds, ...).
SFML does not provide a default font, or an font for that matter.
When you created a Font object using:
sf::Font font;
it is an empty font. What you need to do is download a font from a website, such as http://www.dafont.com/ or find where the font files are on your computer.
Then you should load the font (from the same SFML tutorial):
sf::Font font;
if (!font.loadFromFile("arial.ttf"))
{
// error...
}