Home » Community » Forums » » Enginuity, Part II
  Intel sponsors gamedev.net search:   
[Control Panel] [Register] [Bookmarks] [Who's Online] [Active Topics] [Stats] [FAQ] [Search]

Add Forum to Favorites |  Send Topic To a Friend | View Forum FAQ | Track this topic

Page:   1 2 3 4 5 6 7 8 9 »»

 Last Thread Next Thread 
 Enginuity, Part II
Post Reply 
Yay, lots of good stuff AND a diagram. You are spoiling us!

Just a quick note: for even more portability I've been told it's better to use #ifndef NDEBUG, rather than #ifdef DEBUG. The latter may read more intuitively, but only NDEBUG is guaranteed (DEBUG is common though and seeing as you could add it to the configuration yourself it's not a big deal )

Well done on a thoroughly informative article.


pan narrans | My Website | Study + Hard Work + Loud Profanity = Good Code

 User Rating: 1788   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

YAY! Hurray! Only bad thing is it's DirectX-less..


[edit]

   //Constructing with a pointer
   CMMPointer(T *o)
   {
      obj=0;
      *this=0; // <-----
   }  


shouldn't it be:

   //Constructing with a pointer
   CMMPointer(T *o)
   {
      obj=0;
      *this=o; // <----- Yes I'm a bit sick =D
   }  


[/edit]



.lick


[edited by - Pipo DeClown on June 11, 2003 7:23:24 AM]

 User Rating: 1469   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

A very interesting read, even though I didn't fully understand everything yet. Will definately be coming back for the rest.



 User Rating: 1494   |  Rate This User  Send Private MessageView ProfileView JournalView GD Showcase Entries Report this Post to a Moderator | Link

Hey SuperPig,

Excellent article man!!!

I have some OSX specific sections of code like message box etc that I made when I started playing with the stuff you presented in the draft article, would you be interested in including these in the source ?


Cheers




 User Rating: 1027   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

quote:
Original post by voodoo_john
I have some OSX specific sections of code like message box etc that I made when I started playing with the stuff you presented in the draft article, would you be interested in including these in the source ?



Ooh, yes! Thankee I'm still learning my way around most of OSX, so I'd not figured out how to do that stuff myself. Is is C++ or Objective-C? (Please say C++ )

Pipo: err, whoops Guess proofreading doesn't catch everything. Was that in the source or in the article?

pan narrans: well, the wide world of compiler standards - especially when it comes to common preprocessor symbols - is something I don't know my way around all too well. MSVC had it, so I went with it... I should probably add a footnote at some point later on with your advice, though, if you don't mind.

Superpig
- saving pigs from untimely fates, and when he's not doing that, runs The Binary Refinery.

 User Rating: 2118   |  Rate This User  Send Private MessageView ProfileView JournalView GD Showcase Entries Report this Post to a Moderator | Link

Don't have a clue, probably in the article, you'd better check it yourself.

 User Rating: 1469   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

Was a brilliant article, most important to me wasn't understanding the code as that bit I can do ok (although it was still a very very nice refresher), it's the structure and design of the engine that I've been struggling with somewhat. Were the symbols used in your diagram a specific standard like UML or anything? Trying to find decent resources on diagramatic program design but have yet to find anything much if anyone has any hints on where to look and what modelling language to start with (is UML best for C++ game/app development or is there a better tool for designing games/apps?) Sorry to hijack the thread

Can't wait for part 3, don't keep us waiting too long!

 User Rating: 1015    Report this Post to a Moderator | Link

quote:
Original post by Anonymous Poster
Were the symbols used in your diagram a specific standard like UML or anything? Trying to find decent resources on diagramatic program design but have yet to find anything much if anyone has any hints on where to look and what modelling language to start with (is UML best for C++ game/app development or is there a better tool for designing games/apps?) Sorry to hijack the thread


I'll admit, they're not any particular diagramming standard - UML is something I've been meaning to get around to properly learning, as I'm not an official computer scientist by any means (though I pass the engine around a fair amount before the articles come out, and some of the people who give comments *do* have a computer science background). I can read most UML diagrams, but I'm not competent enough with them to feel able to draw my own.

UML is a good tool for program design, as any systems architect will probably tell you. It's a little C++-specific, but not too much.

I'm not too sure if the engine, the way it's shaping up at the moment, actually sticks to this design all that much. I've certainly coded all the elements you see there - the network system needs a little more work, but meh - but there's a large number of parts that aren't shown on that diagram and probably should be. The foundation layer is concrete - the box at the bottom of the diagram - but the rest may shift around a little bit.

Superpig
- saving pigs from untimely fates, and when he's not doing that, runs The Binary Refinery.

 User Rating: 2118   |  Rate This User  Send Private MessageView ProfileView JournalView GD Showcase Entries Report this Post to a Moderator | Link

Nice article and a cool very memory manager. I'm even more impressed with the frequency you're updating and I hope you can keep it up and see this series through to completion. Will you be building any sort of working game by the end of this or are you just going over engine internals?

 User Rating: 1023   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

quote:
Original post by Impossible
Will you be building any sort of working game by the end of this or are you just going over engine internals?


Oh, very definitely. Like I always say, a general purpose game engine is what you make when you're out of ideas for games

I've already built a basic version of Snake on it, as well as a cylindrical 3D tetris (which I'm told is 'just plain annoying,' but it demonstrates all aspects of the engine, so I don't care ). It's also making for a pretty nice prototyping environment - I wrote a simple tile engine on it in about 20mins.

Superpig
- saving pigs from untimely fates, and when he's not doing that, runs The Binary Refinery.

 User Rating: 2118   |  Rate This User  Send Private MessageView ProfileView JournalView GD Showcase Entries Report this Post to a Moderator | Link

where is part I?

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

//first, a few predefined constants
const int LOG_APP=1;
const int LOG_CLIENT=2;
const int LOG_SERVER=4;
//LOG_USER is used to display the log message to the user - i.e. in a dialog box
const int LOG_USER=8;

#define MAX_LOG_STRINGS 256


Why did you use const int's in the first part, and then suddenly a #define in the second part?

Wouldn't constants be more to the C++ style than macros (and still function in the exact manner for this case)?

 User Rating: 1015    Report this Post to a Moderator | Link

Superpig: The code is C++, I _HATE_ Objective C :grrrr:

Should I email it to you?



 User Rating: 1027   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

zoomcrypt: the article is linked in a box on the right of the artticle, underneath the ads.

AP: I guess there's no definitive reason, except a few problems I've had, over time, with using const ints for stuff that gets done in the compiler rather than the preprocessor. Call it habit, if you will. Feel free to change it.

voodoo_john: sure thing. rfine at tbrf dot net...



Superpig
- saving pigs from untimely fates, and when he's not doing that, runs The Binary Refinery.

 User Rating: 2118   |  Rate This User  Send Private MessageView ProfileView JournalView GD Showcase Entries Report this Post to a Moderator | Link

quote:
Original post by zoomcrypt
where is part I?
On the right side of each page of the article you see the "Contents" sidebar followed by Source code/Printable Version/Discuss the article. Next comes the advert and finally a sidebar called "The Series." As each part is added a link to it is placed under the series sidebar.

I've read the articles and can guarantee the existence of at least 4 parts. There were a few issues that Superpig and I discussed pertaining to internalizing the entire IMMObject class so that it took care of most of its functionality automatically, and could then be blindly used with any common/standard smart pointer implementation (eg std::auto_ptr or boost::shared_ptr). In the final analysis, though, we felt that this was a series of articles with a narrowly-defined scope, and generalizing functionality to all cases would introduce questions and subject matter that would detract from the primary emphasis.

Now I have to make sure to read parts 3 and 4 before they get posted!

 User Rating: 2027   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

Nice article. I have a few questions, though. In the memory manager, there is the method

void IMMObject::Release()
{
   --refCount;
   if(refCount<=0)
   {
      liveObjects.remove(this);
      deadObjects.push_back(this); // Why not delete the object here?
   }
}
  


Why don't you just delete the object right there instead of storing it for deleting later?

My second question isn't directly related to your article. Your log class uses a singleton approach. A log class that I wrote just made all of the methods static:

class Log  
{
   public:
   
      static bool init();
      static void printLog (const char *fmt, ...);
      static void printDebug (const char *fmt, ...);
      static void printError (const char *fmt, ...);
};
 


Now to use the log, all you have to do is include the log class's header file and do this number:

Log::init();
Log:: printLog ("Initialized the log\n");
  


EDIT: The above code causes a stupid smiley

I have it set so that if init fails or isn't called, then printLog writes to stdout instead of a log file, and printError and printDebug write to stderr.

My question is what is the advantage of singletons over a "pure" static class?


[edited by - SpiffGQ on June 11, 2003 3:01:14 PM]

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Excellent Excellent Excellent!!!!!!

great article!

Joel Martinez
http://www.codecube.net/

 User Rating: 1138   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Good questions

I wanted to centralise memory deallocation. By moving things to the deadObjects list, they won't get deleted till the garbage is collected - meaning that you can work with objects without using memory-managed pointers all the time (provided you don't retain them - I think I mentioned this already). If the object were deleted as soon as it's reference count went to zero, something might plausibly be in the middle of using it when it gets deallocated.

Plus, from a conceptual point of view, it fits better with 'garbage collection.' If you were writing a full-scale memory manager, including your own heap manager, it would often be helpful to delete everything at once - because then you can defragment the heap, and other things which it might be useful to do once per frame.

Singletons vs static functions: to be honest, I'm not sure. For your method, you might just as well use global functions with LOG_ prefixed to their names; but the same goes for mine, more or less. Call me a classophile, maybe

Superpig
- saving pigs from untimely fates, and when he's not doing that, runs The Binary Refinery.

 User Rating: 2118   |  Rate This User  Send Private MessageView ProfileView JournalView GD Showcase Entries Report this Post to a Moderator | Link

I love it! Good work I just have one question. In IMMObject's constructor, you push the this pointer into liveObjects. Now, correct me if I'm wrong, but I thought the this pointer wasn't valid until after the constructor was finished?

 User Rating: 1000   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

WOW!!! That was an incredible article! Great work!
quote:
Original post by free lancer
I love it! Good work I just have one question. In IMMObject's constructor, you push the this pointer into liveObjects. Now, correct me if I'm wrong, but I thought the this pointer wasn't valid until after the constructor was finished?

I've never heard that before. I consistantly use 'this' when methods access the objects properties, including constructors. Works fine for me.

- Jay


[ Here, taste this ]


 User Rating: 1177   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

I like these articles. I started an api-independent engine shortly before you started the articles. I'm finding a few design differences between them, but generally they are going about the same things in the same way.

As far as a valid pointer, pointers are nothing more than a location in memory. The object there may or may not be valid. The object isn't valid until the constructor completes. I think his idea was to add it to the list automatically. Because of that he put the code in the constructor. It will become a valid object once the constructor ends.

If you encounter an error in the constructor, you will have to remove the object from the list. That presents some problems. I like his idea about memory management, and must admit it works better than my initial plan for my engine, but there are small holes like that which can come back and bite you.

Besides, it is perhaps too easy to just create a new class and forget about deriving it from IMMObject. Though I love the idea behind it, I kinda get a feeling like it isn't the most solid answer.

Anyway, the point of his article is to make a good engine, not to go into the depths of memory management.

A quick note for SuperPig: What kind of coincidence is this?!? The engine I have been working on was named binaryRefinery. I guess I better go find a new name, huh? Thanks for the articles!

 User Rating: 1032   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Great article Superpig. Looking forward to the rest.

Being my usual nitpicky self I was wondering about this section of code:
if(bEmitWarnings)
{
    //log some kind of error message here
    //we'll be covering how to log messages later this article
}
  

I assume that bEmitWarnings is flag to disable the logging of warnings when unallocated pointers are found, so shouldn't the code be:
if(!bEmitWarnings)
{
    //log some kind of error message here
    //we'll be covering how to log messages later this article
}
  

This is just based on the syntax of the variable name - you could name it bAllowWarnings and your orignal code will work. However if I saw a function with the parameter bEmitWarnings, I would assume that TRUE means no warnings are logged, not the other way around

 User Rating: 2077   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

Nice article, though I have one question about the memory management: Why? How often will it be the case that you'll new something then let it roam about on its own?

Oh, and
quote:
Original post by Anonymous Poster
most important to me wasn't understanding the code as that bit I can do ok, it's the structure and design of the engine

ditto.

Image loads when I'm online!The following statement is true. The previous statement is false.
Shameless promotion:
FreePop: The GPL Populous II clone.

 User Rating: 1324   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Whilst perusing the ringbuffer code I found this:
quote:

while(write<0)write+=bufSize;


But hang on! write is an unsigned long, so this while loop never executes.

 User Rating: 1324   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link
Page:   1 2 3 4 5 6 7 8 9 »»
All times are ET (US)

Post Reply
 Last Thread Next Thread 
Forum Rules:
You may not post new threads
You may post replies
You may not edit your posts
You may not use HTML in your posts
Jump To:
Administrative Options: