Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Another question, but it should be simple

Credits go to Derezo and Hrvoje Ban for helping out!
This thread is locked; no one can reply to it. rss feed Print
Another question, but it should be simple
Simsimius
Member #6,017
July 2005

EDITED MOST RECENT POST (*THE* MOST RECENT ONE)

Sorry for posting for help again, but this one is something I honestly have not learnt before.

How would I create multiple instances of a class (e.g bullet), and how would I, written in the class, "delete" the class.
And how could this be implemented for walls and static obstacles that are part of a map?

I have checked other games to see if I can find out how, but it's not plainly there.

____
There's no place like 127.0.0.1

Derezo
Member #1,666
April 2001
avatar

There are a variety of ways. You can use linked lists, arrays, vectors, or any other method you choose. Google for "data structures", or read this. :)

Or look into the the STL's vector and list.

"He who controls the stuffing controls the Universe"

Simsimius
Member #6,017
July 2005

Thanks for the links.

It's a lot to read, and the information on queues seems to be what I'm looking for.
However, I'm not sure to make a class work with queues (making lots of it), or how the class can delete itself (so the delete part of queues would have to be in the, for example, bullet class). The tutorial actually puts the queue in a class be itself.
So how would I go around doing that? Or am I missing something that I overlooked?

I guess the answer isn't as simple as I was hoping for. If anyone can help me out, or at least make things a little clearer, then thanks. Otherwise, I might stick to the usual "one projectile per character" method I usually opt for.

____
There's no place like 127.0.0.1

Derezo
Member #1,666
April 2001
avatar

Well, the way that I would do it is to use a std::list and do this:

1 
2#include <list>
3 
4using namespace std;
5 
6class Bullet
7{
8public:
9 Bullet(float _x, float _y) { x = _x; y = _y; }
10 ~Bullet() { /* cleanup here */ }
11 
12 void Render() { circlefill(screen,x,y,2,makecol(255,0,0)); }
13 void Update() { y -= 2.3f; }
14private:
15 float x, y;
16};
17 
18list <Bullet *> bullets;
19 
20void AddBullet(Bullet *_bullet)
21{
22 bullets.push_back(_bullet);
23}
24 
25int main()
26{
27 // initialization stuff goes here
28 
29 while(!key[KEY_ESC])
30 {
31 if(key[KEY_SPACE]) AddBullet(new Bullet(player_x, player_y));
32
33 list <Bullet *>::iterator i;
34 for(i = bullets.begin(); i != bullets.end() && !bullets.empty();i++)
35 {
36 (*i)->Update();
37 (*i)->Render();
38 }
39 
40 rest(1);
41 }
42 
43 // to cleanup the bullets:
44 list <Bullet *>::iterator i;
45 for(i = bullets.begin(); i != bullets.end() && !bullets.empty();)
46 {
47 delete *i;
48 i = bullets.erase(i);
49 }
50}

There are 4,890,322 things that should be changed in this code, but I think you might be able to get the idea. :)
Bullets shouldn't delete themselves, they should just let the controller know when to delete them. For example, by returning 0 on their update function or setting a "dead" flag. The controller would check for that and delete the bullet.

"He who controls the stuffing controls the Universe"

Hrvoje Ban
Member #4,537
April 2004
avatar

With queue you can only add/remove at the end. For you purpose use std::list, it's good when you need to add/remove lost of objects in the middle. Here's small example in C++:

class Bullet
{
   public:
      Bullet()
      {
         bulletList.push_back(this);
      }

      ~Bullet()
      {
         bulletList.remove(this);
      }

   private:
      std::list<Bullet *> bulletList;
};

Simsimius
Member #6,017
July 2005

Thanks for the examples. They've cleared it up a lot.

There's a few questions left though:

  void Render() { circlefill(screen,x,y,2,makecol(255,0,0)); }
  void Update() { y -= 2.3f; }

I'm not entirely sure what the Update function does.
The update function changes the bullet location, etc., right?

  // to cleanup the bullets:
  list <Bullet *>::iterator i;
  for(i = bullets.begin(); i != bullets.end() && !bullets.empty();)
  {
    delete *i;
    i = bullets.erase(i);
  }

The other question is about:
bullets.erase();
bullets.begin();
bullets.end()
bullets.empty();

Should I worry about them? (As in, what should I do with them, or are they part of the list/queue/thing?)

And one part that isn't cleared up: If, for example, the bullet collides with an object (let's say that code is in "bullet.detect"), how should that code request for that instance of bullet to be deleted?
I think I got it. The update function, as you said.

Sorry for asking, but my knowledge isn't too great. I've gotten the grasp of it, I hope.

____
There's no place like 127.0.0.1

Derezo
Member #1,666
April 2001
avatar

Quote:

The update function changes the bullet location, etc., right?

That's right. :)
See the link in my first post for a complete rundown of std::list.

list::erase() removes a node from the list.
list::begin() is the first node in the list.
list::end() is the last node in the list.
list::empty() returns true if the list is empty (contains 0 bullets), otherwise returns false.

"He who controls the stuffing controls the Universe"

Simsimius
Member #6,017
July 2005

EDIT AT BOTTOM!

Right. Got it.

I'll try to implement it into my game, or at least a test program.

Thanks for the help!

EDIT:
I managed to get the code to work in a sample program, so the code looks like this:

1#include <list>
2#include <allegro.h>
3 
4using namespace std;
5 
6 BITMAP* buf = create_bitmap(800, 600);
7 
8class Bullet
9{
10public:
11 Bullet(float _x, float _y) { x = _x; y = _y; }
12 ~Bullet() { }
13 
14 void Render( ) { circlefill(buf,x,y,2,makecol(255,0,0)); }
15 int Update() { if(y<30) {return 0;} else { y -= 2.3f;} }
16private:
17 float x, y;
18};
19 
20list <Bullet *> bullets;
21 
22void AddBullet(Bullet *_bullet)
23{
24 bullets.push_back(_bullet);
25}
26 
27int main()
28{
29 // initialization stuff goes here
30 allegro_init();
31 install_keyboard();
32 set_gfx_mode( GFX_AUTODETECT, 800, 600, 0, 0);
33;
34 while(!key[KEY_ESC])
35 {
36 
37 clear(buf);
38 if(key[KEY_SPACE]) AddBullet(new Bullet(400, 300));
39
40 list <Bullet *>::iterator i;
41 for(i = bullets.begin(); i != bullets.end() && !bullets.empty();i++)
42 {
43 (*i)->Update();
44 (*i)->Render();
45 }
46 
47 blit(buf, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
48 rest(1);
49 
50
51 }
52 
53 // to cleanup the bullets:
54 list <Bullet *>::iterator i;
55 for(i = bullets.begin(); i != bullets.end() && !bullets.empty();)
56 {
57 delete *i;
58 i = bullets.erase(i);
59 }
60
61 destroy_bitmap(buf);
62 return 0;
63}
64END_OF_MAIN();

.

It works , but if I push space I get a LONG line of cicles travelling up to the top of the screen, and none seem to get deleted. but I can't get the buffer to work, otherwise, without it, I can't see whether or not the circles do get deleted!

____
There's no place like 127.0.0.1

Derezo
Member #1,666
April 2001
avatar

You'll need to modify that update loop :)
It should look like this:

    list <Bullet *>::iterator i;
    for(i = bullets.begin(); i != bullets.end() && !bullets.empty();)
    {
      if((*i)->Update()) 
      {
        (*i)->Render();
        i++;
      }
      else { delete *i; i = bullets.erase(i); }
    }

You'll also need to create the buffer AFTER setting the graphics mode. Don't use create_bitmap() as the initialization for a global variable.

"He who controls the stuffing controls the Universe"

Ariesnl
Member #2,902
November 2002
avatar

By the way : switch to OpenLayer it's a lot faster and you won't need that offscreen bitmap (foublebuffering comes free)

Perhaps one day we will find that the human factor is more complicated than space and time
(Jean luc Picard)

Simsimius
Member #6,017
July 2005

Areisnl:
I've heard of openlayer, but no idea what it is exactly.

Derezo:
Thanks ever so much! I got a test program running! It all works fine!
Once, again, thanks! All I have to do is implement in my main game (but some of the code needs changing).
Thanks again!

EDIT: Actually, I still need to seperate each bullet. I'm sure I can try and work that out...I hope.

EDIT2:
Is there was for me to display the number of bullet instances on the screen (for developer purposes)?
I hoping to find a way to either limit the number of bullets on the screen, or to limit the number of bullets fired per 3 seconds (still trying to work it out, with no prevail)

____
There's no place like 127.0.0.1

Michael Faerber
Member #4,800
July 2004
avatar

unsigned bullets_on_screen = bullets.size();

--
"The basic of informatics is Microsoft Office." - An informatics teacher in our school
"Do you know Linux?" "Linux? Isn't that something for visually impaired people?"

Ariesnl
Member #2,902
November 2002
avatar

OpenLayer is a "layer" above allegro and OpenGL. It has all kinds of primitives ( line,circle etc) and blitting functions and so on.. just like allegro BUT openLayer routines are hardware accellerated !!!

Besides OpenLayer hase some nice things like translucency, timers, lagtime(the time it toook to complete a game cycle), double buffering etc.

Here's an overview http://retrospec.sgn.net/~openlayer/

It comes with easy to understand examples.

If you use OpenLayer you can still use allegro for everything else ( sound, datastorage etc)

Perhaps one day we will find that the human factor is more complicated than space and time
(Jean luc Picard)

Audric
Member #907
January 2001

Quote:

to limit the number of bullets fired per 3 seconds (still trying to work it out, with no prevail)

The player class (or anything that shoots, anyway) could have a shoot_delay" member. This allows to set different delays for different weapons, if needed.

void Player::update()
{
   if (shoot_delay > 0)
      shoot_delay --;

   // controls
   if (key[KEY_SPACE] && shoot_delay == 0)
   {
      AddBullet(new Bullet(player_x, player_y));
      shoot_delay = 20; // no more shooting for some time
   }
}

(edit: fixed a ( [ mismatch. I use a lousy screen at work)

Simsimius
Member #6,017
July 2005

Thank you!

I was too busy trying to work it out with the existing code!
That's cleared that up. Hopefully I should have no more problems/questions.

Thanks everyone!

____
There's no place like 127.0.0.1

Go to: