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++ > Object oriented programming in C

#27834 - Touchstone - Thu Oct 21, 2004 10:45 pm

Hi all,

I'm just at the beginning of writing an animation system for the agb and I'm curious, does anyone have any good ideas on how to write object oriented code in C? If I want to perform a certain action on an animation, for example set a couple of attributes and play a certain sequence, I currently see two ways of writing the code.

Alt. 1:
Code:
animSetSpeed(&anim_hero, 256); // anim_hero is the animation
animSetFlippedX(&anim_hero, TRUE);
animSetPosition(&anim_hero, 120, 80);
animPlaySequence(&anim_hero, 3);

Alt. 2:
Code:
animSetCurrentAnimation(&anim_hero);
animSetSpeed(256);
animSetFlippedX(TRUE);
animSetPosition(120, 80);
animPlaySequence(3);

Alt. 1 is the most understandable and straight-forward solution, but it sums up to quite a lot of redundant typing. Alt. 2 is .. well .. it's a great way to confuse anyone who reads the code and a veritable bug producer.

I would like to have a C++-like way with accessing methods straight off the animation object and not having to pass the object as parameter.

So, does anyone have a better idea for C code to be more like C++, so to speak. :) What does your object oriented code in C look like?

Cheers.
_________________
You can't beat our meat

#27835 - poslundc - Thu Oct 21, 2004 10:57 pm

Well, if you really want to write your code like C++, you might consider using C++.

That said, if like me you by-and-large prefer plain old vanilla C, the first way would definitely be the preferred way of implementing an OO-style system. But you might consider freeing yourself of the OO paradigm entirely, then, and finding other ways to get the encapsulation and modularization you need.

Dan.

#27836 - sajiimori - Thu Oct 21, 2004 11:42 pm

After he frees himself, how might he represent the state of a given animation and act upon it?

Oh, and the first way is so much better that it could be called the "correct" one. If you write short functions and abstract over repetitive patterns, you'll find that the redundancy tends to be fairly managable.

For instance, what are you really describing in your example? The way a game object should move and animate for a particular action (perhaps walking to the left)? Try giving that set of variables a name, such as an "Action" or an "ActorMotion" or something along those lines, and make functions like "play_action" or "do_motion" or whatever. Then you never have to repeat that sequence of calls again -- just make a new motion for walking to the left.

#27841 - keldon - Fri Oct 22, 2004 1:09 am

Why are you trying to avoid C++, it sounds like you're refusing it more than anything. As for redundant typing, function ( object, param1 ) is no more characters than object.function ( param 1 ), unless you're going to count that extra space break between param1 and the comma =)

your Alt. 2 is similar to something you can do with classes (types) in Basic.

I think the only way to call a function directly from your struct is to do (something like) this

Code:
Struct structClass {
   (void)(*structFunc)(int);   // this may be written a little differently
   int num;
}

structClass a = { a_structFunc };
void a_structFunc ( int param1, 0 ) {
   structFunc ( &a, param1 );
}

void structFunc ( structClass s, int param1 ) {
   s.num = param1;
}

and for every instance include its own structFunc.


Last edited by keldon on Fri Oct 22, 2004 2:19 am; edited 2 times in total

#27850 - sajiimori - Fri Oct 22, 2004 1:59 am

The redundancy is traditionally said to be in the function name, which is prefixed by the type of object that's being operated on. You know, "dog-wash the dog, but car-wash the car"...

#27854 - sgeos - Fri Oct 22, 2004 3:31 am

sajiimori wrote:
The redundancy is traditionally said to be in the function name, which is prefixed by the type of object that's being operated on. You know, "dog-wash the dog, but car-wash the car"...

That could potentially be fixed with the preprocessor tokenizer ## if you use the same prefix.

-Brendan

#27856 - sajiimori - Fri Oct 22, 2004 6:53 am

And how would the preprocessor know the type of the first argument?

Edit: I'm getting ahead of myself here. Let's step back for a moment and realize that what you're suggesting is that every single function call be a macro expansion. Um, no. C is not extensible in the least, so be satisfied or use something else.

#27858 - MumblyJoe - Fri Oct 22, 2004 12:08 pm

Well... if by OOP you mean functions that modify structs you really aren't talking about many of the fundamentals of OOP anyway and your examples are perfectly adequate. However if you want to use some other features of OOP you may just want to bite the bullet and use c++.
_________________
www.hungrydeveloper.com
Version 2.0 now up - guaranteed at least 100% more pleasing!

#27859 - keldon - Fri Oct 22, 2004 12:58 pm

yes, I'm still confused why not. But does my suggestion work for you??? I might try it once I've finished my lab exercises.

#27862 - poslundc - Fri Oct 22, 2004 2:17 pm

sajiimori wrote:
After he frees himself, how might he represent the state of a given animation and act upon it?


Represent the state with a struct. Act upon it by directly manipulating the struct's members for simple state changes (set speed, set flipped, etc.). For more complicated state changes, maintain additional structs that specify how the objects are supposed to change over time and run module functions every frame that iterate over the list and apply those changes.

Not as elegant as OO, but then not everything has to be. :P

Dan.

#27872 - sajiimori - Fri Oct 22, 2004 7:13 pm

Alright, so let's assume animSetCurrentAnimation, animSetSpeed, animSetFlippedX, and animSetPosition are all easily replaced by direct struct assignments (which seems reasonable, though you know the drawbacks of each approach in C/C++).

Now let's say animPlaySequence involves more than one operation, in its function form. Maybe it looks like this:
Code:

Sequence* sequenceGet(int id);

void animPlaySequence(Animator* a, int sequence_id)
{
  a->sequence = sequenceGet(sequence_id);
  a->current_frame = 0;
  a->time_left = a->sequence->frames[0].duration;
}

I can think of 2 ways to translate that abstraction into direct struct assignments: either manually inline the body of that function each time you want to do those operations, or do something like this:
Code:

anim_hero.sequence_id = 3;
anim_hero.flags |= ANIMATOR_FLAG_STARTING_NEW_SEQUENCE;

And then defer the actual work to your per-frame iterators.

To both methods I say: ouch.

#27874 - Gene Ostrowski - Fri Oct 22, 2004 7:31 pm

If it helps, here's a sample of some of my code that I use to maintain my game "objects", and how to OOP-ize the code so that it's just "plain C" but get some of the benefits of OOP:

Part of my generic game object "class":

Code:

struct CObject
{
   s16 x; 
   s16 y; 
   s16 xoff;
   s16 yoff;
   s16 shapenum;
.
.
.
   // here is the important stuff
   void (*f_setup)(struct CObject* obj);
   u8   (*f_move)(struct CObject* obj);
   void (*f_preparedraw)(struct CObject* obj);
   void (*f_project)(struct CObject* obj);

   void *data; // pointer to user defined data structure

};


Then, I can use the function pointers to define functions that handle all of the methods that each object needs. Each object is maintained in it's own file, to keep things together and make it more like "classes":

Then in a file called ObjDefault.cpp:
Code:

void setupDefault(struct CObject* obj) { // do something }
u8 moveDefault(struct CObject* obj) { // do something }
void preparedrawDefault(struct CObject* obj) { // do something }
void projectDefault(struct CObject* obj) { // do something }


In the file ObjPlayer.cpp:
Code:

void setupPlayer(struct CObject* obj) { // do something }
u8 movePlayer(struct CObject* obj) { // do something }
void preparedrawPlayer(struct CObject* obj) { // do something }
void projectPlayer(struct CObject* obj) { // do something }


In the file ObjShot.cpp:
Code:

void setupShot(struct CObject* obj) { // do something }
u8 moveShot(struct CObject* obj) { // do something }
void preparedrawShot(struct CObject* obj) { // do something }
void projectShot(struct CObject* obj) { // do something }


In the file ObjXXX.cpp: (you get the idea)
Code:

void setupXXX(struct CObject* obj) { // do something }
u8 moveXXX(struct CObject* obj) { // do something }
void preparedrawXXX(struct CObject* obj) { // do something }
void projectXXX(struct CObject* obj) { // do something }



Then I have a file that handles all the object management functions, for allocating, freeing, etc. In this "object manager" file:

Code:

void SetObjectFunctions(struct CObject *obj, int type)
{
      obj->f_setup=&setupDefault;
      obj->f_move=&moveDefault;
      obj->f_preparedraw=&preparedrawDefault;
      obj->f_project=&projectDefault;

       if (type==TYPE_PLAYER)
     {
         obj->f_setup=&setupPlayer;
         obj->f_move=&movePlayer;
         obj->f_preparedraw=&preparedrawPlayer;
         obj->f_project=&projectPlayer;
     }
     else if (type==TYPE_SHOT)
     {
         obj->f_setup=&setupShot;
         obj->f_move=&moveShot;
         obj->f_preparedraw=&preparedrawShot;
         obj->f_project=&projectShot;
     }
          else if ....
}

In actuality, though, this function is project specific, to keep the defines out of my object manager, thus allowing me to reuse my object manager libraries in all my projects. This function isn't totally necessary either, since I can do it elsewhere, but it keeps things together...

Then, to actually get the benefit of this, things are kept clean and simple in the object management functions:
Code:

struct CObject *AllocateObject(int type)
{
   struct CObject *newobj=NULL;   

   newobj=<do whatever to allocate the object>
   if (newobj)
   {
      // set all the object's member functions
      SetObjectFunctions(newobj, type);
      // call the object's setup routine
      newobj->f_setup(newobj);
      // do other stuff
      return(newobj);
   }
   else return(NULL);
}


Again, it keeps the code clean when you need to iterate over your object list and call the object's member functions:

Code:

arbitrary_gameloop() 
{
   struct CObject *newobj=NULL;   

   // to allocate objects
   newobj=AllocateObject(TYPE_PLAYER);
   if (newobj) { // do something }
   

   // to "process objects"
   struct CObject *currentobj=NULL;   

   <loop through all objects>
      currentobj=<get the next object>
   
      // call object function to move itself
      currentobj->f_move(currentobj);
      // call object function to project itself
      currentobj->f_project(currentobj);
      // call object function to set up parms to draw itself to screen
      currentobj->f_preparedraw(currentobj);
   <next object>
}



Of course, the "object iterators" are actually kept in with the object management functions, to allow me to reuse this logic in all my projects (i.e. I actually just call a generic "MoveObjects(objectlist)" function).

Each object knows how to setup, move, project, and draw itself. Each object is maintained in it's own file to keep the code clean. I can reuse the code in all my projects. Etc.

This approach works very well. It's fast too. Plus, by "overriding" member functions you can "subclass" your objects to your heart's content.

The nice thing about all this is that I can avoid all the C++ overhead, avoid all new/delete allocations, and still retain a lot of the benefits that C++ provides. It works well for the low memory, low speed, embedded environment that is the GBA.

Hope that helps.
_________________
------------------
Gene Ostrowski

#27876 - poslundc - Fri Oct 22, 2004 7:40 pm

I'm unclear what the point you're making is. In 90% of cases for something like that I probably use the ancestor-of-OO method as well rather than excessive inlining or more hackneyed schemes. By "freeing himself of OO" I'm not suggesting he abandon useful and sensible coding practices. The point is to use the technique as a tool where it is best suited to the task, rather than trying to craft your program around a certain style.

Here's another way to think of it: I may write a function like that in a module of functions pertaining to a certain encapsulation of behaviour. I don't consider that as being a "specifically object-oriented function" as I'm writing it, though; it's just a function that takes a pointer to the struct it modifies. It's OOP that is derived from the more general technique, not the other way around. It may seem like quibbling over semantics, but I find it makes a huge difference when you don't feel confined to the rigours of a single paradigm while coding.

Dan.

Edit: This was posted in response to sajimori two posts up; Gene's submission got in before mine.

#27877 - poslundc - Fri Oct 22, 2004 7:46 pm

And to Gene: dude, you are reinventing the wheel. The C++ overhead is apparently negligible so long as you are savvy in your coding, so if you like C++ then go ahead and use it.

Dan.

#27879 - sajiimori - Fri Oct 22, 2004 7:59 pm

I think I'm mostly responding to "consider freeing yourself of the OO paradigm entirely, then, and finding other ways to get the encapsulation and modularization you need". It seemed to imply that there are always other ways that are better (or even just as good), but now I see that's not what you meant.

As far as quibbling: If you write a program with a totally open mind as to the methodology, and the result happens to match the OO paradigm perfectly, did you write an OO program? Who cares? ;)
Quote:
The nice thing about all this is that I can avoid all the C++ overhead, avoid all new/delete allocations, and still retain a lot of the benefits that C++ provides. It works well for the low memory, low speed, embedded environment that is the GBA.
I disagree in many ways.

Your method calls are slightly faster when compared to virtual functions (one less dereference operation), but it involves a large memory loss in situations where there are a lot of objects of a class with many "virtuals".

Object construction is slower in 3 ways: doing at least one assignment per method, initializing methods with the default values then overriding them with assignments, and switching on types.

If you don't use malloc/free, you lose exactly the same thing you lose if you don't use new/delete in C++ -- dynamic object allocation. If you don't want that feature, don't use it.

Most importantly, it involves a lot of tedious manual labor that is best left to a computer.

#27881 - poslundc - Fri Oct 22, 2004 8:10 pm

sajiimori wrote:
I think I'm mostly responding to "consider freeing yourself of the OO paradigm entirely, then, and finding other ways to get the encapsulation and modularization you need". It seemed to imply that there are always other ways that are better (or even just as good), but now I see that's not what you meant.


Looking back on what I said I see that it comes across that way. So to set the record straight: no, I'm not suggesting you abandon the techniques or even core values used in OOP. Rather, I'm saying you can do yourself a disservice if you bridle yourself to the methodology where it isn't automatically necessary.

I think my point makes itself evident from Gene's code, actually. You've written a needlessly complicated C infrastructure to simulate OO features, and dug yourself a big round hole in the process. I'm sure it works and does what you want it to, but if you're not careful, you may find yourself jamming square pegs into it.

Dan.

#27887 - keldon - Sat Oct 23, 2004 12:17 am

On the free yourself from OO, I think that's important to do. Not to abandon it, or go against it; but to understand that there is possibly more. Some things still cannot be represented properly by OO .. our Systems Engineering lecturer was demonstrating them; if only I could remember them because they're so obviously procedral problems.

And reinventing the wheel is fine if you don't have to chew your way through Michelins to do it. But you're able to use C++, and the scope of your code is begging for classes. A simple animation struct is fine for this stuff; windows API manages with using structs.

But having said that you have done something that had probably seemed impossible to think of happening before. Some 20 years too late I may add though.

#27890 - Touchstone - Sat Oct 23, 2004 2:37 am

Oh, thanks for the discussion guys!

poslundc wrote:
Well, if you really want to write your code like C++, you might consider using C++.

I'm trying to keep the code as assembler-like as possible, with as few dependencies as possible and something I can access from assembler. Not because it's the "best" way to solve the problem, it's just that I want to solve the problem that way, I'm in an assembler kind of mood. You seem to assume that people don't want to reinvent the wheel. And as for Gene's code being needlessly complicated, function pointers offers stuff you cannot do in C++, but there's no argue that he has written a lot of code that basically do what c++ does for you automatically.

sajimori wrote:
If you write short functions and abstract over repetitive patterns, you'll find that the redundancy tends to be fairly managable.

Yes, I like that idea.

Keldon: Yeah, I was thinking of something like that but you still have to specify which object to work on twice. hero_anim.playSequence(&anim_hero, 5);

Gene: That's a way of solving other problems, and I have thought about doing something like that. It doesn't really solve my problem though, but you can do some pretty interesting stuff with function pointers, like instead of having a state-machine for your character idle physics for instance, by default it can be like a regular "affected by gravity"-drop but if for example you use a mini hot-air balloon power-up the function can be replaced with a "float upward" function instead, with simply a function pointer stack and some rules as to when a general purpose stack solver can just remove the latest function, making the character go back to his drop function. Mmmm, yes. (I'm really tired at the moment :)

Thanks again. Hope I haven't missed anything.
_________________
You can't beat our meat

#27892 - sajiimori - Sat Oct 23, 2004 3:01 am

Quote:
...function pointers offers stuff you cannot do in C++...
C++ has function pointers, and what's more, C++ offers method pointers which carry a pointer to both the code and an object. Beat that! ;)

(Ok, closures win hands-down, but we're talking C/C++ land here.)

#27893 - Abscissa - Sat Oct 23, 2004 3:48 am

sajiimori wrote:
Quote:
...function pointers offers stuff you cannot do in C++...
C++ has function pointers, and what's more, C++ offers method pointers which carry a pointer to both the code and an object. Beat that! ;)

(Ok, closures win hands-down, but we're talking C/C++ land here.)


Function pointers in C++ are kind of tricky, though, aren't they?

#27894 - sajiimori - Sat Oct 23, 2004 4:03 am

As far as I know, regular function pointers are the same in C++ as they are in C. Pointers to non-static methods are a little weird, but I think I misremembered the details.

In my experience, function pointers get a lot less interesting as you start using C++ to its fullest.

#27895 - poslundc - Sat Oct 23, 2004 4:39 am

Touchstone wrote:
Oh, thanks for the discussion guys!

poslundc wrote:
Well, if you really want to write your code like C++, you might consider using C++.

I'm trying to keep the code as assembler-like as possible, with as few dependencies as possible and something I can access from assembler. Not because it's the "best" way to solve the problem, it's just that I want to solve the problem that way, I'm in an assembler kind of mood. You seem to assume that people don't want to reinvent the wheel. And as for Gene's code being needlessly complicated, function pointers offers stuff you cannot do in C++, but there's no argue that he has written a lot of code that basically do what c++ does for you automatically.


I'm not opposed to complicated code (well, I am, but for the sake of this explanation I'm not); I'm opposed to complicated infrastructures. I do some crazy shit with things like function pointers in my game, but the point is I use them on a case-by-case basis in situations that call for them, rather than trying to use them to build up a whole paradigm for the rest of my program to follow, such as OOP.

That's the kind of wheel that I don't think is worth reinventing. I use vanilla C because following the OOP paradigm isn't important to me. The code I write is complicated, but the infrastructure is almost always dead-simple.

It's when you're considering writing code basically just to do everything that C++ already does for you... that's when I think it's time to haul ass to Midas instead of trying to sand the corners down off of your triangles.

Dan.

#27896 - LOst? - Sat Oct 23, 2004 5:19 am

And here we go....


C vs C++, as in so many threads you have been going through this lately.

#27897 - sajiimori - Sat Oct 23, 2004 5:26 am

Honestly, I haven't found these discussions to be repetitive yet -- each time the subject comes up, it appears to be centered around a different aspect of programming style, technique, or philosophy. It's rarely about technical differences.

#27899 - LOst? - Sat Oct 23, 2004 5:41 am

sajiimori wrote:
Honestly, I haven't found these discussions to be repetitive yet -- each time the subject comes up, it appears to be centered around a different aspect of programming style, technique, or philosophy. It's rarely about technical differences.


True. Just a warning of things to come. I'm too tired to read all the posts so this was a basic attemt to be smart which failed :P

I better shut up

#27901 - MumblyJoe - Sat Oct 23, 2004 10:21 am

As for function pointers in C++, the language can do ANYTHING C can do and more, also compilers are usually more stirict when compiling in C++ mode and may find errors you made in C, which is a good thing.

Regardless of me trying to make you switch from a very old language to a pretty old language, I can't see the whole problem, looks like what you are trying to do works, so stick with it.
_________________
www.hungrydeveloper.com
Version 2.0 now up - guaranteed at least 100% more pleasing!

#27904 - Touchstone - Sat Oct 23, 2004 1:41 pm

sajiimori wrote:
Quote:
...function pointers offers stuff you cannot do in C++...
C++ has function pointers, and what's more, C++ offers method pointers which carry a pointer to both the code and an object.

Yes of course.

poslundc wrote:
That's the kind of wheel that I don't think is worth reinventing.

The important part is that it is YOUR opinion that it's not worth reinventing, not necessarily mine. Go ahead and recommend changing to C++ for those that are willing to do so but you are not really helping me with my problem. Thanks for trying though, I honestly appreciate it.
_________________
You can't beat our meat

#27906 - keldon - Sat Oct 23, 2004 4:12 pm

with my suggestion you should be able to access a function using object.functionName (params) not object.functionName ( object, params).

#27913 - sajiimori - Sat Oct 23, 2004 6:11 pm

Touchstone, everything that's said here is the opinion of the speaker, whether they present it that way or not (and Dan even said "...I don't think..."). For example, the previous sentence does not have extra verbiage to specify that it is only my belief and that my beliefs do not affect reality. I find such "disclaimers" to be a waste of space.

So, when you say "that's your opinion", what I hear is "don't post in MY thread unless you're going to say something I like". But this is not your thread -- it's gbadev's thread. You should be grateful that anybody bothered to reply at all. Feel free to ignore posts that are not of interest to you.

#27919 - Touchstone - Sat Oct 23, 2004 11:28 pm

keldon wrote:
with my suggestion you should be able to access a function using object.functionName (params) not object.functionName ( object, params).

Ah, yes, I missed that the first time I read your post. That's cool. It does require a few of extra functions, and each object has to be in file-scope. An interesting idea.

sajiimori wrote:
Touchstone, everything that's said here is the opinion of the speaker, whether they present it that way or not

Yes, of course.

sajiimori wrote:
So, when you say "that's your opinion", what I hear is "don't post in MY thread unless you're going to say something I like". But this is not your thread -- it's gbadev's thread. You should be grateful that anybody bothered to reply at all. Feel free to ignore posts that are not of interest to you.

I AM grateful, I even wrote so in the end of my reply to him. And I really don't want to just ignore someone that answer a question of mine just because I don't like the answer. And if you think I'm a bastard then please understand that english is not my native tounge so what I mean to say might not be what I end up writing, even though it looks exactly the same to me. What I meant with my reply to him was that he is not helping me solve my problem the way I want to solve it.

I'm sorry if I upset anyone, of course I don't want to do that.
_________________
You can't beat our meat

#27923 - keldon - Sun Oct 24, 2004 2:24 am

well your english is better than mine; so I don't think you are doing too bad

#27941 - Gene Ostrowski - Sun Oct 24, 2004 6:05 pm

I thought long and hard about posting code as a reply to this thread, knowing:

1) It would be blasted by those who don't understand it or think it's needless work or reinventing the wheel or overly complicated or pointless to do it this way or blah blah blah
2) It would turn into a C vs. C++ "argument".

I decided to post it anyway.

The original post was asking about writing OO C code, which is what my reply was addressing. He clearly was not asking "What's better for OO code, C or C++?", which is what most people in this thread are discussing. If you guys want to argue this, go to the other threads that specifically discusses that topic.

To write OO code in C, of course you have to do things that C++ compilers do for you, that's the whole point. Why is this point even being discussed?

When he asked the original question, I assumed that he had worked out the C vs. C++ issue on his own (and decided to stick with C for his own reasons), and was merely looking for guidance on how to code it in C for use in his object manager.

I'm sure many of you are seasoned software engineers, as am I. I've learned over the years that it's almost pointless to debate things that involve too many shades of grey, including opinions and style. I fully understand every point that was brought up, and for every argument "If you do A then you can't do B or must do C", an equally valid argument of "but if I do A I can also do D" or "but I can then do B by doing E without doing F", ad infinitum.

As a software engineer, I look at what I have to accomplish given the constraints, and decide which tool to use to do it. For what it's worth, I actually had my object manager written in OO C++, but decided to convert it to straight C because I wanted to make it faster and bring the code closer to my new, simplified implementation.

"There's more than one way to skin a cat."
"When all you have is a hammer, everything looks like a nail."
_________________
------------------
Gene Ostrowski

#27942 - tepples - Sun Oct 24, 2004 6:25 pm

sajiimori wrote:
If you don't use malloc/free, you lose exactly the same thing you lose if you don't use new/delete in C++ -- dynamic object allocation. If you don't want that feature, don't use it.

Not exactly. The other thing new and delete do is run your class's constructors, and they can run your constructors even in semi-static situations when you use the "placement new" form.

Anyway, language wars go in the C/C++ thread. Moved.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#27944 - Gene Ostrowski - Sun Oct 24, 2004 6:48 pm

Touchstone wrote:

Quote:
Gene: That's a way of solving other problems, and I have thought about doing something like that. It doesn't really solve my problem though, but you can do some pretty interesting stuff with function pointers, like instead of having a state-machine for your character idle physics for instance, by default it can be like a regular "affected by gravity"-drop but if for example you use a mini hot-air balloon power-up the function can be replaced with a "float upward" function instead, with simply a function pointer stack and some rules as to when a general purpose stack solver can just remove the latest function, making the character go back to his drop function. Mmmm, yes. (I'm really tired at the moment :)


You get the idea. It's actually quite powerful as a supplement to normal state-management. I do still keep a state-machine for the objects, though, and don't rely on modifying function pointers for all the state changes, to keep the code clean. For the example you gave about switching the "gravity" drop to the "float up" drop, I do this only if the function has no object-specific logic in it.

In other words, I'd keep the object's move function as movePlayer(), and would keep a state variable handy within that function to determine if I needed to use the gravity logic or the lift logic. Of course, this is just how I'd do it, as there are many ways-- this approach is abstracted enough that it should handle just about anything you'd throw at it.

If you have a spaceship object that gets hit by a missile, you can call changeObject(obj, TYPE_EXPLOSION) which will set the object's type, move, and draw functions to the "explosion" routines, then forget the object forever letting the object manage itself at that point:

Code:
// does it collide with the missile
if (obj->checkCollision(missileobj))
{
    // yes, turn it into an explosion object
    ChangeObject(obj, TYPE_EXPLOSION);
    // stop processing it as a spaceship anymore
    break;
}


At this point, the object's "functions" will be replaced with the functions that handle animating explosions, adding particles, etc. As far as the system is concerned, it's no longer a spaceship. Somewhere in the explosion routines will be logic to determine the end of the lifecycle for the object and will delete itself. The point is that there is no logic in the "spaceship" code for managing what at this stage is just an "explosion" object. Just my coding style, and you may find something else that works for you equally as well.

You mention that it won't address the specific problem you are having: can you elaborate on what exactly you are trying to do?
_________________
------------------
Gene Ostrowski

#27960 - sajiimori - Mon Oct 25, 2004 5:34 am

Quote:
I've learned over the years that it's almost pointless to debate things that involve too many shades of grey, including opinions and style.
I'm very interested in style, and I think it's an important subject even if there are no absolute answers. If nothing else, I enjoy talking about it.

I also don't feel guilty about letting a thread wander about in its natural course -- the ideas tend to flow more freely that way.
Quote:
The other thing new and delete do is run your class's constructors, and they can run your constructors even in semi-static situations when you use the "placement new" form.
Right, I should have said you lose dynamic object allocation if you don't use malloc/free (or some variant thereof), just as you lose dynamic object allocation if you don't use new/delete (or some variant thereof), though you also lose other capabilities if you don't use new/delete. But that's hard to say, and the simple-yet-not-quite-accurate version seemed to get the point across. =P

#27969 - Gene Ostrowski - Mon Oct 25, 2004 4:54 pm

sajiimori:
Yes, duscussions about style can be interesting, but there's a fine line between discussion and debate. It's always ok to discuss things, as that's how horizons are broadened, but here's a scenario that has probably never happened in the history of communication:

Alice: I love spinach.
Bob: Uungh. Spinach is so nasty. It tastes disgusting.
Alice: No, it tastes good. And it's full of vitamins and its so healthy for you.
Bob: Oh, now I see your points. Oh well, I guess I love it now after all.
_________________
------------------
Gene Ostrowski

#27975 - tepples - Mon Oct 25, 2004 5:56 pm

It has at my dad's house.
-- I hate spinach!
-- It has vitamins.
-- Perhaps if I put some syrup on it to disguise the taste...
-- Here's some.
-- I can handle this.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#27977 - keldon - Mon Oct 25, 2004 6:01 pm

or at my house:
-- Mr Keldon I don't like spinach
-- I told you to eat it, now shut up
-- no, I don't like it
-- you can either have vitamins or no playstation
-- ok, I like it now
=D isn't babysitting cool

#27988 - sajiimori - Mon Oct 25, 2004 7:58 pm

I like debate, too. (Sorry?)

#27997 - Abscissa - Mon Oct 25, 2004 9:12 pm

keldon wrote:
or at my house:
-- Mr Keldon I don't like spinach
-- I told you to eat it, now shut up
-- no, I don't like it
-- you can either have vitamins or no playstation
-- ok, I like it now
=D isn't babysitting cool


lol, I go away for a few hours and look what happens to the C vs C++ thread. ;)

I think someone warned earlier that these new language vs old language debates can get really out of hand, but did anybody listen? Nooo! And now see what happens? :)

#28050 - Touchstone - Tue Oct 26, 2004 4:13 pm

Abscissa wrote:
I think someone warned earlier that these new language vs old language debates can get really out of hand

This thread didn't even start out as a language vs. language discussion either, it just seems like that's what people like to talk about. Well, this should learn me never to ask a question. :-)
_________________
You can't beat our meat