Thursday, March 8, 2012

Super Sprint 1.1 In The Works (The Finish Line Dilemma)

Hey guys, I have a bit of time off from school so I'm polishing Super Sprint!  Why, because I'm a diehard like that.  Here's what I got so far:

* Cleaned up the code a bit.
* Track implementation is all done using text files...no effect on gameplay but good for me!
* Button to toggle volume...if you don't want to hit the speaker settings or you want to listen to something else on the comp while playing.
* Added an application icon.
* Added more authentic Super Sprint sounds.  Now I've implemented the actual engine SFX with shifting gears and everything!
* Changed the volume of the AI sound effects so they don't irritate you as much.
* Buffed the top speed upgrade a bit.
* Fixed a glitch in which driving in reverse thru the finish line may take away two laps instead of one.
EDIT: * I've even added more cool things since then, it's a spoiler I won't give away just yet...
* More accurate lap timing...:

------------

When you look at racing video games, everything works in frames.  This ain't real life in which everything runs at 1,000,000 FPS (or something).  We're working with 60 FPS (approx 16 ms per frame).  Even still, that number can fluctuate if the CPU's performance boggs down, hence why we use time-based movement to keep the game running at the same rate regardless.  But anyway, bad things can happen if you don't catch 'em.  Like this:


Take a look at this scenario.  Let's pretend that the game runs at a constant 10 FPS (which is crap but just bear with me).  Each frame, the game checks each car to see if it crossed the finish line, like this:

1:00.100 No...
1:00.200 No...
1:00.300 YES!!!

According to the game, your final time is 1:00.300.  But wait, that's incorrect from a logical perspective.  Looking at the illustration, you've overshot the finish line at .300.  But the game stops the timer the first frame it detects the car past the finish line.  So what do we do?  We do this:


Examine the frame in which the car crossed the finish line.  The frame was 100 ms long.  Assuming that the car travels at constant velocity during this frame, it crossed the X-plane at about 36% of the car's travel distance for that frame.  So from one frame to the next, it only took 36 ms instead of 100 ms to cross the plane.  Therefore, your final time is 1:00.236, not 1:00.300.  Congratulations, ladies and gentlemen, we've increased our precision down to the milliseconds!  This can be confusing to implement but it doesn't take THAT much code to do so and you'll be glad you did.

But wait, there's more!  What do we do in the case of multiple cars?  Take a look here:


Assume that the game is still running at 10 FPS.  You see two players coming down to the finish line.  Because the red car had a lead on the blue car, you'd assume Player 2's red car won the race, right?

WRONG!!!  According to the game's flawed logic, Player 1 won.  Why?  Like I said before, in each frame, the game checks each car if they crossed the finish line, starting from Car #1 to Car #8.  Like this:

At 1:23.200:
Did P1 cross line?  No.
Did P2 cross line?  No.

At 1:23.300:
Did P1 cross line?  No.
Did P2 cross line?  No.

At 1:23.400:
Did P1 cross line?  YES!!!  1st Place!
Did P2 cross line?  YES!!!  2nd Place!

Basically, how the game works is that it holds up a 1st place ribbon and gives it to the first car that it detects as having finished the race.  Once it's done that, it gives the 2nd place ribbon to the next car to finish, then the 3rd, the 4th, etc.  Notice how I said "detects as having finished" because it sees that Player 1 (Blue) finished before Player 2 (Red) so it makes the false assumption that P1 won when in fact P2 really did.


So how do you remedy this?  It takes a bit more heavy lifting by the CPU but it can be done.  This algorithm runs every time a car finishes and not every single frame so it's not too bad.  Program the frame like this:

At 1:23.400:
Did P1 finish?  YES!  Final time: 1:23.377.  Compare his final time with every other car's time.  He is currently in 1st.
Did P2 finish?  YES!  Final time: 1:23.344.  Compare his final time with every other car's time.  What's this--he's faster than P1?  Swap positions.  So P2 is now in 1st, P1 is in 2nd.

While precision is great, the only time this algorithm makes a bit of difference is that two or more cars finish on the SAME EXACT FRAME and that a higher-number player has a faster time than a lower-number player.  If they finish on different frames, then it makes no difference.  The odds of such a scenario are so slim but don't say that IT CAN'T HAPPEN.

Really, I imagine if this game is played a million times, then odds are you'll get one Kurt Busch/Ricky Craven finish.  And can you imagine if I didn't implement this and one player got a faster time than the other but came in 2nd instead of 1st?  If that guy was pregnant, he would've broke his water.  We don't want anyone's water broken here.


Sorry Ricky, due to our flawed logic, you are 2nd place.

BTW, I've also accomodated this code for TIES.  Down to the millisecond.  If two players tie, then they both get the same number of points.  It also says both came in "First Place" too.  Easy but ridiculous.

...

So some of you at this point have asked "Eric, why does this code make a damn bit of a difference?"  Because this is how EVERY RACING GAME WORKS!!!  Well, all the good ones are, not including the ones from Midway.  If you can implement this system for a dinky little OpenGL game, then you can implement it for a major title like Daytona or OutRun.


It's like when Michelangelo painted the Sistine Chapel.  When asked "Why do you paint the dark corners that no one can see?"  He replied "God can see it."  Ok, I just compared the painting of religious figures to programming a lousy video game.  Oh well, kind of the same thing.  I'm a Christian so I work for the Lord too.


It's Scud Race!

Now, what else to add to Super Sprint 1.1.  If there's a wishlist anywhere (is anyone wishing?) then I'll get that.  The main reason I'm picking up the game again is to get online multiplayer.  Then I'll try to work on better collision detection since right now, the cars can drive though each other, per-se.  Then more sprites such as flames when cars explode, time trial mode, and custom keyboard configs.  Depends on how much free time I have in the future.  Oh well, hope you learned something so cya later.

No comments:

Post a Comment