Xai

Members
  • Content count

    2822
  • Joined

  • Last visited

Community Reputation

1850 Excellent

About Xai

  • Rank
    Contributor

Personal Information

  • Interests
    Programming
  1. Personally, I would not test methods like this via unit tests ... because it is not a "contract" you are going to be committing to memory and counting on as you work through other areas of code. But there is a strategy for testing this kind of thing that is very easy ... and it is good for other cases that do define contracts that matter more. You would create a "mock"/test object of the input manager, and your mock version would do something like verify that each method was called once during the test, or even that they were called in order ... the methods wouldn't DO anything real in the mock object, they'd just track the calls.
  2. Control flow based on type in C++

    As for optimizing out the NxN performance issue of testing every object against every object even though most can't hit each other. This would be a case of maintaining more tightly controlled lists of objects for your business at hand. A universal "full game object database" collection is great for making saving/loading easy (although it isn't really suited for that, because you really want 2 lists the "static/level" objects and the dynamic/active objects ... because then a save is just a reference to a level, and then the dynamic objects. But I digress. For your purpose, depending on the game, you might have lists such as "map objects" and "autonomous objects" if your game rules were such that you only needed to check the list of autonomous objects vs the list of autonomous and map objects. This way you'd check 3 vs 200, not 200 vs 200 ... or whatever. Other optimizations exist as well, such as spatial partitions, or even simply sorted lists by each dimension (for cases where more objects move very little each frame)
  3. Control flow based on type in C++

    So a "decision based on static c++ type" is not a strategy you need to be using anywhere in your code. If it did, this would probably be better served by polymorphism via virtual functions ... but whatever. A decision based on a logical/abstract/property representing a "type" within your game system ... makes tons of sense. This is cases where you have a "collidable object" class or interface or whatever. And it has a type, like "simple rect", "simple circle", or "complex polygon" as its 3 supported collision detection types. then each object's 1 colliadable object has a "detection type" property, and an appropriate associated data info object to match. Yes this is just like the feature of RTTI, but it is a DATA or OBJECT CONSTRUCTION truth, not a code truth. You are free to use inheritance, containment, interface, delegation or any and all other programming strategies to implement this feature - and interestingly, all of them would likely be clearer and/or faster than C++'s RTTI feature ... while giving you more flexibility too.
  4. Is there a way to combine 2 methods?

    There is probably a way, but upon first glance at the Unity API it doesn't seem that the primary click handler "onClick" will allow for this because it does not pass any parameters at all. All other UI control libraries that I've every used allowed this, because they passed a "sender" object in the click method - which would allow you to determine which control raised the click event. But I don't see the equivalent in the Unity API docs upon initial glance. I'm probably missing something and may dig in deeper when I have a chance to open the unity editor later. Good luck.
  5. ok, importantly, you never move boxes (aka memory), you copy values into them, read values from them, etc. So let me give you a script for a comptuer: 1. create a pointer to an integer on the stack (aka declare a local variable for type int*), call this variable "current ptr". We'll assume this is at address 0x200, and the current value stored in it is "undefined" ... int *current_ptr; 2. create a new array of 10 integers, and store the address of the start of this array in the variable called "current ptr". We'll assume the array was allocated on the heap starting at memory location 0x300 and running through 0x327. So now the box at 0x200, has the value 0x300 stored in it. So if you read the value of current_ptr, it is 0x300. But if you read the value POINTED TO by current_ptr, you would get an undefined value. current_ptr = new int[10]; 3. initialize the values of each array element to its index. So now the values at 0x300, 0x304, 0x308 ... are 0, 1, 2 respectively. But the value stored in 0x200 is still 0x300 for(int i=0; i<10; i++) current_ptr = i; 4. Change current pointer to point to the item whose value is 5. So now the value/address 0x314 would be stored in current pointer (aka in the box at 0x200. while(*current_ptr < 5) current_ptr++; NOTE - now that we changes current_ptr and didn't remember the start of the address anywhere, we have a little problem .. we've "lost" the first 5 elements of the array. They are still there at 0x300-0x313 ... but our program no longer knows that. It just has an integer pointer pointed to 0x314 (the middle of the array) ... if we write the following: for(int i=0; i<10; i++) printf("%i", current_ptr); it would print: 5 6 7 8 9 and then it would crash because current_ptr[5] is the address 0x328, 1 byte past the end of the original array of 10 integers we allocated. Basically, we've gone too far - opps! So "numeric variables" are just boxes of memory. "pointers" are also just boxes of memory. The value in a numeric variable is just a number stored in memory, the value in a pointer variable is just a number stored in memory. The difference is in how we USE the value. If the number 20 is stored in an integer, the computer will support operations like x+x which would be 20+20 => 40. If the number 20 were stored in an integer pointer, it is still the same bit pattern 10100, but the computer will support operations like *x which means use the number stored in x (20) as the address of ANOTHER number ... go to that address and get the value there - so *x + *x means ... go get the number value pointed to by x .. and add it to itself ... so whatever number is stored in the bytes in memory at address 20-23 would be read and used (or if we didn't allocate that memory, we would get a memory access violation exception and our program would crash)
  6. most people think of memory as boxes that can hold something. If you picture a 32 bit integer (4 bytes) as a long skinny box, big enough to write a big number in, that support dry erase markers. so write now you have 2 long skinny dry erase boards on them, the first has 15 written on it, and the second one has 30 written on it. the "compiler" knows the first one (called x) is the one on the left (also know as address 0x123456) and the one called y is the one on the right (at address 0x654321). Now a pointer, is also just another number, so in a language like C++ I could have another variable, we'll call it "current pointer" that i write the number 0x123456 into ... this means, the current pointer has a number in it, which happens to be the same number as the address of the box on the left. The better analogy for this is a phone number. Get 2 friends to be those numbers, tell your first friend (mary) to remember the number 15, and your second friend (tom) to remember the number 30. Then write the phone number of mary on your board. If your mom (the program) tries to "look up" the value pointed to by current pointer (look in the box at address 0x123456 or in this case, call mary and ask her for the number she's remembering) then she/it will get the number 15. If the program is supposed to multiple that number by 3 and save it back into the same variable it will store 45 back into the box (tell mary to remember 45 instead of 15), Now an "object" is more like a custom designed box, with more than 1 slot in it, each made to hold a certain thing. So a 2D point object is a box with 2 slots in it, each of which can hold a number. In real computer terms this is just a "map" of how to interpret a set of contiguous memory. So in your example of a class with a Name and Age, it is a map that says, if the object starts at a certain address, then the first thing at that address will be a pointer to a string that shall be referenced as the Name property, and the second thing after that shall be an integer that shall be referenced as the Age property. Lets assume that all objects in Java use 4 bytes for their "vtable" pointer (i'm not going into that right now), and then they use additional bytes for every property they have. In this case then, when you call "a objectreference = new a();", you have allocated 12 bytes of memory, the first 4 bytes (offset 0-3) are a vtable pointer, (offest 4-7) are a string pointer, and (offset 8-11) are an integer. If you allocate an array of 100 objects of type a, then you will have created 1200 bytes of objects in memory, the pattern would repeat every 12 bytes. So if the array started at address 0x800, then at 0x808 would be the first object's age, and at 0x814, 0x820, 0x82C, etc ... would be the age property of the second, third and 4th object. A type is kinda like a stencil, that tells the compiler how to look at/interpret a section of memory. The computer doesn't know much special about what things in memory mean, so if they are told wrong, they just blindly try to do the wrong thing. So if someone the compiler allocated the array of 100 objects are 0x800, but say it got corrupted and accidentally thought the array started at 0x804. Then when it went trying to read the Age property of the first object (which is actually at 0x808) it would erroneously get whatever is in the vtable of the second object (0x804 + 8 byte offset = 0x80C which really the start of the second object) ... so the computer would just start doing stupid stuff, and eventually crash.
  7. When first starting ... you can't help but let your ideas run away with you ... that's ok However, you should learn to separate "possible cool idea sessions" from "design sessions for my current project". You're current project should be something you can do in 1-100 days of work ... and your next project can be a totally different code base / game / direction ... or it can simply be the next iteration of the same code base / game. So an example might be like this: * project 1 - get a character able to move around on a map via user input, fight single type of monster, pick up items (perhaps health drops from the monster) and complete the game by defeating 3 of the monsters at once NOTICE how even that tiny project is really like 5 subprojects: getting a character moving via input, loading a map and supporting "scroll" or "screens", monster and combat logic, pickup/healing, game completion (aka quest completion detection) the project 2 could be another set of 3-8 notable improvement that would make take the game to the next level ... and after 3-5 iterations of project, each doing 3-10 meaningful additions to your game and or feature set, you'd have yourself a really nice little personal game project. (and depending on you and your pace this might be 6 months in the future, or 3 years in the future ... but it would however far and however long was appropriate for you based on how much time you wanted to invest, how driven you were, how much fun you were having, etc) And all along the way, at least every few weeks or months you'd have stuff you could show (to your friends, classmates, future team members, etc). And the whole time, you'd also formulate and think through hundreds of cool ideas for games you could build. And no, you won't build most of those, or maybe any of them, but those ideas will serve you well if the time ever comes where you are in a position to make an actual mid to large scale game with a team.
  8. I think I'm confused all of the sudden. So to set my starting point out explicitly to see if I am missing something, here's a specific randomly imagined set of game components. The entities are of course completely dumb "objects" that exist only to do the following - have an ID, have a totally generic list of components, and perhaps have a list of entities (unless possession of child entities is a component itself - but my purpose I'll assume I didn't implement it that way), and also of course to be serviceable/savable. The following component / behavior interfaces may have been create: Location (includes position and orientation), Inertia (includes mass & vector), Goals (needs, wants, personality info), Status (Health & Other Similar State), Senses (a base component for subtypes like: Sight (parameters about observing the world visually - aka ), Hearing (parameters about observing the world, etc), Controller (a base component with multiple subtypes like: CommandController (support for accepting commands as triggers to action), InputController (support for mapping input to commands), ScriptController (support for attaching 1 or more behavioral scripts)), Metabolism (a component to manage tracking actions taking "energy", and time or materials restoring it - simplified). Now it should be easy enough to see, that in any complex object graphs, for instance things like War Wagons or Tanks. There will be multiple non-trivial relationships between specific subsystems and their parent parent systems. And these things aren't just wired up by "find the COMPONENT_TYPE of my PARENT/CHILD and use it" These are EXPLICIT relationships. The left tank tread has relationships to the 4 wheels on the left side of the tank, which in turn connect to 1 or more drive shaft, which is the same drive shaft as connected to the right side. So the whole point of ECS in my mind is that the game ENGINE as a whole operates by walking the tree in appropriate ways to do universal things to EVERY SINGLE COMPONENT of the appropriate TYPE/INTERFACE. However, no aspect of the actual objects works that same way, but instead would be specific relationship based. More specific example. The game engine would loop through/process all controllers, giving them a chance to act. The game engine would process all Inertia, updating locations. The game engine would process all metabolism, etc, etc etc. But the internal code of the individual component, IE the code controller the Tank Engine's "metabolism" (in this case gas consumption) doesn't have code like "this.Entity.GetComponent<GasTank>.Consume(this.CurrentBurnRate)" but instead has code more like "this.CurrentFuelTank.Consume(this.CurrentBurnRate". Of course I'm not showing code for checking if there isn't enough fuel, triggering reactions to any problems, etc. I'm just showing the idea that the components have DIRECT EXPLICIT RELATIONSHIP to any other entity or component instances they use. If we had the rule that an entity could only have 1 component max for each interface, we could change the relationship to components pointing to entities only, instead of some of these relationships being to entities and some being to components - which might be better in some ways (I'll have to think deeper about that part later) ... but either way, the key is that most lookup from 1 place in a an object graph to another are not based on type but base on relationship.
  9. I don't believe using advanced engines to make games, and learning to program as a programmer have anything to do with each other. If you think of each of these as skills in an RPG called "technology career simulator 2017" you would see that having a "designing games" gives a small bonus to checks of the "designing computer games" skill (full bonus for simple indie games, half bonus for FPS/Sports style games) ... and "basic programming and hacking" is a prerequisite for "advanced programming and design" and so is "computer science and programming theory", but the skill "game modding / level design" doesn't require any of those (it does get bonuses from programming and hacking though) ... and "3D game development (using engine)" gets full bonuses from any programming or hacking or modding or asset skills ... but doesn't require any of them. So what I'm saying ... in a long winded way ... is that these are 2 separate parallel things, that don't form the foundation of each other at all ... but skills in either will somewhat help you in the other, only because they each kind of help you with different aspects of "the big picture" ... a required skill if you want to do things 20 years down the road like "game engine architect" or "lead game producer" (maybe) If you wanted to do a career in music, learning to play guitar/drums/piano wouldn't be directly preferred skills before learning to use sequencing software, be a sound technician, or DJ. nor the other way around. BUT, if you had learned any of those, it would give you a starting point/frame of reference to make learning the other side less like starting from nothing (more of the terms and concepts would feel familiar than when you had done nothing in the field at all).
  10. New game prototype: R.O.W

    I just want to second the idea of not worrying about "market interest" unless your goal is to make money. What you should focus on are 2 questions really. 1. Is there a market (however small) that would like to find your "game" and play it? If so it is worth making. 2. What can you do so that those people will find your game and give it a try. (this is basically a question of presentation and marketing). A math game in the middle of the app store will probably not even get shown. But the same math game when linked to from a "learning algebra" site would probably garner some interest.
  11. getting involved in game development

    Lucas, he cannot read the unreal engine as a means to try to start writing a game engine? or at least not if he plans to make a commercial game engine for money ... read the license, you will see they give you no rights to use the code to compete with them selling any form of engine derived from their work - only games using and tied to their work. He can only look at academic items and projects which do not have such restrictive commercial licenses. But yes, he should look at existing engines and the few books that exist about them. Also, you can read "books" and tutorials on unreal engine, unity engine, etc ... without caring about their copy write, but you cannot reference their actual code in the process of creating your own engine. OP - What type of game engines do you want to make? physical simulations (realistic), space/flight sims, shooter style games, 2d arcade games, RTS games, etc. The engines of these games actual differs quite a bit (although much less than it did 10 years ago thanks to more general engine advances). I would however kind of agree with Lucas in that you should use existing engines before thinking to write your own (first of all because you may find you'd rather make games than engines anyway - secondly because you can't really know how to provide tools to a carpenter if you don't understand carpentry ... so you can't write game engines if you don't understand game writing at some level - just like you can't compose music if you don't understand how it may be performed - that doesn't mean you need to be good at making games, just some level of basic experience to inform your direction). Also, when i say "use" a game engine, I mean as a consumer of the engine and its tools ... not its source code.
  12. I love C++, I like C#, I like ruby ... but I recommend you don't start with C++ as your first programming langauge. Start with python, Javascript, C#, ruby, lua or C. Each of those has a strong reason to be good for starting. some because they are very easy to start with, some because they quickly become powerful and some because they teach the basics well and let you get more advanced later. Python with Pygame is my recommendation for you to try for 3-6 months. If you aren't liking it in that time frame ... try a different approach (python has a very different feel than many programming languages, some people love it, some people hate it ... if it doesn't fit you, just try a C syntax langauge next: Javascript, C#, C, whatever. Install Notepad++ for light simple text editing, but also download a lightweight python IDE (use google), install Paint.Net or GIMP for editing sprites. And make your very first programs VERY VERY SIMPLE ... like 1-3 things only ... here are some examples for startiing: a. write a rock / paper / scissors program ... cause that requires you to get input from the user, have the computer pick a random choice, and solve and display the results. Then make it were you can play until you want to quit. This is the kind of program you would learn to write in your very first programming class. b. write a "screensaver" type program, something that just fills up the UI with something like random colored lines, or circles, etc. c. write the game of "pong" or even 1 player pong (no computer opponent) - just have a ball bouncing around and you try to hit it with the paddle. this is a great code base to have, cause you grow it as long as you want (more speeds, computer opponents, better bounce logic, 2 player mode, etc.) and it needs super simple collision detection and physics, both of which are used in almost every game ever.
  13. C++ Overloading Question

    This C++ coding style guideline is NOT about readability. Not if you mean making people THINK they like reading the code. This is about true readability, accuracy, debug-ability. The overload based version reads easier ... you don't think about the function as 2 functions, and you don't have to think about the type. However, these methods are actually 2 different lookups, semantically, so they should have 2 different names - If I converted the int 5 to the string "5" and called the method, it would NOT return the animation with the index 5, but instead of return a null pointer because there is no animation with the NAME "5". As C++ has evolved with all sorts of anonymous and auto typing, this kind of thing would be almost 100% invisible to a reader and even tough for a debugger. There is nothing wrong with overloads like in the math library: float sqrt(float) double sqrt(double) because they are semantically identical. Never mix (basic) TYPE selection with semantic selection. There are reasons to violate every "rule". But in general only violate rules like this in methods are only FOR violating this rule. in other words a method with overloads that change the behavior based on the type of the input, should ONLY be a facade for selecting different behaviors based on type
  14. languages like c# handle property / data member and type names being the same extremely well (cause they have a simpler parser), while c++ has more trouble with ambiguity partially just because there are so many cases the programmer can't guess which of an identically named concept will be the one selected in all of the various cases that can arise. So for that reason alone, I typically stick with using 2 different naming convention in c++, 1 for types and another 1 for methods and data objects (in my case PascalCase for types, and camelCase for method/data members) .. however all_lower_with_underscores would work just as we for whichever case you prefer, as long as you have 2 total naming conventions to use, all likely c++ cases can be unambiguous enough. As for interfaces, I usually use ITexture, etc. Because it works well with PascalCase ... however in 1 code base I just left it off ... so that my base interfaces just took the core name ... ie: Texture, GameObject, DrawBatch, etc. And in this code base when I had single implementations for the interface I just used warts usually picking either "GeneralXXX"/"StandardXXX" or "SimpleXXX" depending on the case. Also I try to follow the convention that abstract base classes have the word Base at the end "XXXBase" etc. But ONLY abstract classes, not non-abstract base classes. So you can see the 1 thing this makes me do is for certain cases where I could have an interface, and a non-abstract base class (ie in C# terms an IGameObject interface and a GameObject base classes that all game objects would inheirit) ... then I am in trouble. But I honestly considered this a good thing, becuase doing both of those things is almost a sort of design flaw in itself. You should either do you contract as a contract only requirement (GameObject is an interface) or as a requirement that includes some implementation (GameObject is a base class) ... but you really shouldn't do both.
  15. Rutin's answer is how Bethesda handles this with the fallout and skyrim engines ... just loot at: http://www.ign.com/wikis/fallout-3/Item_Codes for an example. Everything's "item id" is just a 32 bit integer, which they write as 8 HEX digits (0-9 or A-F) so that you can recognize they are a game id at a glance.