Writing a game loop for an ncurses game? - multithreading

I am writing a game with ncurses and am having trouble with the game loop. I have read these 2 pages - This one, and This one as well as several others linked via SO, and can just about understand them (or at least, I can understand what he is talking about, if not exactly how the solution works). The problem I have is that with ncurses, the sprites only move one character step at a time, there is no interpolation or integration, it is just sprite.x=sprite.x+1. I tried using pthread and nanosleep and the bad guy sprites move nicely but the player movement is sluggish and unresponsive/unreactive. I tried using 2 threads and having key input on one and game loop on another thread but the key thread didn't do anything at all. So,how do you write a smooth game loop for ncurses?

The main problem is that only key presses (not key releases) can be detected then running in a VT100 style terminal emulator (as ncurses does). This is a little akward for games. Either the player has press keys repeatedly to move (or wait until the key autorepeats if the keybord driver is configured to do so). Or you can make the game so that the player presses a key once to begin to move and presses the key again (or another key perhaps) to stop (like in old Sierra adventure games).
You are probably only making things more difficult for yourself by using threads. Instead you could use poll() to wait for either input or the next tick/scheduled event. You will not get the high precission, high resolution timing which is usually important for games. But then using ncurses I don't think you need to worry even if the timing is a few milliseconds off. You can still keep it steady by calculating the timeout like this:
next_tick = last_tick + TIME_INTERVAL
timeout = next_tick - now();
For smoother movement (especially if things move at varying speed) you can store all coordinates with a higher precicion (for example by using floats) and then round them down to the low precision screen coordinates then drawing.

I don't think ncurses has what you need. On Windows you could use GetAsyncKeyState for each key that you are interested in.

Related

Unity 5 - Collider vs timer in thread

I had a question related to performances.
Here's the context :
Imagine a TempleRun-like game in which the player only moves in 1 direction and is allowed to switch between 3 lanes (all of them going in the same direction).
Unlike temple run, there are no turns.
I wish to make the level generate dynamically and therefore we placed colliders on the ground. When triggered, the level loads the next (random) part of the path and unloads the old one.
Since the player is moving at a constant speed in 1 direction, I was wondering if it wouldn't be better to use a timer to load and unload game parts?
Also, I was wondering how colliders were handled by Unity? Do they work with a thread constantly watching for a collision to happen?
Personally I would not use time in case I want to change the speed of the player through a boost or some other reason.
Here's some information on colliders:
https://docs.unity3d.com/Manual/CollidersOverview.html
https://forum.unity3d.com/threads/collision-detection-at-high-speed.3353/
From what I read, it feels like there is a separate thread that has a fixed time step and fires events to alert when a collision happens.

LabView playing more than one sound at the time

I'm using event structure and want to do some like Launchpad.
Numeric keyboard have for each number added a sound.
Problem is, that when I press number example one, the program is waiting when the music stop play and next I can press example number four.
Is it possible, to play sounds from 3 key's at the same time using event structure ?
I put the files online here and added screenshots below. Block diagram:
Front panel:
Working Solution
I think I got this working much more easily than I expected using the Play Sound File VI under the Graphics and Sound -> Sound -> Output palette. That link is the 2011 documentation (couldn't find a more recent link), but it does not look like it has changed. The working result is shown below, with two different events handled by the event structure:
Key Down? event:
Stop Button event:
You may be fine without using the Sound Output Clear VI to the right of the main event loop, but having it there won't hurt.
It turns out that the Play Sound File VI does not block, so you can play multiple overlapping sound files. If you run into blocking on your machine (one sound file plays, then the next, and so on), let me know because I have another solution that might work.
A word on events
An important thing to understand is that events are handled in a queue. When you press keys, those key presses go in order onto the event queue. Each time your event-handling loop executes, it takes the oldest event out of that queue and processes it. The event structure in LabVIEW will only handle one event per iteration of your event-handling loop. On the next iteration, if events are still in the queue that your structure is set up to process, it will take the next-oldest one for that iteration and repeat.
Now, lets say that you want to do some super complicated processing that takes 10 seconds every time you press a key, and you put that processing inside of your main event loop. Your key presses still go onto the event queue as fast as you press them, but LabVIEW has to wait the full 10 seconds before it can dequeue the next keypress and process it, so you end up with an application that seems to hang while it chugs through the queue much slower than you are adding items to the queue.
One way to get around this is to take that complicated processing and put it outside of the queue in another process. If you have the resources, you can actually call a separate instance of a processing sub-VI in its own thread for every one of those key presses. This allows the event handling loop to spawn processes as fast as you can press keys, and then your processes take whatever time they need to simultaneously (resources permitting) perform whatever actions you wanted.
Essentially that is what the Play Sound File VI is doing. It sees that you want to play a file and spawns a process to play that sound over the speakers, allowing the event-handling loop to continue immediately rather than waiting for the sound to finish playing. As you press more keys, more processes get spawn that kill themselves when they are finished. You can do this manually too, which is the other solution that I have for you if Play Sound File does not behave the same way for you as it did for me.
Update:
Thanks to #Engineero for pointing out that Play Sound File vi actually isn't blocking. The updated code shows how to play overlapping sounds. I'll leave it to the user to add the Stop Sound on Key Up code. No timeout is needed because nothing is taking place in the event structure.
Also, note that for me the Play Sound vi needed to be in a while loop to keep playing. Not sure why this is needed, but the NI examples sets it up this way (\examples\Graphics and Sound\Sound\Sound Player.vi).
Finally, you may crash the vi if your sound card gets overwhelmed as mentioned here. If that happens I would go with a better sound library to try and squeeze more performance out of your sound card.
Original:
First, I assume you a referring to this Launchpad?
I was able to press up to 4 keys at once will the following - the important thing is to set the event timeout to 1 ms. If you need more than that it will require a more sophisticated design.
I was no able to easily implement a sound because all the basic LabVIEW beeps are what's considered "blocking I/O" meaning if you call 2 Beeps simultaneously than Windows will play one after another not both at the same time. You will need to implement you instrument notes using non blocking I/O probably in a language other than LabVIEW such as this C++ library.

Multiple OpenGL contexts, multiple windows, multithreading, and vsync

I am creating a graphical user interface application using OpenGL in which there can be any number of windows - "multi-document interface" style.
If there were one window, the main loop could look like this:
handle events
draw()
swap buffers (vsync causes this to block until vertical monitor refresh)
However consider the main loop when there are 3 windows:
each window handle events
each window draw()
window 1 swap buffers (block until vsync)
(some time later) window 2 swap buffers (block until vsync)
(some time later) window 3 swap buffers (block until vsync)
Oops... now rendering one frame of the application is happening at 1/3 of the proper framerate.
Workaround: Utility Window
One workaround is to have only one of the windows with vsync turned on, and the rest of them with vsync turned off. Call swapBuffers() on the vsync window first and draw that one, then draw the rest of the windows and swapBuffers() on each one.
This workaround will probably look fine most of the time, but it's not without issues:
it is inelegant to have one window be special
a race condition could still cause screen tearing
some platforms ignore the vsync setting and force it to be on
I read that switching which OpenGL context is bound is an expensive operation and should be avoided.
Workaround: One Thread Per Window
Since there can be one OpenGL context bound per thread, perhaps the answer is to have one thread per window.
I still want the GUI to be single threaded, however, so the main loop for a 3-window situation would look like this:
(for each window)
lock global mutex
handle events
draw()
unlock global mutex
swapBuffers()
Will this work? This other question indicates that it will not:
It turns out that the windows are 'fighting' each other: it looks like
the SwapBuffers calls are synchronized and wait for each other, even
though they are in separate threads. I'm measuring the frame-to-frame
time of each window and with two windows, this drops to 30 fps, with
three to 20 fps, etc.
To investigate this claim I created a simple test program. This program creates N windows and N threads, binds one window per thread, requests each window to have vsync on, and then reports the frame rate. So far the results are as follows:
Linux, X11, 4.4.0 NVIDIA 346.47 (2015-04-13)
frame rate is 60fps no matter how many windows are open.
OSX 10.9.5 (2015-04-13)
frame rate is not capped; swap buffers is not blocking.
Workaround: Only One Context, One Big Framebuffer
Another idea I thought of: have only one OpenGL context, and one big framebuffer, the size of all the windows put together.
Each frame, each window calls glViewport to set their respective rectangle of the framebuffer before drawing.
After all drawing is complete, swapBuffers() on the only OpenGL context.
I'm about to investigate whether this workaround will work or not. Some questions I have are:
Will it be OK to have such a big framebuffer?
Is it OK to call glViewport multiple times every frame?
Will the windowing library API that I am using even allow me to create OpenGL contexts independent of windows?
Wasted space in the framebuffer if the windows are all different sizes?
Camilla Berglund, maintainer of GLFW says:
That's not how glViewport works. It's not
how buffer swapping works either. Each window will have a
framebuffer. You can't make them share one. Buffer swapping is
per window framebuffer and a context can only be bound to a single
window at a time. That is at OS level and not a limitation of
GLFW.
Workaround: Only One Context
This question indicates that this algorithm might work:
Activate OpenGL context on window 1
Draw scene in to window 1
Activate OpenGL context on window 2
Draw scene in to window 2
Activate OpenGL context on window 3
Draw scene in to window 3
For all Windows
SwapBuffers
According to the question asker,
With V-Sync enabled, SwapBuffers will sync to the slowest monitor and
windows on faster monitors will get slowed down.
It looks like they only tested this on Microsoft Windows and it's not clear that this solution will work everywhere.
Also once again many sources tell me that makeContextCurrent() is too slow to have in the draw() routine.
It also looks like this is not spec conformant with EGL. In order to allow another thread to eglSwapBuffers(), you have to eglMakeCurrent(NULL) which means your eglSwapBuffers now is supposed to return EGL_BAD_CONTEXT.
The Question
So, my question is: what's the best way to solve the problem of having a multi-windowed application with vsync on? This seems like a common problem but I have not yet read a satisfying solution for it.
Similar Questions
Similar to this question: Synchronizing multiple OpenGL windows to vsync but I want a platform-agnostic solution - or at least a solution for each platform.
And this question: Using SwapBuffers() with multiple OpenGL canvases and vertical sync? but really this problem has nothing to do with Python.
swap buffers (vsync causes this to block until vertical monitor refresh)
No, it doesn't block. The buffer swap call may return immediately and not block. What it does however is inserting a synchronization point so that execution of commands altering the back buffer is delayed until the buffer swap happened. The OpenGL command queue is of limited length. Thus once the command queue is full, futher OpenGL calls will block the program until further commands can be pushes into the queue.
Also the buffer swap is not an OpenGL operation. It's a graphics / windowing system level operation and happens independent of the OpenGL context. Just look at the buffer swap functions: The only parameter they take are a handle to the drawable (=window). In fact even if you have multiple OpenGL contexts operating on a single drawable, you swap the buffer only once; and you can do it without a OpenGL context being current on the drawable at all.
So the usual approach is:
' first do all the drawing operations
foreach w in windows:
foreach ctx in w.contexts:
ctx.make_current(w)
do_opengl_stuff()
glFlush()
' with all the drawing commands issued
' loop over all the windows and issue
' the buffer swaps.
foreach w in windows:
w.swap_buffers()
Since the buffer swap does not block, you can issue all the buffer swaps for all the windows, without getting delayed by V-Sync. However the next OpenGL drawing command that addresses a back buffer issued for swapping will likely stall.
A workaround for that is using an FBO into which the actual drawing happens and combine this with a loop doing the FBO blit to the back buffer before the swap buffer loop:
' first do all the drawing operations
foreach w in windows:
foreach ctx in w.contexts:
ctx.make_current(w)
glBindFramebuffer(GL_DRAW_BUFFER, ctx.master_fbo)
do_opengl_stuff()
glFlush()
' blit the FBOs' renderbuffers to the main back buffer
foreach w in windows:
foreach ctx in w.contexts:
ctx.make_current(w)
glBindFramebuffer(GL_DRAW_BUFFER, 0)
blit_renderbuffer_to_backbuffer(ctx.master_renderbuffer)
glFlush()
' with all the drawing commands issued
' loop over all the windows and issue
' the buffer swaps.
foreach w in windows:
w.swap_buffers()
thanks #andrewrk for all theses research, i personnaly do like that :
Create first window and his opengl context with double buffer.
Active vsync on this window (swapinterval 1)
Create others windows and attach first context with double buffer.
Disable vsync on theses others window (swapinterval 0)
For each frame
For invert each window (the one with vsync enable at the end).
wglMakeCurrent(hdc, commonContext);
draw.
SwapBuffer
In that manner, i achieve the vsync and all window are based on this same vsync.
But i encoutered problem without aero : tearing...

"current vertex declaration does not include all the elements required"

"The current vertex declaration does not include all the elements required by the current vertex shader. TextureCoordinate0 is missing."
I get this error when I try to use a spriteFont to draw my FPS on the screen, on the line where I call spriteBatch.End()
My effect doesn't even use texture coordinates.
But I have found the root of the problem, just not how to fix it.
I have a separate thread that builds the geometry (an LOD algorithm) and somehow this seems to be why I have the problem.
If I make it non-threaded and just update my mesh per frame I don't get an error.
And also if I keep it multithreaded but don't try to draw text on the screen it works fine.
I just can't do both.
To make it even more strange, it actually compiles and runs for a little bit. But always crashes.
I put a Thread.Sleep in the method that builds the mesh so that it happens less often and I saw that the more I make this thread sleep, and the less it gets called, the longer it will run on average before crashing.
If it sleeps for 1000ms it runs for maybe a minute. If it sleeps for 10ms it doesn't even show one frame before crashing. This makes me believe that it has to do with a certain line of code being executed on the mesh building thread at the same time you are drawing text on the screen.
It seems like maybe I have to lock something when drawing the text, but I have no clue.
Any ideas?
My information comes from the presentation "Understanding XNA Framework Performance" from GDC 2008. It says:
GraphicsDevice is somewhat thread-safe
Cannot render from more than one thread at a time
Can create resources and SetData while another thread renders
ContentManager is not thread-safe
Ok to have multiple instances, but only one per thread
My guess is that you're breaking one of these rules somewhere. Or you're modifying a buffer that is being used to render without the appropriate locking.

drop/rewrite/generate keyboard events under Linux

I would like to hook into, intercept, and generate keyboard (make/break) events under Linux before they get delivered to any application. More precisely, I want to detect patterns in the key event stream and be able to discard/insert events into the stream depending on the detected patterns.
I've seen some related questions on SO, but:
either they only deal with how to get at the key events (key loggers etc.), and not how to manipulate the propagation of them (they only listen, but don't intercept/generate).
or they use passive/active grabs in X (read more on that below).
A Small DSL
I explain the problem below, but to make it a bit more compact and understandable, first a small DSL definition.
A_: for make (press) key A
A^: for break (release) key A
A^->[C_,C^,U_,U^]: on A^ send a make/break combo for C and then U further down the processing chain (and finally to the application). If there is no -> then there's nothing sent (but internal state might be modified to detect subsequent events).
$X: execute an arbitrary action. This can be sending some configurable key event sequence (maybe something like C-x C-s for emacs), or execute a function. If I can only send key events, that would be enough, as I can then further process these in a window manager depending on which application is active.
Problem Description
Ok, so with this notation, here are the patterns I want to detect and what events I want to pass on down the processing chain.
A_, A^->[A_,A^]: expl. see above, note that the send happens on A^.
A_, B_, A^->[A_,A^], B^->[B_,B^]: basically the same as 1. but overlapping events don't change the processing flow.
A_, B_, B^->[$X], A^: if there was a complete make/break of a key (B) while another key was held (A), X is executed (see above), and the break of A is discarded.
(it's in principle a simple statemachine implemented over key events, which can generate (multiple) key events as output).
Additional Notes
The solution has to work at typing speed.
Consumers of the modified key event stream run under X on Linux (consoles, browsers, editors, etc.).
Only keyboard events influence the processing (no mouse etc.)
Matching can happen on keysyms (a bit easier), or keycodes (a bit harder). With the latter, I will just have to read in the mapping to translate from code to keysym.
If possible, I'd prefer a solution that works with both USB keyboards as well as inside a virtual machine (could be a problem if working at the driver layer, other layers should be ok).
I'm pretty open about the implementation language.
Possible Solutions and Questions
So the basic question is how to implement this.
I have implemented a solution in a window manager using passive grabs (XGrabKey) and XSendEvent. Unfortunately passive grabs don't work in this case as they don't capture correctly B^ in the second pattern above. The reason is that the converted grab ends on A^ and is not continued to B^. A new grab is converted to capture B if still held but only after ~1 sec. Otherwise a plain B^ is sent to the application. This can be verified with xev.
I could convert my implementation to use an active grab (XGrabKeyboard), but I'm not sure about the effect on other applications if the window manager has an active grab on the keyboard all the time. X documentation refers to active grabs as being intrusive and designed for short term use. If someone has experience with this and there are no major drawbacks with longterm active grabs, then I'd consider this a solution.
I'm willing to look at other layers of key event processing besides window managers (which operate as X clients). Keyboard drivers or mappings are a possibility as long as I can solve the above problem with them. This also implies that the solution doesn't have to be a separate application. I'm perfectly fine to have a driver or kernel module do this for me. Be aware though that I have never done any kernel or driver programming, so I would appreciate some good resources.
Thanks for any pointers!
Use XInput2 to make device(keyboard) floating, then monitor KeyPress and KeyRelease event on the device, using XTest to regenerate KeyPress & KeyRelease event.

Resources