Jump to content

  • Log In with Google      Sign In   
  • Create Account

DekuTree64

Member Since 29 Aug 2000
Online Last Active Today, 07:01 PM

Posts I've Made

In Topic: 2D Affine Transforms of Coordinate System

Today, 04:43 AM

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.


In Topic: Coding-Style Poll

Yesterday, 12:54 AM

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.


In Topic: I want to learn programming 2D games. What's the best E-Book?

20 September 2016 - 02:53 PM

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.


In Topic: How to implement variable-step rendering properly?

15 September 2016 - 10:51 AM

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.
 

I want to have the exact amount of floating point multiplications for every PC in order to preserve simulation predictability.

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.


In Topic: Software design patterns for UI behaviors?

14 September 2016 - 09:26 PM

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.


PARTNERS