SDL_Delay() while getting events (kinda nooby) - c++

C++, SDL 2
Im making a disco simulator thats just loops through pictures and plays music.
(Epilepsy warning) http://imgur.com/9ePOIAw
Basically I want to run this code
while (isPartying){
currentImage = image1;
SDL_BlitSurface(currentImage, NULL, windowSurface, NULL);
SDL_Delay(25);
SDL_UpdateWindowSurface(window);
currentImage = image2;
SDL_BlitSurface(currentImage, NULL, windowSurface, NULL);
SDL_UpdateWindowSurface(window);
SDL_Delay(25);
currentImage = image3;
SDL_BlitSurface(currentImage, NULL, windowSurface, NULL);
SDL_UpdateWindowSurface(window);
SDL_Delay(25);
//image 3, 4, 5 and so on
}
while getting events all the time.
while (SDL_PollEvent(&ev) != 0){
if (ev.type == SDL_QUIT){
isPartying = false;
}
}
I want it to get events while Im in the middle of the isPartying loop. Now it only checks for events at the beginning (or the end, depends on where I put the event loop of course). Anyone know a better way to wait for the next picture then SDL_Delay()? Or maybe even have another solution
Ano

Basically, what you want to do is to achieve two things at a time.
You have two options:
Using SDL_Thread, but I prefere to not use threads when another solution is possible (because you may have to deal with semaphores or mutexes)
Using SDL_TimerCallback (some would say that too much timers kill the flow of the code, but it's what we gonna use)
Here is a code sample (NB: you must pass SDL_INIT_TIMER to SDL_Init()).
void IsPartying() {
SDL_Event ev;
while (SDL_PollEvent(&ev)){
if (ev.type == SDL_QUIT){
return false;
}
}
return true
}
uint32_t ChangeImage(uint32_t interval, void* param) {
int *imageNb = param;
(*imageNb)++
return interval
}
void Processing() {
// Store your images in SDL_Surface **imageArray
int imageNb = 0;
SDL_TimerID t = SDL_AddTimer(25, ChangeImage, &imageNb);
while (IsPartying()) {
SDL_BlitSurface(imageArray[imageNb], NULL, windowSurface, NULL);
SDL_UpdateWindowSurface(window);
SDL_Delay(1); // Release proc charge
}
SDL_RemoveTimer(SDL_TimerID);
}
Of course you still need to check if you iterated over all the images, else you'll got a nice segfault while trying to access an unallocated cell of the array.

Related

SDL_CreateRGBSurfaceFrom / SDL_BlitSurface - I see old frames on my emulator

I'm working on a Space Invaders emulator and for display output I'm using SDL2.
The problem is that on the output window I see all the frames since emulation starts!
Basically the important piece of code is this:
Intel8080 mainObject; // My Intel 8080 CPU emulator
mainObject.loadROM();
//Main loop flag
bool quit = false;
//Event handler
SDL_Event e;
//While application is running
while (!quit)
{
//Handle events on queue
while (SDL_PollEvent(&e) != 0)
{
//User requests quit
if (e.type == SDL_QUIT)
{
quit = true;
}
}
if (mainObject.frameReady)
{
mainObject.frameReady = false;
gHelloWorld = SDL_CreateRGBSurfaceFrom(&mainObject.frameBuffer32, 256, 224, 32, 4 * 256, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
//Apply the image
SDL_BlitSurface(gHelloWorld, NULL, gScreenSurface, NULL);
//Update the surface
SDL_UpdateWindowSurface(gWindow);
}
mainObject.executeROM();
}
where Intel8080 is my CPU emulator code and mainObject.frameBuffer32 is the Space Invaders' video RAM that I converted from 1bpp to 32bpp in order to use SDL_CreateRGBSurfaceFrom function.
Emulation's working fine but I see all the frames generated since emulator starts!
I tried to change Alpha value in the 4 bytes of each RGBA pixel but nothing changes
This is happening because it looks like you're rendering the game without first clearing the window. Basically, you should fill the entire window with a color and then render on top of it constantly. The idea is that filling the window with a specific color before rendering over it is the equivalent of erasing the previous frame (most modern computers are powerful enough to handle this).
You might want to read-up on SDL's SDL_FillRect function, it'll allow you to fill the entire screen with a specific color.
Rendering pseudocode:
while(someCondition)
{
[...]
// Note, I'm not sure if "gScreenSurface" is the proper variable to use here.
// I got it from reading your code.
SDL_FillRect(gScreenSurface, NULL, SDL_MapRGB(gScreenSurface->format, 0, 0, 0));
SDL_BlitSurface(gHelloWorld, NULL, gScreenSurface, NULL);
SDL_UpdateWindowSurface(gWindow);
[...]
}

Drawing SDL_Surface from another class

So I have three classes Application, DrawMgr and Cube. In Application.cpp is my main loop in which I call DrawMgr::DrawCube in which I call Cube::Draw.
Application.cpp
while (!quit)
{
//Draw Background
gDrawMgr.DrawBackground();
gDrawMgr.DrawCube();
//UpdateScreen
gDrawMgr.UpdateScreen();
//Handle events on queue
while (SDL_PollEvent(&e) != 0)
{
//User requests quit
if (e.type == SDL_QUIT || e.key.keysym.sym == SDLK_ESCAPE)
{
quit = true;
}
}
}
DrawMgr.cpp
SDL_Surface* screenSurface;
void DrawMgr::DrawCube()
{
gCube.Draw(screenSurface);
}
Cube.cpp
void Cube::Draw( SDL_Surface* destination )
{
SDL_Rect offset;
offset.x = 100;
offset.y = 100;
SDL_FillRect(cube, NULL, SDL_MapRGB( cube->format, 0, 0, 0 ) );
SDL_BlitSurface( cube, NULL, destination, &offset);
}
When I run the program, the cube doesn't appear, what am I doing wrong?
Are you sure you're using SDL2.0 ? because things have changed, you need a SDL_Renderer and a SDL_Texture. Seems like you're trying to do it in the SDL 1 way.
In SDL2, to update the screen, we use those calls
SDL_RenderClear(sdlRenderer);
SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, NULL);
SDL_RenderPresent(sdlRenderer);
RenderClear to wipe the screen content.
RenderCopy to draw some texture on it.
RenderPresent to draw the final result on the screen.
Go see the migration guide for more details on the new flow.
https://wiki.libsdl.org/MigrationGuide

Can't open a window with SDL/C++

i stuck in a big bug with my code which i can't open the first window of my game after running it! it just open blank for a few secondes and then it closes automatically. I doon't know what wrong with my code beacause i'm following series of tutorials and my code seems like the code in the tutorials. here's my code:
#include "stdafx.h"
#include "FirstClass.h"
FirstClass::FirstClass(void){
bool quit = false;
window = NULL;
window = SDL_CreateWindow("Snaykie v1.0",350, 150, 800, 500, SDL_WINDOW_SHOWN);
if (window == NULL){
std::cout << "Can not open the game!" << std::endl;
}
renderer = NULL;
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
evt = new SDL_Event();
//background image
txt = NULL;
txt = IMG_LoadTexture(renderer, "mainview.bmp");
rct.x = 0 ;
rct.y = 0;
rct.h = 500;
rct.w = 800;
//button start
sbutt = NULL;
sbutt = IMG_LoadTexture(renderer, "startbutton.bmp");
startrct.x = 0 ;
startrct.y = 0;
startrct.h = 100;
startrct.w = 100;
}
FirstClass::~FirstClass(void)
{
SDL_DestroyTexture(txt);
SDL_DestroyTexture(sbutt);
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
delete evt;
}
//the code below is the loops that let the window stucks forever to keep opened
void FirstClass :: GameStart(void){
while (!quit && evt->type != SDL_QUIT){
SDL_PollEvent(evt);
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, txt, NULL, &rct);
SDL_RenderCopy(renderer, sbutt, NULL, &startrct);
SDL_RenderPresent(renderer);
}
}
Please help me and thanks i'm really in a big problem.
You are handling the evt variable in a bad way. It is allocated but not initialized, and you compare the uninitialized value to SDL_QUIT. You should reorder the code inside FirstClass::GameStart and preferably use a local variable (since there is no actual need to use a dynamically allocated one) and remove the allocation and deletion of the existing evt from constructor and destructor. Here is a better version of FirstClass::GameStart:
void FirstClass::GameStart(void){
SDL_Event evt;
while (SDL_PollEvent(&evt)){
if (evt.type == SDL_QUIT) {
// a user requested termination has been received, exit the loop
break;
}
else {
// filter the event?
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, txt, NULL, &rct);
SDL_RenderCopy(renderer, sbutt, NULL, &startrct);
SDL_RenderPresent(renderer);
}
}
}
Also ensure that you are actually invoking the FirstClass::GameStart funcion from main, maybe you are simply not running the event loop at all.

core dump in SDL, where? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
Just in the first lines happened the ** core dump.
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Init(SDL_INIT_VIDEO);
SDL_Surface *screen;
SDL_Surface *background;
SDL_Surface *tablero;
SDL_Surface *x;
SDL_Surface *o;
SDL_Rect posFondo;
//SDL_Rect posPlayerX[5];
//SDL_Rect posPlayerO[5];
SDL_Event suceso;
// Definir
x = SDL_LoadBMP("players.bmp");
o = SDL_LoadBMP("players.bmp");
tablero = SDL_LoadBMP("tablero.bmp");
/* Clear bg colors */
SDL_SetColorKey(x, SDL_SRCCOLORKEY,
SDL_MapRGB(x->format, 255, 0, 255));
SDL_SetColorKey(o, SDL_SRCCOLORKEY,
SDL_MapRGB(o->format, 255, 0, 255));
SDL_SetColorKey(tablero, SDL_SRCCOLORKEY,
SDL_MapRGB(tablero->format, 255, 0, 255));
/* END */
screen = SDL_SetVideoMode(600, 600, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
if (screen == NULL) { return 0; }
/* Positions */
posFondo.x = 0;
posFondo.y = 0;
while (true) {
SDL_BlitSurface(tablero, NULL, screen, &posFondo);
//SDL_BlitSurface
while(SDL_PollEvent(&suceso)) {
if (suceso.type == SDL_QUIT) {
break; break;
}
}
SDL_Flip(screen);
SDL_Delay ( 5 );
}
I can't find the problem, I try to delete some things and add dynamic variables (new, delete types) and nope...
I only see two errors in your code. For starters, there is no need to call SDL_Init() twice. When you call SDL_Init(SDL_INIT_EVERYTHING), you're already initializing video. Get rid of the second call to SDL_Init(). The second issue in your code would be in your:
while(SDL_PollEvent(&suceso)){
if(suceso.type == SDL_QUIT){
break; break;
}
}
When you call the first break, it exits the while loop. The second break is never used. Because of this, I'm going to guess you encounter a situation in which the loop never ends. Here is what I would recommend for your loop:
bool quit = false;
while (!quit) {
SDL_BlitSurface(tablero, NULL, screen, &posFondo);
//SDL_BlitSurface
while(SDL_PollEvent(&suceso)) {
if (suceso.type == SDL_QUIT) {
quit = true;
}
}
SDL_Flip(screen);
SDL_Delay ( 5 );
}
EDIT: You should probably also initialize your SDL_Surface*'s to NULL.
EDIT#2: There's really no need to call SDL_BlitSurface() and SDL_Flip() every frame unless your tablero surface is going to change. If you use SDL_WaitEvent() instead of SDL_PollEvents(), you can update your screen and such whenever the user does something, rather than all the time for no real reason.

Opengl Game Loop Multithreading

I have been messing around with OpenGL lately, and I noticed that the windows message pump is blocking whenever i attempt to resize my window, so as a result rendering is halted whenever i click on the menu bar or resize the window.
To fix this, I am looking into multithreading.
I have the following:
_beginthread(RenderEntryPoint, 0, 0);
while (!done)
{
PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE);
if (msg.message == WM_QUIT)
{
done = true;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
void RenderEntryPoint(void *args)
{
while (1)
{
//render code
}
}
However, my scene isn't being rendered, and I'm not sure why.
You need to make the OpenGL rendering context current in the rendering thread, and make sure it's not current in the windowing thread. This also means that you can't call any OpenGL functions from the windowing thread.