View Full Version: All questions solved.

C++ Learning Community > Misc. C++ library help > All questions solved.


Title: All questions solved.
Description: Lol


ChipChamp - December 17, 2006 05:29 AM (GMT)
ALL ARE SOLVED. :D

Okay, well for a little game I was making just to see what I can do with allegro, I made a little sprite for it, with a width of 25 pixels and a height of 37 pixels. The problem is that when the user presses the left, up, down, or right buttons, he moves extremely fast. I suppose he is moving his whole width to the left.(?) Anyway, how can I make him move slower?

SOLVED

New question(s), see last post.

SOLVED

New question... Lol. In that same game, I just made it so that when the enemy shoots you it, you die. Now, the problem is that I have 5 enemies of the class ENEMIES. Now, it draws all five enemies unless they are dead... except for the fifth one. The fifth enemy on the far right of the row of enemies flickers when you are holding down the space button to shoot. That doesn't happen with any of the other ones, so I see no reason for it to do it for the fifth one. Also, the fifth enemy does not dir when you shoot it. The others do, and I also see no reason for it to do this with the fifth one... apparently there is something wrong in my code, I just can't find the problem. :( Can anyone please help? Here is the code:

SOLVED

CODE
#include <allegro.h>
#include <cstdlib>

BITMAP *buffer;
BITMAP *ship;
BITMAP *enemyship;
BITMAP *laser;

class ENEMIES {
     public:
            int x, y, dead;
};
class BULLETS {
     public:
            int x, y, dead;
} bullet[1000];
class ENEMY_BULLETS {
     public:
            int x, y, dead;
} e_bullet[1000];
int main () {
   
   srand(time(0));
   
   int game_pos = 0;
   int game_check = 0;
   int start_timer = 500;
   int x = 388, y = 500;
   int bullets = 0;
   int bullet_timer = 0;
   
   ENEMIES enemy[5];
   int enemies = 5;
   int dead_enemies = 0;
   int shoot = 0;
   int ship_rand = 0;
   int e_bullets=0;
   
   for (int n=1; n<=enemies; n++){
       enemy[n].x = 120*n;
       enemy[n].y = 100;
   }
       
   allegro_init();
   install_keyboard();
   install_mouse();
   set_color_depth(16);
   set_gfx_mode( GFX_AUTODETECT, 800, 600, 0, 0);
   
   buffer = create_bitmap( 800, 600 );
   ship = load_bitmap( "fighter.bmp", NULL);
   enemyship = load_bitmap( "badfighter.bmp", NULL);
   laser = load_bitmap( "laser.bmp", NULL);
   
   while (!key[KEY_ESC]) {
         
         acquire_screen();
         clear_to_color(buffer, makecol(0,0,0));
         if (game_pos == 0) textout_centre_ex(buffer, font, "Welcome!", 400, 300, makecol(255,255,255), makecol(0,0,0));
         else if (game_pos == 1) textout_centre_ex(buffer, font, "Ready!", 400, 300, makecol(255,255,255), makecol(0,0,0));
         else if (game_pos == 2) textout_centre_ex(buffer, font, "Set!", 400, 300, makecol(255,255,255), makecol(0,0,0));
         else if (game_pos == 3) textout_centre_ex(buffer, font, "Go!", 400, 300, makecol(255,255,255), makecol(0,0,0));
         else if (game_pos == 4) textout_centre_ex(buffer, font, "---Welcome!---", 400, 300, makecol(0,0,0),makecol(0,0,0));
         else if (game_pos == 5) textout_centre_ex(buffer, font, "YOU WIN", 400, 300, makecol(255,255,255), makecol(0,0,0));
         else if (game_pos == 6) textout_centre_ex(buffer, font, "YOU LOSE", 400, 300, makecol(255,255,255), makecol(0,0,0));
         if (game_pos == 4){
            for (int b=1; b<bullets+1; b++){
                if (bullet[b].dead != 1){
                   draw_sprite(buffer, laser, bullet[b].x, bullet[b].y);
                }
            }
         }
         for (int eb=0; eb<e_bullets; eb++){
             if (e_bullet[eb].dead != 1){
                draw_sprite(buffer, laser, e_bullet[e_bullets].x, e_bullet[e_bullets].y);
             }
         }
         for (int i=1; i <=enemies; i++){
             if (enemy[i].dead != 1){
                  draw_sprite(buffer, enemyship, enemy[i].x, enemy[i].y );
             }
         }
         draw_sprite(buffer, ship, x, y);
         draw_sprite(screen, buffer, 0, 0);
         release_screen();
         
         start_timer -= 1;
         if (start_timer < 0) game_pos = 1;
         if (start_timer < -250) game_pos = 2;
         if (start_timer < -500) game_pos = 3;
         if (start_timer < -750) game_pos = 4;
         if (start_timer < -1750 && game_check == 1) game_pos = 6;
         
         bullet_timer -= 1;
         if (bullet_timer < 0) bullet_timer = 0;
         
         if (key[KEY_RIGHT]) ++x;
         else if (key[KEY_LEFT]) --x;
         
         if (game_pos == 4){
            if (key[KEY_SPACE]) {
               if (bullet_timer == 0){
                      bullets += 1;
                      bullet[bullets].x = x+13;
                      bullet[bullets].y = y;
                      bullet_timer = 50;
               }
            }
         }
         for (int t=0; t*999999999 < bullets; t++){
             bullet[bullets].y -= 11;
         }
         
         // Code for making the bullet hit the enemies.
         for (int z=0; z<12; z++){
             for (int a=0; a<=32; a++){
                 for (int v=1; v<=enemies; v++){
                     for (int u=0; u<=bullets; u++){
                         if (enemy[v].dead != 1){
                            if (bullet[u].dead != 1){
                               if (enemy[v].y+z == bullet[u].y && enemy[v].x+a == bullet[u].x) {
                                  dead_enemies+=1;
                                  enemy[v].dead=1;
                                  bullet[u].dead=1;
                               }
                            }
                         }
                     }
                 }
             }
         }
         
         for (int g=0; g<12; g++){
             for (int h=0; h<=32; h++){
                 for (int j=0; j<=e_bullets+1; j++){
                     if (e_bullet[j].dead != 1){
                        if (y+g == e_bullet[j].y && x+h == e_bullet[j].x) {
                           game_pos = 6;
                           game_check = 1;
                           start_timer = -2000;
                           e_bullet[j].dead=1;
                           
                        }
                     }
                 }
             }
         }
         
         rest(2);
         
         if (dead_enemies == 5){
                          game_pos = 5;
         }
         if (game_pos == 4){
            shoot = rand()%50;
            ship_rand = rand()%6;
            if (enemy[ship_rand].dead != 1){
               if (shoot == 0) {
                   e_bullets+=1;
                   e_bullet[e_bullets].x = enemy[ship_rand].x+13;
                   e_bullet[e_bullets].y = enemy[ship_rand].y;
               }
            }
         }
         if (e_bullets>0){
            for (int m=0; m<=e_bullets; m++){
                if (e_bullet[m].dead != 1){
                   e_bullet[m].y += 11;
                }
            }
         }
   }
   return 0;
}
END_OF_MAIN();

Also, you might need the pictures:
The fighter.bmp:
user posted image
The laser.bmp:
user posted image
And the badfighter.bmp:
user posted image

Any help is highly appreciated!

myork - December 17, 2006 02:13 PM (GMT)
That will not work.
Think about it.

CODE
int x = 100;
So x is an integer.
CODE
x += .1;
This is equivalent too:
CODE
x = x + .1;
To perform the addition x is converted into a real then point one is added. This gives a value of 100.1 then the assignment converts this back to an integer so 100 is assigned to x.


The moving fast problem.

Have you counted how many times the sprite moves. Maybee the while loop is being traversed very quickly and that every time you hit a key the thread traverse the loop 100 times before you can let go.

One solution to this is too accept the key then ignore the key until the key has been released by the user.

CODE

int keyPushed;
bool keyDown = false;
   while (!key[KEY_ESC]) {
       
        /* Draw stuff */
       
             if (key[KEY_UP])    {DoKeyDown(KEY_UP,     0,-1);}
        else if (key[KEY_DOWN])  {DoKeyDown(KEY_DOWN,   0,+1);}
        else if (key[KEY_LEFT])  {DoKeyDown(KEY_LEFT,  -1, 0);}
        else if (key[KEY_RIGHT]) {DoKeyDown(KEY_RIGHT, +1, 0);}
        else {keyPushed = false;}
        }
  }


The a DoKeyDown function.
CODE

void DoKeyDown(int key,int xMove,int yMove)
{
   if ((!keyPushed) || (keyDown != key))
   {
       keyPushed = true;
       keyDown = key;
       y+=yMove;
       x+=xMove;
   }
}




I notice that you are accessing the key state directly. Have you though about using an event loop? Key events are desinged to produce one event on key down then a key autorepeat after a set interval.

ChipChamp - December 17, 2006 05:28 PM (GMT)
Hmm... Well, that might work, but right after I read your post I thought of putting a 'rest(10);' thing and that slowed it down. Thanks anyway! :)

ChipChamp - December 17, 2006 10:43 PM (GMT)
.... But now I have another question, and since it has something to do with speed, I will ask it here too. Lol. I am making a game that has bullets, and when I shoot them each bullet gets progressively faster. For example, if the first bullet was moving at a 'speed' of 10, then the second one would be moving at a speed of 20, and the third one would be moving at a speed of 30. Here is the code I am using:
CODE
#include <allegro.h>
#include <cstdlib>

BITMAP *buffer;
BITMAP *ship;
BITMAP *enemyship;
BITMAP *laser;

class ENEMIES {
     public:
            int x, y;
};
class BULLETS {
     public:
            int x, y;
} bullet[100];
int main () {
   
   int game_pos = 0;
   int start_timer = 500;
   int x = 388, y = 500;
   int bullets = 0;
   int bullet_timer = 0;
   
   ENEMIES enemy[5];
   
   for (int n=1; n<=5; n++){
       enemy[n].x = 120*n;
       enemy[n].y = 100;
   }
       
   allegro_init();
   install_keyboard();
   install_mouse();
   set_color_depth(16);
   set_gfx_mode( GFX_AUTODETECT, 800, 600, 0, 0);
   
   buffer = create_bitmap( 800, 600 );
   ship = load_bitmap( "fighter.bmp", NULL);
   enemyship = load_bitmap( "badfighter.bmp", NULL);
   laser = load_bitmap( "laser.bmp", NULL);
   
   while (!key[KEY_ESC]) {
         
         acquire_screen();
         clear_to_color(buffer, makecol(0,0,0));
         if (game_pos == 0) textout_centre_ex(buffer, font, "Welcome!", 400, 300, makecol(255,255,255), makecol(0,0,0));
         else if (game_pos == 1) textout_centre_ex(buffer, font, "Ready!", 400, 300, makecol(255,255,255), makecol(0,0,0));
         else if (game_pos == 2) textout_centre_ex(buffer, font, "Set!", 400, 300, makecol(255,255,255), makecol(0,0,0));
         else if (game_pos == 3) textout_centre_ex(buffer, font, "Go!", 400, 300, makecol(255,255,255), makecol(0,0,0));
         else textout_centre_ex(buffer, font, "---Welcome!---", 400, 300, makecol(0,0,0),makecol(0,0,0));
         for (int b=1; b<bullets+1; b++){
             draw_sprite(buffer, laser, bullet[b].x, bullet[b].y);
         }
         for (int i=1; i <= 5; i++){
             draw_sprite(buffer, enemyship, enemy[i].x, enemy[i].y );
         }
         draw_sprite(buffer, ship, x, y);
         draw_sprite(screen, buffer, 0, 0);
         release_screen();
         
         start_timer -= 1;
         if (start_timer < 0) game_pos = 1;
         if (start_timer < -250) game_pos = 2;
         if (start_timer < -500) game_pos = 3;
         if (start_timer < -750) game_pos = 4;
         bullet_timer -= 1;
         if (bullet_timer < 0) bullet_timer = 0;
         
         if (key[KEY_RIGHT]) ++x;
         else if (key[KEY_LEFT]) --x;
         
         if (key[KEY_SPACE]) {
            if (bullet_timer == 0){
                      bullets += 1;
                      bullet[bullets].x = x;
                      bullet[bullets].y = y;
                      bullet_timer = 50;
            }
         }
         
         for (int t=2; t < bullets+1; t++){
             bullet[bullets].y -= 1;
         }
         
         rest(2);
   }
   return 0;
}
END_OF_MAIN();


PS If anyone can also tell me why the last bullets stop moving once a new bullet is created, that would be great. :) Sorry for piling on a bunch of questions here... :huh:

myork - December 18, 2006 12:44 PM (GMT)
You do know that arrays are indexed starting at 0?
CODE
        for (int b=1; b<bullets+1; b++){
            draw_sprite(buffer, laser, bullet[b].x, bullet[b].y);
        }
        for (int i=1; i <= 5; i++){
            draw_sprite(buffer, enemyship, enemy[i].x, enemy[i].y );
        }
These two loops start at 1 rather than 0. And I hope your bullet attar has a least bullets + 1 members in it.


This array seems to be index from 2 for some reason.
CODE
         for (int t=2; t < bullets+1; t++){
            bullet[bullets].y -= 1;


You know comments are always a good idea.

Also your code is starting to get to the point where you need to sub-divide the code into managable functions.

Does not alegro support the concept of an Event Loop? (AKA Reactor). If it does you need to learn how to use it. No serious interactive GUI application is going to written successfully without the the use of an Event loop (or at least not easily :huh: )


Writing code like this:
CODE
   acquire_screen();

   <STUFF>

   release_screen();
is very C like. In C++ we manage resources that are acquired and released resources via the constructor/destructor mechanism. You should create a class that does the above in the constructor/desctructor. Then just initialise an object of this class inside the loop.

Example:
CODE

class MyResourceAllocator
{
   MyResourceAllocator()  {acquire_screen();}
  ~MyResourceAllocator()  {release_screen();}
}; // See if you can templatise that!

int main()
{
   <STUFF>
   while (!key[KEY_ESC])
   {
       {
           // This should be in a function.
           MyResourceAllocator   screen;

           <DRAW STUFF>
       } // Goes out of scope here. So screen destructor called.


        < OTHER STUFF>
   }
}



Also. Why acuire the screen before you have too.
You should do all your drawing to a buffer. Aquire the screen. Draw to the screen. Release the screen. So Add a method to the above class that draws the buffer (one passed as a parameter).

ChipChamp - December 19, 2006 02:05 AM (GMT)
Yes, I know that arrays start at 0... I don't see where you saw a for statement with an array starting at 2... Hmm... Anyway, I didn't really get the part you said about constructors and deconstructors, but I changed it so that everything was drawn before the acquire_screen();, except drawing the buffer. Thanks for the suggestions! The only problem is... it still doesn't work... :huh:

myork - December 19, 2006 09:53 AM (GMT)
I think your problem is here:
QUOTE
        for (int t=2; t < bullets+1; t++){
            bullet[bullets].y -= 1;
        }


Notice the index into the array bullet.
It is not the loop variable. So you are just moving the last bullet.
But you are moving the last bullet 'n' times so the last bullet is faster than the previous bullet.

This is what I thikn you meant:
CODE
        for (int t=1; t < bullets+1; t++){
            bullet[t].y -= t;
        }

ChipChamp - December 19, 2006 03:21 PM (GMT)
Lol! I understand the problem now. That wasn't it... but the problem is that my newest problem is in the first post of the topic. :D Lol! Try and look through that and see if you can see the new problem with the flickering of the enemy ship on the right. :) Lol

myork - December 19, 2006 04:06 PM (GMT)
QUOTE (ChipChamp @ Dec 19 2006, 10:21 AM)
Lol! I understand the problem now. That wasn't it.


Yeah. You don't think.

OK. Next obvious rookie mistake.
CODE
        for (int i=1; i <=enemies; i++){
            if (enemy[i].dead != 1){


Here you index the array from 1->5 (or enemies).
When the size of the array is 5. This is baddddd


Once again. Arrays are indexed from 0. You should only access elements 0-> (size - 1). So in this case 0->4


myork - December 19, 2006 04:10 PM (GMT)
CODE
        for (int t=0; t*999999999 < bullets; t++){
            bullet[bullets].y -= 11;
        }
OK thats a usfull piece of code. The loop will get executed once.


CODE

        // Code for making the bullet hit the enemies.
        for (int z=0; z<12; z++){
            for (int a=0; a<=32; a++){
                for (int v=1; v<=enemies; v++){   // index into enemies wrong
                    for (int u=0; u<=bullets; u++){
Again the same mistake.

You are accessing beyond the end of the array.

ChipChamp - December 19, 2006 05:19 PM (GMT)
Hmmmm... Okay! Something there fixed it, I'm not sure what though. Lol. Thanks! I think what I did was changed it so that it created 6 enemies and set the enemies variable to 6, and it worked... hmm...

Heh, I solved this like a minute after I asked it... You had to take out the = signs in 'f<=enemies;' and 'u<=enemies;', but I still have no idea why that worked. Lol. :D

But I just added this code into the while statement:
CODE
for (int f=0; f<=enemies; f++){
            if (enemy[f].change >= 100) enemy[f].change = 0;
            if (enemy[f].change == 50) enemy[f].dir = 1;
            else if (enemy[f].change == 0) enemy[f].dir = 0;
        }
        for (int u=0; u<=enemies; u++){
            enemy[u].change += 1;

And all the variables are fine. This code is supposed to make the enemy ships move left and right. Now, it moves left and right just fine, but now the player can't shoot. I have no idea why that little code would make you not able to shoot... I put /* */ around it and you were able to shoot. What would be the cause of this? It's probably very simple... Lol.

myork - December 20, 2006 01:32 PM (GMT)

QUOTE
Thanks! I think what I did was changed it so that it created 6 enemies and set the enemies variable to 6


So again you are illegally accessing beyond the end of the array.
If you have 6 items in an array then you can only access elements 0->5:
CODE
<TYPE> enemies[6];
enemies[0]; // Not used in your code
enemies[1]; //OK
enemies[2]; //OK
enemies[3]; //OK
enemies[4]; //OK
enemies[5]; //OK
enemies[6]; // Invalid. Illegal memory location.

If you write to enemies[6] you will be overwritting the memory allocated to another variable if you are lucky. If you are unlucky you will write to illegal memory location or the stack pointer or some other bad location.

So code like this:
CODE

int s =6;
STYPE  plop[6];

for(int loop=1;loop <=6;++loop)
{
   plop[loop].zzz = 5; // When loop is 1 -> 5 when loop is 6 things will go wrong.
}


Loops are usually of the form:
CODE
for(int loop=0;loop < <SIZE>;++loop)
{
  <STUFF>
}
Not the loop starts at 0. And you use "less than" (<) in the condition.

ChipChamp - December 20, 2006 08:51 PM (GMT)
Well, that's actually what I'm doing. :) Lol

myork - December 21, 2006 10:07 AM (GMT)
QUOTE (ChipChamp @ Dec 20 2006, 03:51 PM)
Well, that's actually what I'm doing. :) Lol


So you have changed your code then?




Hosted for free by InvisionFree