LoginLogin
Nintendo shutting down 3DS + Wii U online services, see our post

Speeding up every 10 points

Root / Programming Questions / [.]

ChaseCZCreated:
Let's say we have a simple game where you run and jump, with every successful jump over an object you get 1 point. Now... I want to make it so you as a player get a little faster every 10 points, but i don't want to make it like you get faster at 10 then 20, 30 etc... because that would be too much copying of code and i totally don't have the mood to make it up to 1000+, i want some short or long code which will make it automatically every 10 points.

WHILE 1 'Main loop
 IF POINTS% MOD 10 == 0 THEN INC SPEED
 'Game stuff
 VSYNC
 WEND

The modulus function (MOD) finds the integer remainder of a division. So, by asking in the IF statement whether POINTS MOD 10 is equal to zero, you find out when your POINTS is completely divisible by 10, because any multiple of 10 divided by 10 yields a remainder of zero. This works for values other than 10 as well.

Oh yeah forgot to mention that.

WHILE 1 'Main loop
 IF POINTS% MOD 10 == 0 THEN INC SPEED
 'Game stuff
 VSYNC
 WEND
While this simple solution looks like it would work at a glance, it might not function the way you would expect or want it to. Let's see why.
  • 1. Acceleration may occur erratically. Since the code says to increase speed if the points are at a number evenly divisible by 10, when the condition is satisfied, the speed will continue to increase until the next point is gained. This means that if you have randomly generated spaces between jumps, the speed will increase further.
  • 2. If you start with 0 points, the game will immediately crash upon executing this code. The modulo operator is just a glorified dividing operator that returns the remainder. Because you cannot divide by zero, you cannot get the remainder of a number divided by zero.
Well, now we can fix it! First, we must fix up that horrible 0 points crash. If you're a monster, you could start with one point. If you're not a monster, you will add a primary condition to the IF block with the modulo operator.
WHILE !. 'one day you'll understand, lad
 IF POINTS > 9 && !(POINTS MOD 10) THEN INC SPEED
 'game logic
 VSYNC
WEND
The reason why this doesn't crash the program is because SB is lazy, and won't even try to check conditions past a false one. The reason why I put POINTS > 9 instead of POINTS > 0 is because it cuts down on a tiny tiny fraction of time dedicated to MOD, while it doesn't need it. Next, we'll need to make the code execute upon the first frame of the point gained. Maybe you want to gradually increase speed, but over a set amount of time. To do this, we can use a special variable to hold a framecount gathered from MAINCNT to see when the 10th point was gained, and work from there.
WHILE !. 'one day you'll understand, lad
 IF POINTS > 9 && !(POINTS MOD 10) THEN
  IF !TENCNT THEN TENCNT = MAINCNT
  IF MAINCNT-TENCNT < 20 THEN INC SPEED, 0.2
 ELSE
  TENCNT=0
 ENDIF
 'game logic
 VSYNC
WEND
Here, we set TENCNT to 0 while not being used to signify that it hasn't been used yet. While it is being used (for 19-20 frames), we increase the speed slowly. Fin. That's probably all you need. Have a wonderful day. <(°< ° )>

Aha, ty. I'll check it out

  • 2. If you start with 0 points, the game will immediately crash upon executing this code. The modulo operator is just a glorified dividing operator that returns the remainder. Because you cannot divide by zero, you cannot get the remainder of a number divided by zero.
Actually, we're not dividing by zero here. We are asking whether POINTS divided by 10 yields a remainder, not 10 divided by POINTS. However, you were right about the sporadic acceleration, especially at 0. Therefore, you want to check the POINTS MOD 10 condition only when you have an increase in points AND points is not 0. To do this, I would suggest sticking the increase of speed code into the same block responsible for increasing points. The code may look like this...
WHILE TRUE
 IF(PlayerGetsAPoint)THEN
  INC POINTS
  IF (POINTS) && (POINTS MOD 10 == 0) THEN INC SPEED
 ENDIF
 'Rest of code
WEND

There's another problem though. If the number of points increases by more than one at a time, it might skip a multiple of 10. A safer solution might be something like:
NEXTINCREASE=10
WHILE 1 'main loop
 ...
 WHILE POINTS>=NEXTINCREASE
  INC NEXTINCREASE,10
  INC SPEED
  'do other things
 WEND
 ...
WEND
You could simplify this is you just want to increase speed by 1 per 10 points, and don't want to play a sound, or animation, or anything else when this happens:
WHILE 1
 ...
 SPEED=ORIGINAL_SPEED + (POINTS DIV 10)
 ...
WEND

Ah, yes, but what if the player loses points?

Maybe something along the lines of this would work?
VAR SCORE=0
VAR NEXT_TEN=1
VAR SPEED=4
VAR ACCELERATION=.2

'REWARD THE PLAYER 'P' POINTS (OR TAKE AWAY IF P IS NEGATIVE)
DEF REWARD P
 IF ABS(P)==P THEN
  WHILE SCORE+P>NEXT_TEN*10
   INC NEXT_TEN
   INC SPEED,ACCELERATION
  WEND
 ELSE
  DEC SCORE,P
 ENDIF
END

WHILE 1
 'GAME LOGIC
WEND
here's a simpler one:
VAR SCORE=0
VAR HSCORE=0
VAR ACCELERATION=.2
VAR SPEED=4

DEF REWARD P
 IF P<0 THEN
  DEC SCORE,P
 ELSE
  INC SCORE,P
  HSCORE=MAX(SCORE,HSCORE)
  SPEED=INT(HSCORE/10)*ACCELERATION
 ENDIF
END

WHILE 1
 'GAME CODE HERE
WEND

Ooh right those problems. Thanks for bringing them up

Oh my goodness.
SPEED% = BASESPEED% + POINTS% / 10

Oh my goodness.
SPEED% = BASESPEED% + POINTS% / 10
Is DIV preferred here?

Huh that works.
Oh my goodness.
SPEED% = BASESPEED% + POINTS% / 10
Is DIV preferred here?
MOD is a fancy division function and it shows up several times in this thread so why not.

Oh my goodness.
SPEED% = BASESPEED% + POINTS% / 10
If the score ever decrements, so will the speed.

Oh my goodness.
SPEED% = BASESPEED% + POINTS% / 10
If the score ever decrements, so will the speed.
SPEED% = MAX(SPEED%,BASESPEED% + POINTS% / 10)

That's better! I didn't even think of that, Nice!