Advertisement Jump to content
  • Advertisement


  • Content Count

  • Joined

  • Last visited

Community Reputation

152 Neutral

About amag

  • Rank
  1. Quote:Original post by Kazgoroth Well I really don't care *how* the word processor makes it possible for me to continue from where I last left off, just that it does! I can put pretty much any program ino that sentence and it still makes sense. Ok, sure if you want to be anal-retentive about it, you can do that. Especially since you didn't even bother commenting on the key-concept in that paragraph. Wow, I can't say I had anticipated such a heated debate, especially since it seems I'm almost the only one thinking this way, well me and xycos. I'm sorry if I hurt anyones feelings with my posts, but really, there's no need to get all anal-retentive about this topic. We're still the minority here. Quote:Original post by KazgorothSo are you therefore arguing that no documents should ever be automatically placed in the My Documents folder by any program? To answer your question, yes, I think that no program should ever automagically create a file/directory in "My Documents". Please note that automagically here means "without the user explicitly asking for it to be stored there". Which brings us to my word-processor. At least it allows me to choose *where* I want to store a document, "My Documents" is then only the default. I agree it would be a little bit better if all games put their savedata in a directory under "My Games" since it wouldn't clutter up the "My Documents"-folder as much. Quote:Original post by MadsterThen, since its a document, you'll want to be able to open it, right? so why not, go ahead and register the filetype. Because every one wants each of their games to have its own registered file extension hooked to the game, since that's the usual way we load games, by double-clicking the savegame file, right? Sure that might be good, but the problem is that many games today seem to favor the "savegame.XXX" naming standard which makes it difficult to distinguish which one I really want.
  2. Ok, I thought I explained it all but I guess my text was a bit dense. Firstly I do certainly *not* advocate putting the savegames in "Program Files" (if you look carefully you'll see I said this in the OP). And of course I care about my savegames, it's just that I only care about them A) when I play the game they belong to, or B) when I need to make a backup. In case of (A) it doesn't matter where the savegames are located just as long as they work even when I'm not admin. In the case of (B) I must first confess that I never backup my savegames as I don't really see a point in doing that. But say that I do, then the game manual or a readme or what not can direct me to the "Application Data"-folder. Anyway, I guess I disagree with most of you whether savegames really are "documents". For me a document has a purpose all by itself whereas a savegame is just the means to an end. I really don't care *how* the game makes it possible for me to continue from where I last left off, just that it does! Another thing that annoys me about programs (ok, it's not just games) creating folders and documents in "My Documents" is that Explorer shows "My Documents" as the default start location when you open it. As "My Documents" is very seldom my desired destination it annoys me that I now have so many folders in "My Documents" that I always need to scroll down to find my harddrives.
  3. I have a huge pet peeve with many of the current computer games running on WIntel and in order to try to stop the infestation I post this message. Why on earth do you store savegames in the "My Documents"-folder? Obviously most game developers are not aware (or do not care) about the concept of "My Documents". In "My Documents", documents that the user cares about should be stored. What I mean about that the user cares about them is that the user might want to rename the file or "oh, where did I put the recipe for that good soup?" or that she somehow by the aid of some program want to alter the contents of a file in for her a deterministic way! That is, the documents in "My Documents" should be documents that the user is aware of! Or as Raymond Chen puts it: "My Documents is where users store their files, whereas Application Data is where programs store their files" (much better and to the point than my ramblings). Some questions for game developers that ponder this: How does that fit with savegame data? Do you want your users to manually rename and/or alter the data in the files? I think not! Afterall does the user even care about where the savegames are stored? Does she need to know? Obviously not! The user plays the game, saves and the only thing the user want is to be able to continue playing from where they last saved! So obviously there's no reason to store savegames in "My Documents" and every reason not to! So where should savegames be stored? Well for security reasons they should not be stored in the game's install directory either. But do we really only have two places to store them? Either the install-directory or "My Documents"? No! A much better way is to store them in the "Application Data" or the "Local Settings\Application Data"! Thank you for reading!
  4. amag


    Quote:but there has error: Error C2228: left of 'lpCreateParams' must have class/struct/union type warning C4244: 'argument': conversion from 'LONG_PTR' to 'LONG', possible loss of data Uhm, since I just wrote that code without letting it through any compiler I missed that it should say: app = reinterpret_cast<CApplication *>(cs->lpCreateParams); The warning you get is, uhm, a compiler bug, it annoys me too but there's nothing to do except turning off 64-bit compatibility warnings. For a 32-bit program LONG and LONG_PTR will be of the same size (32 bits), but in a 64-bit program LONG_PTR will be 64 bits. The problem is that for a 32-bit program SetWindowLongPtr() is simply a macro around SetWindowLong(), so if you pass a LONG_PTR to SetWindowLongPtr() it will actually go to SetWindowLong() which only accepts a LONG, now as I said for a 32-bit app, sizeof(LONG) == sizeof(LONG_PTR), so it's no problem, except that the compiler has been told to look for conversions from LONG_PTR to LONG and warn about it... The linker error means that there's no body for the member function AppProc() in the class CGameApp. If there is make sure the signatures of the declaration and definition of AppProc() are exactly the same! Having said that you need to investigate any of the other possible errors yourself a bit before you post a response, you can't just post what the compiler spits out and expect us to fix/debug/write the whole program for you... Good luck!
  5. amag


    This is what you have to do in your static WndProc: LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) { CApplication *app = 0; if(uMsg == WM_NCCREATE) { const LPCREATESTRUCT cs = reinterpret_cast<const LPCREATESTRUCT>(lParam); app = reinterpret_cast<CApplication *>(cs.lpCreateParams); ::SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(app)); } else { app = (CApplication *) (LONG_PTR)::GetWindowLongPtr(hWnd, GWLP_USERDATA); } if(app) return app->AppProc(hWnd,uMsg, wParam, lParam); else return DefWindowProc(hWnd, uMsg, wParam, lParam); } -- Begin shameless plug Btw, I have designed a much easier way to write Windows applications (which uses this technique under the hood). This makes it all too easy (easier than any other approach I've seen) to write a Windows app. Basically you can write a Windows app like this: void on_paint(HDC hdc) { ... } void on_mousemove(POINTS p) { ... } and WinMain: int WINAPI WinMain(HINSTANCE instance, HINSTANCE, LPSTR cmd_line, int cmd_show) { init_winlib(instance); window w = create_window("Hello World"); w.message(WM_PAINT) += &on_paint; w.message(WM_MOUSEMOVE) += &on_mousemove; w.show_window(cmd_show); main_loop(); } And then if you decide you need a HDC for drawing in your on_mousemove-function, you just add it and everything works! You don't have to change anything but the on_mousemove-function! And of course it works with member-functions in a class as well! Anyone who's interested can read about the thinking behind it at I hope I will be able to finish the next part of the tutorial where I describe how to apply the technique described for Windows programming. I also hope I will be able to clean up the source code enough so I can release it! -- End shameless plug
  6. It's unfortunate that programmers learn to use operator=() in the wrong way. Basically if there's any reason you want to overload the default operator=(), you should use the swap()-pattern for exception safety: class A { type data_; public: A(const A &other) : data_(other.data_) {} // void swap(const A &other) throw () { std::swap(data_, other.data_); } A &operator=(const A &rhs) { A tmp(rhs); // create a temporary A using A's copy ctor tmp.swap(*this); // swap the contents of "this" and the temporary return *this; // at this point tmp dtor is called and freeing up possible resources previously occupied by "this" } }; If you think this is overkill for your operator=(), you don't need to overload the default version with your own!
  7. Hmm, I'm sorry but I think it all sounds quite complex. Why would you want to have two different types of memory allocation? Why not have the faster for strings and other stuff as well? You can hash on the address of the allocated block. The only reason I can see to have two different versions of memory allocations (and I'm a bit dubious about that too) is the one given in "Modern C++ Design" by Alexandrescu. In that book he presents a version that's fast for small objects (smaller than some predefined size). I don't remember the deal now, but he still built it on top of a "real" memory manager (be it your own or the built in). Have you thought about how you will handle reference counting? There's an old article here at GameDev that presents a referenced counted object (I'm sorry I don't have the URL). It is to be used on top of a real memory manager, maybe not what you want? Anyway in this article basically any reference counted object needs to derive from a ReferenceCounter base class and then there's a templated class that wraps it and provides accessor methods (some that calls AddRef/SubRef in the ReferenceCounter class). I think it feels a bit like you're mixing two different concepts together, memory management and game objects. Or maybe it's just me who have misunderstood. But anyway, game objects should not depend on the memory manager to do something for them (except allocate memory). You should be able to switch memory managers under the feet of the game objects and they shouldn't care. Instead you should have a game object manager for handling all game objects. Cheers!
  8. Hey, sure, memory management is fun. I have some questions you might want to answer for yourself as much as for me... * What's the difference between "managed" and "unmanaged" data/objects in your code? Are managed objects garbage collected or is it something else? * About keeping a hash table for quick look ups, when will you need quick look ups? Are you sure a hash table really is what you need? I'm sorry if I ask a lot of stuff but I have a tendency towards liking simplicity and not to optimize (code or design) prematurely. Cheers, Andreas
  9. I don't know any white papers for writing a memory manager, but to get started with something really simple, skip classes (ctor/dtor problems) and just create your own wrappers around *alloc/free. In those wrappers you can do the proper handling to keep track of allocations. To get started write something like: struct mem_header { size_t size; void *block; mem_header *next; }; namespace { mem_header *first_block = 0; }; bool mem_alloc(void **buf, size_t size) { (*buf) = malloc(size); if(*buf == 0) return false; mem_header *mh = static_cast<mem_header *>(malloc(sizeof(mem_header))); if(mh == 0) { free(*buf); return false; } mh->size = size; mh->block = *buf; mh->next = first_block; first_block = mh; return true; } Then you add stuff (some sort of header, either separately allocated or allocated *before* the real allocation) to keep track of all allocations. Then you write tests that only use your own memory functions to verify that they work correctly. After that you can replace new/delete and *alloc/free. Be sure to read about the semantics of each function you want to "overload". A good read to just get some basics in a simple memory manager is "Writing Solid Code" by Steve Maguire (ISBN: 1556155514). Otherwise reading through the sources of the Fluid Studios memory manager will definitely be a useful read. I have to say I find them quite straight forward and not as complex as one might think. So even if you want to roll your own for the case of learning, reading through those sources and trying to understand them is definitely worth the time (besides, it's free). Good luck!
  10. I would suggest you look at an industrial strength memory manager such as the one Paul Nettle has written ( There are some bugs in it which probably won't be apparent until you use templates. I've emailed him about it but I don't know if it has been fixed yet. There are several problems with your solution, for instance you invoke the ctor completly wrong. To invoke the ctor on an allocated object you need to call placement new: unsigned char *buf = (unsigned char *)malloc(size); new (buf)IMemoryObject; But I think a better way for a memory manager would be to overload new globally in your app, then the invocation of the ctor is done automagically for you. A no-throw new could look like this then: void *operator new(size_t bytes) { return malloc(bytes); } Also I think it's a mess if everything that should be allocatable must inherit from IMemoryObject. I promise if you think about it (or start using this seriously) you'll realise there are loads of problems with this design. I'm sorry to say this but I'm afraid you're in a dead end here. One of the big gains of using a globally overloaded new/delete is other stuff like STL will use your memory manager too. This makes it ideal to track memory leaks and illegal accesses. Good luck!
  11. What you could do (and I believe Linux worked like this in the beginning) is to make your os a DOS-executable. So you install DOS on your machine, you get a compiler for DOS (preferably one able to compile protected mode programs) on another machine. Then you write your os. The first thing your os should do when starting up, though, is to kick out DOS, that is replace all irq-vectors with your own stuff. This way you can exchange part after part of DOS without having to write a whole os from scratch. You could keep the same executable format as DOS for starters, which would simplify writing programs since you don't have to write your own compiler as well (or at least a back-end for GCC). Good luck!
  12. amag

    Is dynamic_cast the solution?

    Quote: I'd prefer to use polymorphism - add IsCollidable() and IsRenderable() to the base class and override them in the derived classes to return the relevant value. Actually an IsXYZ() method isn't going to be much use, of course it will help to put the object in the right list (without dynamic_cast) which is good, but then you need to add (abstract) methods in the base class to handle rendering and collision detection/response and whatelse, which means that you don't really need a class hierarchy at all, why not just have one base-class? And if you still want one (like that) it won't be very scalable since when you need to add PlayingSoundable and Serializable, you need to change the base-class. In this case it's better to use interfaces or in C++ multiple inheritance from abstract base-classes.
  13. amag

    Is dynamic_cast the solution?

    Quote: ...least of all in an extreamly fast object like a bullet that must be near spontaniously generated... Uhm, there seems to be some misconception of the speed of dynamic_cast. dynamic_cast doesn't take seconds to execute if that's what you think. Speed-wise it's perfectly acceptable to use something like dynamic_cast in this case (unless you add maybe thousands of objects every frame (in which case you get other problems with speed)), however from a design point of view, it can be a sign of an incorrectly designed class-hierarchy (as I would argue it is in this case).
  14. amag

    Is dynamic_cast the solution?

    So a Renderable object can't be a Collidable? So you can only collide against objects you cannot see? I would suggest splitting the class-hierarchy. Make Renderable and Collidable abstract base-classes in that they do not derive from any other class. class Renderable { public: virtual ~Renderabel() {} virtual void render() = 0; }; class Collidable { public: virtual ~Collidable() {} virtual void onCollide(Collidable &obj) = 0; // add methods that Collidable requires to correctly handle collisions virtual void setVelocity(const vector3d &v) = 0; }; This way you don't need dynamic_cast, but you need one add(Renderable *) and one add(Collidable *).
  15. Wow, that's a long post...:) (sorry but I didn't have the strength to read through it all). Anyway about game loading. I would suggest an abstract factory for serialisable objects. I also suggest writing your own binary io-stream class (at least I have never got the ones in the std-lib to write anything else than ASCII). class serialisable { public: virtual ~serialisable() {} virtual const char *type() = 0; virtual void read(bin_istream &in) = 0; virtual void write(bin_ostream &out) = 0; }; class turret : public serialisable { int shots_to_fire_; public: virtual const char *type() {return "turret";} virtual void read(bin_istream &in) {in >> shots_to_fire_;} virtual void write(bin_ostrean &out) {out << shots_to_fire_;} }; class quad_rail_gun_turret : public turret { // add data here public: virtual void read(bin_istream &in) {turret::read(in); /*read other data*/} virtual const char *type() {return "quad_rail_gun_turret";} }; For the factory you can use or roll your own. I could post my own bin_*stream classes but I need to access another computer to fetch them. I you want I'll get back to you on that.
  • Advertisement

Important Information

By using, you agree to our community Guidelines, Terms of Use, and Privacy Policy. is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!