• Content count

  • Joined

  • Last visited

Community Reputation

1802 Excellent

About AzureBlaze

  • Rank
    3rd Place - The Week of Awesome 2014

Personal Information

  1. In my opinion by gameplay RTS is the second hardest genre, with MMO being the hardest (harder by several order). So it would probably be better if you forget about the 3D part for a while. If you really want to learn about 3D programming, try make a FPS or TPS instead. RTS has too many stuff to hit your toe with before it can barely become a "game".   Start with a flat, 2D world, model everything as simple circles and rectangles.   Make a tiny circle as your "unit". Make it move around. Make a rectangle wall. Stop the circle from going into that wall. Make other circles. Stop circles from going into each other. Make circles fight. Make circles die. Make a map format so it can contain many walls and probably a basic map editor. Make circle figure out how to get from A to B (pathfinding). Make circle actually go from A to B (steering). Make a lot of circle go from A to B together without traffic jam (boids or other techniques). Make simple AI for circle auto attack, etc. Make UI.   Steps above had took me 4 week solo for a prototype our studio was investigating, and another 2 week for LAN multiplayer. Definitely doable but some of the subjects are hard, especially for beginners.   And you have a full model for your RTS world, then you can try to render it in 3D. Make your tank go up and down, pretending it was following a ramp while it was actually in a 2D world.
  2.     If you do care about performance, you should revert to normal flags. Your linear search through the deque will already be too slow if you check a billion time through a billion flags.   But I guess this is not the case you're going to use it with. For these non performance critical part you should always choose the easier way. Easier to code, understand, maintain, less chance of misusing. Those 2 microseconds you saved from the user's CPU which you're not paying for is not worth a week of debugging hell.   Your method have severe flaw in it: people don't expect normal operators other than assignments or ++/-- to modify their operand. If you write y = x+5, you'll expect only y will change, not x and certainly not 5.   If you write UFlag foo = getFlags(); if(foo & 1){ //... } if(foo & 2){ //... } you are going to run into trouble because the content of foo have changed in the first if statement. You'll have to state clearly in your documents that UFlag can't be used like this and hope people (and yourself) will remember.   Although if you have access to c++11 you can avoid some of the performance penalty by using rvalue reference //this operator is called when the left hand side is an rvalue, which is some temp value that is going to be thrown away. //google rvalue for more details. UFlag &&operator&(const UFlag &rhs) && { //we are not going to use "this" later, so we are free to mess with it to improve performance. this->list.blah(...); //return as an rvalue return move(*this); }
  3. 1. Normally the only operator that will return a reference to itself is an assignment operator like = or +=. The rest should take constant parameters (including "this") and return a new object. "c = a + b" does not alter the content of a or b.   UFlag<T> operator |(const UFlag<T> &b) const   should do the trick.   2. Implement explicit operator bool() const;    
  4. Are you sure it is going to cost you too much performance? My game calls several hundred Lua scripts and a few quite complex ones per tick, and the Lua VM itself have never cause me any performance trouble.   My metric is if some operations happen less then 1 million times per second, then even considering to optimize or not is often not worth it.
  5. I know globals are bad only because people say so, but I didn't fully understand why they are bad, especially the public access part. With your explanation now I know how they are bad for cache coherency.   I still have some questions regarding your engine structure.   Different features might have data the flow through the subsystems in different order, and might go through the same subsystem multiple times. For example, we might need to do several consecutive raycasts that depends on each others result. How do we ensure all the works are done before we finish a single frame? Do we start by raising a update event and loop through all the subsystems until there are no more works queued for this frame?   By batching jobs subsystems will operate on a command pattern. I once used a engine whose rendering system is done like this, but debugging it was quite a headache. With procedural methods, if we received a segfault or other exceptions, all the inputs and callers down until main() is probably still on the stack so it is easier to track where it went wrong. But with a command pattern the information of who gave us this garbage is lost, unless we do some excessive logging. For the footstep example, suppose one of the many sound effects played is wrong, how would you suggest to track down where went wrong?   Thanks a lot!
  6. Why didn't somebody tell me?

    Learned English for more than 20 years but I recently found that:   "Expect" and "Except" are different words, spelled differently.   As a programmer they always come in the same place like "Runtime exception: foo expected after bar", and human brain only identify the first/last character and composition, so I assumed they were the same thing.
  7. This question was kind of derived from the other thread, But since it has degenerated into another singleton war, I guess I'll start a new one.   I'm currently using the "Passing around pointers to anyone interested." method. But since I have a huge set of subsystems, and I don't know who could be interested in what, I wrap all the subsystems as forward declared pointers in a giant context object.   Suppose a feature is one kind of entity will play a footstep sound according to the material it is standing on, syncing with its' animation, this is what I'll do: class Foo :public Entity{ //called every frame, //or maybe a event triggered by animation frame or physics contact... virtual void update(){ if (this.animation.isFootstepFrame()){ //find what we are standing on //don't have to be a raycast, could be contact checking, sensors, etc... Entity ground = this.context.physics.Raycast(this, downward); //Entity have properties as string-string pair string materialName = ground.getProperty("Material"); //lookup the actual material from its' name Material material = this.context.MaterialRegistry.getByName(materialName); string stepSound = material.getStepSound();,this.position); //do other stuffs //a lot of subsystem is involved; this.context.scene.AddEntity(new FootPrint(this.context, this.position); /* FootPrint::FootPrint(...): Entity(context) { this.texture = context.resourceManager.getTexture("footprint.png"); ... } */ this.footStep.RaiseEvent(this); /* somewhere else void OnFooFootStep(Foo *f){ f.context.logger.log("footstep"); } */ } //the script could do a huge variety of stuffs, //possiblely using any subsystems.; } }; This method is working great for me, for now.   I read that context objects are considered anti-pattern, but don't understand why.  Also with all those "contexts" floating around and easily retrievable, I feel it is not a lot better than a global, other than I can have multiple contexts.   Are there better solutions than this "I don't know what you'll need so I'll give you everything"?
  8. Common platformer features can be implemented well with a physics engine, here's mine as an example using Box2D: [media][/media]   I'd admit it's quite a headache to bend a physic engine into the unrealistic nature of a platformer, but this path could be easier if you don't know how to write collision codes or many objects need realistic movements.   For engine selection, I don't think there are any competitors with Box2D. For a platformer you don't need to modify Box2D's source, but you do need a lot of extra code to make it fit the features you want.   Here are some tips:   For "non-floaty" movements, instead of applying force, calculate the impulse to reach the desired speed and then apply it. Don't directly set the speed, you'll get weird results while pushing objects.   For "one wayed platforms", those you can jump on from beneath but won't fall from above, Box2D has a contact listener that will let you disable collision on conditions. You'll need to remember the result for the whole duration of the contact. For example, if the contact began with the character coming from below, disable collision until the contact has ended.   For objects following a path, use a kinematic body. You can set its' position directly, but remember to adjust its' velocity according to the last frame or objects on it won't move with it.   I'm better with physics(majored in mechanical engineering) than physics engine (I don't understand what the hell Box2D is doing internally, and mathematically impaired to check simple collisions), so bending rules with supernatural forces at my command is easier than defining the rules of this new universe. Depending on your ability it could vary, but whichever you chose I think there are people that can help.
  9. inline virtual is a nonsense ?

    It is well named for it's original purpose, pasting code instead of the cost of a function call. That's is IF your compiler respects your decision, and they probably don't. They think they are too good to use your kind advice. Now the only use is to avoid the one definition rule, and it became misleading.   I'm also perfectly fine while using it (C++ is my main language). I just think that teachers/books should alert you it is likely that actual inlining will be done regardless of this. This keyword has almost nothing to do with performance today.   I also googled around for inlining in C#, and they have this [MethodImpl(MethodImplOptions.AggressiveInlining)]. Funny thing is .NET also only regard it as an hint. Compilers this day are all like "write assembly yourself or don't tell me what how I do my job".
  10. inline virtual is a nonsense ?

      It is still a nonsense because we only use it for its' side effect and not the original purpose. It should be something like   allow_duplicated_definition_and_assume_they_are_all_same void foo(){};   Nothing is actually inlined, why call it "inline"? The name only trick people to think it will "optymize" things, waste half a second to type and 7 bytes of precious disk space.   Newer languages don't even need the side effect of inline. Today's compilers are perfectly capable of knowing two definitions means exactly the same thing or not. They also don't use copy-and-paste based include so nothing is duplicated just because every source file must know about some source file.   Although this is the burden of an old language. It kind of surprised me that they decided the original meaning of "auto" is too silly to live in C++ anymore, but I think "inline" was used too much, and we will be stuck with it.
  11. inline virtual is a nonsense ?

    In some sense the "inline" keyword itself is a nonsense.   "inline" only hint the compiler something should be inlined, but does not guarantee the compiler will do so. The compiler could also inline something else without that keyword.   Today's compiler think they are better than you and might completely disregard the keyword. And most of the time they are right.
  12. When you realize how dumb a bug is...

    Once had a bug in my font rendering, a glyph at a certain position was malformed (something like the top-left part pointing out of 'r' is missing), looking like misaligned mesh or some glitch with FreeType. I spent hours digging all the way into the engine code, but still can't figure out what went wrong.   Turns out it was a stain on my monitor.
  13. All Jokes aside, what is 6/2(1+2)?

    Both interpretations are very logical. Proving one right does not prove the other wrong. There are people from all part of the world and in different disciplines, their convention or in this case more of instinction will differ.   The problem is no one has the authority to universally decide which interpretation is "right", it is just a short ASCII string with no context at all. If you are a math teacher you can probably force the interpretation in your class if they want your grade. If you design your own programming language or calculator you can specify how this should be parsed by your grammar. If your are a journal editor you can write a guideline or probably best reject the paper and tell them to get an equation editor. But none of this hold across all field. If International Mathematical Union passed some resolution regarding this, maybe people will respect it, but remember what happened when they say Pluto is not a planet.   Judging from the poll, I would say there is no "now common way of interpreting it". 80% is not common enough. If your project have a simple but important expression that only 80%, or 20% qualified worker that can get it right by instinct, you are going to loss money, lives, and have a bad time.   Conventions regarding these less used subjects evolve very slow because we shun them. Sane usage will produce same result for both interpretation so we normally don't have to debate over it. I think the "more common way of interpreting it" is "Don't do this". Make your expression/program easy to do right and hard to do wrong. I personally add parenthesis whenever in doubt, split complex expressions into smaller steps, and even add a link in the comment to the actual human-readable equation. I've wrote an C++ compiler and don't even remember the operator precedence, I consider those knowledge dangerous to rely upon.   This expression is just like the gold white/black blue dress. People are crazy about it because they think "this is so simple how could you get it WRONG". In the end it was just a badly taken photo.   Your answer is correct, but mine is MORE correct[citation needed].
  14. All Jokes aside, what is 6/2(1+2)?

      Whether it is defined is undefined. Recurse.   Who are you and who am I to define what it should mean?   ISO C++ Standard says it is a syntax error, the program is ill-formed. Maybe they are right?