Jump to content

  • Log In with Google      Sign In   
  • Create Account

DekuTree64

Member Since 29 Aug 2000
Offline Last Active Yesterday, 06:35 PM

#5310942 How to implement variable-step rendering properly?

Posted by on 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.




#5310497 C++ Going Beyond Basics

Posted by on 12 September 2016 - 02:54 PM

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 for loops. They're just a sort of shorthand. While 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.




#5243020 Breaking out of a nested loop

Posted by on 27 July 2015 - 12:20 PM

If you've got two for loops you're looking at O(n*n) execution times.I'd be tempted to refactor the code and eliminate the for loops if possible but that's just me...

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 tongue.png

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 tongue.png


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 https://derpibooru.org/883523


#5241072 How do you write this down?

Posted by on 17 July 2015 - 10:29 AM

Two more versions smile.png 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(); }
}



#5240618 Has anyone got a feeling of this when you were starting as game developer?

Posted by on 15 July 2015 - 05:10 PM

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.




#5240487 Has anyone got a feeling of this when you were starting as game developer?

Posted by on 15 July 2015 - 08:04 AM

Excellent post, n3Xus smile.png
 

5) You realize that for almost every new gameplay feature you want to add you need to write a entirely new part of the engine.

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.
 

6) Eventually you create a simple prototype for your game and you realize that you hardly even wrote any gameplay code, you mostly just added engine functionality.

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.
 

12) You stop working on your game because you lose motivation.

The nearly inevitable end to all amateur games tongue.png 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.




#5240294 Has anyone got a feeling of this when you were starting as game developer?

Posted by on 14 July 2015 - 12:17 PM

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 tongue.png




#5240176 Outside simulator help for giant ping pong game!

Posted by on 13 July 2015 - 08:29 PM

Sounds like a fun project :) My first thought is to have each player wear a belt with infrared LEDs on it, and put two IR cameras in the center of the field to watch them, and calculate their positions by finding the bright spots in the video data. Either that or put the LEDs on their heads and a single camera above the field, if there's a convenient place to hang it.

 

Either way, it would be a lot like the wii remote and its sensor bar... except in that case it's the camera that's moving.




#5240171 Efficient 2D collision detection with many dynamic OBB

Posted by on 13 July 2015 - 08:01 PM

Yeah, use circles for the bullets. To do a circle->OBB check, subtract the box center from the circle center, and then rotate the circle center by -boxAngle. Then it's just a regular circle->AABB check.

 

And since it looks like your boxes will tend to be in clumps that share the same angle, you could probably optimize it further by making a "box group" collision object, which has a center point, and list of child boxes relative to that point. Then inverse rotate the circle center around the box group center, and you can check against all the child boxes without having to do the rotation operation every time. But it might not be worth the effort since every time the enemy is split into two chunks, you'd have to split the box group as well, and recalculate the box positions relative to the new center points.




#5237200 how to program A LOT of skills/spells?

Posted by on 27 June 2015 - 11:13 PM

A function pointer table and array of unlock flags would be better.

 

As for how to code them, the more you know upfront, the better. If you've already designed all of them, then go through the list and write down groups of skills that have common elements to them. Then write functions to do the common things. Use data tables when possible, where you index in with the skill ID to get whatever values the common function needs. Doing huge if/else chains or switch statements is ok sometimes too, but tables are usually nicer to work in. Keep the individual functions for each skill short when possible, mostly making calls to common functions. Easier to navigate and work in than a scattering of long and short functions.




#5177600 For-loop-insanity

Posted by on 02 September 2014 - 12:51 AM

Classic mistake. There is a generic way to make it work, if you really want to, though:

uint8_t j = 0;

do
{
  printf("%i\n", j);
}
while (j++);

Which is pretty readable, since the while loop is clearly going to terminate as soon as j overflows. And like Ravyne said, it doesn't really make anything faster in general, that said I personally don't see this as an optimization tactic, but more as a type correctness thing, in other words, the loop variable is going to be used as an 8-bit unsigned integer, so let's not lie to ourselves, make it an 8-bit unsigned integer. But with this comes the responsibility of watching out for overflow and other low-level things which generally don't come up when simply using a sufficiently large signed integer like int, people will have their own opinions on that matter smile.png

Don't you mean ++j?

 

I just tried it on ARM7, which has only 32-bit registers, and it compiled to a compare with 256, branch if not equal. So it doesn't actually force the wrapping, but did get the logic correct, and no different than using an int and comparing with 256.




#5173199 Can't solve problems without googling?

Posted by on 12 August 2014 - 04:31 PM

Lots of good answers here. I especially like Glass_Knife and phantom's.

 

Another thing you can do is read just the overview of the solution, and try to work out the details yourself, but with a chicken exit if you need it.

 

Also, don't be afraid to solve the same problem more than once :) Sometimes when you have a large and complex challenge, you just have to dive head first into it and make a big mess of code. Then refactor and it looks a little better. But with your deeper understanding of the problem, you might be able to approach it from a different angle and come up with a more elegant system overall.

 

A good example for me is side scroller collision detection with slopes. It seems so simple, and often it is, depending on how many cases you want to handle. But it can get really complicated if you want to support slopes steeper than 45 degrees, sloped ceilings, not having off-by-one problems between left and right slopes, colliding the center of your rectangle with the slope but corner when standing at the edge of a solid tile, etc. I finally managed a system that does everything I want, but it's not quite the level of elegance I want to reach before writing an article series on it (because all the articles I've read don't solve it completely). So one more iteration, one of these days :)




#5147238 How to stop users from manipulating Game Save Data

Posted by on 15 April 2014 - 06:48 PM

First thing, don't make it so readable tongue.png Use meaningless labels, and no newlines so it's a pain to find the number you're after.

 

Second, do some sort of encryption on the numbers (could be as simple as differential encoding, so changing one number modifies everything after it).

 

For a single player game, there's no need to prevent save hacking... just deter it so the player doesn't feel like they're wasting time by playing the game when it would be so easy to type in a number. If anyone cares enough to make a save editor tool, let them have their fun.




#5146917 I need help with matrices

Posted by on 14 April 2014 - 09:20 AM

Not meaning to hijack the thread, but I suspect using matrices would help me too.

 

I have a camera class, it has this simple function to apply it.

//Some weird shit going on here
//Old comment but kept for lols
void Camera::ApplyICam()
{
  glRotatef(-m_rotation.m_xValue*180/PI, 1.0, 0.0, 0.0);
  glRotatef(-m_rotation.m_yValue*180/PI, 0.0, 1.0, 0.0);
  glRotatef(-m_rotation.m_zValue*180/PI, 0.0, 0.0, 1.0);

  glTranslatef(-m_position.m_xValue, 
               -m_position.m_yValue, 
               -m_position.m_zValue);
}

 

 

My object class also stores position and rotation as two 3 dimensional vectors. Using this system I can move my camera and view my objects just fine, the problem comes when I want to rotate the object.

 

Doing a simple initial rotation is easy, I simply set my m_rotate in object, my question is how to rotate my object after this initial rotation. Say we have an aircraft and I want the plane to bank left aka roll anticlockwise along it's central axis by say 15 degrees. I am unsure how to calculate this rotation given that the plane is no longer aligned along one of our axis, it has its own arbitrary axis. Simply put I cannot figure out how I need to alter my initial rotation.

 

Here is part of my code showing the order of transformations

  glLoadIdentity();
  cam->ApplyICam();
  obj->AddRotation(0.0, 0.025, 0.0);
  obj->ApplyTransformations();
  obj->GetMesh()->DrawMesh();
  cam->ApplyICam();

This code correctly draws my object in position, spinning around the y axis by 0.025 per frame. What I want to know is how to make my object bank as described above, no matter how it happens to be rotated at the time.

 

I am sorry for the poor description, I have always had a hard time visualizing these rotations 

This is where you get into "incremental rotations". Store the aircraft's orientation as a matrix (or quaternion), and when the player wants to turn, generate a pitch, yaw or roll matrix with the small angle delta (your 0.025 value) and multiply the orientation by it. So for example a yaw rotation will rotate around the plane's current up axis, modifying the X and Z axes in the process. Then next time you want to do a pitch rotation, it will be around the modified X axis..It doesn't really matter what order you do them in if the player wants to rotate around multiple axes at the same time, since the change is so small each frame.

 

It can be more tricky at first, working with the orientation as a matrix/quaternion rather than angles, but it's actually easier once you get the hang of it. For example, if you want to move the plane forward, just multiply a vector (0,0,speed) by the orientation, and add it to the position.

 

And don't forget to re-normalize/orthogonalize the orientation periodically to correct any numerical accuracy problems that accumulate.




#5128303 "Oh God, Who Wrote This?", "You Did", "Wait? I wrote Thi...

Posted by on 02 February 2014 - 08:22 PM

laugh.png That is indeed horrible. Way too many parenthesis to keep track of what's inside what (and some are entirely unnecessary). Try separating the function arguments onto separate lines so you can see them, and separate out some of the repeating ugly things into variables.

for (totalMatches = 1; totalMatches <= (pIt)->first->getSize(); ++totalMatches)
{
    int eventIndex = eventLog.size()-totalMatches;
    const Event *event = eventLog[eventIndex];
    if (!(pIt)->first->compare(
         (pIt)->first->getSize()-totalMatches,
         event->getType(),
         translator->translate(event->getKeyCode()),
         getTimeDiff(eventIndex)))
         break;
}

Or better yet, put the whole thing in a function that returns true at the end, and have the if statement return false instead of breaking.






PARTNERS