• Content count

  • Joined

  • Last visited

Community Reputation

1168 Excellent

About DekuTree64

  • Rank
    Advanced Member
  1. Fast Approximation to memcpy()

    On ARM CPUs, stmia and ldmia are usually better than single load/store instructions. Especially for memset, you can fill 8 registers with the value and write 32 bytes per instruction :) Or unroll it to 32 stmia instructions and get a whole KB per iteration. But dealing with unaligned addresses/non-multiple-of-32 size is a pain.   Mostly I'd be looking at why you're copying so much data around every frame in the first place.
  2. 1. If you're passing the same ResourceManager to everything everywhere, then you may as well just make it a global. Singleton is just a fancy name for a global to try and make it sound less evil. You could even go C style and interact with it strictly via global functions rather than OOP style.   2. Don't pass App to the NetworkManager, pass whatever members of App that the function actually needs to interact with. Or in some cases it's better to use a pass-by-value approach, where the NetworkManager function takes some arguments and/or returns a value, and App handles the job of fetching the arguments from its members and feeding the return value to whatever member needs it.   3. I think the GameState thing is good as-is. It's ok if changing the App state involves more than just creating a new GameState object.
  3. CTM * ScaleMatrix will get one result, ScaleMatrix * CTM will get another. One will be applying the scale "inside" the coordinate system defined by CTM, the other will scale around the world axes. I'm not sure which is which offhand, but I'm pretty sure "inside" is what you want. Then a Y scale matrix will scale the local Y axis, so it will have the same effect whether it's done before or after a rotation.   Something that took me a long time to notice is that a row-major rotate/scale matrix is really just an array of axis vectors. In 3D, with a 3x3 matrix, the first 3 elements are the X axis (1,0,0 in an identity matrix), middle 3 are the Y axis (0,1,0 identity), and last 3 are the Z axis (0,0,1). After rotating, those axis vectors will be pointing in different directions, but they'll still be orthogonal to eachother. And the length of each axis vector is the scale for that axis. Instead of applying a Y scale matrix, you could cheat and simply multiply the middle 3 elements by the Y scale you want :)   In 2D, the first 2 elements are the X axis (1,0) and the second two are the Y axis (0,1), and the same rules apply. It's actually simpler, but a bit harder to see the beauty of it in 2D, at least for me.
  4. Coding-Style Poll

    I'm nowhere near as picky as I used to be.   Usually I use braces and member variable/function names like this: if (mPosition.y < 0) {     doSomething(); } Except I prefer not to use braces on single line if statements. Not terribly annoying, but I do think it hurts readability a bit.   One exception I make to my normal bracing style is in switch statements. Normally I don't like to use braces around cases, but if I need a variable, then I do it like this: switch (something) { case 0:     qwer();     break; case 1: {     int a = 0;     asdf(a);     } break; case 2:     zxcv();     break; } Not only does it save two lines, it keeps the indentation level the same without looking as funky as it does if the braces are on their own lines. But again, I could easily give it up if it went against a project's style standard.   I like the m prefix to differentiate member variables from local variables/function arguments, so it's more clear where the side effects are. And I think it looks nicer than m_ and is slightly faster to type.   Classes, structs and global functions are all upper camel case with no prefixes. I would be slightly annoyed if I had to use the C prefix for classes.   Global variables are prefixed with g, constants prefixed with k, enum values with e. I could easily be talked out of any of those, although I do think global variables should have something to mark them as the necessary evils that they are ;)   Long ago, I used Hungarian prefixes on variable names, but I hate them nowadays.   One thing that really bothers me is excessive use of single-letter variable names. It's ok for x, y, z, one or two loop iterators, and stuff like that. But it can quickly turn unreadable if you have a big equation with lots of them. That's why I like programming better than math/physics :) Use meaningful names so you don't have to memorize what each variable is. Long names are ok, especially on things that aren't used very often.   I like spaces around operators so equations don't get too crowded looking. I'd be pretty annoyed without them.   I don't have much preference on spaces around the parentheses of if statements/loops/etc., but I usually do them like the examples above.   Tabs and spaces have plenty of potential drama. Especially if someone uses a different tab size than everyone else, and makes a big table where everything is aligned with tabs. I have a bit of OCD to make my code tab-independent, where I use tabs only at the beginning of lines, and then use spaces between tokens to align things. So even if you change the tab size, it just shifts the whole block left or right but the alignment remains correct.
  5. The IDE doesn't really matter. C++ is more or less the same whichever one you use. Just need to figure out where it is that you type in libraries to link, like sdl.dll if you're using SDL.   Don't worry too much about OOP. It's a good approach for a lot of things, but not the be-all-end-all of programming. Most likely you'll end up inventing it yourself when you need it :)   Regardless of which API you use, the basic approach to realtime programming is to use a function that returns a real time value, such as the WinAPI function GetTickCount(). It continually counts up in milliseconds, so if you want to run at 30 frames per second, do something like this: int lastTick = GetTickCount(); while(1) {     int thisTick = GetTickCount();     if (thisTick - lastTick >= 1000/30)     {         lastTick = thisTick;         UpdateFrame();     } } And I would recommend running at fixed frame rate. Variable frame rate is a pain, and not particularly beneficial for most 2D games.   The basic idea of graphics is that the screen is a huge array of pixels, and each pixel is a number representing its color. Every frame, you update character positions and such based on player input and enemy AI, and then copy all the background and sprite images to the screen at their updated positions. Draw the background first, and then the sprites, so they'll overwrite part of the background. Sprites are actually rectangles, but can look like any shape by using a color key (when copying pixels from the sprite image to the screen, check if the pixel is the transparent color, and if so, skip copying it).   Library code often handles all the pixel copying for you, but if you like a barebones approach where you do it all yourself, then SDL is the best. I like to allocate my own chunk of memory to use as the screen (32 bit pixels), and blit 8 bit paletted images to that using my own code. Then when the frame is done, lock the SDL screen surface and copy my screen buffer to it.
  6. To do interpolation instead of extrapolation, when you read the input state, timestamp it in the future by a constant amount (probably one frame's time). Then the current time will be between the previous input state and the most recent state. Or more specifically, if t is between 0.0 and 1.0, you get interpolation, and greater than 1.0 becomes extrapolation.   That approach is called lockstep, and only works on fast local networks like between handheld game systems. I have worked on games that used it to run at 30fps in perfect synchronization with no added latency (and therefore no need for any prediction or interpolation), but it is very tricky making sure that everything (including the main random number generator) gets called identically on all systems. And I'm not sure I'd ever trust floating point to come out exactly the same unless you can ensure that both CPUs are exactly the same model. Fixed-point is entirely predictable, though. But for PC games, and especially over the internet, you'll have to use a packet system to inform players about events, and use prediction while you wait. And when you do receive a packet, setting the position immediately could make things jumpy, so it may be better to interpolate between the old predicted position and new predicted position so it looks smooth even if it's less accurate.   I've never actually done internet multiplayer, but you'll probably need to declare one player to be the boss, who resolves conflicts between events if necessary.   Approach #1: When you shoot at someone, you can check if you hit your target at its visible position on the local machine, and if so, send out a packet to everyone else saying "hey, I just shot Doofus in the arm", and everyone including Doofus will accept that as fact, even if he had actually rounded a corner before the shot was fired.   Approach #2: Send a packet to Doofus saying "hey, I shot you", and if he agrees that it was plausible for him to be shot, he sends out a packet to everyone saying "that guy just shot me". That gives Doofus an opportunity to modify the event, if he was actually past the corner a significant amount of time before the shot was fired, or if he'd done some special move to block the shot.   Approach #3: Send a packet to boss saying "I just shot Doofus", and if boss agrees, then he sends out a packet to everyone.   In the first two approaches, you can end up with conflicts, like if two players believe they picked up the same item. The third approach allows the boss to resolve that before it happens. Alternatively you could do one of the first approaches, but have the boss check for conflicts among all the information he receives and send out corrections to everyone when necessary. But it's also wise to think in terms of what is the most fun. If it doesn't cause any problems, you could just let both players have the item.
  7. First of all with this kind of thing, you need to iron out the details of how it should behave. Is it possible for game code to request data to be displayed on one of the panels while it's already open? Should it queue and wait for a button press, or automatically slide out and slide in with the new text, or instantly redraw without sliding out and in? What if there's a blue panel request while the orange panel is open? Is the blue panel simply ignored and never displayed, or queued so it will slide in after the orange panel is dismissed? And how should the popup window behave?   I agree with the others that you need a manager object. Something that owns the overlay and all the panels. Game code sends panel requests to the manager, and it coordinates their behavior. Then you don't need a refcount on the overlay. Just a logical OR of all panels' visibility. If they're all hidden offscreen, then disable the overlay, otherwise enable it. If needed, the manager can also have a queue of panels and popups, and after a close event, display whatever is the next highest priority thing in the queue.
  8. Your state machine chart looks good. All the states are mutually exclusive, but shooting is something that can be done in all of them except death. Therefore, call your shooting code in addition to updating the state machine. Perhaps with a check to make sure you're not dead (which I would call a special case). Or if you end up needing multiple states where you can't shoot, then instead of special casing each one, you could add a bool canShoot to your data table of stuff related to each state (or create a table if you don't have one already).   Choosing which animation to display can also be done by a table lookup, where you have two animations for each state (one shooting and one not).
  9. C++ Going Beyond Basics

    Fake it till you make it :D It took me a long time to really "get it" with pointers. It wasn't until I learned assembly programming that I could really see what was going on internally. All of the computer's RAM is like a giant array. A pointer is just a number, which is an index into that array. The type of the pointer says what kind of data is stored at that location. All data is really just binary numbers, but it can be interpreted and operated on in different ways, and that's what variable types are for in C++. Learn loops and functions and arrays before tackling pointers. The concepts aren't that difficult, so just keep at it and you'll get it. Don't worry about [b]for[/b] loops. They're just a sort of shorthand. [b]While[/b] loops can do all the same things and have easier syntax. As for how I went past basics, I took classes at a community college. But more important than the class itself is just doing the exercises from the book, writing small programs that introduce you to all the concepts. To a large extent, the classes were a waste of time and money. Even the third one "advanced C++" wasn't anywhere near what I needed for game programming. Still just text mode with no real-time elements to it. I didn't know about this forum or anywhere else to find people to ask where to go from there, so you're already in a better position to get up and coding quickly than I was even after college :)   If you can't think of what to write, then buy a book and do some exercises from it. Or look for programming exercises online.
  10. Breaking out of a nested loop

    In all seriousness, I'd be interested to see that. for(int i = 0; i < 100; ++i) { if(((i / 10) - 1) == ((i % 10) + 1)) break; } at least 1 is gone and we only need a normal break And suddenly the code is more complicated and about 10-100x slower, because the divisions are taking many more cycles than the other simple operations. for(int i=0,n=0; n<10; n += ((i+1)==10), i+=((i+1)==10)*-9+((i+1)!=10)){ } look ma, no division or additional branching Anyone else who is going to stop using nested loops at all? Help! How do I break out of nested quotes?? break; If you want to see a real masterpiece, look at page 3 or 4 of the comments here
  11. How do you write this down?

    Two more versions These are not precisely equivalent to the original, because of the x != 0 condition instead of < or >. But if x is guaranteed to start off in the direction that it will reach 0 without having to wrap around the long way, then they should work. int inc = 1; bool (*f1)() = doA; bool (*f2)() = doB; if (v <= 0)     inc = -1, f1 = doB, f2 = doA; while(x != 0) {     x += inc;     y += x - inc;     z += y + inc;     if (f1())         f2(); }int inc = v > 0 ? 1 : -1; while(x != 0) {     x += inc;     y += x - inc;     z += y + inc;     if(v > 0) { if(doA()) doB(); }     else      { if(doB()) doA(); } }
  12. I feel like I'm cheating by not refining my own silicon to grow into crystals to cut wafers and make microchips to program my games on.
  13. Excellent post, n3Xus   Exactly. This is what "make games, not engines" means. Trying to anticipate everything you'll need just ends up making a bunch of wasted functionality. Do the bare minimum to get stuff moving on the screen, and then write only what you actually need for this specific game.   Yep, this is another big one. Gameplay code is hard to envision, and under-taught compared to engine code. Small games like Pong/Tetris are easy, because everything just does what it does until some condition happens and the game is over. But in an adventure or RPG type game, you need some way of defining where enemies/interactable things are on maps, some way to control what gets spawned when, and how to control the game progression. A lot of the time it can feel pretty silly how simple it is... just place an object in front of a door, and when some variable is set, remove the object. But I would recommend starting early on this aspect of the game, to be sure that all the gameplay code you write can interact properly with the level data and game progression.   The nearly inevitable end to all amateur games Anticipate it, and prepare yourself emotionally to muscle through it. IME, games tend to go in this progression: 1) Yay! Everything is clean and new, the possibilities are endless! 2) It's starting to get cluttered and it doesn't really do anything yet. 3) Miserable, endless code. More and more and more, for months on end, and it just looks like a random collection of features, not a functioning game. 4) All the main features are more or less done. Running out of time. Bugs everywhere. Fix bugs. More bugs. Why does it still not look like a game? 5) Wait a second, it looks like a game now? It's done? Yay! 6) If you have any time left, go beyond simply making it function. Add little finishing touches to make it really special.   ...and that's if you have other people making all the artwork/level design for you.
  14. At least if I'm understanding correctly, won't the players be staying within a set space? I think it would be pretty reliable, provided your lights are bright enough. Also if you go with belts, you'll have to account for arms going in front of them and blocking some percentage of the LEDs from the camera's view.   I don't think the players will typically be running into things or rolling on the ground or anything. Just running back and forth in an open space. But your idea of reflection is good too. No batteries needed then. Hopefully it would be bright enough. The more surface area you can get covered in reflector, the better. Fully coated helmets with camera above would probably be most effective, but may be a bit gross to share if it will be something that people cycle through playing all day, sweating from running...
  15. Yep. But eventually I realized that eschewing the use of all libraries is another form of cheating. To be a software developer requires constant learning and adaptation. One way or the other won't cut it unless you're a hobbyist working alone. Learn how to create games from scratch, and learn how to use engines to save yourself the time. And by then the industry will be different, and you'll have to learn a bunch more stuff