Stuck in programming with winBGIm with C - 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.

Related

How to stop the constant flickering while playing animation?

I was trying to make a simple animation of a stickman walking, in graphics library in C.
My code:
#include<stdio.h>
#include<graphics.h>
void swap(int *x, int *y){
int temp=0;
temp=*x;
*x=*y;
*y=temp;
}
int main(){
int gd=DETECT,gm=0;
int i=0;
int a=30+i;
int b=50+i;
initgraph(&gd,&gm,"C:\\TURBOC3\\BGI");
while(i!=600){
swap(&a,&b);
circle(40+i,40,30);
line(40+i,70,a+i,90);
line(40+i,70,b+i,90);
i++;
delay(10);
cleardevice();
}
getch();
closegraph();
return 0;
}
The problem is that, the monitor screen keeps flickering constantly while playing the animation and moreover, the leg positions are not swapping according to the swap(&b,&c) function. Where am I going wrong here? Can someone please help me?
Fix: So, I realised that, there's no point in having the swap() function as, swapping the lines will make the alignment same again for both of them (as a result it will look like the legs are not moving), so I decided to tweak some things here:
while(i!=600){
if(i%2==0){
circle(40+i,40,30);
line(40+i,70,(a+b)/2+i,90);
line(40+i,70,(b+a)/2+i,90);
}else{
circle(40+i,40,30);
line(40+i,70,a+i,90);
line(40+i,70,b+i,90);
}
i++;
delay(10);
cleardevice();
}
Now, it actually looks like the figure is walking. But I still don't know how to fix the screen flickering problem.

Codeblocks C Debugging

I've got a new challenge to return the factorial of a number. Got ideas on how to do this, but the challenger has given some starting code - which is shown below.
Now this isn't how I would have started it (with my extremely limited experience!) - BUT I wasn't sure how system would grab some text & place within an int array - hence I tried running it within codeblocks, debugging and looking at the watch table. However I can't see 'num'.
So I tried copying num to num1:
int num1[30] = {0};
memset(num1[0],num[0], sizeof(num));
that doesn't seem to affect anything...
So question really is - is there something wrong with my codeblocks config (it debugs other programs and I've tried both cygwin & MiniGW) or is there another reason for this behavious?
#include <stdio.h>
#include <string.h>
void FirstFactorial(int num[]) {
// code goes here
printf("%d", num);
}
int main(void) {
// keep this function call here
FirstFactorial(gets(stdin));
return 0;
}

How do I can call initgraph more than one time?

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

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.

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