GIDForums  

Go Back   GIDForums > Computer Programming Forums > C Programming Language
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

 
 
Thread Tools Search this Thread Rate Thread
  #1  
Old 07-Feb-2004, 06:42
DWk DWk is offline
Junior Member
 
Join Date: Feb 2004
Location: Guatemala
Posts: 38
DWk is on a distinguished road
Question

Having trouble with Galaga-game


Hello everyone. This is my first time posting, but I've been watching here for some time. I'm currently taking a C course in the university, and have a project due on monday. The program is basically a Galaga type of game. I currently have the ship, it fires, and moves.

The problem is, however, that I can't create the enemy ships because I use clrscr whenever the ship moves.

Here's my code

CPP / C++ / C Code:
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <dos.h>

int x = 37;
int y = 25;
char b;


void ship (int x, int y);
void shoot (int x, int y);
void menu ();
void enemy();
void salida ();


void salida(){
clrscr();
delay(500);
printf("Gracias por jugar\n");
exit(0);
}


void enemy(int x, int y){
gotoxy(x,y);
printf("w0otage");

}

void shoot(int x, int y){
int i=21;
while (i>0){
 int ejex = x;
 gotoxy(ejex+3, i);
 printf("|");
 delay (14);
 i--;

}
ship(x,y);

}

void ship(int x, int y){
clrscr();
gotoxy(x,y);
printf("*-----*");
gotoxy(x,y-1);
printf(" *---* ");
gotoxy(x,y-2);
printf("  *-*  ");
gotoxy(x,y-3);
printf("   *   ");


delay(3000);
enemy(x,y);

b = getch();

switch (b){

 case 'a':
  if(x<=5){
   ship(x,y);
  }else {
   ship(x-7,y);
   }
  break;
  
    
 case 'd':
  if(x>=72){
   ship(x,y);
  }else {
   ship(x+7,y);
   }
  break;
 
 case 's':
  shoot(x,y);
  break;
 
 case 'm':
  menu();
  break;

 case 'z':
  salida();
  break;

 default:
  ship(x,y);
}

}

void menu(){

clrscr();
gotoxy(22,10);
printf("Izquierda   A\n");
gotoxy(22,11);
printf("Disparar   S\n");
gotoxy(22,12);
printf("Derecha    D\n");
gotoxy(22,13);
printf("Menu    M\n");
gotoxy(22,14);
printf("Salir    Z\n");
gotoxy(22,16);
printf("Para empezar a jugar, presione E\n");
gotoxy(22,17);
printf("Para salir, presione Z\n");

b = getch();

switch (b){

 case 'e':
  ship(x,y);
  break;

 case 'z':
  salida();
  break;

 default:
  menu();
    
}

}


void main(){

menu();
}


Press E to play, A-D for left-right, S for shooting, M for menu, and Z for quitting. I compiled with borlandC 3.1

So I need some advice on how to create the enemy ships.

Any help would be really appreciated : 8-)
Thanks
Last edited by dsmith : 07-Feb-2004 at 07:42. Reason: Added c syntax highlighting code
  #2  
Old 07-Feb-2004, 07:59
dsmith's Avatar
dsmith dsmith is offline
Senior Member
 
Join Date: Jan 2004
Location: Utah, USA
Posts: 1,351
dsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of light
Hi DWk. Bienvenidos. (Man, I love spanish - I was in Argentina for several years).

I haven't tried to compile your program yet, but when I boot into windows I will give it a go.

If I was you, I would try to avoid using clrscr at all. Otherwise you will need to redraw everything when your ship moves. Instead, I would call a clear routine that draws blanks at where the ship is before it moves

CPP / C++ / C Code:
case 'a':
  if(x>5){
    erase_ship(x,y);
    x-=7;
    draw_ship(x,y); 
   }
  break;

You will need to change your looping routine a bit. Maybe just throw it into a function called game_loop. Then set a timer to create your enemy ships. I assume that you are going to have several ships? Either use a structure or a couple of arrays to define these enemies and then do the movement similar to your ship. For example:
CPP / C++ / C Code:
int enemy_x[MAX];
int enemy_y[MAX];

and then when it comes to moving, throw these into a for loop:
CPP / C++ / C Code:
for(int index=0;index<MAX;index++){
  if(enemy_x[index]>5){     //Check for your limits (x-y)
    erase_enemy(enemy_x[index],enemy_y[index]);
    enemy_x[index]-=7;     //move either x or y or whatever
    draw_enemy(enemy_x[index],enemy_y[index]); 
   }

I think with todays computers this shouldn't lag too bad. Let us know what you come up with.

BTW - I editted your post to sorround your code with c and /c. This gives the lovely syntax highlighting that you see...
  #3  
Old 07-Feb-2004, 08:09
DWk DWk is offline
Junior Member
 
Join Date: Feb 2004
Location: Guatemala
Posts: 38
DWk is on a distinguished road
Quote:
Originally Posted by dsmith
Hi DWk. Bienvenidos. (Man, I love spanish - I was in Argentina for several years).

I haven't tried to compile your program yet, but when I boot into windows I will give it a go.

If I was you, I would try to avoid using clrscr at all. Otherwise you will need to redraw everything when your ship moves. Instead, I would call a clear routine that draws blanks at where the ship is before it moves

CPP / C++ / C Code:
case 'a':
  if(x>5){
    erase_ship(x,y);
    x-=7;
    draw_ship(x,y); 
   }
  break;

You will need to change your looping routine a bit. Maybe just throw it into a function called game_loop. Then set a timer to create your enemy ships. I assume that you are going to have several ships? Either use a structure or a couple of arrays to define these enemies and then do the movement similar to your ship. For example:
CPP / C++ / C Code:
int enemy_x[MAX];
int enemy_y[MAX];

and then when it comes to moving, throw these into a for loop:
CPP / C++ / C Code:
for(int index=0;index<MAX;index++){
  if(enemy_x[index]>5){     //Check for your limits (x-y)
    erase_enemy(enemy_x[index],enemy_y[index]);
    enemy_x[index]-=7;     //move either x or y or whatever
    draw_enemy(enemy_x[index],enemy_y[index]); 
   }

I think with todays computers this shouldn't lag too bad. Let us know what you come up with.

BTW - I editted your post to sorround your code with c and /c. This gives the lovely syntax highlighting that you see...


Hehe. Gracias

Avoid clrscr? Yea, I'm thinking about that, since I would have to re-draw not only the ship, but the enemies. I don't have trouble re-drawing the ship, but the enemies would be a pain, I think.

Bare with me on this - I'm in no way a l33t programmer (or resembling a good one ). So from your comment about function game_loop to the end I got lost

I worked on the other program already, the one that doesn't use clrscr. Check it out

Refer to Attached code file

There are 2 current problems I have there: If I go all the way to the left side, and I press A again to go left again, it goes right. And when I go all the way to the right side, and press D to go right again, it shoots.

Oh boy I'm a mess
Attached Files
File Type: txt galaga.c.txt (2.4 KB, 23 views)
Last edited by dsmith : 08-Feb-2004 at 12:11. Reason: Moved in-line program to attachment
  #4  
Old 07-Feb-2004, 08:31
dsmith's Avatar
dsmith dsmith is offline
Senior Member
 
Join Date: Jan 2004
Location: Utah, USA
Posts: 1,351
dsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of light
DWk
Your two problems have similar solutions. Take a look at this code snippet and where you have placed your break command. It is inside the else statement. Therefore if x<=5, your code will not break out of the switch and will proceed to the next case comparison, which in this instance is the d.
CPP / C++ / C Code:
case 'a':
      if (x<=5){
      }else {
        gotoxy(x,y);
        printf("       ");
        gotoxy(x,y-1);
        printf("       ");
        gotoxy(x,y-2);
        printf("       ");
        gotoxy(x,y-3);
        printf("       ");
        gotoxy(x-7,y);
        printf("*-----*");
        gotoxy(x-7,y-1);
        printf(" *---* ");
        gotoxy(x-7,y-2);
        printf("  *-*  ");
        gotoxy(x-7,y-3);
        printf("   *   ");
        ship(x-7,y);
        break;
      }

That should solve your problems there.

I think that you have a good start to this game, but if I were you, I would change a thing or two, that may make it easier in the long run.

First of all, you have defined x and y as globals, this is confusing for me, because you are passing x & y as well. So in your functions which x is being used, the global one or the local one?

Also, I think I would try indexing x and y instead of calling the function iteratively like you have. For example, your 'a' case and 'd' case do the exact same thing, except that 'a' subtracts 7 and 'd' adds 7. If you use subroutines for erase_ship and draw_ship, I think it would be much more efficient.

for example:
CPP / C++ / C Code:
void erase_ship(int x, int y)
{
   gotoxy(x,y);
   printf("       ");
   gotoxy(x,y-1);
   printf("       ");
   gotoxy(x,y-2);
   printf("       ");
   gotoxy(x,y-3);
   printf("       ");
}

void draw_ship(int x, int y)
{
   gotoxy(x,y);
   printf("*-----*");
   gotoxy(x,y-1);
   printf(" *---* ");
   gotoxy(x,y-2);
   printf("  *-*  ");
   gotoxy(x,y-3);
   printf("   *   ");
}

Then your case statement can be rewritten as:
CPP / C++ / C Code:
if (x>5){
    erase_ship(x,y);
    x -= 7;
    draw_ship(x,y);
}
break;

Also, if you notice, instead of using if/else, I just used if because there is no code to run for instances where x is less than 5. Does this make more sense?

One more note that you may want to consider. Look at the erase_ship routine that we have, it can be written easier:
CPP / C++ / C Code:
void erase_ship(int x, int y)
{
   for(int index = 0; index<4;index++){
       gotoxy(x,y-index);
       printf("       ");
   }
}

I'm lazy. Less code is good...

I think with this logic, creating your enemies and moving them will be alot easier.
  #5  
Old 07-Feb-2004, 08:54
DWk DWk is offline
Junior Member
 
Join Date: Feb 2004
Location: Guatemala
Posts: 38
DWk is on a distinguished road
Unhappy

Quote:
Originally Posted by dsmith
DWk
Your two problems have similar solutions. Take a look at this code snippet and where you have placed your break command. It is inside the else statement. Therefore if x<=5, your code will not break out of the switch and will proceed to the next case comparison, which in this instance is the d.
CPP / C++ / C Code:
case 'a':
      if (x<=5){
      }else {
        gotoxy(x,y);
        printf("       ");
        gotoxy(x,y-1);
        printf("       ");
        gotoxy(x,y-2);
        printf("       ");
        gotoxy(x,y-3);
        printf("       ");
        gotoxy(x-7,y);
        printf("*-----*");
        gotoxy(x-7,y-1);
        printf(" *---* ");
        gotoxy(x-7,y-2);
        printf("  *-*  ");
        gotoxy(x-7,y-3);
        printf("   *   ");
        ship(x-7,y);
        break;
      }

That should solve your problems there.

Someone else advised me to put a break inside the if as well. However, if I do that, my program exits to bash

Quote:
Originally Posted by dsmith

I think that you have a good start to this game, but if I were you, I would change a thing or two, that may make it easier in the long run.

First of all, you have defined x and y as globals, this is confusing for me, because you are passing x & y as well. So in your functions which x is being used, the global one or the local one?

Ok hold up
x&y are just the position of the ship (you already know that). However, they are global at first because they are sent to centership, which is just called once (at the start of the game). Therefore, it all goes chained up, and I still use x&y because it tells you where you are gonna have to fire, erase, etc.

Quote:
Originally Posted by dsmith
Also, I think I would try indexing x and y instead of calling the function iteratively like you have. For example, your 'a' case and 'd' case do the exact same thing, except that 'a' subtracts 7 and 'd' adds 7. If you use subroutines for erase_ship and draw_ship, I think it would be much more efficient.

for example:
CPP / C++ / C Code:
void erase_ship(int x, int y)
{
   gotoxy(x,y);
   printf("       ");
   gotoxy(x,y-1);
   printf("       ");
   gotoxy(x,y-2);
   printf("       ");
   gotoxy(x,y-3);
   printf("       ");
}

void draw_ship(int x, int y)
{
   gotoxy(x,y);
   printf("*-----*");
   gotoxy(x,y-1);
   printf(" *---* ");
   gotoxy(x,y-2);
   printf("  *-*  ");
   gotoxy(x,y-3);
   printf("   *   ");
}

Then your case statement can be rewritten as:
CPP / C++ / C Code:
if (x>5){
    erase_ship(x,y);
    x -= 7;
    draw_ship(x,y);
}
break;


Sorry for being such a n0ob but what do you mean by indexing? I think I get what you just did, but don't understand why it would be easier?

Quote:
Originally Posted by dsmith

Also, if you notice, instead of using if/else, I just used if because there is no code to run for instances where x is less than 5. Does this make more sense?

There should be a break here, or at least the ship shouldn't move. If I put the break, the program exits.

Quote:
Originally Posted by dsmith
One more note that you may want to consider. Look at the erase_ship routine that we have, it can be written easier:
CPP / C++ / C Code:
void erase_ship(int x, int y)
{
   for(int index = 0; index<4;index++){
       gotoxy(x,y-index);
       printf("       ");
   }
}


Yea I understand this. It would be the same, but just in a cyclic way



Quote:
Originally Posted by dsmith
I think with this logic, creating your enemies and moving them will be alot easier.

But it still remains without solution. I've been trying and my head is like this guy because of that

Thanks for your help, btw
  #6  
Old 07-Feb-2004, 09:01
DWk DWk is offline
Junior Member
 
Join Date: Feb 2004
Location: Guatemala
Posts: 38
DWk is on a distinguished road
Hmmmm nevermind about the break problem and the program exiting.

Another guy advised me to put

ship(x,y);
break;

inside the if, and it works

now to the real deal

edit - by the way: what is that "x-=7" inside the case? I've never seen that
  #7  
Old 07-Feb-2004, 09:41
dsmith's Avatar
dsmith dsmith is offline
Senior Member
 
Join Date: Jan 2004
Location: Utah, USA
Posts: 1,351
dsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of light
Quote:
Originally Posted by DWk
edit - by the way: what is that "x-=7" inside the case? I've never seen that

Sorry, that is what I meant by indexing. The statement above is equivalent to:
CPP / C++ / C Code:
x = x - 7;

You will see this a lot in c, for instance:
CPP / C++ / C Code:
x -=7;  //x = x - 7;
x += 7; //x = x + 7;
x *= 7;  //x = x * 7;
x /= 7;  //x = x / 7;
x++;   //x = x + 1;
x--;    //x = x -1;

As for your structure, I would write a main game_loop that looks something like this:
CPP / C++ / C Code:
int ship_x = ??;  //initialize to center
int ship_y = ??;  //initialize to center
int enemy_x[MAX];    //Array to track enemies x coordinate
int enemy_y[MAX];    //Array to track enemies y coordinate
int exit_loop = 0;              //when z is hit, this is set to 1 and the do/while will exit.
time_t set_time;        //Hold the current time
time_t check_time;    //Hold the check time.

draw_ship(x,y);    //Draw the ship initially on the screen
time(&set_time);

do{
  if(kbhit()){
     switch(getch()){
         case 'a':
             ....   //move to the left
             break;
          case 'd':
              ....  // move to the right.
              break;
           case 'z':
               exit_loop = 1;
               break;
       }
    }
    time(&check_time);
    if( (check_time - set_time) >= GAP_TIME){
        set_time = check_time;
       //move all the enemies
    }
}while(!exit_loop);

Anytime in C (at least in my syntax ) when you see a word in all capitals, it is a Compiler definition. So at the top of your file, you would need to add :
CPP / C++ / C Code:
#define GAP_TIME 15         //Time to wait to move enemies
#define MAX 20                 //Maximum number of enemies

The reason to do it like this, is that it will be easier to modify your program to wait longer between enemy movements & the maximum number of enemies.

Look at this and let me know if there is something that you don't understand.
  #8  
Old 07-Feb-2004, 10:56
DWk DWk is offline
Junior Member
 
Join Date: Feb 2004
Location: Guatemala
Posts: 38
DWk is on a distinguished road
Hey

Ok, I just edited it with the draw_ship and erase_ship. Yea looks pretty good, and it works perfectly

Now, what you said about the game_loop is what I don't understand

Remember, I'm a n0ob at this

By the way, I'm posting my program again, just so that you see what I have

Refer to attachment

By the way, the draw_radar, etc, took out 10 lines out of the program

Peace, and thanks again for your help
Attached Files
File Type: txt galaga.c.txt (2.2 KB, 11 views)
Last edited by dsmith : 08-Feb-2004 at 12:14. Reason: Moved in-line program code to attachment
  #9  
Old 07-Feb-2004, 11:07
DWk DWk is offline
Junior Member
 
Join Date: Feb 2004
Location: Guatemala
Posts: 38
DWk is on a distinguished road
By the way, I'm not intending to make it A galaga game. I just want enemies that go from the upper screen to the down screen. If you shoot em, fine. If you don't, fine as well. If they go to the bottom of they screen, they disappear. However, I don't want more than 3 or 4 enemies on-screen, and specially not with a special move or whatever. However, I DO need a Score and a boss

Hope you got what I meant :O

EDIT - by the way, how can I create random numbers? between 80x25?

EDIT2 - by the way...(i use a lot of "by the way", eh? ), I'm gonna put here what they told us we need to do (I'm translating so bare with me )

Quote:
You have to create a galaga or invaders type of game in which there's a ship that can fire (the number and type of bullet is up to you), the enemies die by 1 hit (unless you create a boss, or master ship), the ship has to have sever lives (3-5 possibly)

The enemies should also shoot and move in some way. There must be several enemies, and you have to get points accordingly to how many enemies you destroy.
  #10  
Old 07-Feb-2004, 15:05
dsmith's Avatar
dsmith dsmith is offline
Senior Member
 
Join Date: Jan 2004
Location: Utah, USA
Posts: 1,351
dsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of light
Hey, its looking good. I am being a bit elusive in my answers because I want to make sure that you will understand your program when you are done.

Anyway - one comment I have on your code so far. Look how similar the centership and draw_ship functions are. Just a suggestion, but if it were me, I would combine them.

Now for the game loop. Let me try to explain what I see should happen in there.
  • We want to make a loop structure that will continue, until the user presses the exit key. I am using the do/while function to do this.
  • We want to be able to get key presses from the user. This is the getch() function.
  • We also want the enemies to move based upon a time sequence right?

The first thing you should do is make your functions to draw and erase your enemies. In addition, you could make seperate functions to draw/erase your boss.

Next, do you understand the do/while loop okay?
CPP / C++ / C Code:
exit_loop = 0;
do{
     
}while(!exit_loop);  //Also could be while(exit_loop != 0);

Basically, the kbhit() call is part of the conio library. It should return a 0 when no charecter is waiting and a 1 when a charecter is waiting. So this is the basic part to find a charecter (but not wait for it) and process it:
CPP / C++ / C Code:
 if(kbhit()){   //or if(kbhit() == 1)
   key = getch();
   switch(key){
       //Your case statements go here for the various items
    }
  }
 }

Finally, the time part. In order to use the time library, you need to include <time.h>. Basically the call to the function time will return the current time in seconds. So we want to make a basic timer using this call. First I set the time before entering the loop with:
CPP / C++ / C Code:
time(&set_time);

Then I compare the time at each iteration through the loop. If it is greater than 5 seconds, I move my enemies and reset the timer.
CPP / C++ / C Code:
    time(&check_time);
    if( (check_time - set_time) >= 5){
        set_time = check_time;
       //move all the enemies
    }

Basically, this program is going to fly through this loop and most of the time do nothing. But it will always check to see if a key has been pressed and see if 5 seconds has elapsed and do what it needs to from there.

Let me know what parts you don't understand.

For random numbers, see this thread. Basically using rand()%80 or rand()%25 should work.
 
 

Recent GIDBlogProblems with the Navy (Chiefs) by crystalattice

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Game Cheating? pcxgamer Computer Software Forum - Games 18 24-Nov-2005 12:12
Trouble With .htaccess amneziac85 Apache Web Server Forum 2 27-Jan-2004 18:35
Trying to create the game of life warny_maelstrom C Programming Language 10 21-Jan-2004 22:14
Tips for game troubleshooting pcxgamer Computer Software Forum - Games 0 02-Jan-2004 06:27
X2 The Threat pcxgamer Computer Software Forum - Games 0 25-Dec-2003 10:16

Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The

All times are GMT -6. The time now is 17:59.


vBulletin, Copyright © 2000 - 2009, Jelsoft Enterprises Ltd.