Sign in to follow this  
BoReDoM_Inc

Game Engine Instances

Recommended Posts

Heres the problem: I have a bunch of classes that are enemies etc. There is a 255 array of each class. Then I have an int array called ObjType[1024] which hold a number of a certain Obj type (class). I also have an int array called ObjID[1024] which holds the address of a certain object... Like Obj 25 (ObjType[25] = 2) it's a ship... It's instance (the actual object) is Ship[5]... ObjID is supposed to have the address of the correct ship. I'm doing something horribly wrong I just have no idea. How do I make a game engine with classes and instances. It's the worst explanation ever but hopefully you get what I mean.

Share this post


Link to post
Share on other sites
You won't want to use separate structures for each class of objects, instead use Polymorphism.

Store pointers to a base class which has virtual methods, overridden for each class.

That way you can add new classes without having to alter your management code.

Mark

Share this post


Link to post
Share on other sites
Would probably be better to use a Data Structure for your enemies rather than an array. That way you don't have to have a limit on how many enemies can be added at a certain time.

Share this post


Link to post
Share on other sites
Here's a basic way of how I did it with my game engine (that no one has seen yet... Mwaha... ha):
//Base class for any graphics, such as instances, tiles, backgrounds, etc.
class CGraphic {
public: //I don't really like the "private" scope, yet I don't know why...
bool visible;
long depth; //If you know how to draw with depth :)
virtual bool Draw();
//Any other members/methods related to drawing
};
//This is the base class of an instance, derrived from a graphic
class CInstance : public CGraphic {
public:
//Basic data for an object in your game...
long id; //My index in the current room's object list
??? object_id; //My type? (for checking collision with certain objects and such... I use my own structure for this)
float x, y, hspeed, vspeed; //Position, Movement (yes, it's based off of Game Maker)
CSprite *sprite_pointer; //Pointer to my sprite for drawing?
long image_index; //Currrent frame of my sprite?
CMask *mask_pointer; //Pointer to my mask for collision?
//And more...
//Methods:
//Constructors?
virtual bool Create(), Step(), Destroy();
//Create - When created, Step - Each step (frame), Destroy - I think you get it
bool Draw(); //Already virtual in CGraphic
};
//NOTE: For instances, make a create function and a destroy function. With the create function, it is inserted in the list, its Step method is executed, and the user specifies position also. For the destroy function, the instance is removed from the list, and then slaughtered horrifical--er, its Destroy method is executed.
//An example class:
class CBob : public CInstance {
bool Create(), Step(), Draw()
};
bool CBob::Create() { sprite_pointer=&sprBob; }
bool CBob::Step() { //Move Bob according to his movement variables
x+=hspeed;
y+=vspeed;
}
bool CBob::Draw() {
//Draw Bob's sprite with his sprite pointer, frame, and position
}
//Room class...
class CRoom {
//Other information for the room, such as views
//Dynamic list for the instances in the room
vector<CInstance*> object;
vector<bool> object_exists;
//Vectors for tiles, backgrounds, etc?
bool Step(); //Execute the Step method for each instance
bool Draw(); //Draw all of the graphics in this room (instances, tiles, backgrounds)
};
//A basic function for CRoom::Step() [pseudocode!]
bool CRoom::Step() {
For each instance in "object"
If the object exists
object[current]->Step(); //Polymorphism will execute the object's unique Step function only
Next iteration
}
bool CRoom::Draw() {
Compile graphics into a list ("vector<CGraphic*> my_graphic;"
Sort graphics by depth (if you know how to :) [again])
For Each Graphic
If the current graphic is visible
my_graphic[current]->Draw();
Next iteration
}




NOTE: Most of these names are exactly the same as in my engine, so for those that aren't super-generic, I'd appreciate it if they weren't copied exactly

Share this post


Link to post
Share on other sites
Wow thanks for the help!
Don't worry I know how you feel about the names. Whenever I release code I've made I generally waste time changing little bits (names etc.). So I won't even copy and paste I'll just work out what you did and re-write it my way :D

Thanks again

Share this post


Link to post
Share on other sites
Now that I've read that I feel kind of stupid. If I actually had have thought about it properly I could have worked it out. Just one little problem left. Obviously like what has been said I'd need a create function which inserts the object into a list. What exaclty is the list, is it an array? Or like a database of some sort?
Probably vectors or lists, what would be the best method?

Share this post


Link to post
Share on other sites
#include <list>

std::list<CObject *> objects;

objects.push_back(some object)

for (std::list<CObject *>::iterator i = objects.begin(); i != objects.end(); ++i)
{
(*i)->SomeObjectFunction();
}


One caveat of this approach is that - when you're done with the list - you'll have to iterate through all of them and manually delete each one.

Alternately, you could create your own list class, although the reasons for doing so are generally academic.

Share this post


Link to post
Share on other sites
Ah, sorry 'bout that.
The list of instances is the variable "vector<CInstance*> CRoom::object". As for the create method which inserts, I will post the series of functions I have in my engine. Some of it has been changed, but most of it is original. *General litany of precautions included*
CRoom *room; //This is the pointer which points to the current room, and this is declared somewhere out there in my code.
//This is the base function for inserting a instance in a room's list.
//NOTE: This function recycles, therefore is a little slower than simply appending a new item
long instance_register(CInstance *srcInst) {
long index=-1;
for (long i=0;i<room->object.size();i++) {
if (room->object_exists[i]==false) {
index=i;
break; }
if (room->object[i]==srcInst) return false; //Already registered
}
if (index==-1) { //An empty space was not found
//Add a new pointer and exists boolean
room->object.push_back(0);
room->object_exists.push_back(false);
index=room->object.size()-1; //The last index
}
if (room->object[index]!=0) delete room->object[index]; //Remove previous instance memory if not already
room->object[index]=srcInst;
room->object_exists[index]=true;
room->object[index]->id=index;
return index;
}
//Base function which removes an instance's link to a list, but doesn't delete it
bool instance_unregister(long id) {
//Add your own error handling here! I would add something that checks if the id is bounded inside the list and that the object is actually registered
//Remember to set the 'object' equal to 0!
room->object[id]=0;
room->object_exists[id]=false;
return true;
}
//The more 'refined' functions:
//This creates registers the instance first, then sets it position and executes its Create method.
long instance_create(instance *myInstance,float x,float y) {
long index=instance_register(myInstance);
if (index==-1) return -1; //Prevent this from making any changes!
myInstance->x=x;
myInstance->y=y;
myInstance->Create();
return index;
}
//This actually deletes the instance before it is unregistered (you might want to switch the order)
bool instance_destroy(long id) {
if (room->object_exists[id]==false || room->object[id]==0) return false;
room->object[id]->Destroy(); //Execute Destroy method
delete room->object[id];
instance_unregister(id);
return false;
}




And to use this somehow:
long SomeBob=instance_create(new CBob,20,20);
...
instance_destroy(SomeBob);

Pretty simple.

EDIT: Sorry, but I might not be able to reply for a while after this...

Share this post


Link to post
Share on other sites
Yay I've finally got it and it's all working. Don't worry everything is my own functions. But I a still using an array of each type of object (inherited ship) and then using the vector to store information about that object. Is this right or is there some better way that will leave me open to have as many instances of an object that I want?

EDIT: Sorry it's alright I was looking at the code and missed the little bit outside the code block. Thanks for all the help everyone I'm set now. Time to implement A* Pathfinding :D

[Edited by - BoReDoM_Inc on June 7, 2005 8:50:59 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by BoReDoM_Inc
But I a still using an array of each type of object (inherited ship) and then using the vector to store information about that object. Is this right or is there some better way that will leave me open to have as many instances of an object that I want?

class IObject
{
public:
virtual void DoSomething() = 0;
};

class CShip : public IObject
{
public:
void DoSomething() { printf("CShip::DoSomething()\n"); }
};

class CMissile : public IObject
{
public:
void DoSomething() { printf("CMissile::DoSomething()\n"); }
};

class CAsteroid : public IObject
{
public:
void DoSomething() { printf("CAsteroid::DoSomething()\n"); }
};

void main()
{
list<IObject *> gameObjects; //Contains ships, missiles and asteroids
IObject * o = new CShip;
gameObjects.push_back(o);
o = new CAsteroid;
gameObjects.push_back(o);
o = new CMissile;
gameObjects.push_back(o);

for (list<IObject *>::iterator i = gameObjects.begin(); i != gameObjects.end(); ++i)
(*i)->DoSomething();
}


Output:

CShip::DoSomething()
CAsteroid::DoSomething()
CMissile::DoSomething()

If you have a FrameUpdate() function for each type of object, they'll all update correctly without you having to care what type they are. All you know is you have an IObject pointer, and calling FrameUpdate() will do exactly what it's supposed to do. You don't have to worry about the actual type of the object except when constructing it.

Share this post


Link to post
Share on other sites
std::vectors (derrived from std::lists?) allow dynamic memory allocation, therefore you have no limit (well, except for memory) on how many elements you have. [Was that what you were asking about?]

Share this post


Link to post
Share on other sites
Sorry to bring this up again but I'm really confused about something.
I create my ships like this:
for (int i = 0; i < 50; i++)
{
Object[i] = Instance_Create(new Ship, 1.0f, 1.0f);
}

I'm not actually sure if an Object array is neccessary they are also created fine if i remove the "Object[i] =".

I also have some projectiles created each time a key is pressed:
for (int i = 0; i < 1024; i++)
{
if (Object[i] == 0)
{
Object[i] = Instance_Create(new Bullet, PlayerX, PlayerY);
break;
}
}

Then each time the projectile steps it checks for collision with any other object:
for(int i=0; i < CurrentMap->object.size(); i++)
{
if((X > CurrentMap->object[i]->X - CurrentMap->object[i]->Width - X) // Projectile > Obj L. - Projectile Radius
&& (X < CurrentMap->object[i]->X + CurrentMap->object[i]->Width + X) // Projectile < Obj R. + Projectile Radius
&& (Y > CurrentMap->object[i]->Y - CurrentMap->object[i]->Height - Y) // Projectile > Obj B. - Projectile Radius
&& (Y < CurrentMap->object[i]->Y + CurrentMap->object[i]->Height + Y)) // Projectile < Obj T. + Projectile Radius
{
if (CurrentMap->object[i]->ID != ID) // So projectiles doesn't collide with themselves!
{
// Destroy Self
// Destroy Contact Object
break;
}
}
}

I want to know how to make it destroy itself, and the contact object.
Instance_Destroy(ID);
Instance_Destroy(i);

and

Instance_Unregister(ID);
Instance_Unregister(i);

do not work. The program exits and brings up and error.
This happens even when all my instance functions are exactly copied from above except for variable names!
I'm not sure why this. What am I doing wrong? I suspect it has something to do with the way I created my objects.
Any help would be appreciated.

Share this post


Link to post
Share on other sites
Quote:
Original post by BoReDoM_Inc
I want to know how to make it destroy itself, and the contact object.


just flag the objects as "dead"( use a member like bool m_IsAlive or something ).

you would then check for "dead" objects at the begining of each frame and remove them from the array/vector/list/whatever.

Share this post


Link to post
Share on other sites
I have something along the lines of what benishor stated in my example, the variable named "vector<bool> CRoom::object_exists", if that is the problem.
*Takes more time to read the post*

EDIT: That's odd... Unless you forgot to copy something, using "instance_destroy(id)" or "instance_unregister(id)" ought to work, for that is how I do it with my instances... Are your sure you are setting the ID of the instance when it is registered? (In "instance_register()")

Share this post


Link to post
Share on other sites
Yeah I'm definitely setting the object ID. It just won't unregister. I have made a simple console text file that I write to when functions are run. Every loop it tries to delete the projectile and contact over and over and it still stays registered in the vector.


void Projectile::Step() {
for(int i=0; i < CurrentMap->object.size(); i++)
{
if((X > CurrentMap->object[i]->X - CurrentMap->object[i]->Width - X) // Projectile > Obj L. - Projectile Radius
&& (X < CurrentMap->object[i]->X + CurrentMap->object[i]->Width + X) // Projectile < Obj R. + Projectile Radius
&& (Y > CurrentMap->object[i]->Y - CurrentMap->object[i]->Height - Y) // Projectile > Obj B. - Projectile Radius
&& (Y < CurrentMap->object[i]->Y + CurrentMap->object[i]->Height + Y)) // Projectile < Obj T. + Projectile Radius
{
if (CurrentMap->object[i]->ID != ID) // So projectiles doesn't collide with themselves!
{
Instance_Destroy(ID); // It just say ID because it's inside the projectile move function... Is this the problem?
// Destroy Contact Object
break;
}
}
}
}




Instead of calling Instance_Destroy(ID) do I have to replace ID with the original object? Cause that kind of sucks. If someone can could they give me and example of how they delete instances.

[Edited by - BoReDoM_Inc on June 16, 2005 2:29:08 AM]

Share this post


Link to post
Share on other sites
Here's the code for the bullet in my MegaMan X movement example (using the same instance functions as I pasted above):
bool CXBSmall::Step() {
long hspd=5;
if (active) {
if (view_outside()) { instance_destroy(id); return true; }
hspeed=(lr==0) ? -hspd : hspd;
image_index=lr;
x+=hspeed;
if (place_meeting(Ground,x,y)) active=false;
}
if (!active) {
//Death graphics
if (image_index>7) { instance_destroy(id); return true; }
image_index++;
}
}

Can't see why it wouldn't work with your code... Can you paste the versions of your instance handling functions (register,unregister,create,destroy)?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this