How do I can call initgraph more than one time? - c

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 ...

Related

XServer first key typed is always in lowercase

I'm writing a method for keyboard handling where I'm passing the key unicodes and firing keystrokes using the XTestFakeKeyEvent Method of X11. Now my issue is that after the opening the display, if the very first Character I send is in Uppercase, it still is typed in lowercase. So provided is the minimal implementation.
Compiled using command: gcc typekeys.c -o typekeys.exe -lX11 -lXtst
#include <stdio.h>
#include <stdbool.h>
#include <X11/extensions/XTest.h>
#include <X11/XKBlib.h>
#include <X11/Xlib.h>
static Display *mainDisplay = NULL;
Display *XGetMainDisplayK(void) {
if (mainDisplay == NULL) {
mainDisplay = XOpenDisplay(NULL);
if (mainDisplay == NULL) {
printf("\nCould not open main display");
}
}
return mainDisplay;
}
void toggleKeySym(unsigned int key){
KeySym sym;
Display *dpy;
dpy = XGetMainDisplayK();
sym=key;
printf("\nKeysym recieved:%u \n",key);
int min, max, numcodes;
XDisplayKeycodes(dpy, &min, &max);
KeySym *keysym;
keysym = XGetKeyboardMapping(dpy, min, max-min+1, &numcodes);
keysym[(max-min-1)*numcodes]=sym;
XChangeKeyboardMapping(dpy, min, numcodes, keysym, (max-min));
XFree(keysym);
XFlush(dpy);
unsigned int code;
printf("Keysym value:%d \n",sym);
code=XKeysymToKeycode(dpy, sym);
printf("Code Generated:%u. \n",code);
XTestFakeKeyEvent(dpy, code, True, CurrentTime);
XTestFakeKeyEvent(dpy, code, False, CurrentTime);
XSync(dpy, false);
XFlush(dpy);
}
void main(){
printf("Start \n");
toggleKeySym(65);
toggleKeySym(65);
printf("Done.\n");
}
The problem is XKeysymToKeycode(dpy, sym);:
If you look at the output of your program, you will see that it outputs something like this:
Code Generated:38.
...
Code Generated:254.
At least on my computer it behaves this way.
(By the way: I can only reproduce the problem the first time after logging off from my computer and logging on again.)
However, your program should write the same value twice because the same key code (254) is pressed.
This means that XKeysymToKeycode(dpy, sym); has returned the wrong value.
The reason is that XKeysymToKeycode() works the following way:
The XOpenDisplay() function calls XGetKeyboardMapping() reading the keyboard information to some "internal" variable (of the type KeySym *); the information in the "internal" variable is then used by XKeysymToKeycode().
The "internal" variable is updated later - maybe during XSync(). However, it seems that the "internal" variable is not updated before XKeysymToKeycode() is called the first time, so XKeysymToKeycode() returns the information still based on the old value of the "internal" variable.
However, you know that you have changed the symbol generated by the key max-1, so you know that code should have the value max-1. Therefore, calling XKeysymToKeycode() is not necessary at all.

How to access the PC Keyboard Buffer for Detecting multiple key press and key release?

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.

DDA Line Drawing Algorithm has errors

Why am I getting an error saying 'setPixel not defined' with this code?
#include <windows.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include<GL/glut.h>
inline int round(const float a)
{
return int (a+0.5);
}
void init(void)
{
glClearColor(0.0f,0.0f,1.0f,1.0f);
gluOrtho2D(0.0,200.0,0.0,200.0);
glMatrixMode(GL_PROJECTION);
}
void LineSegment(int xa, int ya,int xb,int yb)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0f,0.0f,0.0f);
printf("Enter the initial value");
scanf("%d%d",&xa,&ya);
printf("Enter the final value");
scanf("%d%d",&xb,&yb);
int dx=xb-xa;
int dy=yb-ya;
int steps,k;
float xIncrement,yIncrement,x=xa,y=ya;
if(fabs(dx)>fabs(dy))
steps=fabs(dx);
else
steps=fabs(dy);
xIncrement=dx/(float)steps;
yIncrement=dy/(float)steps;
setPixel(round(x),round(y));
for(k=0;k<steps;k++);
{
x += xIncrement;
y += yIncrement;
setPixel(round(x),round(y));
}
glFlush();
}
int main(int argc, char** argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGBA);
glutCreateWindow("DDA Line Algorithm");
glutDisplayFunc(LineSegment);
init();
glutMainLoop();
return 0;
}
Because there is no setPixel method in OpenGL or GLUT and as far as I can see from your code, you do not define one either. OpenGL deals with rendering primitives like points, lines, triangels etc, but not directly with setting single pixels on the screen. Since it is unclear what you want to achieve some suggestions:
If you want to draw a line in OpenGL, use the appropriate methods like glBegin(GL_LINES), etc. (although they are deprecated and should not be used anymore.) or glDrawArrays(GL_LINES, ....
If the goal is to implement a dda software rasterizer, then you might have to write the pixels to a texture and then display this texture.
Because you haven't defined setPixel anywhere. It's not an OpenGL call. You need to write it yourself, and it should set pixels on a buffer (if you're using double buffering) which you then later use as an argument to glDrawPixels(), or a call to the display buffer using glVertex2i(x,y). You can see an example of both approaches here and here.
Also, your LineSegment function is broken. In OpenGL you call glutDisplayFunc to specify a function which is called as fast as possible to render the display. However, in this function you call scanf() to prompt the user for data - this is broken. You should prompt them once at the start, and then pass that data into the function (which will then run as often as possible once glutMainLoop is called).

Stuck in programming with winBGIm with C

I recently discovered winBGIm libraries, and I find it very useful to learn to code, so I started creating something to get some practice but I got stuck with my program.
The program should show a little ball and two rectangles approaching to the ball itself, and the player can move the ball up and down simply by pressing a button on the keyboard. Initially, I wrote everything in the main to make it fast, but since this is terrible I divided the program into functions.
First of all, even when everything was together, the getch function seemed to not work, because, while it should wipe the input buffer for the kbhit function, it made the ball not move at all, while the mere kbhit function worked, but obvioulsy the ball continued going up even when you stopped pressing a key. I used the same procedure in another text-only program and it worked very well, so I don't know where the problem is.
The second and most important problem is that, after splitting the program into functions, it became static, since the main loop which would make the graphic move stops at the end of the first iteration. It only restarts working when I delete the cleardevice function at the end of the loop and I disable the duble buffering in the initwindow function, but I can't understand the relationship between these things.
Finally, when I set a new background color, if it is not 0 (black), the window remains completely black.
I hope someone can help me.
Best regards, Giacomo.
#include <graphics.h>
#include <time.h>
#include <stdio.h>
int rettangoli(int b);
void bird(int x_default, int y_default);
void bird();
int main() {
int a=640;
int b=480;
int x_default=150;
int y_default=400;
int verifica=0;
srand(time(NULL));
initwindow(a, b, "BGI", 0, 0, true, true);
setbkcolor(0);
while(1) {
bird(x_default, y_default);
verifica=rettangoli(b);
if(verifica==1) {
outtextxy(0, 0, "HAI PERSO");
outtextxy(0,20, "PREMERE UN TASTO PER CONTINUARE");
break;
}
delay(50);
while(kbhit()) {
getch();
}
swapbuffers();
cleardevice();
}
delay(350);
getch();
closegraph();
return 0;
}
void bird(int x_default, int y_default) {
static int x_pos=x_default;
static int y_pos=y_default;
if(kbhit()) {
if(y_pos-16>0)
y_pos=y_pos-5;
circle(x_pos, y_pos, 16);
setfillstyle(SOLID_FILL, YELLOW);
floodfill(x_pos, y_pos, 15);
}
else {
while(y_pos<400)
y_pos=y_pos+15;
circle(x_pos, y_pos, 16);
setfillstyle(SOLID_FILL, YELLOW);
floodfill(x_pos, y_pos, 15);
}
return;
}
int rettangoli(int b) {
static int x_rett=615;
int verifica=0;
int contatore;
int altezza;
if(x_rett==615)
altezza=rand()%(b-60)+1;
rectangle(x_rett, 0, x_rett+25, altezza);
rectangle(x_rett, altezza+60, x_rett+25, 480);
setfillstyle(SOLID_FILL, GREEN);
floodfill(x_rett+1, 1, 15);
floodfill(x_rett+1, 479, 15);
for(contatore=0;contatore<altezza && x_rett>100;contatore++) {
if(getpixel(x_rett-1, contatore)!=getbkcolor())
verifica=1;
}
for(contatore=altezza+60;contatore<b && x_rett>100;contatore++) {
if(getpixel(x_rett-1, contatore)!=getbkcolor())
verifica=1;
}
for(contatore=0;contatore<15;contatore++) {
if(getpixel(contatore, altezza)!=getbkcolor())
verifica=1;
}
for(contatore=0;contatore<15;contatore++) {
if(getpixel(contatore, altezza+60)!=getbkcolor())
verifica=1;
}
x_rett=x_rett-5;
printf("%i", x_rett);
return verifica;
}
Nevermind, I solved the problem on my own. There was an incompatibility issue between Windows 8 x64 and Codeblocks-EP, and I think there is a general incompatibility between winBGIm and x64 systems.
I created a virtual machine using Vmware Player and Windows XP x86 and now everything is fine.

How to pause a loop in C/C++

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?

Resources