i'm trying to write a stupid game.
the interface of the game is a menu list and it asks for an input.. ex.. 'f' for fight, 'r' for run.
the thing is, i'm using fgets() for the input and while this works ok, it is very annoying because it requires me to press enter after the letter.
how would i go about implementing some sort of 'hotkeys' so that the player would only have to press a single character without pressing <ENTER>.
__________________
sample code, sorry, don't know any UBB codes.
__________________
int main(void)
{
char Choice[2];
while(1)
{
puts( "Press a to attack");
puts( "Press b to run");
puts( "Press q to quit");
fgets( Choice, 2, stdin);
switch( Choice[0])
{
case 'a':
{
attack();
break;
}
case 'r':
{
run();
break;
}
case 'q':
{
return;
}
}
}
}
vhg119
01-22-2001, 10:56 AM
anyone?
f'lar
01-22-2001, 02:55 PM
getch() ? or is that c++ only?
vhg119
01-22-2001, 02:58 PM
either its C++ or i havent learned it yet..
i'll try it
would you happen to know the prototype for it?
ndogg
01-22-2001, 03:00 PM
The getch you're thinking of, f'lar, is C and C++, but only works properly in DOS for some reason (you have to jump through a lot of hoops to get it to work the way you think it will). Someone else had the same prob, and someone else solved it, but I don't know where the post is.
------------------
Too much Sun can give you cancer. Windows break too easily.
Apples/Macintoshes can rot. BSD... sounds too much like LSD.
Penguins are the only animals sophisticated enough to wear a
tuxedo.
Linux, the only one with the Penguin.
http://ndogg.n3.net
TheLinuxDuck
01-22-2001, 03:52 PM
Originally posted by vhg119:
the thing is, i'm using fgets() for the input and while this works ok, it is very annoying because it requires me to press enter after the letter.how would i go about implementing some sort of 'hotkeys' so that the player would only have to press a single character without pressing <ENTER>.
The trick is to change the terminal settings so that the users input is not buffered. Buffered input and output means that it waits for a newline to flush the buffer (I think this is true of output, but it is of input).
So, you'll have to jump through a few hoops to set this up. Let me find my C code for it. http://www.linuxnewbie.org/ubb/smile.gif
Oh, and btw, to post code with ubb tags, simply put [ code ] before the code and [ /code ] after. (Of course, remove the spaces between the brackets and the word code.
/* user input functions that allow for immediate response to keyboard input
including a string building function
TheLinuxDuck on linuxnewbie.org - bfkester@yahoo.com
This code works on my machine. I haven't done any extensive testing with it
or anything so it may not work for you. I don't know. I'm just a duck with
a keyboard... whatdoyouwantfromme?
*/
#include <stdio.h> // stdout, fflush, sprintf, printf
#include <string.h> // memset, called from macro FD_ZERO
#include <sys/time.h> // struct timeval
#include <sys/types.h> // fd_set (also FD_ZERO, FD_SET, select from select.h)
#include <termios.h> // struct termios, tcgetattr, tcsetattr, TCSAFLUSH
#include <unistd.h> // read
//
char singlekey(short int waittime); // one single key press
char stringkey(char *bptr,short int stringlength); // string input
//
int main(void)
{
//
// Savetty is used to store the current
// terminal settings, newtty is a copy that
// gets modified to allow unbuffered input,
// text is a string buffer.
//
struct termios newtty,Savetty; // for new terminal settings, and save
char quit=0,text[256];
//
if(tcgetattr(0,&Savetty)==-1) { // load current setting
printf("Could not initialize save of terminal settings.\n");
return 1;
}
//
newtty=Savetty; // copy current to new terminal settings
/* I used the source for the 'top' program to learn how to do this, so the
settings for the new terminal type where taken directly from it. I'm not
sure what these all really do, but they work. http://www.linuxnewbie.org/ubb/smile.gif
*/
newtty.c_lflag &= ~ICANON;
newtty.c_lflag &= ~ECHO;
newtty.c_cc[VMIN]=1;
newtty.c_cc[VTIME]=0;
//
if(tcsetattr(0,TCSAFLUSH,&newtty)==-1) { // Set new terminal
printf("Could not set new terminal type.\n");
return 1;
}
//
printf("Press any key, q to quit.\n"); // Single key press loop
while(!quit) {
if((quit=singlekey(5))>0) {
printf("You pressed the %c [%d] key.\n",quit,quit);
if((quit&223)=='Q')
quit=1;
else
quit=0;
}
}
//
printf("Enter some text:\n");
stringkey(text,100); // Get a string
printf("\nYou entered: %s\n", text);
//
tcsetattr(0,TCSAFLUSH,&Savetty); // restore original settings
return 0;
}
//
// waittime indicates the number of seconds
// to wait before select will stop waiting
//
char singlekey(short int waittime)
{
fd_set input;
char returnchar;
struct timeval delay;
//
while(1) {
/*
According to the man info about select, these next four items must be set
each time before select is called, as the vars are reset each time (if I
understood it correctly)
*/
delay.tv_sec=waittime;
delay.tv_usec=0;
FD_ZERO(&input);
FD_SET(0,&input);
/*
We're letting select tell us if a key is waiting in the input buffer, and
reading a char to return if it happens in the alloted 'waittime'
*/
if(select(1,&input,NULL,NULL,&delay)>0 && read(0,&returnchar,1)==1)
return(returnchar);
}
return(0);
}
//
char stringkey(char *bptr,short int stringlength)
{
char buffer[256]={0};
char quit=0,current=0;
//
if(stringlength>255) stringlength=255; // set max stringlength
//
while(quit!=10) {
switch((quit=singlekey(5))) {
case 8: // backspace pressed
if(current>0) {
buffer[(int)(--current)]='\0';
printf("%c %c",8,8); fflush(stdout);
}
break;
case 10: // enter pressed
sprintf(bptr,"%s",buffer);
break;
default: // any other key added to string
if(current+1<stringlength-1) {
buffer[(int)(current++)]=quit;
printf("%c",quit); fflush(stdout);
}
break;
}
}
return(1);
}
The code could be cleaner, but I don't feel like cleaning it up right now.. http://www.linuxnewbie.org/ubb/smile.gif
------------------
TheLinuxDuck
I have a belly button.
:wq
MrNewbie
01-22-2001, 03:55 PM
Isnt there getc() that does that?
Sterling
01-22-2001, 06:51 PM
There may be - man ncurses should get you a list of terminal handling functions. (Warning - its rather long, so be prepared to do a lot of hunting) man getc should give you information on that function, if there is one by that name. One can also push a newline back onto the input buffer, after getch()-ing, then immediately read to a garbage buffer.
------------------
-Sterling
"There is no Linuxnewbie.org cabal..."
TheLinuxDuck
01-22-2001, 07:02 PM
Originally posted by MrNewbie:
Isnt there getc() that does that?
getc that is included with stdio.h will work exactly the same as fgets or getchar or any variation in that if the input is buffered, it waits for return to be pressed before returning the keystroke(s).
I'm sure that ncurses has something to set up the terminal, but I say why bother. ncurses is bloated (IMHO), and I can accomplish all the same things, with relative ease.. at least, everything I've wanted to do that ncurses does..
The stuff I did above was fairly simple to set up, and doesn't require all the overhead that ncurses does, from my experience.
If someone can offer code to prove me otherwise, I'd surely (don't call me Shirley) be willing to look! http://www.linuxnewbie.org/ubb/smile.gif
I'm also biased because I know how to set this up, but I don't know much about ncurses.. http://www.linuxnewbie.org/ubb/smile.gif (just slap me now!)
------------------
TheLinuxDuck
I have a belly button.
:wq
bradh352
01-23-2001, 11:57 PM
Whew...lot's of advice...but nobody says anything about using select?!
Alright...you really need to write your own getch routine...
To do this is simple...the we just use it like good ol' dos!
#include <unistd.h>
int mygetch() {
char byte;
fd_set readfs;
FD_ZERO(&readfs);
// Put stdin into the readfs buffer
FD_SET(stdin, &readfs);
// Now just wait until we have something
// Via stdin
// This will block until a key is hit
// Read the select man page if you want
// Timeouts!!!
select(stdin+1, &readfs, NULL,NULL,NULL);
// Got something
read(stdin, &byte, 1);
return(byte);
}
Well, that's off the top of my head...should be correct though....
-Brad
[This message has been edited by bradh352 (edited 23 January 2001).]
mastersibn
01-24-2001, 12:20 AM
Originally posted by TheLinuxDuck:
getc that is included with stdio.h will work exactly the same as fgets or getchar or any variation in that if the input is buffered, it waits for return to be pressed before returning the keystroke(s).
I'm sure that ncurses has something to set up the terminal, but I say why bother. ncurses is bloated (IMHO), and I can accomplish all the same things, with relative ease.. at least, everything I've wanted to do that ncurses does..
The stuff I did above was fairly simple to set up, and doesn't require all the overhead that ncurses does, from my experience.
If someone can offer code to prove me otherwise, I'd surely (don't call me Shirley) be willing to look! http://www.linuxnewbie.org/ubb/smile.gif
I'm also biased because I know how to set this up, but I don't know much about ncurses.. http://www.linuxnewbie.org/ubb/smile.gif (just slap me now!)
Correct me if I'm wrong here, but libncurses is NOT bloated. Why? Because it's a shared (dynamic) lib. IIUC dynamic libs properly, Linux needs to only load ONE copy of it for the benefits to be applied to all the programs that request it. This means that if you run ONE program that uses ncurses, you're using up enough ram for ncurses. If you run TWO programs using ncurses, you're STILL only using up enough ram for one copy. Now, unless this understanding is wrong, I'd like to say that:
Ncurses is NOT bloated. It embodies the opposite of bloat, much in the same way GNOME does. So it's big; that doesn't mean it's bloated. GNOME is made with sharing in mind. Instead of re-inventing the wheel and avoiding dynamic libs for every app you create, you re-use what's there. It shortens development time, and makes the program run better on that system. Imagine if every programmer had to manually implement all the GNOME features his app would use; then all the apps would be bloated. But not now. GNOME provides a foundation for sharing.
And people whining about having to have KDE+GNOME installed just to be able to use whatever apps they want: You can quit whining. After all, if you don't want Kde, don't install it. Many Kde apps have Gnome counterparts in some fashion or other. Likewise if you don't like Gnome: You don't have to have all those Gnome-centric apps on your system, either. You *can* safely go all out for one or the other. You aren't robbing yourself of any decisions, because then it becomes your decision to NOT use the other environ, which you can freely reverse at any time. Me? I keep both Gnome and Kde on my system. I use GNOME more recently, because I like the look/feel of themed Gtk better than the look/feel of Qt for some strange reason. Don't analyze it too hard; lots of people have really strange preferences for the littlest things (I.E., philadelphia vanilla ice cream is ok, but french vanilla is not. They're different, deal with it. http://www.linuxnewbie.org/ubb/smile.gif). I'm just more at ease with Gtk-bound applications. Ah, well. didn't mean for this to turn out into some religious debate http://www.linuxnewbie.org/ubb/biggrin.gif, so I'm gonna halt it with this:
I don't think ncurses is bloated. If you used ncurses, you could probably even save some ram. Of course, that DOES depend on the system you run. Hey, not everybody uses ncurses-friendly apps all the time, so on their system, it would be a little bit unnecessary. But even accounting for that: Why reinvent the wheel? http://www.linuxnewbie.org/ubb/biggrin.gif
------------------
grab my gnupg key (http://jove.prohosting.com/~msibn/sibn-p.asc) if you feel so inclined.
cAPS lOCK? wHAT cAPS lOCK?
I cna ytpe 300 wrods pre mniuet!!!
an operating system has not just advantages...
TheLinuxDuck
01-24-2001, 12:39 AM
Originally posted by bradh352:
Whew...lot's of advice...but nobody says anything about using select?!
If you'll examine the source I posted above you'll find that is exactly what I used.
Alright...you really need to write your own getch routine...
Which was done in the posted code above. The function 'singlekey' does that very thing. http://www.linuxnewbie.org/ubb/smile.gif When i post code, I don't like to post a segment.. I prefer to post a complete piece of code. That way, the person can get a working example. http://www.linuxnewbie.org/ubb/smile.gif
Well, that's off the top of my head...should be correct though....
The only thing you've forgotten is to turn off input buffering. With input buffering on, you still have to press enter before select/read will work... which the code I posted did.. http://www.linuxnewbie.org/ubb/smile.gif
------------------
TheLinuxDuck
I have a belly button.
:wq
TheLinuxDuck
01-24-2001, 10:20 AM
mastersibn:
I admit wholeheartedly that ncurses is not my thing.. I've never really used it, and don't know much about the way it works.. my comments on it are based solely on what little experience I have with it.
If you have experience with it, you are far more a wiser choice to give good and solid info on it. http://www.linuxnewbie.org/ubb/smile.gif
My comment about ncurses being bloated refers to the amount of things it can do.. every time I've ever got into reading up on it, I was overwhelmed with choices and functionality. I couldnt' ever find a simple straight-forward answer to any of my questions and things I was trying to do.. granted what I posted above isn't the simplest and most easy to follow thing in the world, but it was a solution i could understand. http://www.linuxnewbie.org/ubb/smile.gif
Forgive me if I sounded rude or insulting.. I was kinda in a ranting mood when I wrote that, am I'm sure I came across with a sharp tongue. http://www.linuxnewbie.org/ubb/smile.gif
------------------
TheLinuxDuck
I have a belly button.
:wq
vhg119
01-24-2001, 07:38 PM
thanx alot guys.. i'll try anything.
i'll tell you how it goes.
vince
justlinux.com
Copyright Internet.com Inc. All Rights Reserved.