I am currently writing a program in c++ that is very similar to the classic "snake" program with a few changes. I am writing it so that it will update the screen five times a second, based on ctime, possibly more if it can be handled. One thing that I would like to do is make it so that the program has a variable in the .h file "currkeypressed." This variable will hold the key that the user is currently holding down and the snake head will go in that direction. Each node in the snake will be a separate object so the currkeypressed will only affect the head. Directional and locational data will be passed down the snake from node to node at each update.
My question is: how can I get the program to keep this data constantly, rather than updating only with a cin when the key is pressed or at a certain interval? I know that I can accept the ascii value for the arrow keys in some sort of for loop, but that doesn't seem to work if the key is held down and if the loop is very long it can miss a press. Does anybody know how to do this?
EDIT: I am using a Linux OS, Ubuntu to be more precise
The simplest method is to use ncurse library.
However, if you prefer "raw" linux programming, you can use select and getchar:
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int main() {
fd_set readfs;
struct timeval timeout;
int res, key;
while (1) {
/* .. do something else .. */
FD_SET(0, &readfs); /* 0 is STDIN */
timeout.tv_usec = 10; /* milliseconds */
timeout.tv_sec = 0; /* seconds */
res = select(maxfd, &readfs, NULL, NULL, &timeout);
if (res) {
/* key pressed */
key = getchar();
if (key == 'A') { /* blar */ }
}
}
}
Once you are looking beyond simple line oriented or character orient input, you are into the details of the user input device. Each operating system has a particular mechanism for notifying a program of events like keydown and keyup.
To get an answer, add a tag for which programming environment you are in: MSWindows, Linux, Android, MacOS, etc.
You can use the library conio.h and you can use the function _getch() in a loop to get live input without any restriction.
#include<conio.h>
#include<iostream>
using namespace std;
int main()
{
char n='a';//Just for initialization
while(n!='e')
{
n=_getch();
}
return 0;
}
The simplest (although really not that simple) way would be to have a thread to capture the user input and then either have some kind of event driven system that can alert the head of the snake or the snake can poll for the current key.
Related
So, I'm, trying to be able to correctly resize my console window using ncurse in C++. I've been able to catch when the window is resize, the problem is that I'm not 100% sure how should I proceed after that. Let's say I have this loop in my main function (after initializing ncurse and those things...):
while(ch = getch())
{
if(ch == KEY_RESIZE)
{
DoSometing();
}
}
As I said the DoSomething in that example is called. But if I try to use ncurse's functions to get the new size of the window with
getmaxyx(stdscr, yMax, xMax);
I'm get the same values (the initial values) over and over again. I guess that's because when I do initscr(), the window size is stored somewhere and that's the value that the getmaxyx function provides. I've tried to do something like call endwin() and the again initscr() to restore those values, but that doesn't seem to work, the value that getmaxyx returns is fixed.
After searching for alternative solutions, I kind of solve the problem, using some other libraries. That's an small example, which actually works as I wanted:
#include <cstdlib>
#include <ncurses.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
initscr();
noecho();
box(stdscr, 0, 0);
struct winsize w;
int ch, x, y;
while(ch = getch())
{
if(ch == KEY_RESIZE)
{
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
resize_term(w.ws_row, w.ws_col);
clear();
box(stdscr, 0, 0);
}
refresh();
}
}
The thing is I'm kind of worried about portability while using this new libraries (I'm not completely sure, because I haven't started testing yet, but I understand that ncurse programs can be port to Windows).
I would really appreciate any information about how to do this in ncurse without using any other library (if it's possible), if what I'm doing now is OK or if I should be doing it in any other way. Any hint in the right direction is what I'm looking for :)
I'm using Arch Linux (kind of noobie) and qtile as a window manager. If you need any other relevant information, just ask me. Thanks for the help!
This is causing the example to produce bogus results:
if(ch = KEY_RESIZE)
since it is always true (not a comparison, but an assignment). The "something" is not doing anything useful, because the condition is incorrect.
Change that to
if(ch == KEY_RESIZE)
and get rid of
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
resize_term(w.ws_row, w.ws_col);
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#define MAX_THREADS 1
#include <windows.h>
#include <iostream>
using namespace std;
DWORD WINAPI printNumbe(LPVOID);
// We need an array of Handles to threads
HANDLE hThreads[MAX_THREADS];
//...an array of thread id's
DWORD id[MAX_THREADS];
//And a waiter
DWORD waiter;
DWORD WINAPI printNumber(LPVOID n)
{
int num = (int)n;
for (int i = 0; i <= num; i++)
{
cout << "Hey there!" << endl;
}
return (DWORD)n;
}
//get ready, because here's where all the REAL magic happens
int main(int argc, char* argv[])
{
int number;
cout << "Please enter a number:" << endl;
cin >> number;
//here is where we call the CreateThread Win32 API Function that actually
//creates and begins execution of thread
//please read your help files for what each parameter does on
//your Operating system.
//Here's some basics:
//Parameter 0: Lookup, 1: Stack Size, 2: The function to run with this thread, 3: Any parameter that you want to pass to thread
//function, 4: Lookup , 5: Once thread is created, an id is put in this variable passed in
hThreads[0] = CreateThread(NULL, 0, printNumber, (LPVOID)number, NULL, &id[0]);
//now that all three threads are created and running, we need to stop the primary thread
// which is this program itself - remember that once "main" returns, our program exits
//so that our threads have time to finish. To do this, we do what is called "Blocking"
//we're going to make main just stop and wait until all three threads are done
//this is done easily with the next line of code. please read the help file about the specific API call
//"WaitForMultipleObjects"
waiter = WaitForMultipleObjects(MAX_THREADS, hThreads, TRUE, INFINITE);
//after all three threads have finished their task, "main" resumes and we're now ready
//to close the handles of the threads. This is just a bit of clean up work.
//Use the CloseHandle (API) function to do this.
for (int i = 0; i < MAX_THREADS; i++)
{
CloseHandle(hThreads[i]);
}
system("PAUSE");
return 0;
}
Hi all. Recently I've started taking Operating System class at my college.
I got some chance to learn about threads and multi threads. My professor gave me a power point slide with some sample codes on how to start multi-threading program in C++.
So I have decided to use his code as the base and decided to tweak it a bit so that I can understand it better.
Please disregard all those comments I made (most of comments don't apply to this program, those comments were basically in the slide and I just left it there as a reference).
SO I've tweaked to produce "Hey there!" "x" times depends on what number the user inputs into "x". As you are seeing, I made it to print inside printNumber function (sorry about the name, since my main assignment is on printing prime numbers , so forgive me about that).
So the program runs fine and exactly produces "Hey there!" multiple times.
But here's the question. Since my professor wants me to use multi-threads, how do I verify myself in C++ that the program in running with a multi-thread?
This program seems like printing "Hey there!" in a row (just like under a single thread) and there's no way I can tell if multi-threading has been applied to the program or not.
Keep in mind that, I am not that familiar with those syntax and it's my first time using WINAPI in C++ as well as first time doing threading programming.
Thank you very much.
GetCurrentThreadId will return the unique id for the current thread, if you print this inside your threaded function and main you should find it returns different values.
I know this question has been asked several times on the net, but I could not find any of those answers helpful.
I want to keep running a loop and break it once the user press a key (e.g. enter or esc). I don't want it to ask user any input during the process.
I have a while loop.
I am new to C++, so please answer simply.
My system is Mac OS X.
There you go. I hope this helps.
#include <iostream>
#include <thread>
#include <atomic>
// A flag to indicate whether a key had been pressed.
atomic_bool keyIsPressed(false);
// The function that has the loop.
void loopFunction()
{
while (!keyIsPressed) {
// Do whatever
}
}
// main
int main(int argc, const char * argv[])
{
// Create a thread for the loop.
thread loopThread = thread(loopFunction);
// Wait for user input (single character). This is OS dependent.
#ifdef _WIN32 || _WIN64
system("pause");
#else
system("read -n1");
#endif
// Set the flag with true to break the loop.
keyIsPressed = true;
// Wait for the thread to finish.
loopThread.join();
// Done.
return 0;
}
Update: Since the flag keyIsPressed is shared between threads, I added atomic for that. Thanks to #hyde.
This is indeed OS dependent, but probabilities are that you use Windows.
First, you'll need to include :
#include <Windows.h>
It gives you access to the function GetAsyncKeyState, and to Windows' key macros (list of Windows' key macros).
You'll also need the Most Significant Bit to evaluate key press ; just initialize it as a const in your code :
const unsigned short MSB = 0x8000;
Finally, let's put all together in a function :
bool listenKeyPress(short p_key)
{
//if p_key is pushed, the MSB will be set at 1
if (GetAsyncKeyState(p_key) & MSB)
{
return true;
}
else return false;
}
//Example of a call to this function to check if up enter is pressed :
listenKeyPress(VK_RETURN)
Then your while loop can be typed either :
while (!listenKeyPress(VK_ENTER))
{
}
or
bool quit = false;
while (!quit)
{
if (listenKeyPress(VK_ENTER) || listenKeyPress(VK_ESCAPE)
quit = true;
}
There you go!
Was curious myself how to do this when started... turns out never really used it was better to just getch() but if you need this and using windows include Windows.h and the following code should point you in the right direction (hopefully)
bool f = true;
while (f)
{
if (GetAsyncKeyState(VK_UP)){
//Enter code for when a button is pushed here
f = false;
}
else{
//Code to run until the button is pushed
}
}
If you want to use a different button VK_UP can be changed to any key or mouse button you have, just scroll through the list(assuming you are probably a student using visual studio) if you have no list look up what key applies for the button you wish to press.
EDIT: Also if you want it to run forever remove the f = false and it will work while button is pressed and while not pressed to do whatever you like (Not great coding practice to leave no exit of a while loop though so probably best to test for a key being pressed in another while loop to exit)
I am trying to get a keyboard input, but if it doesn't happen in about half a second I want it to continue to the rest of the loop. I tried using kbhit(); but it won't wait for the input, it just loops with out stopping. This is the loop in question:
while(flags)
{
gameing.updateDraw(0, 0);
keyIn = getch();
//Sleep(20);
switch(keyIn)
{
case UP_ARROW:
flags = gameing.updateDraw(-1, 1);
break;
case DOWN_ARROW:
flags = gameing.updateDraw(1, 1);
break;
case WKEY:
flags = gameing.updateDraw(-1, 2);
break;
case SKEY:
flags = gameing.updateDraw(1, 2);
break;
}
All help will be greatly appreciated. I am trying to avoid using alarm();
The comnented call to Sleep indicates that this is a Windows program using <conio.h> functionality, and not a *nix program using curses.
With <conio.h> you can use the kbhit function to check whether there is a keypress.
Place that in a loop that sleeps a little bit between each call.
More advanced you can use the Windows API. Its wait functions can wait on a console handle, with a specified timeout.
The C++ standard library does not have unbuffered keyboard input functionality.
Try using something like ctime.h or chrono to get the time difference. Then do something like
long lastTime=CurrentTime();
int input=0;
while(!(input=kbhit()) && CurrentTime()-lastTime < 20);
if(input)
// do stuff with input
// do all the other stuff
lastTime=CurrentTime();
Disclaimer. I'm not particularly familiar with kbhit and things, but based on a little bit of googling, this seems like it ought to work. Also the implementation of CurrentTime is up to you, it doesn't have to be a long or anything, I just chose that for simplicity's sake.
Here's an oddity from the past!
I'm writing an ASCII Pong game for the command prompt (Yes yes oldschool) and I'm writing to the video memory directly (Add. 0xB8000000) so I know I'm rendering quickly (As opposed to gotoxy and then printf rendering)
My code works fine, the code compiles fine under Turbo C++ V1.01 BUT the animation lags... now hold on hold on, there's a cavaet! Under my super fast boosted turbo Dell Core 2 Duo this seems logical however when I hold a key on the keyboard the animation becomes smooth as a newly compiled baby's bottom.
I thought maybe it was because I was slowing the computer down by overloading the keyboard buffer (wtf really? come on...) but then I quickly smartened up and tried compiling for DJGPP and Tiny C Compiler to test if the results are the same. On Tiny C Compiler I found I coulnd't compile 'far' pointer types... still confused on that one but I was able to compile for DJGPP and it the animation ran smoothly!
I want to compile this and have it work for Turbo C++ but this problem has been plagueing me for the past 3 days to no resolve. Does anyone know why the Turbo C++ constant calls to my rendering method (code below) will lag in the command prompt but DJGPP will not? I don't know if I'm compiling as debug or not, I don't even know how to check if I am. I did convert the code to ASM and I saw what looked to be debugging data at the header of the source so I don't know...
Any and all comments and help will be greatly appreciated!
Here is a quick example of what I'm up against, simple to compile so please check it out:
#include<stdio.h>
#include<conio.h>
#include<dos.h>
#include<time.h>
#define bX 80
#define bY 24
#define halfX bX/2
#define halfY bY/2
#define resolution bX*bY
#define LEFT 1
#define RIGHT 2
void GameLoop();
void render();
void clearBoard();
void printBoard();
void ballLogic();
typedef struct {
int x, y;
}vertex;
vertex vertexWith(int x, int y) {
vertex retVal;
retVal.x = x;
retVal.y = y;
return retVal;
}
vertex vertexFrom(vertex from) {
vertex retVal;
retVal.x = from.x;
retVal.y = from.y;
return retVal;
}
int direction;
char far *Screen_base;
char *board;
vertex ballPos;
void main() {
Screen_base = (char far*)0xB8000000;
ballPos = vertexWith(halfX, halfY);
direction = LEFT;
board = (char *)malloc(resolution*sizeof(char));
GameLoop();
}
void GameLoop() {
char input;
clrscr();
clearBoard();
do {
if(kbhit())
input = getch();
render();
ballLogic();
delay(50);
}while(input != 'p');
clrscr();
}
void render() {
clearBoard();
board[ballPos.y*bX+ballPos.x] = 'X';
printBoard();
}
void clearBoard() {
int d;
for(d=0;d<resolution;d++)
board[d] = ' ';
}
void printBoard() {
int d;
char far *target = Screen_base+d;
for(d=0;d<resolution;d++) {
*target = board[d];
*(target+1) = LIGHTGRAY;
++target;
++target;
}
}
void ballLogic() {
vertex newPos = vertexFrom(ballPos);
if(direction == LEFT)
newPos.x--;
if(direction == RIGHT)
newPos.x++;
if(newPos.x == 0)
direction = RIGHT;
else if(newPos.x == bX)
direction = LEFT;
else
ballPos = vertexFrom(newPos);
}
First, in the code:
void printBoard() {
int d;
char far *target = Screen_base+d; // <-- right there
for(d=0;d<resolution;d++) {
you are using the variable d before it is initialized.
My assumption is that if you are running this in a DOS window, rather than booting into DOS and running it, is that kbhit is having to do more work (indirectly -- within the DOS box's provided environment) if there isn't already a keypress queued up.
This shouldn't effect your run time very much, but I suggest that in the event that there is no keypress you explicitly set the input to some constant. Also, input should really be an int, not a char.
Other suggestions:
vertexFrom doesn't really do anything.
A = vertexFrom(B);
should be able to be replaced with:
A = B;
Your macro constants that have operators in them should have parenthisis around them.
#define Foo x/2
should be:
#define Foo (x/2)
so that you never ever have to worry about operator precedence no matter what code surrounds uses of Foo.
Under 16 bit x86 PCs there are actually 4 display areas that can be switched between. If you can swap between 2 of those for your animation, and your animations should appear to happen instantaneously. It's called Double Buffering. You have one buffer that acts as the current display buffer and one that is the working buffer. Then when you are satisfied with the working buffer (and the time is right, if you are trying to update the screen at a certain rate) then you swap them. I don't remember how to do this, but the particulars shouldn't be too difficult to find. I'd suggest that you might leave the initial buffer alone and restore back to it upon exit so that the program would leave the screen in just about the state that it started in. Also, you could use the other buffer to hold debug output and then if you held down the space bar or something that buffer could be displayed.
If you don't want to go that route and the 'X' is the only thing changing then you could forgo clearing the screen and just clear the last location of the 'X'.
Isn't the screen buffer an array of 2 byte units -- one for display character, and the other for the attributes? I think so, so I would represent it as an array of:
struct screen_unit {
char ch;
unsigned char attr;
}; /* or reverse those if I've got them backwards */
This would make it less likely for you to make mistakes based on offsets.
I'd also probably read and write them to the buffer as the 16 bit value, rather than the byte, though this shouldn't make a big difference.
I figured out why it wasn't rendering right away, the timer that I created is fine the problem is that the actual clock_t is only accurate to .054547XXX or so and so I could only render at 18fps. The way I would fix this is by using a more accurate clock... which is a whole other story