Jump to content

Rick

Members
  • Posts

    7,936
  • Joined

  • Last visited

Everything posted by Rick

  1. I personally don't like the syntax, and don't care about the next to nothing savings you get, but also sounds like there are some caveats that come with this. 1) The items are not necessarily initialized in the order that they're listed in the initializer list. They're actually initialized in the order in which they're declared in the class. class Foo { vector<int> vec; int count; public: Foo(int val) : count(val * 3), vec(count) // problem because count isn't what you think it is { } }; 2) They can complicate multiple ctors and produce a lot of redundant code. Say you have a class that has 20 members and 5 different ctors (most of which are initialized the same way for every ctor). 3) Sounded like arrays also can't be in there. No need to get upset (the use of "why the hell" would lead me to believe your passion here) as it doesn't affect you in any way. Lots of people use things in which they weren't intended and the world still goes round I was just being honest in that I've been using C++ for 10 years and have never used initializer list. I'm not really heavy into C++ right now as I'm using lua more and to change my habits of 10 years most likely isn't going to happen
  2. Rick

    #include?

    In your main lua game script, you could find all loaded NPC models in the scene and assign them to a generic NPC script. Then you loop through the list of NPC scripts and call it's Update() methods. Not actual code just the idea main lua file -- a table to store all loaded NPC's in the scene npcs = {} loop through all entities in scene looking for "type" "npc" as a variable or model key -- take the model and associate it with your NPC code AddToNPCList(CreateNPC(model, "custom params for this model")) end -- main game loop while true loop npcs -- run npc logic on each npc in the list UpdateNPC(npc) end end You can use Lua OOP to get fancy with the above where each NPC is an "object" and has it's own functions. The main idea is that you are just associating the model with your own shared code. If you weren't to use Lua this is how you/could do it.
  3. I guess I'm a bad boy then because I never do that. Honestly I've never had any issues with not doing that. I've never seen any performance issues to worry about, and never had any strange bugs come up because of it. I feel like I'd need a more solid reason to make me change my ways with this. :/
  4. I don't think I've ever done that before. I always just use pointers Dang, add like 5 or 6 entities and using the ctor like that to init them could get messy.
  5. Generally when you think about the design of a game and the engine you have to use pointers in some fashion. The engine has to be initialized before you can create models. Generally your entities will be in a class and so doing Model model("mymodel.mdl") in the class declaration isn't possible (not sure about the new C++ but I'm talking original C++ if you will) But like Josh said, things can get tricky with his design of graphics driver making the model. He's sort of got a factory design with that, which is fine.
  6. Are there any reasons why DrawText() could take up to 5 seconds to complete? I have a really big project but I've narrowed down that DrawText() was killing my performance, but it didn't before. I'm not sure what I've added to cause this. I know it's the culprit because I put Notify() right before and right after the DrawText function call and the after Notify doesn't popup for 5 seconds after the before Notify. Here is what I find interesting. If I have the below called once at the start of the program DrawText() doesn't take long to be called. It's normal time to call. However, the font that gets drawn is the buffFont and NOT the myFont, which is what I set it to. That's not making any sense to me. myFont = LoadFont("abstract::Comic20") buffFont = LoadFont("abstract::BuffFont") SetFont(myFont) If I comment out buffFont, DrawText goes back to taking 5 seconds and interestingly enough goes back to the default LE font.
  7. This was my problem when trying to simulate Minecraft lighting. The closer you come to blocking yourself in the darker it should get, but the ambient light messes that up. You can't really mess with the ambient lighting because you could potentially still see outside from inside your hole so it would still need to be bright outside, but dark inside. Is there a reason realistic lighting like that isn't out of the box and default in LE?
  8. Oh yeah, I remember having that conversation before.
  9. Model* m = new Model("mymodel.mdl"); Ctors were made for this. The people who weren't comfortable with C++ complained because the above requires pointers. Pointers are part of the power of C++. Interestingly enough the above works in all 3 languages too
  10. Rick

    Collision Decisions

    Bind adds the class function pointer to a list so when you raise the event by calling Raise() (or just () with operator overloading) it can loop through this list and call all the class functions that were added. These can be from all different classes as long as the method signatures match. This allows you to chain together events. You call Raise on an event once and it can end up calling 10+ different class methods. It's how you get different classes to talk to each other without having to know about each other (you don't have to store a pointer of class A inside class B so it can query the object every cycle to find what changed). This is one of those things where I tell someone to understand it is hard but to use it is easy. Ask a mechanic to describe every piece inside an alternator and they probably can't do it. Ask them to use it and they can. Note that below is the outfacing class the user would use (the engine really the user wouldn't need to define one just call Bind) like Event2<x, y>, but it has supporter functions that I linked to in my previous post. You can see this class stores a list 'mCaller', and Bind simply adds to this list, and Raise simply loops through the list calling the functions. template<class T1, class T2> class Event2 { public: list<TFunctor2<T1, T2>* > mCaller; template<class Target> Event2(Target* t, void (Target::*fnPtr)(T1, T2)) { mCaller.push_back(new TSpecificFunctor2<Target, T1, T2>(t,fnPtr)); } Event2(){} template<class Target> void Bind(Target* t, void (Target::*fnPtr)(T1, T2)) { mCaller.push_back(new TSpecificFunctor2<Target, T1, T2>(t,fnPtr)); } void Raise(T1 V1, T2 V2) { list<TFunctor2<T1, T2>*>::reverse_iterator iter; for (iter = mCaller.rbegin(); iter!= mCaller.rend(); iter++) { (*iter)->Call(V1, V2); } } void Clear() { mCaller.clear(); } };
  11. Rick

    Collision Decisions

    @Josh, I'd say that works and is similar to what I have to do in LE2 today to get the same functionality. I'd venture to say it's not as pretty as the event way but I understand why you wouldn't go that route just yet I promise you if you would take the time to read and understand that event code and think about all the uses you'd never go back and you'd use it in so many places Chaining events together is such a cool and powerful ability that really lets you separate your code but still have them linked. It also removes a good number of polling mechanics which generally makes your game faster because you aren't wasting time polling for things that aren't happening. class Actor { private: void _TakeDamage(int value) { } public: Player() { // we link the actor method to this event so it will be notified when it's called TakeDamage.Bind(this, &Actor::_TakeDamage); } Event1<int> TakeDamage; }; class HUD { public: void UpdateDamage(int dmg) { } }; class Game { Actor* player = new Player(); HUD* hud = new HUD(); Game() { // you would setup your interactions between objects when your game initializes, which means you don't have // to go hunting for object interactions. they are all done right up front. with dynamic objects you can // still set those up when the object is created (bullets for example) player->TakeDamage.Bind(hud, hud->UpdateDamage); } }; // when your enemy hits the player you would call player.TakeDamage(15); this uses operator overloading to make TakeDamage look like a function when it's really a variable. same as: TakeDamage.Raise(15) When the above is called it'll actually fire 2 class methods. the one in Actor and the one in HUD. now the player can take damage in many different ways but you don't have to remember to deal with the HUD in each of those situations because you've created this one time link right at the start Again, I don't expect you to adapt this but just giving you something to think about if you wish. Another way of looking at a problem.
  12. The game GUI/HUD doesn't though does it? Thinking of CS when I played that and I'm pretty sure the HUD where you pick your weapon slots scales. Now you may be trying to separate in game GUI's from menu GUI's but I don't think doing that would be right.
  13. Screen resolution always seems to be an issue if you don't do that. GUI's generally scale with screen res in games so that's something that'll need to be addressed. They aren't "hardcoded" for the supported game resolutions. Taking windowed games into account where you can resize the window shows this.
  14. Rick

    Collision Decisions

    That quote out of context. The sentence before flows into the sentence you quoted. You are correct but that's not the way you have it above. You had MyEntity* entity;. You wouldn't do that because you'd have 20 different classes like MyEntity*. Instead you would do Entity* entity (using the engine's base class), which is what you are saying, but not what you typed above. That aside I see where you are coming from with things being automatically loaded. This is generally why virtual methods are limiting and I like using the slot/signal design. Ideally your model class would expose a public event (variable) called OnCollision that my class that I put the model instance in can subscribe to. When the engine calls the model class OnCollision it's really firing all the methods I've chained to it. This is a little different and I'm sure you won't use it as I'm sure you don't feel comfortable with it, but it works like a charm and can fit into C# & Lua. I've posed that code to do it in C++ a bunch of times on the forums. I didn't create it, but someone showed me the code a long time ago and it has so many uses and is very flexible and is standard C++. http://www.leadwerks.com/werkspace/topic/4032-raknet-in-leadwerks-tutorial-files/page__p__35748__hl__events__fromsearch__1#entry35748 To describe it in Lua terms it would be like your Model class has a table that stores functions. Any other object can add it's own function to that table. Then your Model class loops through every entry in that table and calls each function. In Lua it's even more flexible because the function signatures can have variable parameters. In C++ the function signature has to be static (the same, not static keyword) but that's fine because it would be anyway in the OnCollision situation. To me this solves the "problem" you'll have by being heavy OO in the engine design and then having a standard C callback method for collisions. Guessing people will think that a little odd. Also if you stick with a C callback are you still having user data functionality because below is generally what I do, but I have to screw around with storing the pointer to the class (this) as user data to the entity so that in the C collision function I can extract it so I can call it's Collision function. Honestly if you leave the user data stuff in I'm cool because I can still do that. If you take it out it'll become harder to do what I need to do in that C callback and that'll suck. Usage: class BigBossMan { private: Model* _mdl; void mdl_OnCollision(Model* mdl) { } public: BigBossMan(Model mdl) { _mdl = mdl; // hook the models collision event to this classes function _mdl.OnCollision.Bind(this, &BigBossMan::mdl_OnCollision); } }; Now you handle collisions normally in the engine. When this _mdl variable has a collision with it you call it's OnCollision event behind the scenes and that will loop through all the methods hooked to it and call them. From the users perspective this is nice and clean. The collision logic for BigBossMan happen in the BigBossMan class and not some global collision function that you might have to go searching through 100 files to find. The "cool" thing is that inside this event class you can accept both class methods or standard C methods. You would just overload the Bind() method to accept both styles and then store 2 separate lists. When calling loop through both lists. This is nice because it allows the user to pick how they want to bind to events of the model. Honestly this would be sweet if every callback that is entity specific would be setup this way. Would be sweet if this was how you handled GUI events too
  15. Make it a singleton. The difference will be I can store a variable for L3D but it always gets the one same instance when I request it. "Does a single class for global functions look totally weird to you, or does it make sense?" It takes sense to me. "Have you seen this done before, and can you provide any examples?" Not where the entire library is setup like this. If you were starting from scratch you would do your same C++ design and so does everyone else, but via a DLL you don't have all that many options. "What would you call this class in which global functions are kept?" L3D looks good to me. Remembering different class names will be a pain. Typing L3D. and seeing the intellisense kick is in ideal.
  16. Yes, let's get some artists making GUI components to see what kind of cool stuff they can make! When you see things like winamp skins it makes you think that's the way game GUI's should be setup.
  17. Rick

    Collision Decisions

    I'm not saying I have the answers. I've been out of C++ for a couple months now and using only Lua for my game so kind of rusty, but. Instead of what you have you would do: Model* entity = new EvilBadGuy(); // note that I use Model for the variable type entity->Load("evil.bad.guy.mdl"); Where MyEntity is derived from Model. Now the entity variable is of type Model AND MyEntity. But more importantly you can now pass the entity variable to any function that takes a Model pointer like a collision function and like all the functions in your engine that are just of type Model. The entity variable can then be cast to MyEntity by the user inside their function if they so need, but that would be up to the user. I guess I don't know about the ModelGenerator thing you have above. Not sure what that's all about and how it relates to limbs. There shouldn't be too many reasons to ever store your models as a type that you derived from (ie. the left side of the variable declaration). You can't store them in a list which will almost always be what you want to do. The whole point in assigning it as the base class you derived from is so you can store it in 1 list, pass it around to common methods. Then the reason for deriving is to override the virtual methods and give custom behavior to them. If you ever need to query the data or call the methods in the child class then you cast it. "static_cast can perform conversions between pointers to related classes, not only from the derived class to its base, but also from a base class to its derived. " This is what we would use inside the Collision method if we needed more information about the model we collided with that we stored inside our derived model and isn't part of the base engine model.
  18. Rick

    Collision Decisions

    Just curious as to why you couldn't do something like: // engine class class Entity { public: virtual void OnCollision(Entity* e) { } }; // my class class MyEntity : public Entity { public: virtual void OnCollision(Entity* e) { // now I can handle collision with this object } };
  19. Rick

    Collision Decisions

    gamecreator brings up a good point. I like collision callbacks personally but it can require more thought & design (a different way of thinking) than inline checking for collisions. One would probably want LE3D to let the developer design which collision method they wish to use.
  20. I got this working. My last post shows what the issue was. Josh is using LuaJIT and I was using pure Lua. There are slight differences in the lua_State variable between the 2 so mixing them doesn't work.
  21. My bad. Saw the imagine which to me resembled LE Editor more than 3DWS, and skimmed the message. Carry on.
  22. Do you have any lua code running with this? Something might be going crazy with that.
  23. I use Paint.NET (free) to convert my images do DDS.
  24. guess I ask because I primarily use these for animations which requires ms. I use it for other stuff as well and being in ms let's me use it for more precise timing in ms or less precise timing in seconds. It's more flexible I find. I don't use the fmod() way in the tutorials to do animations. I just find it easier to work with timers to increase the frames myself.
  25. Is that returning ms for you? Looking http://lua-users.org/wiki/OsLibraryTutorial it looks like it's in seconds. Not sure if you require ms accuracy or not, but in mine I multiply os.clock by 1000 to get ms and then I just subtract that the values to get the difference in ms.
×
×
  • Create New...