gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

C/C++ > How to spawn enemies?

#78846 - LOst? - Mon Apr 10, 2006 4:13 am

I have programmed a C++ class that is used to handle enemies in my game. The class is being inherited from a standard object class, with a few overloadable virtals and some extended variables and methods.

Now, it would be really easy to spawn an enemy using the operator new.

So here comes my question. If I want to use static memory instead of dynamic memory. How do I do?

I want to create multiple instances of an enemy, or other objects. I don't really know the size of the class. But what about making a static memory area and by force casting a class to it? Is it possible?

What options do I have? Can I overload the operator new in some way? Can I cast classes to a memory area?
_________________
Exceptions are fun

#78848 - DekuTree64 - Mon Apr 10, 2006 5:00 am

You could use placement new
Code:
#include <new>
u8 enemyMem[MAX_ENEMIES * sizeof(Enemy)];
...
Enemy *dude = new(enemyMem + index * sizeof(Enemy)) Enemy;

That will basically just call Enemy's constructor on that address, which sounds like what you want. I don't think you can call delete on objects created that way though, so if it has a destructor you'll have to call it manually.
_________________
___________
The best optimization is to do nothing at all.
Therefore a fully optimized program doesn't exist.
-Deku

#78849 - LOst? - Mon Apr 10, 2006 5:08 am

DekuTree64 wrote:
You could use placement new
Code:
#include <new>
u8 enemyMem[MAX_ENEMIES * sizeof(Enemy)];
...
Enemy *dude = new(enemyMem + index * sizeof(Enemy)) Enemy;

That will basically just call Enemy's constructor on that address, which sounds like what you want. I don't think you can call delete on objects created that way though, so if it has a destructor you'll have to call it manually.


Oh interresting. Thank you! I didn't know about this. Does this work for inherited classes?

The main problem is that new takes too long time to dynamically allocate memory. Longer than a frame of 60fps.

So this "new" you are using, how does it create the class in memory?

I want like an array of enemies. And I want to assign an enemy class when it needs to be spawned. But without a delay. It should be like immediate action.


EDIT: DekuTree64, your example makes sence! Thank you so much!
_________________
Exceptions are fun

#78863 - poslundc - Mon Apr 10, 2006 7:50 am

LOst? wrote:
So here comes my question. If I want to use static memory instead of dynamic memory. How do I do?


The simplest answer is to not use class features like inheritance and polymorphism. Use another paradigm, such as unions and function tables wherever you need them to provide polymorphism.

There are more complicated answers, such as creating a static pool of enough objects of different types so that you can have the correct kind available (which results in wasted objects), or using placement new (as DT64 shows) and keeping your memory blocks the size of the largest descendant of your class (which results in wasted memory for smaller subclasses).

Quote:
I want to create multiple instances of an enemy, or other objects. I don't really know the size of the class. But what about making a static memory area and by force casting a class to it? Is it possible?


Possible, yes. But very, very dangerous if you don't know how your compiler is implementing its classes. This is part of the reason why C++ provides you with your different cast operators.

Quote:
What options do I have? Can I overload the operator new in some way? Can I cast classes to a memory area?


Yes, you can overload operator new; have a look at a C++ FAQ for precise notation (I don't have it on me).

Quote:
The main problem is that new takes too long time to dynamically allocate memory. Longer than a frame of 60fps.


Then you are doing something wrong.

Your heap allocator should NOT be such a drain on resources. If I were you, I would profile your code and make sure this is the case.

The far greater danger on a system like the GBA is from heap fragmentation due to the limited memory size. For this reason, I'm disinclined to use dynamic allocation pretty much at all, or only with the greatest of care. But speed should not be the issue.

Dan.

#78869 - LOst? - Mon Apr 10, 2006 9:05 am

This was my idea when I created this system:

Have a base class called Object, with a virtual function for the AI.

Then create objects and enemies using the Object class as a template. E. g.:
class Rock : public Object
class Boss : public Object
class Player : public Object


Then have a list of pointers to Object classes:

Object* objs [128];

objs [0] = (Object*) new Player ();
objs [1] = (Object*) new Rock ();


And so on...
_________________
Exceptions are fun

#78885 - sgeos - Mon Apr 10, 2006 11:56 am

Code:
enemy_t enemyTable[MAX_ENEMIES];

I'd write a class constructor that finds the first open slot in the array, reinitializes it and returns a reference to the newly created critter. The enemy table and max size probably want to be class variables.

-Brendan