I use C and SDL 2.0, but i have a problem, this(when you click on the window's "x" it quits):
void function(SDL_Surface *screen) {
SDL_Event event;
bool quit=false;
while (!quit) {
SDL_WaitEvent(&event);
switch (event.type) {
case...
case SDL_QUIT:
quit = true;
break;
}
}
This is working, but not well. If this is in a function like this, it quits only to the main(), so I need to click on "x" again to quit from the whole program.
How can I solve it? (I want to quit from the whole program everytime, does not matter if it's in a function or not).
As already mentioned in comments you, most probably, have multiple event handling loops, which is usually incorrect design. You game general layout should be something like:
int main(int argc, char* argv[]) {
// do initialize stuff
bool run = true;
SDL_Event evt;
// game loop
while (run) {
// process OS events
while(SDL_PollEvent(&evt) != 0) {
switch (evt.type) {
case SDL_QUIT:
run = false;
break;
}
}
update();
render();
}
// clean up
SDL_Quit();
return 0;
}
Related
I have tried to write a program which will detect the mouse movement. But it is showing error while running in linux environment. i also want to implement the program where if user move the mouse in x axis for different distance like 2cm, 4 cm then it will print some statement. how can i initialize the mouse in linux and get the cursur point coordinate(x,y) while user move mouse.
#include <dos.h>
#include <graphics.h>
union REGS in, out;
void detect_mouse ()
{
in.x.ax = 0;
int86 (0X33,&in,&out); //invoke interrupt
if (out.x.ax == 0)
printf ("\nMouse Failed To Initialize");
else
printf ("\nMouse was Succesfully Initialized");
}
void showmouse_graphics ()
{
int gdriver = DETECT, gmode, errorcode;
initgraph(&gdriver, &gmode, "c:\\tc\\bgi");
in.x.ax = 1;
int86 (0X33,&in,&out);
getch ();
closegraph ();
}
void detect ()
{
int button;
while (!kbhit () )
{
in.x.ax = 3;
int86 (0X33,&in,&out);
button=out.x.bx&7
switch(button)
{
case 1:
print(“left button pressed\n”);
break;
case 2:
print(“right button pressed\n”);
break;
case 4:
print(“middle button pressed\n”);
break;
case 3:
print(“left and right button pressed\n”);
break;
case 5:
print(“left and middle button pressed\n”);
break;
case 6:
print(“right and middle button pressed\n”);
break;
case 7:
print(“all the three buttons pressed\n”);
break;
default:
print(“No button pressed\n”);
}
delay (200); // Otherwise due to quick computer response 100s of words will get print
}
}
void hide_mouse ()
{
in.x.ax = 2;
int86 (0X33,&in,&out);
}
int main ()
{
detect_mouse ();
showmouse_graphics ();
detect ();
hide_mouse ();
return 0;
}
You are using dos.h which is a header available for MS/PC-DOS, not available in Linux. It's my strong belief that it doesn't even compile under gcc in Linux.
In my SDL 2.0 based application, I would like to handle both Control + and Control =.
I understand that I could handle the SDL_KEYDOWN event and look for the SDLK_EQUALS keycode in combination with KEYMODE_CTRL. And even check for KEYMOD_SHIFT' to distinguish between+and=`. However, this is not portable and breaks on keyboards where those symbols are mapped to different keys.
Another thing I have tried is to enable SDL_StartTextInput() and then listen to SDL_TEXTINPUT events. However that only works for printable characters. It ignores control sequences completely.
What is the correct the way to do this? I see SDL 1.2 actually had a unicode field in the SDL_Keysym structure. That would definitely make this a lot easier for me. Does anyone know why that was removed and what the equivalent in SDL 2.0 would be?
Here is an example how you can get unicode input as SDL_TEXTINPUT but the rest as SDL_KEYDOWN:
#include "SDL.h"
#include <stdio.h>
int main(int argc, char *argv[]) {
int done = 0;
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *w = SDL_CreateWindow("foo", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
640, 480, 0);
int lctrl = 0, rctrl = 0;
SDL_StartTextInput();
while (!done) {
SDL_Event event;
while(SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
done = 1;
break;
case SDL_TEXTINPUT: {
int ctrl_state = lctrl || rctrl;
printf("%s, ctrl %s\n", event.text.text, (ctrl_state) ? "pressed" : "released");
} break;
case SDL_KEYDOWN:
if(event.key.keysym.sym == SDLK_RCTRL) { rctrl = 1; }
else if(event.key.keysym.sym == SDLK_LCTRL) { lctrl = 1; }
break;
case SDL_KEYUP:
if(event.key.keysym.sym == SDLK_RCTRL) { rctrl = 0; }
else if(event.key.keysym.sym == SDLK_LCTRL) { lctrl = 0; }
break;
}
}
SDL_UpdateWindowSurface(w);
}
SDL_Quit();
return 0;
}
To simplify things, it ignores SDL_TEXTEDITING, which may (or not) be what you want. Also SDL_GetKeyboardState can be used instead of manually processing events and accumulating modifier keys flags, with the same result.
I'm unable to move the rectangle I made in the program. There is no error message in the compiler when I run the program. Can you please tell me what I missed out in the keyboard event. Other event that I assigned to the window works fine. Thanks (an example will also be helpful).
#include <SDL.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
SDL_Window *o;
SDL_Renderer *r;
SDL_Event e;
int i = 1;
SDL_Rect q;
SDL_Init(SDL_INIT_VIDEO);
o = SDL_CreateWindow("Game test",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
1024,
800,
SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
r = SDL_CreateRenderer(o, -1,SDL_RENDERER_ACCELERATED);
SDL_SetRenderDrawColor(r,0,0,255,255);
SDL_RenderClear(r);
//Creating a box
q.x=475;
q.y=700;
q.h=50;
q.w=50;
SDL_SetRenderDrawColor(r,0,0,0,255);
SDL_RenderFillRect(r,&q);
//SDL_Delay(10);
SDL_RenderPresent(r);
while(i)
{
while(SDL_PollEvent(&e) !=0)
{
if(e.type == SDL_QUIT)
i=0;
else if(e.type == SDL_KEYDOWN)
{
switch(e.key.keysym.sym)
{
case SDLK_ESCAPE:
case SDLK_q:
i=0;
break;
case SDLK_UP:
q.y -=10;
SDL_Delay(11);
break;
case SDLK_DOWN:
q.y +=10;
SDL_Delay(11);
break;
case SDLK_RIGHT:
q.x +=10;
SDL_Delay(11);
break;
case SDLK_LEFT:
q.x -=10;
SDL_Delay(11);
break;
default:
break;
}
}
}
}
SDL_DestroyWindow(o);
SDL_DestroyRenderer(r);
SDL_Quit();
return 0;
}
You are only rendering the contents of the window before you enter your event loop. Since you never redraw the contents in the event loop, it's not very strange that no changes happen.
In SDL, you need to constantly redraw the window to see any changes you make. Since you only call the redraw function once, you only see what's happening in the very first moment of the window's creation. You simply need to add a redraw call inside of the loop, and it'll show you moving the rectangle as expected.
I've been working with my own game engine for awhile now and I've been trying to get the input and controls to flow much more like a AAA FPS game, or at least a decent indie one. I've posted several topics in the past on this issue about making a smooth camera, and at the time of posting them, I had been satisfied with the results. Now however, I feel that it is not quite smooth enough, and I've switched the whole engine to SDL so I have control over the loop. (previously I was using GLUT). After changing everything to SDL, the mouse is smooth as butter, but the camera movement (walking) is still stutters and looks bad. I've implemented the last of Dwitter's game loop, the one with interpolation, and here is the relevant code:
int main (int argc, char** argv)
{
arg1 = argc;
arg2 = argv;
engineInit();
//the loop has to stay here
//kill all extra threads so they don't cause problems after we quit
//gameloop
SDL_Event event;
bool running = true;
const int TPS = 20;
const int SKIP_TICKS = 1000 / TPS;
const int MAX_FRAMESKIP = 5;
int loops;
long lastSec = 0;
long nextGameTick = SDL_GetTicks();
while (running)
{
while (SDL_PollEvent(&event)) {
//do crap with events
switch (event.type)
{
int x,y,button;
case SDL_QUIT:
SDL_GL_DeleteContext(glContext);
SDL_DestroyWindow(window);
SDL_Quit();
cout << "The window has been closed.\n";
running = false;
break;
case SDL_MOUSEMOTION:
SDL_GetMouseState(&x, &y);
passiveMouse(x,y);
break;
case SDL_MOUSEBUTTONDOWN :
button = SDL_GetMouseState(&x, &y);
mouseFunc(button,1,x,y);
break;
case SDL_KEYDOWN:
keyboardDownFunc(event.key.keysym.sym);
break;
case SDL_KEYUP:
keyboardUpFunc(event.key.keysym.sym);
break;
default:
break;
}
}
loops = 0;
while (SDL_GetTicks()> nextGameTick && loops < MAX_FRAMESKIP) {
nextGameTick+=SKIP_TICKS;
loops++;
TickHandler.tps++;
TickHandler.onTick();
int tickTime = int(SDL_GetTicks()/1000);
if (tickTime > lastSec+1)
{
TickHandler.tps = 0;
lastSec = tickTime;
}
}
TickHandler.interpolation = double(SDL_GetTicks() + SKIP_TICKS - nextGameTick )
/ double( SKIP_TICKS );
TickHandler.onRender();
render();
}
Console.consoleActivated = false;
SDL_GL_DeleteContext(glContext);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
TickHandler.onRender() calls a few interpolated functions and here is the one that controls movement of the camera:
void renderTick(float intp)
{
if (cameraPlayer == true)
{
Physics.pos3 = -camy;
Physics.collisions();
Input.applyGravity();
if (Input.walking == true)
Input.moveCameraFirstPerson(1*intp);
else
{
roll = 0;
Input.change = false;
}
}
}
And here is the move camera first person:
void inputs::moveCameraFirstPerson(float speed)
{
speed = speed*walkspeed;
float radx = ((yaw+addedAngle)*MPI/180);
camx -= (sinf(radx)/10)*speed;
camz += (cosf(radx)/10)*speed;
Physics.pos1 = -camx;
Physics.pos2 = -camz;
if (Physics.collided == true)
{float radx = ((yaw+Input.addedAngle)*3.1415926535/180);
camx += (sinf(radx)/20)*speed;
camz -= (cosf(radx)/20)*speed;
Physics.collided = false;
}
Client.x = camx;
Client.z = camz;
Client.y = camy;
Projectile.x = camx;
Projectile.z = camz;
}
I'd love if I could get this all sorted out, any help or references?
Beginner user of C here.
I'm trying to build a library in C using X11/Xlib so I can use it just for little projects and I'm running into a problem when trying to handle events to get input(button presses and key presses) from the user. It works fine for a while and then it starts to build up a significant lag over time.
Right now what I have is my program checking if there is an event waiting and if there is, retrieving it.
I think that my problem right now is that the events are getting stored in memory and its bogging down the program. But that's just a total guess.
Any help will be appreciated. Thank you.
EDIT: Forgot code (I knew I forgot something)
The two functions in question are:
int event_waiting()
{
XEvent event;
if(XCheckMaskEvent(dspy,-1,&event)) {
if(event.type==KeyPress) {
XPutBackEvent(dspy,&event);
return 1;
} else if (event.type==ButtonPress) {
XPutBackEvent(dspy,&event);
return 1;
}
} /* <<=== added missing close-curly here */
return 0;
}
char wait()
{
XEvent event;
XNextEvent(dspy,&event);
if(event.type==KeyPress) {
saved_x = event.xkey.x;
saved_y = event.xkey.y;
return XLookupKeysym(&event.xkey,0);
} else if(event.type==ButtonPress) {
saved_x = event.xkey.x;
saved_y = event.xkey.y;
return event.xbutton.button;
}
}
And then they are called in the main like so,
if (event_waiting()){
char c = wait();
//Switch case goes here
}
EDIT 2: UPDATED CODE
XEvent event;
if(XCheckMaskEvent(display,-1,&event))
{
if(event.type==KeyPress) {
XPutBackEvent(display,&event);
return 1;
} else if (event.type==ButtonPress) {
XPutBackEvent(display,&event);
return 1;
}
}
XFlush(display);
return 0;
`
The lag, which gets worse over time, means that you have many untouched events in your event queue, which slows down XCheckMaskEvent().
Try specifying events using XSelectInput(... ButtonPressMask | KeyPressMask), and try flushing the event queue using XFlush() if there is no event in which you are interested:
if(event.type==KeyPress) {
XPutBackEvent(dspy,&event);
return 1;
} else if (event.type==ButtonPress) {
XPutBackEvent(dspy,&event);
return 1;
} else {
XFlush(dspy); // this
}