I am trying to make a screen for a car game and make the screen wait for a key to go into the next screen, thing is that with this code it changes colors too fast. I've already tried delay() and sleep() which haven't worked properly. Also, after hitting a key, it closes and doesn't wait for me to enter a key. I just want the title to blink between white and red until a key is hit, and get to know why it exits after hitting a key.
Here is my code:
#include <dos.h>
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
int main(void)
{
int gdriver = DETECT, gmode, errorcode;
initgraph(&gdriver, &gmode, "C|\\BORLANDC\\BGI");
outtextxy(250,280,"POINTER DRIVER 1.0");
outtextxy(250,290,"LCCM 10070249");
do
{
setcolor(WHITE);
outtextxy(250,380,"PRESS ANY KEY TO CONTINUE");
// delay(10); nothing works here :(
setcolor(RED);
outtextxy(250,380,"PRESS ANY KEY TO CONTINUE");
} while(!kbhit());
cleardevice();
outtextxy(250,290,"HELLO"); //here it draws mega fast and then exits
getch();
closegraph();
return 0;
}
Instead of using delay(10), maybe try using some sort of timer variable to do this. Try something like the following (a modification of your do-while loop):
unsigned flashTimer = 0;
unsigned flashInterval = 30; // Change this to vary flash speed
do
{
if ( flashTimer > flashInterval )
setcolor(RED);
else
setcolor(WHITE);
outtextxy(250,380,"PRESS ANY KEY TO CONTINUE");
++flashTimer;
if ( flashTimer > flashInterval * 2 )
flashTimer = 0;
// Remember to employ any required screen-sync routine here
} while(!kbhit());
kbhit() returns true if there's a character in the buffer, but doesn't remove the character before it returns. Once you reach the getch() line, it takes the first key that you pressed to break out of the while loop.
Possible solution: While it's a bit hacky, adding a getch() right after your while loop would probably fix it.
May I also suggest using ncurses instead of those Borland libraries?
Related
Im hoping to make a clicker game from C. I already have the clicking mechanics down and im pretty confident i can do everything else but I can seem to find any articles or help regarding having a running line in the background. For example I have a line of code that allows whenever I click a key i get +1 money, but like most clicker games I want a auto klicker to be running every second or so. So i can just be normally clicking while at the same time theirs a function or line of code that adds +5 money every so often. Ive made my own (delay) code so thats not an issue, its just running a line in the background. Heres what I have so far...
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <time.h>
int main()
{
int menu;
char ch;
int klicks;
int klickses;
klicks=0;
void delay(unsigned int mseconds)
{
clock_t goal = mseconds + clock();
while (goal > clock());
}
printf("Welcome to Key Klicker! This game is a idle game where you slowly gain more and more klicks over time.\n The game is never ending but their are milestones to reach.\n A menu will open up to help navigate through the game.\n");
do{
printf(" 1: Clicking\n 2: Shop\n 3: Exit\n\n");
scanf("%d", &menu);
if(menu == 1)
{
klickses=0;
{
char ch;
printf("Klick as fast as you can! (ESC to exit)\n");
while (1) { //define infinite loop for taking keys
if (kbhit) {
ch = getch(); // Get typed character into ch
klicks=klicks+1;
klickses=klickses+1;
if ((int)ch == 27) //when esc button is pressed, then it will comeout from loop
break;
printf("+1\n");
}
}
}
printf("You have a total of %d klicks!\n", klicks);
printf("You earned %d klicks that session!\n\n", klickses);
}
else if(menu == 2)
{
printf("work in progress\n");
}
else if (menu == 3)
{
printf("exit work in progress\n");
}
}while (1);
}
Hey guys I got it to work! Basically instead of having a auto adder every so seconds I decided to make a stopwatch that starts at the beginning and ends when I go out of the auto clicker. I then minus the end time from the start time and just calculate the auto clicks from their!
I also think with a new variable I just learned called time_t I could make an if statement that if a certain time is passed it would add 5 but anyhoo im not going to vere onto another path. This communities super helpful keep it going!
Please look at the following code:
#include <stdio.h>
#include <graphics.h>
#include <conio.h>
using namespace std;
void drawrect()
{
int gdriver = IBM8514, gmode;
initgraph(&gdriver, &gmode, "");
rectangle(500, 500, 700, 700);
getch();
cleardevice();
closegraph();
}
int main()
{
int f=1;
while(f)
{
char c;
printf("Press \"e\" to end, and any other character to draw a rectangle");
scanf("%c",&c);
c=='e' ? f=0:f=1;
drawrect();
fflush(stdin);
}
}
at the first time when I run this program, It works correctly and draws a rectangle, but after the first time, the rectangle function doesn't work and the GUI screen is completely blank, While I've cleared and closed previous graphic
So why it doesn't work at second time?
You code has undefined behaviour. The call to initgraph
int gdriver = IBM8514, gmode;
initgraph(&gdriver, &gmode, "");
should pass a pointer to the graphics mode you want to use. This page describes the function and its arguments, and about the mode it says:
*graphmode is an integer that specifies the initial graphics mode (unless *graphdriver equals DETECT; in which case, *graphmode is set
by initgraph to the highest resolution available for the detected
driver). You can give *graphmode a value using a constant of the
graphics_modes enumeration type, which is defined in graphics.h and
listed below.
graphdriver and graphmode must be set to valid values from the
following tables, or you will get unpredictable results. The exception
is graphdriver = DETECT.
But you have not set the mode, and as the second paragraph quoted says, the result is unpredictable. This can be: working how you intended, not working, working strangely, or frying the processor.
So set the graphics mode you want to use with say
int gdriver = IBM8514, gmode = 0;
or whatever mode you need to use. Alternatively you can tell the system to detect for itself, in which case you can use
int gdriver = DETECT, gmode;
Init and close should be called just once and not be called in the drawrect but usually in the main instead ... also having getch in rendering routine makes no sense too...
I will not touch other issues here of your code as I am not coding console stuff for years and BGI even longer but I would start with reordering the code to this:
#include <stdio.h>
#include <graphics.h>
#include <conio.h>
using namespace std;
void drawrect()
{
rectangle(500, 500, 700, 700);
}
int main()
{
int f=1;
int gdriver = IBM8514, gmode;
initgraph(&gdriver, &gmode, "");
while(f)
{
char c;
printf("Press \"e\" to end, and any other character to draw a rectangle");
scanf("%c",&c);
c=='e' ? f=0:f=1;
drawrect();
getch();
fflush(stdin);
}
cleardevice();
closegraph();
}
Also in future address the library by its real name BGI because graphics.h has no meaning as almost all gfx api/libs got a file with that name ...
I have a piece of code that will read a key event from the console using the ReadConsoleInput function. It works mostly, except that it fails to read when a button is released while the shift key is pressed.
I wrote the most minimal example code I could. What it does right now is reads whether the 'a' key is pressed or not and displays it to the screen. If you run it and press 'a' you get
41[down]
41[up]
if you run it and hold down the shift key before pressing 'a', all you get is
41[down]
and you will not get a key up event until you release the shift key and press 'a' again.
Here is my code:
#include <stdlib.h>
#include <stdio.h>
#include <Windows.h>
#include <Tchar.h>
int main()
{
HANDLE rhnd = GetStdHandle(STD_INPUT_HANDLE);
while(1)
{
INPUT_RECORD buf[128];
DWORD Events = 0;
DWORD EventsRead = 0;
GetNumberOfConsoleInputEvents(rhnd, &Events);
if(Events == 0)continue;
int i;
for(i=0;i<sizeof(buf);++i)//clear buf in case ReadConsoleInput doesn't do it for me, probably unnecessary
((char *)buf)[i]=0;
ReadConsoleInput(rhnd, buf, 128, &(EventsRead));
for(i=0;i<128;++i)//I would just loop while i<EventsRead but this ensures there are not extra elements (a little paranoid, I know)
{
if(buf[i].EventType == KEY_EVENT && (buf[i].Event.KeyEvent.wVirtualKeyCode & 0xff) == 0x41 /*keycode for 'a' button -- you can remove this condition to see the results for all key presses*/)
{
printf("%x",buf[i].Event.KeyEvent.wVirtualKeyCode);
if(buf[i].Event.KeyEvent.bKeyDown)
{
printf("[down]\n");
}
else //if this else gets executed it's what I'm calling a key up event
//this conditional should only be reached if either 'a' is pressed or 'a' was just released
//and the else should only be executed if it was just released
{
printf("[up]\n");
}
}
}
}
}
Any ideas on why this is happening and how to fix it
Compiled on windows 10 using gcc (MinGW-64) and also using Visual Studio 15
I am making a harmonium synthesizer software for PC in C language, for that I have to detect multiple keypress and keyrelease so that to play notes simultaneously accordingly. So, I am thinking that accessing the keyboard buffer would be helpful. But I don't know how to. So can anyone suggest the method to do so or some new idea to detect multiple keypress. For detecting single keypress and keyrelease I have made following C code using kbhit() and getch() functions:-
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<time.h>
void keypress(char);
void delay(int);
int flag=0;
int main()
{
char c;
while(1)
{
if(kbhit())
{
c=getch();
printf("\nCharacter:%c",c);
getch();
keypress(c);
printf("\nKey Released");
}
}
return 0;
}
void keypress(char ch)
{
char c;
delay(50);
if(kbhit())
{
c=getch();
if(c==ch)
{
keypress(c);
}
}
}
void delay(int milliSeconds)
{
clock_t final_time = milliSeconds + clock();
while (final_time > clock());
}
But it has some issues like:-
1).Multiple keypress not detected
2).It generates a very small delay
So can anybody suggest Improvement to code to solve the above issue or some new techniques for detecting multiple key press and key release.
Platform:-Windows 8.1
It would be good if the solution would platform friendly.
Thanks!
This shows how to use the Windows GetAsyncKeyState function. It does not need to be in a GUI - this console app works as shown. It will be up to you to examine the bit status flags as documented to determine action. For example, auto-repeat is honoured when a key is pressed. You probably won't need to check every key either.
#include <stdio.h>
#include <windows.h>
int main(void)
{
unsigned short buff[256] = {0};
unsigned short kval;
int i;
while (1) {
for(i=0; i<256; i++) {
kval = GetAsyncKeyState(i);
if(kval != buff[i]) {
printf("%02X:%04X ", i, kval);
buff[i] = kval;
}
}
}
return 0;
}
In this test, the first line was output before I pressed any key. The second line was output when I pressed and released 'A'.
0D:0001 26:0001 45:0001 53:0001 54:0001 0D:0000 26:0000 45:0000 53:0000 54:0000
41:8001 41:8000 41:0000
Note: linked with user32.lib.
As you include conio.h, the solution is already tied to a Windows (or MS/DOS) platform.
Here as i assume you do not really need a command line program, the best way would be build a Windows GUI program having an event loop and directly processing the WM_KEYDOWN and WM_KEYUP messages to be alerted as soon as a key is pressed on released on the keyboard. To avoid any risk of loosing one change in the state of the key, you could even consistently use the GetKeyboardState API function to load the current state of all keys on the keyboard.
I know this is more a hint that a precise answer, but a detailed answer would be much too long for a SO post.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
char b;
// the loop is executed until the "Return key" or "Enter" is pressed by the user
while(b!='\n')
{
b=getch();
putch('*');
}
return 0;
}
The program is something like typing password.As you press alphabets the output displays successive "*"s.
Until you press Return key and the program gets finished.
My problem is that my compiler(Codeblocks 13.12-->GNU GCC) doesn't understand the control keys like Return.Even when I replace '\n' with the ASCII code 10(the concerning ASCII code for Return key) the program makes a mistake again.The mistake is to continue displaying "*"s even when Return key is pressed!
What's going on with the compiler and how it 'll be fixed?
Try using
/* 13 refers to '\r' (carriage return) */
while(b != 13) {
//Code
}