Jump to content
IGNORED

Stupid question I probably shouldn't be asking...


Dragnerok X

Recommended Posts

I know I have to bankswitch, but: A. How? and B: How should I divide my code up

Bankswitching in bB is easy.

 

Somewhere in your code (typically at the beginning, where it's easy to spot-- although bB doesn't care where it is), add a line that says "set romsize ?k," where the "?" is replaced by the number of K you want the cart to be, as follows:

 

2k = use half the standard cart size (noty bankswitched)

4k = use the standard cart size (not bankswitched)

8k = use Atari's "F8" bankswitching method (has two banks-- 1 and 2)

16k = use Atari's "F6" bankswitching method (has four banks-- 1, 2, 3, and 4)

32k = use Atari's "F4" bankswitching method (has eight banks-- 1, 2, 3, 4, 5, 6, 7, and 8)

 

To tell bB where you want each bank to begin in your program, put a "bank ?" statement at the point where a particular bank should start, where the "?" is replaced by the bank number.

 

Warning: Do *NOT* declare the start of the first bank, or you will confuse bB. It is automatically understood that the first section of your program code is supposed to go in bank 1.

 

Warning: Be sure to put a space after the word "bank" when you are declaring the start of a bank (e.g., it's "bank 2," not "bank2").

 

You don't need to fill up each bank before going on the next. But if you want to "skip over" a bank so you can put something in another bank, you still need to declare the start of any banks in between.

 

For example, the following program will not compile, because the banks preceding bank 3 haven't been declared:

 

  set romsize 32k
  bank 3
  COLUBK = $24
  scorecolor = $0E
loop
  drawscreen
  goto loop

However, the next program *will* compile, because bank 2 has been declared (and bank 1 must *not* be declared):

 

  set romsize 32k
  bank 2
  bank 3
  COLUBK = $24
  scorecolor = $0E
loop
  drawscreen
  goto loop

Warning: You *cannot* skip over bank 1 (as I tried to do in the preceding example), because when your program is compiled, bB wil set the starting address of your code to the beginning of bank 1. For example, although the preceding example will compile, it will not run correctly, because after the boot-up routine initializes the Atari's memory, it will try to go to your program at the start of bank 1-- but there's no code in bank 1, so the Atari will go bonkers.

 

You will also note from the preceding example that you do *not* need to declare any banks at the end (e.g., banks 4, 5, 6, 7, and 8) if you aren't using them, because bB will be able to handle it.

 

To jump to a line or subroutine in a different bank, you must add the word "bank?" after the "goto" or "gosub" statement-- e.g., "if a = 1 then goto line_100 bank2" or "gosub line_200 bank3."

 

Warning: Note that in *this* instance, you should *omit* the space after "bank." The difference is, when you're declaring the start of a new bank, you're using the "bank" statement to tell bB that a new bank begins there, and the bank number is a parameter of the "bank" statement, so the space has to be in between them. But when you're using "bank" as part of a "goto" or "gosub" statement, the "bank" word isn't a separate statement with its own parameters, it's just a special keyword that's part of the "goto" or "gosub" statement, and the bank number is actually part of the keyword-- e.g., in "goto line_300 bank4," "bank4" is a keyword that indicates which bank "line_300" is in.

 

You can organize your code by using certain banks for certain things-- e.g., data lookup tables, subroutines, etc.

 

Warning: bB puts its own code (or its "system routines," like "drawscreen" or "pfpixel") at the start of the last bank, so the last bank won't contain as much available memory as you might expect.

 

Warning: Since bB's "drawscreen" routine will always be in the last bank, certain kinds of graphics data must also be placed in the last bank (at least, in the current version of bB). For example, if you use the "playfield:" command to draw an entire playfield at once, the "playfield:" command must go in the last bank, because bB's routines are in the last bank, and they must be able to see any data that's being used to draw the screen;and in order for that to happen, the data must either be in the same bank as the routine that's trying to read it, or it must be in some other memory area that's accessible even when the last bank is switched in-- e.g., anything in the zero-page RAM or Superchip RAM will be visible to all banks.

 

When you split your code up across different banks, be sure that you declare the banks in order, and that you don't try to go back to a previous bank. For example, the following code is *BAD*, because it declares the banks out of order and tries to go back to previous banks (aside from the fact that it's an awful case of "spaghetti code"):

 

  set romsize 16k
  goto start_me_up bank3
  bank 3
start_me_up
  rem * insert game initialization here
  bank 2
  rem * now add a bunch of subroutines here
  bank 3
continue
  if a = 1 then goto loop bank2 else goto get_selection bank4
  bank 2
loop
  drawscreen
  if joy0up then goto jump_up bank 1
  goto loop
  bank 4
get_selection
  rem * add processing of console switches here
  bank 1
jump_up
  player0y = player0y - 6

Michael

Link to comment
Share on other sites

I know I have to bankswitch, but: A. How? and B: How should I divide my code up

Bankswitching in bB is easy.

 

Somewhere in your code (typically at the beginning, where it's easy to spot-- although bB doesn't care where it is), add a line that says "set romsize ?k," where the "?" is replaced by the number of K you want the cart to be, as follows:

 

2k = use half the standard cart size (noty bankswitched)

4k = use the standard cart size (not bankswitched)

8k = use Atari's "F8" bankswitching method (has two banks-- 1 and 2)

16k = use Atari's "F6" bankswitching method (has four banks-- 1, 2, 3, and 4)

32k = use Atari's "F4" bankswitching method (has eight banks-- 1, 2, 3, 4, 5, 6, 7, and 8)

 

To tell bB where you want each bank to begin in your program, put a "bank ?" statement at the point where a particular bank should start, where the "?" is replaced by the bank number.

 

Warning: Do *NOT* declare the start of the first bank, or you will confuse bB. It is automatically understood that the first section of your program code is supposed to go in bank 1.

 

Warning: Be sure to put a space after the word "bank" when you are declaring the start of a bank (e.g., it's "bank 2," not "bank2").

 

You don't need to fill up each bank before going on the next. But if you want to "skip over" a bank so you can put something in another bank, you still need to declare the start of any banks in between.

 

For example, the following program will not compile, because the banks preceding bank 3 haven't been declared:

 

  set romsize 32k
  bank 3
  COLUBK = $24
  scorecolor = $0E
loop
  drawscreen
  goto loop

However, the next program *will* compile, because bank 2 has been declared (and bank 1 must *not* be declared):

 

  set romsize 32k
  bank 2
  bank 3
  COLUBK = $24
  scorecolor = $0E
loop
  drawscreen
  goto loop

Warning: You *cannot* skip over bank 1 (as I tried to do in the preceding example), because when your program is compiled, bB wil set the starting address of your code to the beginning of bank 1. For example, although the preceding example will compile, it will not run correctly, because after the boot-up routine initializes the Atari's memory, it will try to go to your program at the start of bank 1-- but there's no code in bank 1, so the Atari will go bonkers.

 

You will also note from the preceding example that you do *not* need to declare any banks at the end (e.g., banks 4, 5, 6, 7, and 8) if you aren't using them, because bB will be able to handle it.

 

To jump to a line or subroutine in a different bank, you must add the word "bank?" after the "goto" or "gosub" statement-- e.g., "if a = 1 then goto line_100 bank2" or "gosub line_200 bank3."

 

Warning: Note that in *this* instance, you should *omit* the space after "bank." The difference is, when you're declaring the start of a new bank, you're using the "bank" statement to tell bB that a new bank begins there, and the bank number is a parameter of the "bank" statement, so the space has to be in between them. But when you're using "bank" as part of a "goto" or "gosub" statement, the "bank" word isn't a separate statement with its own parameters, it's just a special keyword that's part of the "goto" or "gosub" statement, and the bank number is actually part of the keyword-- e.g., in "goto line_300 bank4," "bank4" is a keyword that indicates which bank "line_300" is in.

 

You can organize your code by using certain banks for certain things-- e.g., data lookup tables, subroutines, etc.

 

Warning: bB puts its own code (or its "system routines," like "drawscreen" or "pfpixel") at the start of the last bank, so the last bank won't contain as much available memory as you might expect.

 

Warning: Since bB's "drawscreen" routine will always be in the last bank, certain kinds of graphics data must also be placed in the last bank (at least, in the current version of bB). For example, if you use the "playfield:" command to draw an entire playfield at once, the "playfield:" command must go in the last bank, because bB's routines are in the last bank, and they must be able to see any data that's being used to draw the screen;and in order for that to happen, the data must either be in the same bank as the routine that's trying to read it, or it must be in some other memory area that's accessible even when the last bank is switched in-- e.g., anything in the zero-page RAM or Superchip RAM will be visible to all banks.

 

When you split your code up across different banks, be sure that you declare the banks in order, and that you don't try to go back to a previous bank. For example, the following code is *BAD*, because it declares the banks out of order and tries to go back to previous banks (aside from the fact that it's an awful case of "spaghetti code"):

 

  set romsize 16k
  goto start_me_up bank3
  bank 3
start_me_up
  rem * insert game initialization here
  bank 2
  rem * now add a bunch of subroutines here
  bank 3
continue
  if a = 1 then goto loop bank2 else goto get_selection bank4
  bank 2
loop
  drawscreen
  if joy0up then goto jump_up bank 1
  goto loop
  bank 4
get_selection
  rem * add processing of console switches here
  bank 1
jump_up
  player0y = player0y - 6

Michael

 

Wow that was educational!!! Now why does there always have to be a problem involved? :roll:

 

Combat_DX.bas

 

Combat_DX.bas.bin

Link to comment
Share on other sites

Warning: Since bB's "drawscreen" routine will always be in the last bank, certain kinds of graphics data must also be placed in the last bank (at least, in the current version of bB). For example, if you use the "playfield:" command to draw an entire playfield at once, the "playfield:" command must go in the last bank, because bB's routines are in the last bank, and they must be able to see any data that's being used to draw the screen;and in order for that to happen, the data must either be in the same bank as the routine that's trying to read it, or it must be in some other memory area that's accessible even when the last bank is switched in-- e.g., anything in the zero-page RAM or Superchip RAM will be visible to all banks.

why does there always have to be a problem involved?

I removed all of the quoted text except what's pertinent to your problem. Your "player0:" statements and "player1:" statements are in bank 1, so bB's "drawscreen" routine (which is now in bank 2) can't see your player data in bank 1. I didn't specifically mention "player0:" and "player1:," because I couldn't remember all of the graphics-related statements that need to be in the last bank, and which ones can be in other banks. But basically, if your bB program is exceeding the 4K limit and you want to use bankswitching with it, the first thing you should probably do (after adding "set romsize" and declaring where the banks start in your program) is to relocate all of your "playfield:," "player0:," and "player1:" statements into the last bank. Graphics-related statements that can go outside the last bank include those related to the missiles or ball, position statements (e.g., "player0x"), playfield drawing statements, and any color statements that don't involve tables (e.g., "COLUPF =" can go anywhere, but "pfcolors:" would have to be in the last bank).

 

I've moved the "bank 2" declaration to the end of your program, and then moved all the "player0:" and "player1:" statements into bank 2. Where they used to be, there are now "gosub" statements.

 

By the way, I like how you can push the other tank around. You seem to be coming along nicely. :)

 

Michael

Combat_DX.bas

Combat_DX.bas.bin

Link to comment
Share on other sites

...By the way, I like how you can push the other tank around. You seem to be coming along nicely....

 

Thanks for the compliment! :) My goal for this project, mainly, is to maintain the original "feel" of combat (tank mode), yet at the same time add a whole new degree of open-ended-ness to it. This, in which case, is only a taste of what's to come.

 

;)

 

BTW - One last problem before another release. Why does, when you push the tank to the edge with your tank, your tank pass through it and re-appear (as normal) on the other side?

 

Combat_DX.bas

Edited by Dragnerok X
Link to comment
Share on other sites

BTW - One last problem before another release. Why does, when you push the tank to the edge with your tank, your tank pass through it and re-appear (as normal) on the other side?

I haven't examined the code, but I'd guess it has something to do with the values of player0x and player1x, and how they're being processed whenever the tanks go past the edge of the screen and wrap around to the other side, or how they're being processed whenever the tanks collide with each other and one tank keeps pushing against the other one. If you can't figure out what's causing it-- and I don't have time to look into it tonight-- then one way to fix it might be to add some borders made up of playfield pixels at the edges of the screen, and prevent the tanks from passing through the borders.

 

Michael

Link to comment
Share on other sites

BTW - One last problem before another release. Why does, when you push the tank to the edge with your tank, your tank pass through it and re-appear (as normal) on the other side?

I haven't examined the code, but I'd guess it has something to do with the values of player0x and player1x, and how they're being processed whenever the tanks go past the edge of the screen and wrap around to the other side, or how they're being processed whenever the tanks collide with each other and one tank keeps pushing against the other one. If you can't figure out what's causing it-- and I don't have time to look into it tonight-- then one way to fix it might be to add some borders made up of playfield pixels at the edges of the screen, and prevent the tanks from passing through the borders.

 

Michael

 

O.K. That gave me an idea of what to look for. Just give me a day or so and it'll be fixed.

Link to comment
Share on other sites

O.K. I admit it. I'm stuck. :(

 

At least I was able to find the cause of it.

 

Ye Olde Combat Dx Code':

31 if collision(player0, player1) && x > v && c = 6 then x = x + 1

32 if collision(player0, player1) && x < v && c = 6 then x = x - 1

33 if collision(player0, player1) && y > w && c = 6 then y = y + 1

34 if collision(player0, player1) && y < w && c = 6 then y = y - 1

35 if collision(player1, player0) && v > x && c = 6 then v = v + 1

36 if collision(player1, player0) && v < x && c = 6 then v = v - 1

37 if collision(player1, player0) && w > y && c = 6 then w = w + 1

38 if collision(player1, player0) && w < y && c = 6 then w = w - 1

 

The bolded area says it all.

Edited by Dragnerok X
Link to comment
Share on other sites

O.K. I admit it. I'm stuck. :(

 

At least I was able to find the cause of it.

 

Ye Olde Combat Dx Code':

31 if collision(player0, player1) && x > v && c = 6 then x = x + 1

32 if collision(player0, player1) && x < v && c = 6 then x = x - 1

33 if collision(player0, player1) && y > w && c = 6 then y = y + 1

34 if collision(player0, player1) && y < w && c = 6 then y = y - 1

35 if collision(player1, player0) && v > x && c = 6 then v = v + 1

36 if collision(player1, player0) && v < x && c = 6 then v = v - 1

37 if collision(player1, player0) && w > y && c = 6 then w = w + 1

38 if collision(player1, player0) && w < y && c = 6 then w = w - 1

 

The bolded area says it all.

I still haven't had/don't have time to study your code, but one thing you might want to consider is using the "dim" statement to give bB's 26 user variables more self-explanatory names, so it will be easier for people to follow what your code is doing. For example, what are x, v, c, y, and w used for? I can make a pretty good guess, even without looking at the rest of your program-- x and y hold the (x,y) coordinates for player0, v and w hold the (x,y) coordinates for player1, and c maybe holds the number of times (frames?) that player0 and player1 have collided?

 

If that's the case, then I see some possible issues with your code. But before I say what they are, let me point out that you can use player0x, player0y, player1x, and player1y directly, instead of wasting 4 of bB's 26 user variables on them, because they're variables themselves, rather than registers. In other words, you *cannot* do something like "COLUBK = COLUBK + 2," because COLUBK is a color register, and you can't read it or do math on it like that, hence you'd need to use a variable to store the background color in, read it, and do math on it, then set the COLUBK register to the new value of the background color variable. But you *can* do something like "player0x = player0x + 1," or "if player0x > player1x," because player0x and player1x are variables that bB has defined and uses (since the TIA doesn't have registers for the players' coordinates).

 

Now, possible problem 1 is that you may need to jump over one or more of the other "if" statements after performing an "if." For example, after you've performed the "then" clause of the "if" in line 31, there's no point in doing line 32, because you've already determined that x > v, so you could do

 

31 if collision(player0, player1) && [b]x > v[/b] && c = 6 then x = x + 1 : goto 33
32 if collision(player0, player1) && [b]x < v[/b] && c = 6 then x = x - 1
33 if collision(player0, player1) && [b]y > w[/b] && c = 6 then y = y + 1 : goto 35
34 if collision(player0, player1) && [b]y < w[/b] && c = 6 then y = y - 1
35 if collision(player1, player0) && [b]v > x[/b] && c = 6 then v = v + 1 : goto 37
36 if collision(player1, player0) && [b]v < x[/b] && c = 6 then v = v - 1
37 if collision(player1, player0) && [b]w > y[/b] && c = 6 then w = w + 1 : goto 39
38 if collision(player1, player0) && [b]w < y[/b] && c = 6 then w = w - 1

Of course, it shouldn't make much difference, since the "then" clause in line 32 wouldn't be done anyway, except it wastes processor time to do the checks in line 32 after you've already determined (in line 31) that the checks in line 32 can be skipped over.

 

Possible problem 2 is that "collision(player0,player1)" and "collision(player1,player0)" are the same thing, because it doesn't matter what order the objects are in-- a collision between player0 and player1 is the same as a collision between player1 and player0. So what's happening is, you're doing some things twice. No, that's not exactly correct-- but what I mean is, having line 31 *and* line 36 is functionally equivalent to this:

 

31 if collision(player0, player1) && [b]x > v[/b] && c = 6 then x = x + 1 : v = v - 1

Furthermore, you're checking the same things more often than you need to, which is wasting a lot of processor time. The code you've posted could be optimized as follows:

 

31 if !collision(player0, player1) then goto 37 : rem * note the not (!)
32 if c <> 6 then goto 37
33 if player0x > player1x then player0x = player0x + 1 : player1x = player1x - 1 : goto 35
34 if player0x < player1x then player0x = player0x - 1 : player1x = player1x + 1
35 if player0y > player1y then player0y = player0y + 1 : player1y = player1y - 1 : goto 37
36 if player0y < player1y then player0y = player0y - 1 : player1y = player1y + 1
37 rem * continue with next part of code

In other words, if player0 and player1 are *not* colliding, skip ahead to line 37. Or, if c is *not* equal to 6, skip ahead to line 37. Otherwise, compare the x and y coordinates of player0 and player1, and update them accordingly. Note that I'm assuming-- or putting an "ass" before "u" and "me"-- that x, y, v, and w are being used to keep track of the player coordinates, in which case you can scrap the use of x, y, v, and w (throughout your program), and use the player0x, player0y, player1x, and player1y instead.

 

Now, even though your original snippet of code can be greatly optimized as shown above, I don't see any problem with it, because it seems reasonable that if the two tanks collide, then both of them will be knocked back. So that by itself probably isn't the problem.

 

However, there *are* some other possible problems, which may or may not be taken care of in other parts of your code (I haven't looked to see).

 

First, what are you doing if player0 and player1 are colliding, but c is not equal to 6 yet? Are you still updating the player coordinates without knocking the tanks back? If you are, then the tanks may be overlapping too much by the time c eventually gets to be equal to 6, such that the adjustments to the player coordinates aren't big enough, since the two tanks will probably still be overlapping after the screen is drawn with the new player coordinates.

 

Second, are you checking the player coordinates and adjusting them appropriately if they go past the screen boundaries?

 

And third-- which may be the real problem-- note that if a player gets close to the right edge of the screen, its shape will wraparound to the left side of the screen, such that the left portion of the shape will be on the right edge of the screen, and the right portion of the shape will be on the left edge of the screen. So what this means is, if one tank gets pushed off the edge of the screen and ends up on the other side, and you adjust its coordinates appropriately, but the other tank is still on the original side of the screen, then the coordinates of the two tanks won't compare the same any more. This is confusing explain, so let me try to put it into an example:

 

Suppose that player0x is 159, and player1x is 1, and the two tanks are colliding, since player0 is partly on the right side of the screen and partly on the left side of the screen, whereas player1 is fully on the left side of the screen (but overlapping with part of player0). Then your code is going to say that player0x is greater than player1x, so it will decrement player0x and increment player1x. Is that what you want to happen, or is that an error? If it is *not* what you want to have happen, then you will need to modify your comparisons to make them "smarter," by checking for cases where the two tanks are colliding even though one is at the left edge of the screen and the other is at the right edge of the screen-- maybe something like this:

 

31 if !collision(player0, player1) then goto 37 : rem * note the not (!)
32 if c <> 6 then goto 37
33a if player0x < 4 && player1x > 155 then goto 33c
33b if player0x <= player1x then goto 34a
33c player0x = player0x + 1 : player1x = player1x - 1 : goto 35
34a if player0x > 155 && player1x < 4 then goto 34c
34b if player0x >= player1x then goto 35
34c player0x = player0x - 1 : player1x = player1x + 1
35 if player0y > player1y then player0y = player0y + 1 : player1y = player1y - 1 : goto 37
36 if player0y < player1y then player0y = player0y - 1 : player1y = player1y + 1
37 rem * continue with next part of code

Now, I haven't checked the actual coordinate values that correspond to the left and right edges of the screen, so I'm not sure about the values I've used in the above code-- you may need to adjust them. But hopefully you'll understand what I'm trying to accomplish here. If the two players *are* colliding, the program will fall through line 31 and hit line 32. If c *is* equal to 6, the program will fall through line 32 and hit line 33a. So now we can compare the coordinates. But before we check for the simple situation, where the two tanks are side-by-side, we need to check for the weird case-- one tank near the left edge and the other tank near the right edge. If that's the situation, then we go to line 33c, where the coordinates are adjusted. Otherwise, we can do the normal check.

 

Note that the sprites do *not* wraparound from top to bottom or bottom to top, the way they do with the left and right edges of the screen.

 

I hope I haven't confused you too much! :ponder: It's definitely a weird kind of situation, and hard to explain easily without pictures.

 

Michael

Link to comment
Share on other sites

O.K. I admit it. I'm stuck. :(

 

At least I was able to find the cause of it.

 

Ye Olde Combat Dx Code':

31 if collision(player0, player1) && x > v && c = 6 then x = x + 1

32 if collision(player0, player1) && x < v && c = 6 then x = x - 1

33 if collision(player0, player1) && y > w && c = 6 then y = y + 1

34 if collision(player0, player1) && y < w && c = 6 then y = y - 1

35 if collision(player1, player0) && v > x && c = 6 then v = v + 1

36 if collision(player1, player0) && v < x && c = 6 then v = v - 1

37 if collision(player1, player0) && w > y && c = 6 then w = w + 1

38 if collision(player1, player0) && w < y && c = 6 then w = w - 1

 

The bolded area says it all.

I still haven't had/don't have time to study your code, but one thing you might want to consider is using the "dim" statement to give bB's 26 user variables more self-explanatory names, so it will be easier for people to follow what your code is doing. For example, what are x, v, c, y, and w used for? I can make a pretty good guess, even without looking at the rest of your program-- x and y hold the (x,y) coordinates for player0, v and w hold the (x,y) coordinates for player1, and c maybe holds the number of times (frames?) that player0 and player1 have collided?

 

If that's the case, then I see some possible issues with your code. But before I say what they are, let me point out that you can use player0x, player0y, player1x, and player1y directly, instead of wasting 4 of bB's 26 user variables on them, because they're variables themselves, rather than registers. In other words, you *cannot* do something like "COLUBK = COLUBK + 2," because COLUBK is a color register, and you can't read it or do math on it like that, hence you'd need to use a variable to store the background color in, read it, and do math on it, then set the COLUBK register to the new value of the background color variable. But you *can* do something like "player0x = player0x + 1," or "if player0x > player1x," because player0x and player1x are variables that bB has defined and uses (since the TIA doesn't have registers for the players' coordinates).

 

Now, possible problem 1 is that you may need to jump over one or more of the other "if" statements after performing an "if." For example, after you've performed the "then" clause of the "if" in line 31, there's no point in doing line 32, because you've already determined that x > v, so you could do

 

31 if collision(player0, player1) && [b]x > v[/b] && c = 6 then x = x + 1 : goto 33
32 if collision(player0, player1) && [b]x < v[/b] && c = 6 then x = x - 1
33 if collision(player0, player1) && [b]y > w[/b] && c = 6 then y = y + 1 : goto 35
34 if collision(player0, player1) && [b]y < w[/b] && c = 6 then y = y - 1
35 if collision(player1, player0) && [b]v > x[/b] && c = 6 then v = v + 1 : goto 37
36 if collision(player1, player0) && [b]v < x[/b] && c = 6 then v = v - 1
37 if collision(player1, player0) && [b]w > y[/b] && c = 6 then w = w + 1 : goto 39
38 if collision(player1, player0) && [b]w < y[/b] && c = 6 then w = w - 1

Of course, it shouldn't make much difference, since the "then" clause in line 32 wouldn't be done anyway, except it wastes processor time to do the checks in line 32 after you've already determined (in line 31) that the checks in line 32 can be skipped over.

 

Possible problem 2 is that "collision(player0,player1)" and "collision(player1,player0)" are the same thing, because it doesn't matter what order the objects are in-- a collision between player0 and player1 is the same as a collision between player1 and player0. So what's happening is, you're doing some things twice. No, that's not exactly correct-- but what I mean is, having line 31 *and* line 36 is functionally equivalent to this:

 

31 if collision(player0, player1) && [b]x > v[/b] && c = 6 then x = x + 1 : v = v - 1

Furthermore, you're checking the same things more often than you need to, which is wasting a lot of processor time. The code you've posted could be optimized as follows:

 

31 if !collision(player0, player1) then goto 37 : rem * note the not (!)
32 if c <> 6 then goto 37
33 if player0x > player1x then player0x = player0x + 1 : player1x = player1x - 1 : goto 35
34 if player0x < player1x then player0x = player0x - 1 : player1x = player1x + 1
35 if player0y > player1y then player0y = player0y + 1 : player1y = player1y - 1 : goto 37
36 if player0y < player1y then player0y = player0y - 1 : player1y = player1y + 1
37 rem * continue with next part of code

In other words, if player0 and player1 are *not* colliding, skip ahead to line 37. Or, if c is *not* equal to 6, skip ahead to line 37. Otherwise, compare the x and y coordinates of player0 and player1, and update them accordingly. Note that I'm assuming-- or putting an "ass" before "u" and "me"-- that x, y, v, and w are being used to keep track of the player coordinates, in which case you can scrap the use of x, y, v, and w (throughout your program), and use the player0x, player0y, player1x, and player1y instead.

 

Now, even though your original snippet of code can be greatly optimized as shown above, I don't see any problem with it, because it seems reasonable that if the two tanks collide, then both of them will be knocked back. So that by itself probably isn't the problem.

 

However, there *are* some other possible problems, which may or may not be taken care of in other parts of your code (I haven't looked to see).

 

First, what are you doing if player0 and player1 are colliding, but c is not equal to 6 yet? Are you still updating the player coordinates without knocking the tanks back? If you are, then the tanks may be overlapping too much by the time c eventually gets to be equal to 6, such that the adjustments to the player coordinates aren't big enough, since the two tanks will probably still be overlapping after the screen is drawn with the new player coordinates.

 

Second, are you checking the player coordinates and adjusting them appropriately if they go past the screen boundaries?

 

And third-- which may be the real problem-- note that if a player gets close to the right edge of the screen, its shape will wraparound to the left side of the screen, such that the left portion of the shape will be on the right edge of the screen, and the right portion of the shape will be on the left edge of the screen. So what this means is, if one tank gets pushed off the edge of the screen and ends up on the other side, and you adjust its coordinates appropriately, but the other tank is still on the original side of the screen, then the coordinates of the two tanks won't compare the same any more. This is confusing explain, so let me try to put it into an example:

 

Suppose that player0x is 159, and player1x is 1, and the two tanks are colliding, since player0 is partly on the right side of the screen and partly on the left side of the screen, whereas player1 is fully on the left side of the screen (but overlapping with part of player0). Then your code is going to say that player0x is greater than player1x, so it will decrement player0x and increment player1x. Is that what you want to happen, or is that an error? If it is *not* what you want to have happen, then you will need to modify your comparisons to make them "smarter," by checking for cases where the two tanks are colliding even though one is at the left edge of the screen and the other is at the right edge of the screen-- maybe something like this:

 

31 if !collision(player0, player1) then goto 37 : rem * note the not (!)
32 if c <> 6 then goto 37
33a if player0x < 4 && player1x > 155 then goto 33c
33b if player0x <= player1x then goto 34a
33c player0x = player0x + 1 : player1x = player1x - 1 : goto 35
34a if player0x > 155 && player1x < 4 then goto 34c
34b if player0x >= player1x then goto 35
34c player0x = player0x - 1 : player1x = player1x + 1
35 if player0y > player1y then player0y = player0y + 1 : player1y = player1y - 1 : goto 37
36 if player0y < player1y then player0y = player0y - 1 : player1y = player1y + 1
37 rem * continue with next part of code

Now, I haven't checked the actual coordinate values that correspond to the left and right edges of the screen, so I'm not sure about the values I've used in the above code-- you may need to adjust them. But hopefully you'll understand what I'm trying to accomplish here. If the two players *are* colliding, the program will fall through line 31 and hit line 32. If c *is* equal to 6, the program will fall through line 32 and hit line 33a. So now we can compare the coordinates. But before we check for the simple situation, where the two tanks are side-by-side, we need to check for the weird case-- one tank near the left edge and the other tank near the right edge. If that's the situation, then we go to line 33c, where the coordinates are adjusted. Otherwise, we can do the normal check.

 

Note that the sprites do *not* wraparound from top to bottom or bottom to top, the way they do with the left and right edges of the screen.

 

I hope I haven't confused you too much! :ponder: It's definitely a weird kind of situation, and hard to explain easily without pictures.

 

Michael

 

Nice guesses, you pretty much were on target. I get what your saying about the x/y positions being two places at once and such, so I'll see what I can do, but I'd at least like to thank you for helping crunch my code down a bit.

 

:)

Link to comment
Share on other sites

Combat DX Demo 4: Player 2

 

Combat_DX.bas

 

Combat_DX___Demo_4.bin

 

Demo 4 is here, and with a ton of changes. First off, there's a second player! Next, I've added code in for the not-yet-implemented AI mode (both players) which can be toggled with each player's difficulty switch ("A" is on). Also, I boxed the playfield off invisibly because of technical constriants (thanks for the suggestion, atari2600land). Finally the code is better organized, but still not smaller than the last release!

 

:)

 

BTW: We've just hit attachment ID 66666.

 

:evil:

Link to comment
Share on other sites

  • 2 weeks later...

This game's not dead yet! :D

 

I just been very busy lately, however, I've already gotten started on a primative firing system for this, using the x/y/v/w variables the tanks used to use. Which leads me to why I posted.

 

Why the heck is the second player's tank popping up from the bottom of the screen when I start?

 

Oh well, at least I know how the programmers at microsoft feel with all these bugs!

 

:lolblue:

 

Microsoft%20Bug%20List.gif

 

Combat_DX.bas

Edited by Dragnerok X
Link to comment
Share on other sites

Why the heck is the second player's tank popping up from the bottom of the screen when I start?

Hey, that actually looks pretty cool! :) Too bad you can't have tanks pop up like that out of nowhere, like gophers popping out of the ground, and let the player try to shoot (or avoid getting shot by) the other tanks before they disappear again. "Be vehhhhhwwy qwiet, I'm hunting wabbit tanks!" :D

 

If I can figure out what's going on, I'll let you know.

 

Michael

Link to comment
Share on other sites

Why the heck is the second player's tank popping up from the bottom of the screen when I start?

If I can figure out what's going on, I'll let you know.

I haven't figured out why yet, but I figured out where and what. Line 46 is where, and player1y being (repeatedly) decremented because it's greater than 88 is what. You do initialize player1y to 50, so it must be that player1y is getting set or incremented to some value greater than 88, thereby causing line 46 to kick in and slide the player1 tank up into view until player1y is no longer greater than 88.

Link to comment
Share on other sites

Thanks for the tip, I just fixed it. :)

 

Actually, this bug was kind of strange, and yet painfully obvious. What it was, was that there was too much code on line two so it ended up completely ignoring the "player1y = 50" and thus started it out on the bottom causing my "inviso-wall" code to push it upwards. The reason why it didn't effect tank one (the red tank) was because tank one's code was placed earlier on line two.

 

Easy fix, just re-arranged the code on lines one and two.

 

Combat_DX.bas

Link to comment
Share on other sites

Thanks for the tip, I just fixed it. :)

 

Actually, this bug was kind of strange, and yet painfully obvious. What it was, was that there was too much code on line two so it ended up completely ignoring the "player1y = 50" and thus started it out on the bottom causing my "inviso-wall" code to push it upwards. The reason why it didn't effect tank one (the red tank) was because tank one's code was placed earlier on line two.

 

Easy fix, just re-arranged the code on lines one and two.

I actually considered that possibility, but I thought the line should be short enough, and I didn't take the time to check the assembly listing. If I had, I would have seen that the line was too long.

 

Here's a helpful tip: Modify your compile/assemble batch file so that DASM generates a listing when it assembles your program. Listing files can be very large-- especially with bB programs, because the way the include files are coded causes some of the include files (e.g., the VCS.H file) to be included multiple times. Thus, if you're worried about disk space, you might want to periodically delete all of your bB assembly code files (*.bas.asm) and bB assembly listing files (*.bas.lst), since the only files you need to keep are the bB code files (*.bas) and bB binary files (*.bas.bin).

 

To tell DASM to generate an assembly listing, edit your bB compile batch file and add "-l%1.lst" to the end of the DASM command line, as follows:

 

dasm.exe %1.asm -f3 -o%1.bin -l%1.lst

Sometimes the bB assembly code file (*.bas.asm) will show you what you're looking for-- as it does in this case (see below)-- but it won't show you the code that's inside the include files (just the code that's generated for your bB program), it won't show you the machine code and addresses (just the assembly source code), and it won't show you any DASM error messages. It's been my experience that sometimes you need to see the code that's in the include files, the machine code and addresses, or-- most especially-- the DASM error messages. Anyway, if you look at the Combat_DX.bas.asm file and search for "player1y" (since that's the thing that you're having trouble with), you'll see that bB converts the second line into the following assembly code:

 

.2; 2 k  =  0  :  l  =  0  :  m  =  0  :  n  =  0  :  o  =  0  :  p  =  0  :
q  =  0  :  r  =  0  :  s  =  0  :  player0x  =  40  :  player0y  =  50  :
player1x  =  140  :  player1y  =  50

LDA #0
STA k
STA l
STA m
STA n
STA o
STA p
STA q
STA r
STA s
LDA #40
STA player0x
LDA #50
STA player0y
LDA #140
STA player1x
STA player1y

As you can see, bB didn't *entirely* "ignore" the last statement on line 2, because the "player1y =" portion of the statement must have fit within the maximum line length, and only the "50" went over the limit. So apparently bB saw the "player1y =" without a number after it, and ended up setting player1y to the same value that it was setting player1x to. In this case it was a bug caused by the line being too long, but as you can see in the first part of line 2, it's something that bB does to help optimize the assembly code for the ROM space. I'm thinking the bB compiler should have put out an error message about the maximum line length being exceeded when it tried to parse "player1y =" and couldn't find anything after the "=". But even so, you can see that looking at the *.bas.asm or *.bas.lst file can help you find where the problems are in your program.

 

Michael

Edited by SeaGtGruff
Link to comment
Share on other sites

I actually considered that possibility, but I thought the line should be short enough, and I didn't take the time to check the assembly listing. If I had, I would have seen that the line was too long.

 

Here's a helpful tip: Modify your compile/assemble batch file so that DASM generates a listing when it assembles your program. Listing files can be very large-- especially with bB programs, because the way the include files are coded causes some of the include files (e.g., the VCS.H file) to be included multiple times. Thus, if you're worried about disk space, you might want to periodically delete all of your bB assembly code files (*.bas.asm) and bB assembly listing files (*.bas.lst), since the only files you need to keep are the bB code files (*.bas) and bB binary files (*.bas.bin).

 

To tell DASM to generate an assembly listing, edit your bB compile batch file and add "-l%1.lst" to the end of the DASM command line, as follows:

 

dasm.exe %1.asm -f3 -o%1.bin -l%1.lst

 

Sometimes the bB assembly code file (*.bas.asm) will show you what you're looking for-- as it does in this case (see below)-- but it won't show you the code that's inside the include files (just the code that's generated for your bB program), it won't show you the machine code and addresses (just the assembly source code), and it won't show you any DASM error messages. It's been my experience that sometimes you need to see the code that's in the include files, the machine code and addresses, or-- most especially-- the DASM error messages. Anyway, if you look at the Combat_DX.bas.asm file and search for "player1y" (since that's the thing that you're having trouble with), you'll see that bB converts the second line into the following assembly code:

 

.2; 2 k  =  0  :  l  =  0  :  m  =  0  :  n  =  0  :  o  =  0  :  p  =  0  :
q  =  0  :  r  =  0  :  s  =  0  :  player0x  =  40  :  player0y  =  50  :
player1x  =  140  :  player1y  =  50

LDA #0
STA k
STA l
STA m
STA n
STA o
STA p
STA q
STA r
STA s
LDA #40
STA player0x
LDA #50
STA player0y
LDA #140
STA player1x
STA player1y

 

As you can see, bB didn't *entirely* "ignore" the last statement on line 2, because the "player1y =" portion of the statement must have fit within the maximum line length, and only the "50" went over the limit. So apparently bB saw the "player1y =" without a number after it, and ended up setting player1y to the same value that it was setting player1x to. In this case it was a bug caused by the line being too long, but as you can see in the first part of line 2, it's something that bB does to help optimize the assembly code for the ROM space. I'm thinking the bB compiler should have put out an error message about the maximum line length being exceeded when it tried to parse "player1y =" and couldn't find anything after the "=". But even so, you can see that looking at the *.bas.asm or *.bas.lst file can help you find where the problems are in your program.

 

Michael

 

Hmm...enlightening. I always thought it parsed code statement-by-statement, but apparently not. I'll see if I can get a listing file set up like you suggested, especially with how often I run into bugs.

 

Well...the good news is that I already have gotten most of the firing figured out, I just have to implement it. Oh well, back to work!

 

;)

Link to comment
Share on other sites

An interesting bug I found is if you press "fire" you can no longer move the tanks. If this has been mentioned, my apologies.

 

No, actually, it hasn't been mentioned. The thing is though is that it's not really a bug, just a missing feature. I haven't finished the firing yet, but once it's done that and possibly a few more things will be fixed. Also I've been kicking around the idea of a playfield based, well...playfield, kind of like Gosub. My apologies if I break any copyrights (or ligaments from typing all this code!).

 

;)

Link to comment
Share on other sites

Well, since I'm going to be going on a trip for a while (Disneyland, no less :D ), I thought i'd post up my current code, bin, and a little status.

 

Right now, the firing works, but it still needs some work before it will be usable.

 

Here's my definition of "Working".

 

-Both players have missiles which can be controlled using the fire button and necessary collisions have been accounted for.

 

However...

 

1. The missiles only move when the player is pressing fire, and stay there when the player is not.

 

2 The collision detection on the sides of the "battlefield" need's tweaking. (I used the players collision #'s so I have to account for that ~8 pixel difference

 

3. When backing up the tank the missile also "backs up".

 

4. The code is in serious need of reorganization.

 

So, in short, it works. But barely...

 

Combat_DX.bas

 

Combat_DX.bas.bin

 

Comments?

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