Lodmot Posted March 10, 2012 Share Posted March 10, 2012 (edited) 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 March 10, 2012 by Lodmot Quote Link to comment Share on other sites More sharing options...
SeaGtGruff Posted March 10, 2012 Share Posted March 10, 2012 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. Quote Link to comment Share on other sites More sharing options...
GroovyBee Posted March 10, 2012 Share Posted March 10, 2012 From my experience algorithmic changes generally yield better optimisation results than micro optimisations. If you can explain what you are trying to do there may be better solutions than the one you are currently using. Quote Link to comment Share on other sites More sharing options...
RevEng Posted March 10, 2012 Share Posted March 10, 2012 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. Quote Link to comment Share on other sites More sharing options...
Lodmot Posted March 11, 2012 Author Share Posted March 11, 2012 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 Quote Link to comment Share on other sites More sharing options...
GroovyBee Posted March 11, 2012 Share Posted March 11, 2012 Wow! That is a load of "if" statements. I'm not sure if bB supports "bail early" on multiple logical ANDs in the same conditional check. Quote Link to comment Share on other sites More sharing options...
RevEng Posted March 11, 2012 Share Posted March 11, 2012 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. 1 Quote Link to comment Share on other sites More sharing options...
Lodmot Posted March 11, 2012 Author Share Posted March 11, 2012 (edited) 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 March 11, 2012 by Lodmot Quote Link to comment Share on other sites More sharing options...
GroovyBee Posted March 11, 2012 Share Posted March 11, 2012 Taking another look at your code many of the variables are either 0 or 1. If you use bitwise variables you can combine a whole load of comparisons at once. Quote Link to comment Share on other sites More sharing options...
Lodmot Posted March 12, 2012 Author Share Posted March 12, 2012 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. Quote Link to comment Share on other sites More sharing options...
GroovyBee Posted March 12, 2012 Share Posted March 12, 2012 I think using bitwise variables would improve things. However, if you took some time out and explained your algorithms maybe an even better approach could be found. 1 Quote Link to comment Share on other sites More sharing options...
Lodmot Posted March 12, 2012 Author Share Posted March 12, 2012 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 Quote Link to comment Share on other sites More sharing options...
SeaGtGruff Posted March 12, 2012 Share Posted March 12, 2012 (edited) 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 March 12, 2012 by SeaGtGruff Quote Link to comment Share on other sites More sharing options...
Lodmot Posted March 12, 2012 Author Share Posted March 12, 2012 (edited) 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 March 12, 2012 by Lodmot Quote Link to comment Share on other sites More sharing options...
SeaGtGruff Posted March 13, 2012 Share Posted March 13, 2012 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. Quote Link to comment Share on other sites More sharing options...
Lodmot Posted March 13, 2012 Author Share Posted March 13, 2012 (edited) I tried that line of code, and it gave an error... o.o; Edited March 13, 2012 by Lodmot Quote Link to comment Share on other sites More sharing options...
SeaGtGruff Posted March 13, 2012 Share Posted March 13, 2012 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. Quote Link to comment Share on other sites More sharing options...
SeaGtGruff Posted March 13, 2012 Share Posted March 13, 2012 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. Quote Link to comment Share on other sites More sharing options...
Lodmot Posted March 13, 2012 Author Share Posted March 13, 2012 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 Quote Link to comment Share on other sites More sharing options...
SeaGtGruff Posted March 13, 2012 Share Posted March 13, 2012 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 Quote Link to comment Share on other sites More sharing options...
+Random Terrain Posted March 13, 2012 Share Posted March 13, 2012 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 Quote Link to comment Share on other sites More sharing options...
Lodmot Posted March 13, 2012 Author Share Posted March 13, 2012 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. Quote Link to comment Share on other sites More sharing options...
Lodmot Posted March 13, 2012 Author Share Posted March 13, 2012 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. Quote Link to comment Share on other sites More sharing options...
+Random Terrain Posted March 13, 2012 Share Posted March 13, 2012 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 Quote Link to comment Share on other sites More sharing options...
Lodmot Posted March 13, 2012 Author Share Posted March 13, 2012 Ah, okay. So it's like the TIA values, in that SWCHA can't be read. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.