Jump to content
IGNORED

Questions about optimizing code


Lodmot

Recommended Posts

Alright, so I'm still kind of a beginner programmer using Batari Basic, but I've also been working on a pretty ambitious project called Auto Mayhem.

Everything in the game works the way I want it to, but now I'm at the point where I wish I knew how to optimize my code, because it's running over the 262 scanline limit. So there are a few questions I have in regards to this:

  • Are there any detailed tutorials on code optimization for people who know the language, but are still relatively new to it?
  • When the code is processed by the Atari 2600 or an emulator, and an if-then statement proves to be false, does that if-then statement still use up cycles? (I'm guessing it does, seeing that it still has to determine whether the statement is true or false regardless)
  • I have a crap-ton of if-then statements in my game that are half-duplicate, e.g.:
     
    if P1_Acceleration&--#62;60 && P1_Direction1 && P1_Direction2 && joy0right then P1_Acceleration=0 : P1_Direction1=0 : P1_Direction2=1 : P1_Resistance=4
    if P1_Acceleration&--#62;60 && P1_Direction1 && P1_Direction2 && joy0left then P1_Acceleration=0 : P1_Direction1=1 : P1_Direction2=0 : P1_Resistance=4
    


    Even though the if statements are checking for very similar conditions, they're also checking another slightly different condition as well. It almost seems like I should be able to simplify these two statements into one. Is there any way to do this to save on cycles?

  • When action is at its max in my game, it runs up to about 280 scanlines. That's 18 scanlines over where I should be. Codewise, how "too much" exactly is that? In other words, do I have to remove/optimize the code by just a little to get down to 262, or do I have to remove/optimize almost the entire game?

Any help is greatly appreciated. Thank you. ^^

Edited by Lodmot
Link to comment
Share on other sites

Optimization can be for speed (machine cycles), size (ROM bytes), or both. There's a batari Basic compiler directive that can help. Start by adding "set optimization speed" to your program, then see if there's anything else you can do to help optimize for speed. Note that optimizing code for speed can increase the number of ROM bytes used, although ROM size generally isn't the critical issue it used to be thanks to bankswitching.

 

Better organization of your code can help. In batari Basic you can often save a number of cycles and bytes by grouping similar "let" statements together on a line. (Even though the "let" keyword is usually omitted from assignment statements, I'm still calling them "let" statements.) For example:

 

  A = 1
  B = 2
  C = 1
  D = 0
  E = 1
  F = 0
  G = 2

 

These would be compiled as follows:

 

  LDA #1
  STA A
  LDA #2
  STA B
  LDA #1
  STA C
  LDA #0
  STA D
  LDA #1
  STA E
  LDA #0
  STA F
  LDA #2
  STA G

 

If you group the similar "let" statements together on a line, they'll compile into faster/smaller code:

 

  A = 1:C = 1:E = 1
  B = 2:G = 2
  D = 0:F = 0

 

  LDA #1
  STA A
  STA C
  STA E
  LDA #2
  STA B
  STA G
  LDA #0
  STA D
  STA F

 

With a group of "if" statements, you can optimize for speed by checking for some common requirement first, and branching out if that requirement is false, so you don't spend any more cycles than you need to. For example:

 

  if A = 1 && B = 2 && C = 1 then do_this
  if A = 1 && B = 2 && C = 2 then do_that

 

This could be optimized as follows:

 

  if A <> 1 || B <> 2 then do_neither
  if C = 1 then do_this
  if C = 2 then do_that
do_neither

 

And if you know that C will always be either 1 or 2, you could optimize further by using "else":

 

  if A <> 1 || B <> 2 then do_neither
  if C = 1 then do_this else do_that
do_neither

 

One way you can burn up cycles needlessly is by using the "playfield" statement in your main loop. Once you set the playfield pixels in RAM, they'll stay that way until you change them again, so there's no need to keep performing the "playfield" statement in your loop. In other words, don't do this:

 

loop
  playfield:
  etc.
end
  drawscreen
  goto loop

 

Do this instead:

 

  playfield:
  etc.
end
loop
  drawscreen
  goto loop

 

If your program is running over 262 lines (or over 312 lines for a PAL/SECAM game), you should consider moving some of the "overscan" routines to the "vblank." This has been discussed in other threads, so you might want to review those threads for more information.

Link to comment
Share on other sites

Are there any detailed tutorials on code optimization for people who know the language, but are still relatively new to it?

I wrote some tips on space optimization but there isn't one on speed optimization as far as I know. The closest was the discussion that happened in this thread.

 

 

When the code is processed by the Atari 2600 or an emulator, and an if-then statement proves to be false, does that if-then statement still use up cycles? (I'm guessing it does, seeing that it still has to determine whether the statement is true or false regardless)

In pretty much every computer language, bB included, testing each condition in an if...then takes CPU time until one of the conditions is tested as false, at which point the if...then is skipped.

 

 

I have a crap-ton of if-then statements in my game that are half-duplicate...Even though the if statements are checking for very similar conditions, they're also checking another slightly different condition as well. It almost seems like I should be able to simplify these two statements into one. Is there any way to do this to save on cycles?

SeaGtGruff's post demonstrates how to improve on a lot of if...then's with similar conditions (answering the question you posed), but GroovyBee is right that the first thing you should look for is an algorithmic improvement. It seems to me you might be able to do away with a lot of those if...then's and use table lookups instead, but it's hard to say for sure without all of the details.

 

 

When action is at its max in my game, it runs up to about 280 scanlines. That's 18 scanlines over where I should be. Codewise, how "too much" exactly is that? In other words, do I have to remove/optimize the code by just a little to get down to 262, or do I have to remove/optimize almost the entire game?

You need to optimize enough to get under 262. Like a lot of things in life, the 80/20 rule applies here too - it's likely that 20 percent of your code is taking 80 percent of the time. Look for those hotspots and optimize them, rather than optimizing everything.

Link to comment
Share on other sites

Well, those sound like really good suggestions. I'll give it a shot tonight. It will take a long time though. xD

 

The code I think is the main culprit is the physics engine, and the entire thing looks like this:

 

__Physics_P1
   rem PLAYER 1 CAR PHYSICS
   rem Calculate Car Acceleration and move car accordingly
   if P1_Health=0 then P1_Acceleration=0
   if P1_Acceleration<=75 then P1_Velocity=P1_Velocity+P1_Acceleration
   if P1_Acceleration>75 then P1_Velocity=P1_Velocity+P1_Acceleration/2
   if !switchleftb && P1_Acceleration=100 then P1_Velocity=101
   if P1_Velocity>100 && P1_Acceleration>75 then P1_Velocity=100 : P1_Speed1=1 : P1_Speed2=1
   if P1_Velocity>100 && P1_Acceleration<=75 then P1_Velocity=100 : P1_Speed1=0 : P1_Speed2=1
   if joy0right then P1_Acceleration=P1_Acceleration+4
   if joy0up then P1_Acceleration=P1_Acceleration+4
   if joy0down then P1_Acceleration=P1_Acceleration+4
   if joy0left then P1_Acceleration=P1_Acceleration+4
   if P1_Acceleration>0 then P1_Acceleration=P1_Acceleration-1
   if P1_Acceleration<1 then P1_Acceleration=0
   if P1_Acceleration>100 then P1_Acceleration=100 : P1_Resistance=0
   if P1_Acceleration=100 then P1_Speed1=1 : P1_Speed2=1
   if P1_Acceleration=0 then P1_Velocity=0
   if P1_Velocity<100 then P1_Speed1=0 : P1_Speed2=0
   if P1_Velocity=100 then P1_Velocity=0
   if !joy0up && !joy0down && !joy0left && !joy0right then P1_Resistance=0
   if !P1_Direction1 && P1_Direction2 && P1_Speed1 && P1_Speed2 then player0x=player0x+2
   if !P1_Direction1 && P1_Direction2 && !P1_Speed1 && P1_Speed2 then player0x=player0x+1
   if !P1_Direction1 && !P1_Direction2 && P1_Speed1 && P1_Speed2 then player0y=player0y-2
   if !P1_Direction1 && !P1_Direction2 && !P1_Speed1 && P1_Speed2 then player0y=player0y-1
   if P1_Direction1 && !P1_Direction2 && P1_Speed1 && P1_Speed2 then player0x=player0x-2
   if P1_Direction1 && !P1_Direction2 && !P1_Speed1 && P1_Speed2 then player0x=player0x-1
   if P1_Direction1 && P1_Direction2 && P1_Speed1 && P1_Speed2 then player0y=player0y+2
   if P1_Direction1 && P1_Direction2 && !P1_Speed1 && P1_Speed2 then player0y=player0y+1

   rem Decrease carspeed when the opposite directional key is pressed while the car is moving
   if P1_Acceleration>1 && !P1_Direction1 && P1_Direction2 && joy0left then P1_Acceleration=P1_Acceleration-6
   if P1_Acceleration>1 && !P1_Direction1 && !P1_Direction2 && joy0up then P1_Acceleration=P1_Acceleration-6
   if P1_Acceleration>1 && P1_Direction1 && !P1_Direction2 && joy0right then P1_Acceleration=P1_Acceleration-6
   if P1_Acceleration>1 && P1_Direction1 && P1_Direction2 && joy0down then P1_Acceleration=P1_Acceleration-6
   rem Check whether car's acceleration is being resisted or not
   if P1_Acceleration<=60 && joy0right then P1_Direction1=0 : P1_Direction2=1
   if P1_Acceleration<=60 && joy0down then P1_Direction1=0 : P1_Direction2=0
   if P1_Acceleration<=60 && joy0left then P1_Direction1=1 : P1_Direction2=0
   if P1_Acceleration<=60 && joy0up then P1_Direction1=1 : P1_Direction2=1
   if P1_Acceleration>60 && P1_Direction1 && P1_Direction2 && joy0right then P1_Acceleration=0 : P1_Direction1=0 : P1_Direction2=1 : P1_Resistance=4
   if P1_Acceleration>60 && !P1_Direction1 && !P1_Direction2 && joy0right then P1_Acceleration=0 : P1_Direction1=0 : P1_Direction2=1 : P1_Resistance=2
   if P1_Acceleration>60 && P1_Direction1 && P1_Direction2 && joy0left then P1_Acceleration=0 : P1_Direction1=1 : P1_Direction2=0 : P1_Resistance=4 
   if P1_Acceleration>60 && !P1_Direction1 && !P1_Direction2 && joy0left then P1_Acceleration=0 : P1_Direction1=1 : P1_Direction2=0 : P1_Resistance=2
   if P1_Acceleration>60 && P1_Direction1 && !P1_Direction2 && joy0up then P1_Acceleration=0 : P1_Direction1=1 : P1_Direction2=1 : P1_Resistance=3
   if P1_Acceleration>60 && !P1_Direction1 && P1_Direction2 && joy0up then P1_Acceleration=0 : P1_Direction1=1 : P1_Direction2=1 : P1_Resistance=1
   if P1_Acceleration>60 && P1_Direction1 && !P1_Direction2 && joy0down then P1_Acceleration=0 : P1_Direction1=0 : P1_Direction2=0 : P1_Resistance=3
   if P1_Acceleration>60 && !P1_Direction1 && P1_Direction2 && joy0down then P1_Acceleration=0 : P1_Direction1=0 : P1_Direction2=0 : P1_Resistance=1
   if P1_Resistance=1 then player0x=player0x+1
   if P1_Resistance=2 then player0y=player0y-1
   if P1_Resistance=3 then player0x=player0x-1
   if P1_Resistance=4 then player0y=player0y+1
   if player1y<98 then goto __Physics_A1 bank4
   goto __GAME_Main_Loop bank2
----------------------------------------------------------
bank 4
__Physics_A1
   rem AI1 CAR PHYSICS
   rem Calculate Car AI1 Acceleration and move car accordingly
   if Car2_Health=0 then AI1_IsAccel=0
   if Car2_Acceleration<=75 then Car2_Velocity=Car2_Velocity+Car2_Acceleration
   if Car2_Acceleration>75 then Car2_Velocity=Car2_Velocity+Car2_Acceleration/2
   if !switchleftb && Car2_Acceleration=100 then Car2_Velocity=101
   if Car2_Velocity>100 && Car2_Acceleration>75 then Car2_Velocity=100 : Car2_Speed1=1 : Car2_Speed2=1
   if Car2_Velocity>100 && Car2_Acceleration<=75 then Car2_Velocity=100 : Car2_Speed1=0 : Car2_Speed2=1
   if AI1_IsAccel then Car2_Acceleration=Car2_Acceleration+4
   if Car2_Acceleration>0 then Car2_Acceleration=Car2_Acceleration-1
   if Car2_Acceleration<1 then Car2_Acceleration=0
   if Car2_Acceleration>100 then Car2_Acceleration=100
   if Car2_Acceleration=100 then Car2_Speed1=1 : Car2_Speed2=1
   if Car2_Acceleration=0 then Car2_Velocity=0
   if Car2_Velocity<100 then Car2_Speed1=0 : Car2_Speed2=0
   if Car2_Velocity=100 then Car2_Velocity=0
   if !Car2_Direction1 && Car2_Direction2 && Car2_Speed1 && Car2_Speed2 then player1x=player1x+2
   if !Car2_Direction1 && Car2_Direction2 && !Car2_Speed1 && Car2_Speed2 then player1x=player1x+1
   if !Car2_Direction1 && !Car2_Direction2 && Car2_Speed1 && Car2_Speed2 then player1y=player1y-2
   if !Car2_Direction1 && !Car2_Direction2 && !Car2_Speed1 && Car2_Speed2 then player1y=player1y-1
   if Car2_Direction1 && !Car2_Direction2 && Car2_Speed1 && Car2_Speed2 then player1x=player1x-2
   if Car2_Direction1 && !Car2_Direction2 && !Car2_Speed1 && Car2_Speed2 then player1x=player1x-1
   if Car2_Direction1 && Car2_Direction2 && Car2_Speed1 && Car2_Speed2 then player1y=player1y+2
   if Car2_Direction1 && Car2_Direction2 && !Car2_Speed1 && Car2_Speed2 then player1y=player1y+1
   rem Check whether car's acceleration is being resisted or not
   if AI1_IsAccel && Car2_Acceleration<70 && !Car2_Direction1 && Car2_Direction2 && Car2_ResistanceDir1 && Car2_ResistanceDir2 then player1y=player1y+1
   if AI1_IsAccel && Car2_Acceleration<70 && Car2_Direction1 && !Car2_Direction2 && Car2_ResistanceDir1 && Car2_ResistanceDir2 then player1y=player1y+1
   if AI1_IsAccel && Car2_Acceleration<70 && !Car2_Direction1 && Car2_Direction2 && !Car2_ResistanceDir1 && !Car2_ResistanceDir2 then player1y=player1y-1
   if AI1_IsAccel && Car2_Acceleration<70 && Car2_Direction1 && !Car2_Direction2 && !Car2_ResistanceDir1 && !Car2_ResistanceDir2 then player1y=player1y-1
   if AI1_IsAccel && Car2_Acceleration<70 && Car2_Direction1 && Car2_Direction2 && !Car2_ResistanceDir1 && Car2_ResistanceDir2 then player1x=player1x+1
   if AI1_IsAccel && Car2_Acceleration<70 && !Car2_Direction1 && !Car2_Direction2 && !Car2_ResistanceDir1 && Car2_ResistanceDir2 then player1x=player1x+1
   if AI1_IsAccel && Car2_Acceleration<70 && !Car2_Direction1 && !Car2_Direction2 && Car2_ResistanceDir1 && !Car2_ResistanceDir2 then player1x=player1x-1
   if AI1_IsAccel && Car2_Acceleration<70 && Car2_Direction1 && Car2_Direction2 && Car2_ResistanceDir1 && !Car2_ResistanceDir2 then player1x=player1x-1
   if Car2_Acceleration>70 && Car2_Acceleration<=75 then Car2_ResistanceDir1=Car2_Direction1 : Car2_ResistanceDir2=Car2_Direction2
   if Car2_Acceleration>75 && !Car2_Direction1 && Car2_ResistanceDir1 then Car2_Acceleration=0
   if Car2_Acceleration>75 && Car2_Direction1 && !Car2_ResistanceDir1 then Car2_Acceleration=0
   if Car2_Acceleration>75 && Car2_Direction2 && !Car2_ResistanceDir2 then Car2_Acceleration=0
   if Car2_Acceleration>75 && !Car2_Direction2 && Car2_ResistanceDir2 then Car2_Acceleration=0
   if player2y<98 then goto __A2_Physics
   goto __GAME_Main_Loop bank2
__A2_Physics
   rem AI2 CAR PHYSICS
   rem Calculate Car AI1 Acceleration and move car accordingly
   if AI2_Health=0 then AI2_IsAccel=0
   if AI2_Acceleration<=75 then AI2_Velocity=AI2_Velocity+AI2_Acceleration
   if AI2_Acceleration>75 then AI2_Velocity=AI2_Velocity+AI2_Acceleration/2
   if !switchleftb && AI2_Acceleration=100 then AI2_Velocity=101
   if AI2_Velocity>100 && AI2_Acceleration>75 then AI2_Velocity=100 : AI2_Speed1=1 : AI2_Speed2=1
   if AI2_Velocity>100 && AI2_Acceleration<=75 then AI2_Velocity=100 : AI2_Speed1=0 : AI2_Speed2=1
   if AI2_IsAccel then AI2_Acceleration=AI2_Acceleration+4
   if AI2_Acceleration>0 then AI2_Acceleration=AI2_Acceleration-1
   if AI2_Acceleration<1 then AI2_Acceleration=0
   if AI2_Acceleration>100 then AI2_Acceleration=100
   if AI2_Acceleration=100 then AI2_Speed1=1 : AI2_Speed2=1
   if AI2_Acceleration=0 then AI2_Velocity=0
   if AI2_Velocity<100 then AI2_Speed1=0 : AI2_Speed2=0
   if AI2_Velocity=100 then AI2_Velocity=0
   if !AI2_Direction1 && AI2_Direction2 && AI2_Speed1 && AI2_Speed2 then player2x=player2x+2
   if !AI2_Direction1 && AI2_Direction2 && !AI2_Speed1 && AI2_Speed2 then player2x=player2x+1
   if !AI2_Direction1 && !AI2_Direction2 && AI2_Speed1 && AI2_Speed2 then player2y=player2y-2
   if !AI2_Direction1 && !AI2_Direction2 && !AI2_Speed1 && AI2_Speed2 then player2y=player2y-1
   if AI2_Direction1 && !AI2_Direction2 && AI2_Speed1 && AI2_Speed2 then player2x=player2x-2
   if AI2_Direction1 && !AI2_Direction2 && !AI2_Speed1 && AI2_Speed2 then player2x=player2x-1
   if AI2_Direction1 && AI2_Direction2 && AI2_Speed1 && AI2_Speed2 then player2y=player2y+2
   if AI2_Direction1 && AI2_Direction2 && !AI2_Speed1 && AI2_Speed2 then player2y=player2y+1
   rem Check whether car's acceleration is being resisted or not
   if AI2_IsAccel && AI2_Acceleration<70 && !AI2_Direction1 && AI2_Direction2 && AI2_ResistanceDir1 && AI2_ResistanceDir2 then player2y=player2y+1
   if AI2_IsAccel && AI2_Acceleration<70 && AI2_Direction1 && !AI2_Direction2 && AI2_ResistanceDir1 && AI2_ResistanceDir2 then player2y=player2y+1
   if AI2_IsAccel && AI2_Acceleration<70 && !AI2_Direction1 && AI2_Direction2 && !AI2_ResistanceDir1 && !AI2_ResistanceDir2 then player2y=player2y-1
   if AI2_IsAccel && AI2_Acceleration<70 && AI2_Direction1 && !AI2_Direction2 && !AI2_ResistanceDir1 && !AI2_ResistanceDir2 then player2y=player2y-1
   if AI2_IsAccel && AI2_Acceleration<70 && AI2_Direction1 && AI2_Direction2 && !AI2_ResistanceDir1 && AI2_ResistanceDir2 then player2x=player2x+1
   if AI2_IsAccel && AI2_Acceleration<70 && !AI2_Direction1 && !AI2_Direction2 && !AI2_ResistanceDir1 && AI2_ResistanceDir2 then player2x=player2x+1
   if AI2_IsAccel && AI2_Acceleration<70 && !AI2_Direction1 && !AI2_Direction2 && AI2_ResistanceDir1 && !AI2_ResistanceDir2 then player2x=player2x-1
   if AI2_IsAccel && AI2_Acceleration<70 && AI2_Direction1 && AI2_Direction2 && AI2_ResistanceDir1 && !AI2_ResistanceDir2 then player2x=player2x-1
   if AI2_Acceleration>70 && AI2_Acceleration<=75 then AI2_ResistanceDir1=AI2_Direction1 : AI2_ResistanceDir2=AI2_Direction2
   if AI2_Acceleration>75 && !AI2_Direction1 && AI2_ResistanceDir1 then AI2_Acceleration=0
   if AI2_Acceleration>75 && AI2_Direction1 && !AI2_ResistanceDir1 then AI2_Acceleration=0
   if AI2_Acceleration>75 && AI2_Direction2 && !AI2_ResistanceDir2 then AI2_Acceleration=0
   if AI2_Acceleration>75 && !AI2_Direction2 && AI2_ResistanceDir2 then AI2_Acceleration=0
   goto __GAME_Main_Loop bank2

Link to comment
Share on other sites

It supports them. Here's how "if a>13 && b = 12 && c then d = 1" is represented in bB assembly code...

 

LDA #13
CMP a
BCS .skipL00
.condpart0
LDA b
CMP #12
BNE .skip0then
.condpart1
LDA c
BEQ .skip1then
.condpart2
LDA #1
STA d
.skip1then
.skip0then
.skipL00

 

Regarding the racing code, it sure is a whole lot of if...thens, especially for acceleration+velocity code. Lodmot, you might want to look at re-implementing it with fixed point numbers and skip all of the if...then's, though there's a lot of opportunity to group together conditionals like SeaGtGruff demonstrated.

  • Like 1
Link to comment
Share on other sites

Okay. xDDD!!!!!

Yeah, I'm almost 154% certain that that's why the game is slowing down! LOL!

The only thing is, is there a limit to how many loops for skipping some code I could do?

Or maybe I could use line numbers instead.

Edited by Lodmot
Link to comment
Share on other sites

Alright, so I gave a crack at optimizing my code.

This is really just way too confusing for me to even figure out.

 

Right now the code looks like this:

 

__Physics_P1
   rem PLAYER 1 CAR PHYSICS
   rem Calculate Car Acceleration and move car accordingly
   if P1_Health=0 then P1_Acceleration=0
   if P1_Acceleration<=75 then P1_Velocity=P1_Velocity+P1_Acceleration
   if P1_Acceleration>75 then P1_Velocity=P1_Velocity+P1_Acceleration/2
   if !switchleftb && P1_Acceleration=100 then P1_Velocity=101
   if P1_Velocity>100 && P1_Acceleration>75 then P1_Velocity=100 : P1_Speed1=1 : P1_Speed2=1
   if P1_Velocity>100 && P1_Acceleration<=75 then P1_Velocity=100 : P1_Speed1=0 : P1_Speed2=1
   if joy0right then P1_Acceleration=P1_Acceleration+4
   if joy0up then P1_Acceleration=P1_Acceleration+4
   if joy0down then P1_Acceleration=P1_Acceleration+4
   if joy0left then P1_Acceleration=P1_Acceleration+4
   if P1_Acceleration>0 then P1_Acceleration=P1_Acceleration-1
   if P1_Acceleration<1 then P1_Acceleration=0
   if P1_Acceleration>100 then P1_Acceleration=100 : P1_Resistance=0
   if P1_Acceleration=100 then P1_Speed1=1 : P1_Speed2=1
   if P1_Acceleration=0 then P1_Velocity=0
   if P1_Velocity<100 then P1_Speed1=0 : P1_Speed2=0
   if P1_Velocity=100 then P1_Velocity=0
   if !joy0up && !joy0down && !joy0left && !joy0right then P1_Resistance=0
   if !P1_Direction1 && P1_Speed2 then goto 694 else goto 698
694    if P1_Direction2 && P1_Speed1 then player0x=player0x+2
   if P1_Direction2 && !P1_Speed1 then player0x=player0x+1
   if !P1_Direction2 && P1_Speed1 then player0y=player0y-2
   if !P1_Direction2 && !P1_Speed1 then player0y=player0y-1
698    if P1_Direction1 && P1_Speed2 then 699 else 707
699    if !P1_Direction2 && P1_Speed1 then player0x=player0x-2
   if !P1_Direction2 && !P1_Speed1 then player0x=player0x-1
   if P1_Direction2 && P1_Speed1 then player0y=player0y+2
   if P1_Direction2 && !P1_Speed1 then player0y=player0y+1

   rem Decrease carspeed when the opposite directional key is pressed while the car is moving
707    if P1_Acceleration<=1 then 714
   if !P1_Direction1 && P1_Direction2 && joy0left then P1_Acceleration=P1_Acceleration-6
   if !P1_Direction1 && !P1_Direction2 && joy0up then P1_Acceleration=P1_Acceleration-6
   if P1_Direction1 && !P1_Direction2 && joy0right then P1_Acceleration=P1_Acceleration-6
   if P1_Direction1 && P1_Direction2 && joy0down then P1_Acceleration=P1_Acceleration-6
   rem Check whether car's acceleration is being resisted or not
714 if P1_Acceleration>60 then 720
   if P1_Acceleration<=60 && joy0right then P1_Direction1=0 : P1_Direction2=1
   if P1_Acceleration<=60 && joy0down then P1_Direction1=0 : P1_Direction2=0
   if P1_Acceleration<=60 && joy0left then P1_Direction1=1 : P1_Direction2=0
   if P1_Acceleration<=60 && joy0up then P1_Direction1=1 : P1_Direction2=1
   goto 728
720    if P1_Direction1 && P1_Direction2 && joy0right then P1_Acceleration=0 : P1_Direction1=0 : P1_Direction2=1 : P1_Resistance=4
   if !P1_Direction1 && !P1_Direction2 && joy0right then P1_Acceleration=0 : P1_Direction1=0 : P1_Direction2=1 : P1_Resistance=2
   if P1_Direction1 && P1_Direction2 && joy0left then P1_Acceleration=0 : P1_Direction1=1 : P1_Direction2=0 : P1_Resistance=4 
   if !P1_Direction1 && !P1_Direction2 && joy0left then P1_Acceleration=0 : P1_Direction1=1 : P1_Direction2=0 : P1_Resistance=2
   if P1_Direction1 && !P1_Direction2 && joy0up then P1_Acceleration=0 : P1_Direction1=1 : P1_Direction2=1 : P1_Resistance=3
   if !P1_Direction1 && P1_Direction2 && joy0up then P1_Acceleration=0 : P1_Direction1=1 : P1_Direction2=1 : P1_Resistance=1
   if P1_Direction1 && !P1_Direction2 && joy0down then P1_Acceleration=0 : P1_Direction1=0 : P1_Direction2=0 : P1_Resistance=3
   if !P1_Direction1 && P1_Direction2 && joy0down then P1_Acceleration=0 : P1_Direction1=0 : P1_Direction2=0 : P1_Resistance=1
728    if P1_Resistance=1 then player0x=player0x+1
   if P1_Resistance=2 then player0y=player0y-1
   if P1_Resistance=3 then player0x=player0x-1
   if P1_Resistance=4 then player0y=player0y+1
   if player1y<98 then goto __Physics_A1 bank4
__Physics_A1
   rem AI1 CAR PHYSICS
   rem Calculate Car AI1 Acceleration and move car accordingly
   if Car2_Health=0 then AI1_IsAccel=0
   if Car2_Acceleration<=75 then Car2_Velocity=Car2_Velocity+Car2_Acceleration else Car2_Velocity=Car2_Velocity+Car2_Acceleration/2
   if !switchleftb && Car2_Acceleration=100 then Car2_Velocity=101
   if Car2_Velocity>100 && Car2_Acceleration>75 then Car2_Velocity=100 : Car2_Speed1=1 : Car2_Speed2=1
   if Car2_Velocity>100 && Car2_Acceleration<=75 then Car2_Velocity=100 : Car2_Speed1=0 : Car2_Speed2=1
   if AI1_IsAccel then Car2_Acceleration=Car2_Acceleration+4
   if Car2_Acceleration>0 then Car2_Acceleration=Car2_Acceleration-1
   if Car2_Acceleration<1 then Car2_Acceleration=0
   if Car2_Acceleration>100 then Car2_Acceleration=100
   if Car2_Acceleration=100 then Car2_Speed1=1 : Car2_Speed2=1
   if Car2_Acceleration=0 then Car2_Velocity=0
   if Car2_Velocity<100 then Car2_Speed1=0 : Car2_Speed2=0
   if Car2_Velocity=100 then Car2_Velocity=0
   if Car2_Direction1 then 813
   if Car2_Direction2 && Car2_Speed1 && Car2_Speed2 then player1x=player1x+2
   if Car2_Direction2 && !Car2_Speed1 && Car2_Speed2 then player1x=player1x+1
   if !Car2_Direction2 && Car2_Speed1 && Car2_Speed2 then player1y=player1y-2
   if !Car2_Direction2 && !Car2_Speed1 && Car2_Speed2 then player1y=player1y-1
   goto 821
813    if !Car2_Direction2 && Car2_Speed1 && Car2_Speed2 then player1x=player1x-2
   if !Car2_Direction2 && !Car2_Speed1 && Car2_Speed2 then player1x=player1x-1
   if Car2_Direction2 && Car2_Speed1 && Car2_Speed2 then player1y=player1y+2
   if Car2_Direction2 && !Car2_Speed1 && Car2_Speed2 then player1y=player1y+1

  rem Check whether car's acceleration is being resisted or not
821    if AI1_IsAccel && Car2_Acceleration<70 then 822 else 831
822    if !Car2_Direction1 && Car2_Direction2 && Car2_ResistanceDir1 && Car2_ResistanceDir2 then player1y=player1y+1
   if Car2_Direction1 && !Car2_Direction2 && Car2_ResistanceDir1 && Car2_ResistanceDir2 then player1y=player1y+1
   if !Car2_Direction1 && Car2_Direction2 && !Car2_ResistanceDir1 && !Car2_ResistanceDir2 then player1y=player1y-1
   if Car2_Direction1 && !Car2_Direction2 && !Car2_ResistanceDir1 && !Car2_ResistanceDir2 then player1y=player1y-1
   if Car2_Direction1 && Car2_Direction2 && !Car2_ResistanceDir1 && Car2_ResistanceDir2 then player1x=player1x+1
   if !Car2_Direction1 && !Car2_Direction2 && !Car2_ResistanceDir1 && Car2_ResistanceDir2 then player1x=player1x+1
   if !Car2_Direction1 && !Car2_Direction2 && Car2_ResistanceDir1 && !Car2_ResistanceDir2 then player1x=player1x-1
   if Car2_Direction1 && Car2_Direction2 && Car2_ResistanceDir1 && !Car2_ResistanceDir2 then player1x=player1x-1
   goto 836
831    if Car2_Acceleration<=75 then Car2_ResistanceDir1=Car2_Direction1 : Car2_ResistanceDir2=Car2_Direction2 : goto 836 else 832
832    if !Car2_Direction1 && Car2_ResistanceDir1 then Car2_Acceleration=0
   if Car2_Direction1 && !Car2_ResistanceDir1 then Car2_Acceleration=0
   if Car2_Direction2 && !Car2_ResistanceDir2 then Car2_Acceleration=0
   if !Car2_Direction2 && Car2_ResistanceDir2 then Car2_Acceleration=0
836 if player2y<98 then goto __A2_Physics
   goto __GAME_Main_Loop bank2
__A2_Physics
   rem AI2 CAR PHYSICS
   rem Calculate Car AI1 Acceleration and move car accordingly
   if AI2_Health=0 then AI2_IsAccel=0
   if AI2_Acceleration<=75 then AI2_Velocity=AI2_Velocity+AI2_Acceleration else AI2_Velocity=AI2_Velocity+AI2_Acceleration/2
   if !switchleftb && AI2_Acceleration=100 then AI2_Velocity=101
   if AI2_Velocity>100 && AI2_Acceleration>75 then AI2_Velocity=100 : AI2_Speed1=1 : AI2_Speed2=1
   if AI2_Velocity>100 && AI2_Acceleration<=75 then AI2_Velocity=100 : AI2_Speed1=0 : AI2_Speed2=1
   if AI2_IsAccel then AI2_Acceleration=AI2_Acceleration+4
   if AI2_Acceleration>0 then AI2_Acceleration=AI2_Acceleration-1
   if AI2_Acceleration<1 then AI2_Acceleration=0
   if AI2_Acceleration>100 then AI2_Acceleration=100
   if AI2_Acceleration=100 then AI2_Speed1=1 : AI2_Speed2=1
   if AI2_Acceleration=0 then AI2_Velocity=0
   if AI2_Velocity<100 then AI2_Speed1=0 : AI2_Speed2=0
   if AI2_Velocity=100 then AI2_Velocity=0
   if AI2_Direction1 then 862
   if AI2_Direction2 && AI2_Speed1 && AI2_Speed2 then player2x=player2x+2
   if AI2_Direction2 && !AI2_Speed1 && AI2_Speed2 then player2x=player2x+1
   if !AI2_Direction2 && AI2_Speed1 && AI2_Speed2 then player2y=player2y-2
   if !AI2_Direction2 && !AI2_Speed1 && AI2_Speed2 then player2y=player2y-1
   goto 868
862    if !AI2_Direction2 && AI2_Speed1 && AI2_Speed2 then player2x=player2x-2
   if !AI2_Direction2 && !AI2_Speed1 && AI2_Speed2 then player2x=player2x-1
   if AI2_Direction2 && AI2_Speed1 && AI2_Speed2 then player2y=player2y+2
   if AI2_Direction2 && !AI2_Speed1 && AI2_Speed2 then player2y=player2y+1
   rem Check whether car's acceleration is being resisted or not
868    if AI2_IsAccel && AI2_Acceleration<70 then 869 else 877
869    if !AI2_Direction1 && AI2_Direction2 && AI2_ResistanceDir1 && AI2_ResistanceDir2 then player2y=player2y+1
   if AI2_Direction1 && !AI2_Direction2 && AI2_ResistanceDir1 && AI2_ResistanceDir2 then player2y=player2y+1
   if !AI2_Direction1 && AI2_Direction2 && !AI2_ResistanceDir1 && !AI2_ResistanceDir2 then player2y=player2y-1
   if AI2_Direction1 && !AI2_Direction2 && !AI2_ResistanceDir1 && !AI2_ResistanceDir2 then player2y=player2y-1
   if AI2_Direction1 && AI2_Direction2 && !AI2_ResistanceDir1 && AI2_ResistanceDir2 then player2x=player2x+1
   if !AI2_Direction1 && !AI2_Direction2 && !AI2_ResistanceDir1 && AI2_ResistanceDir2 then player2x=player2x+1
   if !AI2_Direction1 && !AI2_Direction2 && AI2_ResistanceDir1 && !AI2_ResistanceDir2 then player2x=player2x-1
   if AI2_Direction1 && AI2_Direction2 && AI2_ResistanceDir1 && !AI2_ResistanceDir2 then player2x=player2x-1
   goto 882
877    if AI2_Acceleration<=75 then AI2_ResistanceDir1=AI2_Direction1 : AI2_ResistanceDir2=AI2_Direction2 : goto 882 else 878
878    if !AI2_Direction1 && AI2_ResistanceDir1 then AI2_Acceleration=0
   if AI2_Direction1 && !AI2_ResistanceDir1 then AI2_Acceleration=0
   if AI2_Direction2 && !AI2_ResistanceDir2 then AI2_Acceleration=0
   if !AI2_Direction2 && AI2_ResistanceDir2 then AI2_Acceleration=0
882    goto __GAME_Main_Loop bank2

 

A bit better than it was before, and I did notice a small decrease in scanlines when I do an ALT-L in Stella.

But it's still pretty bad, and ontop of that, the changes I made caused the actual control to feel different.

I preferred how the car controlled before, and it seems to me nothing should be acting different.

 

I'm probably doing something wrong, but there really is so much code I have to go through and it's just

turning my brain into a watermelon.

Link to comment
Share on other sites

Well, what I'm trying to do exactly is make a car game that has physics (obviously).

In the physics engine here, I have two directional variables, one is the direction the car is facing, and another is resistance direction, which allows the car to swerve around a corner if it turns while it's at full throttle.

Then I have the velocity variable which is always adding up by 1's till it gets to 100 at which it loops back to 0.

When you press right, left, up or down on the joystick, an acceleration variable adds up by 4, and maxes out at 100.

At the same time, it will also set the velocity value to the value of the acceleration variable. This is to make it so the

higher the velocity value is, the sooner it gets to 100.

The velocity variable then reads the acceleration variable and detects whether it's higher than 100, and if so, it moves the car one pixel in the corresponding direction.

If you let go of the joystick, I have that variable decrease by 1 until it gets back to 0, allowing for the car to keep momentum for a period of time.

 

 

I'm not sure if that's EXACTLY how it works... It's extremely confusing even for me, even though I wrote it...

It took me a while to get it to do exactly what I wanted it to do. xD

Link to comment
Share on other sites

How many cars are there? I'm wondering if you can split the routines between two or three frames, instead of trying to do them all during the same frame.

 

Also, have you tried moving any of the routines to the vblank period?

 

Looking at your original set of ifs (because you said the physics "feels" better to you), I see some places where you might be able to optimize a bit:

 

if P1_Acceleration<=75 then P1_Velocity=P1_Velocity+P1_Acceleration
if P1_Acceleration>75 then P1_Velocity=P1_Velocity+P1_Acceleration/2

 

You can turn these into an "if...then...else":

 

if P1_Acceleration<=75 then P1_Velocity=P1_Velocity+P1_Acceleration else P1_Velocity=P1_Velocity+P1_Acceleration/2

 

if P1_Velocity>100 && P1_Acceleration>75 then P1_Velocity=100 : P1_Speed1=1 : P1_Speed2=1
if P1_Velocity>100 && P1_Acceleration<=75 then P1_Velocity=100 : P1_Speed1=0 : P1_Speed2=1

 

Ideally, this would be rewritten as follows:

 

if P1_Velocity>100 then P1_Velocity=100 : P1_Speed2=1 : if P1_Acceleration>75 then P1_Speed1=1 else P1_Speed1=0

 

Unfortunately, batari Basic doesn't handle the "else" correctly, but you could do this instead:

 

if P1_Velocity<=100 then skip_it
P1_Velocity=100 : P1_Speed2=1
if P1_Acceleration>75 then P1_Speed1=1 else P1_Speed1=0
skip_it

 

if joy0right then P1_Acceleration=P1_Acceleration+4
if joy0up then P1_Acceleration=P1_Acceleration+4
if joy0down then P1_Acceleration=P1_Acceleration+4
if joy0left then P1_Acceleration=P1_Acceleration+4

 

Is this correct? Do you want to add 8 to P1_Acceleration if the joystick is pushed in a diagonal direction?

 

Assuming you want to add 4 (not 8 ) if the joystick is pushed in any direction, I think this should work:

 

if SWCHA & 240 <> 240 then P1_Acceleration=P1_Acceleration+4

 

Those are just a few places where you could optimize. But I don't know if you can optimize enough to get below 262 lines. If you can't, and moving some stuff into the vblank period isn't enough, then splitting the routines between two or more frames may be the way to go-- but first try optimizing and using vblank.

Edited by SeaGtGruff
Link to comment
Share on other sites

Thank you for the suggestions SeaGtGruff, I think they'll work with what I'm doing here. ^^

 

There's 3 cars in the game.

I spent about 3 to 4 hours going through the entire code and optimizing whatever I could, and I got it to the point where two cars can move around and shoot at the same time with it just barely reaching 263 scanlines, but there's still room for improvement when the 3rd car is added to the mix (which makes it run at about 274, give or take).

I'm using the multisprite kernel, so I'll be pretty limited to how much I can do in the vblank. I'm not sure how much space the multikernel gives there.

 

Also I tried replacing:

 

       if joy0right then P1_Acceleration=P1_Acceleration+4
       if joy0up then P1_Acceleration=P1_Acceleration+4
       if joy0down then P1_Acceleration=P1_Acceleration+4
       if joy0left then P1_Acceleration=P1_Acceleration+4

 

with this:

 

   if !joy0up && !joy0down && !joy0left && !joy0right then P1_Resistance=0 else P1_Acceleration=P1_Acceleration+4

 

 

 

Edited by Lodmot
Link to comment
Share on other sites

Also I tried replacing:

 

	if joy0right then P1_Acceleration=P1_Acceleration+4
	if joy0up then P1_Acceleration=P1_Acceleration+4
	if joy0down then P1_Acceleration=P1_Acceleration+4
	if joy0left then P1_Acceleration=P1_Acceleration+4

 

with this:

 

if !joy0up && !joy0down && !joy0left && !joy0right then P1_Resistance=0 else P1_Acceleration=P1_Acceleration+4

That was my first thought, but when I tried it and checked how it compiled to assembly code, I saw that it wasn't as optimized as it could be, because it does four BIT instructions on SWCHA-- two of which are identical. So I decided to suggest using AND (&) to bit-mask SWCHA and check the results. The idea is that if any of the bits in the upper nibble are 0 (which means the result will not be 240), then joystick 0 is pushed in one or more of the four directions. That was the most optimized method I could think of.

Link to comment
Share on other sites

Regarding my suggestion about splitting the routines between two frames-- if you're handling 3 cars (1 is controlled by the player and the other 2 are controlled by the computer, or AI?), then you could try doing the player's car every frame, and swap between the 2 AI cars on alternating frames:

 

frame 1 -- player's car and AI car 1

frame 2 -- player's car and AI car 2

frame 3 -- player's car and AI car 1

frame 4 -- player's car and AI car 2

etc.

 

That should give the best responsiveness for the player's car. On frame 2 the AI car 1 would keep whatever settings had been determined from frame 1, and on frame 3 the AI car 2 would keep whatever settings had been determined from frame 2, etc. That might make the AI cars a bit less responsive, but it should help with the cycles.

 

An alternative would be to split the logic like this:

 

frame 1 -- player's car and AI car 1 (AI car 2 keeps its previous settings)

frame 2 -- AI car 2 and player's car (AI car 1 keeps its previous settings)

frame 3 -- AI car 1 and AI car 2 (player's car keeps its previous settings)

frame 4 -- player's car and AI car 1 (AI car 2 keeps its previous settings)

frame 5 -- AI car 2 and player's car (AI car 1 keeps its previous settings)

frame 6 -- AI car 1 and AI car 2 (player's car keeps its previous settings)

etc.

 

That should equalize the responsiveness for all 3 cars without going way over on the line counts.

 

By the way-- it's okay to go a little over 262 lines in an NTSC 2600 game-- as long as the line count is stable on all frames. For example, you could draw 264 lines on each frame and it would be okay, as long as each frame is always 264 lines. You could customize the kernel a bit to change the values being written to the timer, so the frames will always be 264 lines.

Link to comment
Share on other sites

Alright, cool. Thanks. ^^

 

How would it work if done this way:

 

if SWCHA & 240 <> 240 then P1_Acceleration=P1_Acceleration+4 else P1_Resistance=0

Assuming I got the if right, that should add 4 to the acceleration whenever the joystick is pushed in any of the four directions, or set the resistance to 0 if the joystick is *not* being pushed in any direction.

Link to comment
Share on other sites

Alright, cool. Thanks. ^^

 

How would it work if done this way:

 

if SWCHA & 240 <> 240 then P1_Acceleration=P1_Acceleration+4 else P1_Resistance=0

Assuming I got the if right, that should add 4 to the acceleration whenever the joystick is pushed in any of the four directions, or set the resistance to 0 if the joystick is *not* being pushed in any direction.

Yes, that's correct. ^^

I tried the code you suggested, and it gave an error. But thank you for trying anyway. Maybe we have different versions of the compiler or something, because judging by the guide on RT's site, your suggestion looks like it should work

Link to comment
Share on other sites

Try compiling the following program as a test. If joystick 0 is *not* being pushed in any direction, the screen should be red. Pushing the joystick in any direction should turn the screen green until you stop pushing.

 

loop
  if SWCHA & 240 <> 240 then COLUBK = $C4 else COLUBK = $44
  drawscreen
  goto loop

Link to comment
Share on other sites

This is from the bB page:

 

"The else keyword might not work correctly in a statement containing &&. The else keyword may also not work as expected when there is more than one if-then on a single line."

 

 

Also take a look at this:

 

http://www.randomter...ds.html#boolean

 

Boolean operators are used as conditions in if-then statements. They are tokenized as:

 

&& = AND

 

|| = OR

 

! = NOT

Link to comment
Share on other sites

Try compiling the following program as a test. If joystick 0 is *not* being pushed in any direction, the screen should be red. Pushing the joystick in any direction should turn the screen green until you stop pushing.
 loop if SWCHA & 240 <> 240 then COLUBK = $C4 else COLUBK = $44 drawscreen goto loop 

 

I tried that in Visual BB but it didn't work.. I also tried getting rid of the "else" portion of the sentence and that didn't work either. There must be something wrong with either my compiler or the version of Visual BB that I'm using.

Link to comment
Share on other sites

This is from the bB page:

 

"The else keyword might not work correctly in a statement containing &&. The else keyword may also not work as expected when there is more than one if-then on a single line."

 

 

Also take a look at this:

 

http://www.randomter...ds.html#boolean

 

Boolean operators are used as conditions in if-then statements. They are tokenized as:

 

&& = AND

 

|| = OR

 

! = NOT

 

Yeah, but technically in this case we're not using "&&" xD

 

Instead of using a long list of if-then statements, an on … gosub or on … goto statement can be used. For Joy0, we read the value in SWCHA and divide it by 16 which discards the Joy1 bits and shifts the joy0 bits into the lower 4 bit positons, so we'd use temp1 = SWCHA / 16. For Joy1, temp1 = SWCHA & %00001111 would be used.

 

SWCHA uses a single & sign. Not sure if that makes a difference, but I just noticed that and thought it was interesting.

 

Also...

 

It may be surprising, but the SWCHA method is often less efficient in terms of cycles and space than if-thens. There is a point at which the on…goto with SWCHA will become more efficient. For example, if you are doing something different for up-left than for up and left individually, such as a diagonal sprite, SWCHA may be the better choice.

 

However here we're not using "on.... goto" so maybe that doesn't apply.

Link to comment
Share on other sites

SWCHA uses a single & sign. Not sure if that makes a difference, but I just noticed that and thought it was interesting.

 

Oh, if that's what you are doing, as far as I know, instead of this:

 

   if SWCHA & 240 <> 240 then P1_Acceleration=P1_Acceleration+4 else P1_Resistance=0

 

You'd have to do something like this:

 

  temp5 = SWCHA & 240
  if temp5 <> 240 then P1_Acceleration=P1_Acceleration+4 else P1_Resistance=0

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...