Jump to content
IGNORED

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


Dragnerok X

Recommended Posts

O.k. I'm back! :) So... :ponder:

Heh, I haven't really tested the last version you posted, I've been kind of busy/distracted by other things in the last week. So I'll give it a play tonight and let you know. :)

 

Michael

 

Thanks. I understand with gosub and all that you've been quite busy lately so I'll try not too bug you too much.

Link to comment
Share on other sites

Heh, I haven't really tested the last version you posted, I've been kind of busy/distracted by other things in the last week. So I'll give it a play tonight and let you know. :)

 

Michael

 

Thanks. I understand with gosub and all that you've been quite busy lately so I'll try not too bug you too much.

I just tried it out, and the missile is quite... interesting. Here's something you might want to do, just for fun: Fire the missile, and then start spinning in a circle while you keep firing. :) That might even be useful for doing a "guided missile"! :cool: But the missile should keep moving once it's fired. That *is* what you want, right-- for the missile to keep moving on its own?

 

Michael

Link to comment
Share on other sites

That *is* what you want, right-- for the missile to keep moving on its own?

 

Michael

 

Exactly. ;) I'm just not sure how to do it quite yet.

Well, if you haven't started changing the code again yet, I can post a version that I was "cleaning up" (i.e., changing to more of my own coding style-- no line numbers, use of line labels only where needed, etc.). I can also try to get the missile working correctly-- although I'll probably leave the "guided missile" behavior as is, because I think it's kind of cool (but I can see where it might get aggravating if the player wanted to fire and duck, since the action of ducking would make the missile change direction).

 

Michael

Link to comment
Share on other sites

Well, if you haven't started changing the code again yet, I can post a version that I was "cleaning up" (i.e., changing to more of my own coding style-- no line numbers, use of line labels only where needed, etc.). I can also try to get the missile working correctly-- although I'll probably leave the "guided missile" behavior as is, because I think it's kind of cool (but I can see where it might get aggravating if the player wanted to fire and duck, since the action of ducking would make the missile change direction).

 

Michael

 

Sure, why not? :D Actually, I haven't even touched the code yet (I was waiting for a response from you, irronically) so well... have at it!

 

BTW: I like the guided missiles too, it started as more of a "bug" than a feature though. Just see if you can keep the missile from going backwards, o.k.?

Edited by Dragnerok X
Link to comment
Share on other sites

BTW: I like the guided missiles too, it started as more of a "bug" than a feature though. Just see if you can keep the missile from going backwards, o.k.?

Why not backwards, too? If the tank fires a "SCUD" missile and it goes past the other tank, he might want to turn it back around and try to hit the tank from behind. :D

 

Michael

Link to comment
Share on other sites

BTW: I like the guided missiles too, it started as more of a "bug" than a feature though. Just see if you can keep the missile from going backwards, o.k.?

Why not backwards, too? If the tank fires a "SCUD" missile and it goes past the other tank, he might want to turn it back around and try to hit the tank from behind. :D

 

Michael

 

Hmm...never thought of that. Sure then, does this mean that this could add a "kamikaze" feature to the game (you can kill your tank)?

 

;)

Edited by Dragnerok X
Link to comment
Share on other sites

Okay, here is a partially "cleaned up" version of the code, with the missiles corrected so that they keep moving once fired, until they either go off the screen or hit something. I think I compiled it using Chris's score graphics file, so you might want to recompile it with the normal score graphics-- but then, you aren't displaying a score right now, so the difference isn't visible yet, although it will make a difference in the number of bytes free in bank 2.

 

Michael

 

PS -- You might want to rename this thread back to Combat_DX or something.

combat_DX.bas

Combat_DX.bas.bin

Edited by SeaGtGruff
Link to comment
Share on other sites

Okay, here is a partially "cleaned up" version of the code, with the missiles corrected so that they keep moving once fired, until they either go off the screen or hit something. I think I compiled it using Chris's score graphics file, so you might want to recompile it with the normal score graphics-- but then, you aren't displaying a score right now, so the difference isn't visible yet, although it will make a difference in the number of bytes free in bank 2.

 

Michael

Nice! :cool: I downloaded the source over my existing and it compiled great, but even better was the clean-up you did. It's so open it's almost scarry! :o I guess this should motivate me to work on this more, but to tell you the truth all I can say is WOW.

 

PS -- You might want to rename this thread back to Combat_DX or something.

Good idea, but how?

 

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

 

BTW: 5 things...

 

1. I'm going to see if I can keep the tank from firing backwards, it seems odd and yet kinda cheap.

 

2. I'm also going to see if I can ramp up the speed of the missiles a bit (to give "guiding" missiles a little challenge/realism.

 

3. I've got an idea on how to increase this games rom space by 4 times! Why not just assign names to the tank sprites, link player 1 and two to both and mirror those decreasing the sprite count to eight?

 

4. Instead of having the tanks spin, I'm thinking of using a killing off/respawning approach and possibly using missile command's mushroom cloud effect for the explosions.

 

5. I guess after all that is done I can release demo five.

Edited by Dragnerok X
Link to comment
Share on other sites

Nice! :cool: I downloaded the source over my existing and it compiled great, but even better was the clean-up you did. It's so open it's almost scarry! :o I guess this should motivate me to work on this more, but to tell you the truth all I can say is WOW.

There are a lot of ways that you (and other bB programmers of course) can change your coding styles to help save ROM and RAM. It seems like some bB programmers come to the language with a history of having programmed in BASIC before, and of having to use line numbers, plus having to try to squeeze the code into the smallest possible space by putting as many statements as possible in each line of code, plus (in some cases) having to use very short variable names, plus being used to special keywords in a particular computer's version of BASIC. That means you may need to unlearn a few things when you start writing programs in bB, because bB doesn't require line numbers (and it actually uses line *labels* instead of line *numbers*); the programs are compiled and assembled rather than interpreted, so the size of the source code doesn't really come into play the way that it does with BASICs that have to keep the program code in memory while the program is running; you can use long and descriptive names instead of short and non-descriptive names (including using names instead of numbers for your routines' line labels); and a lot of bB's keywords (e.g., "player0x" and "missile0height") are actually just variable names for RAM addresses that bB uses for specific purposes-- what I call "bB system variables," as opposed to the "a" to "z" "bB user variables." So in many cases, I have seen bB programmers do something like "player0x = x" in their programs, and do a lot of things to update "x" in the code, when they could save some ROM and RAM by simply updating "player0x" directly.

 

Anyway, there is a lot more that I can do to "clean up" your code-- I actually haven't worked on it very much yet. If you want to give it a try yourself, go for it! :)

 

What I usually do is start by putting a carriage return after every line number, and then indenting each line by three spaces (just because I think that three spaces helps those lines stand out better from the line labels), as follows:

 

10 rem * before cleanup
20 a=0:b=1:c=0:d=1:goto 100
30 if a=6 then a=0:goto 60
40 if a<6 then goto 60
50 if a>6 then a=0:goto 60
60 if joy0up then b=b+1
70 if joy0down then b=b-1
80 player0x=a
90 player0y=b
100 drawscreen
110 goto 30

10
  rem * cleanup, step 1
20
  a=0:b=1:c=0:d=1:goto 100
30
  if a=6 then a=0:goto 60
40
  if a<6 then goto 60
50
  if a>6 then a=0:goto 60
60
  if joy0up then b=b+1
70
  if joy0down then b=b-1
80
  player0x=a
90
  player0y=b
100
  drawscreen
110
  goto 30

At the same time that I'm doing that, I put each statement on a line by itself, unless it's part of an "if...then...else" or "for...next," as follows:

 

10
  rem * cleanup, step 2
20
  a=0
  b=1
  c=0
  d=1
  goto 100
30
  if a=6 then a=0:goto 60
40
  if a<6 then goto 60
50
  if a>6 then a=0:goto 60
60
  if joy0up then b=b+1
70
  if joy0down then b=b-1
80
  player0x=a
90
  player0y=b
100
  drawscreen
110
  goto 30

Additionally, I generally put a space around each operator (i.e., "+" or "-" or "=" and so forth), because I think it helps make the code easier to read, as follows:

 

10
  rem * cleanup, step 3
20
  a = 0
  b = 1
  c = 0
  d = 1
  goto 100
30
  if a = 6 then a = 0 : goto 60
40
  if a < 6 then goto 60
50
  if a > 6 then a = 0 : goto 60
60
  if joy0up then b = b + 1
70
  if joy0down then b = b - 1
80
  player0x = a
90
  player0y = b
100
  drawscreen
110
  goto 30

Next, I determine which line numbers or line labels are actually being referenced somewhere in the program (since those ones will *not* be able to be deleted). To do that, I either search for the line number to see if it's referenced anywhere, or I add " rem " in front of the line number (e.g., "100" would become " rem 100") and then compile to see whether or not I get errors. If the line number isn't actually needed, then I remove it, as follows:

 

  rem * cleanup, step 3
  a = 0
  b = 1
  c = 0
  d = 1
  goto 100
30
  if a = 6 then a = 0 : goto 60
  if a < 6 then goto 60
  if a > 6 then a = 0 : goto 60
60
  if joy0up then b = b + 1
  if joy0down then b = b - 1
  player0x = a
  player0y = b
100
  drawscreen
  goto 30

Note that I generally do those first four steps all at once, from top to bottom as I go through the program.

 

Next, I start looking for places where the code can be optimized somehow. For example, if you initialize two variables to the same value, but you either put the two statements on separate lines, or put them on the same line but with something else between them, then bB takes more bytes to translate the bB code into assembly code:

 

 ; a = 0
  LDA #0
  STA a

 ; b = 1
  LDA #1
  STA b

 ; c = 0
  LDA #0
  STA c

 ; d = 1
  LDA #1
  STA d

On the other hand, if you put the variables being initialized to the same value on the same line as each other, and right next to each other, then bB can save a few bytes when it converts the bB code into assembly code:

 

 ; a = 0 : c = 0
  LDA #0
  STA a
  STA c

 ; b = 1 : d = 1
  LDA #1
  STA b
  STA d

The first version took 16 bytes, but the second version took only 12 bytes. Depending on how many identical values you string together like that, and how many times you can string similar assignment statements together like that in your program, you could end up saving a *huge* number of bytes! So now our little program looks like this:

 

  rem * cleanup, step 4
  a = 0 : c = 0
  b = 1 : d = 1
  goto 100
30
  if a = 6 then a = 0 : goto 60
  if a < 6 then goto 60
  if a > 6 then a = 0 : goto 60
60
  if joy0up then b = b + 1
  if joy0down then b = b - 1
  player0x = a
  player0y = b
100
  drawscreen
  goto 30

Another thing I do is see if there are any initializations at the beginning of the code that aren't needed. For instance, none of the lines before line 30 in our little sample program will be performed more than once, since the program doesn't loop back up to those lines. And bB automatically clears (or "zeros") all of the page zero memory locations while the bB program is starting up for the first time. Thus, there's no need to set any variables to 0 at the beginning of the program, unless the program loops bavk to those lines so it can perform them again when needed (e.g., when the game is being restarted after the player has lost). So we can simply a little further as follows:

 

  rem * cleanup, step 5
  b = 1 : d = 1
  goto 100
30
  if a = 6 then a = 0 : goto 60
  if a < 6 then goto 60
  if a > 6 then a = 0 : goto 60
60
  if joy0up then b = b + 1
  if joy0down then b = b - 1
  player0x = a
  player0y = b
100
  drawscreen
  goto 30

Also, in this little program, "player0x" and "player0y" are being set to "a" and "b" respectively, and the program is doing stuff with "a" and "b"-- but there's no reason why the program can't be changing "player0x" and "player0y" directly, by replacing "a" with "player0x" and by replacing "b" with "player0y" as follows:

 

  rem * cleanup, step 5
  player0y = 1 : d = 1
  goto 100
30
  if player0x = 6 then player0x = 0 : goto 60
  if player0x < 6 then goto 60
  if player0x > 6 then player0x = 0 : goto 60
60
  if joy0up then player0y = player0y + 1
  if joy0down then player0y = player0y - 1
100
  drawscreen
  goto 30

You have to be careful when making those sorts of changes, because you have to check all the places first to make sure it's going to be okay to replace the bB user variable with the bB system variable.

 

Next, I look for places (especially involving the "if" statements) where the logic can be simplified, as follows:

 

  rem * cleanup, step 5
  player0y = 1 : d = 1
  goto 100
30
  if player0x >= 6 then player0x = 0
  if joy0up then player0y = player0y + 1
  if joy0down then player0y = player0y - 1
100
  drawscreen
  goto 30

After the code has been simplified to where it's a little easier for a stranger (e.g., me) to read it and understand what it's trying to do, then the bB user variable names can be replaced by longer descriptive names with "dim" statements, and uninformative line numbers can be replaced by self-explanatory line labels, as follows:

 

  rem * cleanup, step 6
  dim weird_variable_that_isnt_even_being_used_anywhere = d
  player0y = 1 : weird_variable_that_isnt_even_being_used_anywhere = 1
  goto draw_the_screen
main_kernel_loop
  if player0x >= 6 then player0x = 0
  if joy0up then player0y = player0y + 1
  if joy0down then player0y = player0y - 1
draw_the_screen
  drawscreen
  goto main_kernel_loop

Of course, our little sample program is complete crap (e.g., it will draw just a black screen, since no colors are being set, and the player0 movements don't really make much sense), and there are ways it might be optimized even more (e.g., by removing the lines involving the "d" variable that isn't actually being used for anything)-- but it does illustrate how a bB program written with an "old style BASIC" coding style can be made easier to read and understand, and can be optimized so that it takes up less ROM space and needs to use fewer bB user variables.

 

PS -- You might want to rename this thread back to Combat_DX or something.

Good idea, but how?

I guess I was saying that we should stop posting in this thread, and you should start a new thread with a better name to continue the discussion! :D

 

1. I'm going to see if I can keep the tank from firing backwards, it seems odd and yet kinda cheap.

I think that if you're going to have "guided missiles" or "SCUD missiles," then it makes sense to let the tank direct them in a "backwards" direction, too.

 

However, I think you should either have two different types of missiles in the game (i.e., guided SCUD missiles and non-guided-- but aimed-- tank artillery), or else have different game variations (some with SCUD missiles, and some with tank artillery).

 

I'm not sure how you could do both types of missiles at the same time in a game-- not in terms of the logic, which shouldn't be a problem, but rather in terms of the game controllers. For example, you could say that if the player fires a SCUD missile, and moves the joystick while pressing the fire button, then the tank doesn't move, but the movement of the SCUD missile can be controlled. But how would the player inform the program that he (or she) wants to fire a SCUD missile rather than tank artillery, or vice versa-- maybe by flipping the difficulty switch?

 

2. I'm also going to see if I can ramp up the speed of the missiles a bit (to give "guiding" missiles a little challenge/realism.

I think that would be good, because the missiles do seem to move too slowly.

 

3. I've got an idea on how to increase this games rom space by 4 times! Why not just assign names to the tank sprites, link player 1 and two to both and mirror those decreasing the sprite count to eight?

I understand the mirroring, but I'm not certain that I understand what you mean about linking player0 with player1. You *can* do something like that, but I'm not certain that you understand how to do it, so let me explain it. First of all, note that you *cannot* change the names of "player0" and "player1" in the statements that define their graphics. But you *can* manually set the pointers and height variables for player0 and player1 in your program, which lets you do what you're thinking of doing. I'll have to see if I can post a little sample program to illustrate this.

 

4. Instead of having the tanks spin, I'm thinking of using a killing off/respawning approach and possibly using missile command's mushroom cloud effect for the explosions.

I like the mushroom cloud idea, but you might want to try a variety of things for destroying the tanks. For example, if you have variables to store each tank's "hit points," plus variables to store each tank's "fire power," then you could let each tank's hit points go down as it's hit. If the tank still has more hit points, it survives the hit, but maybe (or maybe not) it gets knocked into a spin. If the tank loses all its hit points, then it blows up with a mushroom cloud. If you let the tanks get killed, then you could start each player with a certain number of tanks, and let them earn an extra tank every so many points (if they don't lose all of their tanks first). Then, bonus points could be awarded to the survivor at the end, maybe with additional bonus points awarded for each spare tank he has left. Then it could be up to the players to decide between themselves whether "winning the game" was determined by the number of points earned, or who survived. :D

 

5. I guess after all that is done I can release demo five.

I think "Combat" is a fun game to play-- if you have someone to play it with you-- so it would be nice to see you do a "Combat"-like game that puts a new "spin" on things. I think you should probably add some landmarks or terrain to give the tanks something to hide behind, and it would be cool if you could somehow let the tanks move around from one screen to another. The problem with that is, it's hard to let one player move around from screen to screen while there's supposed to be another player in the game. I just had an idea, though-- a split screen, with the left half for player0, and the right half for player1. You could let the players move around independently of each other, but if they find each other (i.e., are in the same "room" or screen), then they see each other and can fire at each other. I'll have to work up a little test to see if or how that works.

 

Michael

Link to comment
Share on other sites

There are a lot of ways that you (and other bB programmers of course) can change your coding styles to help save ROM and RAM. It seems like some bB programmers come to the language with a history of having programmed in BASIC before, and of having to use line numbers, plus having to try to squeeze the code into the smallest possible space by putting as many statements as possible in each line of code, plus (in some cases) having to use very short variable names, plus being used to special keywords in a particular computer's version of BASIC. That means you may need to unlearn a few things when you start writing programs in bB, because bB doesn't require line numbers (and it actually uses line *labels* instead of line *numbers*); the programs are compiled and assembled rather than interpreted, so the size of the source code doesn't really come into play the way that it does with BASICs that have to keep the program code in memory while the program is running; you can use long and descriptive names instead of short and non-descriptive names (including using names instead of numbers for your routines' line labels); and a lot of bB's keywords (e.g., "player0x" and "missile0height") are actually just variable names for RAM addresses that bB uses for specific purposes-- what I call "bB system variables," as opposed to the "a" to "z" "bB user variables." So in many cases, I have seen bB programmers do something like "player0x = x" in their programs, and do a lot of things to update "x" in the code, when they could save some ROM and RAM by simply updating "player0x" directly.

 

Anyway, there is a lot more that I can do to "clean up" your code-- I actually haven't worked on it very much yet. If you want to give it a try yourself, go for it! :)

 

What I usually do is start by putting a carriage return after every line number, and then indenting each line by three spaces (just because I think that three spaces helps those lines stand out better from the line labels), as follows:

 

10 rem * before cleanup
20 a=0:b=1:c=0:d=1:goto 100
30 if a=6 then a=0:goto 60
40 if a<6 then goto 60
50 if a>6 then a=0:goto 60
60 if joy0up then b=b+1
70 if joy0down then b=b-1
80 player0x=a
90 player0y=b
100 drawscreen
110 goto 30

10
  rem * cleanup, step 1
20
  a=0:b=1:c=0:d=1:goto 100
30
  if a=6 then a=0:goto 60
40
  if a<6 then goto 60
50
  if a>6 then a=0:goto 60
60
  if joy0up then b=b+1
70
  if joy0down then b=b-1
80
  player0x=a
90
  player0y=b
100
  drawscreen
110
  goto 30

At the same time that I'm doing that, I put each statement on a line by itself, unless it's part of an "if...then...else" or "for...next," as follows:

 

10
  rem * cleanup, step 2
20
  a=0
  b=1
  c=0
  d=1
  goto 100
30
  if a=6 then a=0:goto 60
40
  if a<6 then goto 60
50
  if a>6 then a=0:goto 60
60
  if joy0up then b=b+1
70
  if joy0down then b=b-1
80
  player0x=a
90
  player0y=b
100
  drawscreen
110
  goto 30

Additionally, I generally put a space around each operator (i.e., "+" or "-" or "=" and so forth), because I think it helps make the code easier to read, as follows:

 

10
  rem * cleanup, step 3
20
  a = 0
  b = 1
  c = 0
  d = 1
  goto 100
30
  if a = 6 then a = 0 : goto 60
40
  if a < 6 then goto 60
50
  if a > 6 then a = 0 : goto 60
60
  if joy0up then b = b + 1
70
  if joy0down then b = b - 1
80
  player0x = a
90
  player0y = b
100
  drawscreen
110
  goto 30

Next, I determine which line numbers or line labels are actually being referenced somewhere in the program (since those ones will *not* be able to be deleted). To do that, I either search for the line number to see if it's referenced anywhere, or I add " rem " in front of the line number (e.g., "100" would become " rem 100") and then compile to see whether or not I get errors. If the line number isn't actually needed, then I remove it, as follows:

 

  rem * cleanup, step 3
  a = 0
  b = 1
  c = 0
  d = 1
  goto 100
30
  if a = 6 then a = 0 : goto 60
  if a < 6 then goto 60
  if a > 6 then a = 0 : goto 60
60
  if joy0up then b = b + 1
  if joy0down then b = b - 1
  player0x = a
  player0y = b
100
  drawscreen
  goto 30

Note that I generally do those first four steps all at once, from top to bottom as I go through the program.

 

Next, I start looking for places where the code can be optimized somehow. For example, if you initialize two variables to the same value, but you either put the two statements on separate lines, or put them on the same line but with something else between them, then bB takes more bytes to translate the bB code into assembly code:

 

; a = 0
  LDA #0
  STA a

; b = 1
  LDA #1
  STA b

; c = 0
  LDA #0
  STA c

; d = 1
  LDA #1
  STA d

On the other hand, if you put the variables being initialized to the same value on the same line as each other, and right next to each other, then bB can save a few bytes when it converts the bB code into assembly code:

 

; a = 0 : c = 0
  LDA #0
  STA a
  STA c

; b = 1 : d = 1
  LDA #1
  STA b
  STA d

The first version took 16 bytes, but the second version took only 12 bytes. Depending on how many identical values you string together like that, and how many times you can string similar assignment statements together like that in your program, you could end up saving a *huge* number of bytes! So now our little program looks like this:

 

  rem * cleanup, step 4
  a = 0 : c = 0
  b = 1 : d = 1
  goto 100
30
  if a = 6 then a = 0 : goto 60
  if a < 6 then goto 60
  if a > 6 then a = 0 : goto 60
60
  if joy0up then b = b + 1
  if joy0down then b = b - 1
  player0x = a
  player0y = b
100
  drawscreen
  goto 30

Another thing I do is see if there are any initializations at the beginning of the code that aren't needed. For instance, none of the lines before line 30 in our little sample program will be performed more than once, since the program doesn't loop back up to those lines. And bB automatically clears (or "zeros") all of the page zero memory locations while the bB program is starting up for the first time. Thus, there's no need to set any variables to 0 at the beginning of the program, unless the program loops bavk to those lines so it can perform them again when needed (e.g., when the game is being restarted after the player has lost). So we can simply a little further as follows:

 

  rem * cleanup, step 5
  b = 1 : d = 1
  goto 100
30
  if a = 6 then a = 0 : goto 60
  if a < 6 then goto 60
  if a > 6 then a = 0 : goto 60
60
  if joy0up then b = b + 1
  if joy0down then b = b - 1
  player0x = a
  player0y = b
100
  drawscreen
  goto 30

Also, in this little program, "player0x" and "player0y" are being set to "a" and "b" respectively, and the program is doing stuff with "a" and "b"-- but there's no reason why the program can't be changing "player0x" and "player0y" directly, by replacing "a" with "player0x" and by replacing "b" with "player0y" as follows:

 

  rem * cleanup, step 5
  player0y = 1 : d = 1
  goto 100
30
  if player0x = 6 then player0x = 0 : goto 60
  if player0x < 6 then goto 60
  if player0x > 6 then player0x = 0 : goto 60
60
  if joy0up then player0y = player0y + 1
  if joy0down then player0y = player0y - 1
100
  drawscreen
  goto 30

You have to be careful when making those sorts of changes, because you have to check all the places first to make sure it's going to be okay to replace the bB user variable with the bB system variable.

 

Next, I look for places (especially involving the "if" statements) where the logic can be simplified, as follows:

 

  rem * cleanup, step 5
  player0y = 1 : d = 1
  goto 100
30
  if player0x >= 6 then player0x = 0
  if joy0up then player0y = player0y + 1
  if joy0down then player0y = player0y - 1
100
  drawscreen
  goto 30

After the code has been simplified to where it's a little easier for a stranger (e.g., me) to read it and understand what it's trying to do, then the bB user variable names can be replaced by longer descriptive names with "dim" statements, and uninformative line numbers can be replaced by self-explanatory line labels, as follows:

 

  rem * cleanup, step 6
  dim weird_variable_that_isnt_even_being_used_anywhere = d
  player0y = 1 : weird_variable_that_isnt_even_being_used_anywhere = 1
  goto draw_the_screen
main_kernel_loop
  if player0x >= 6 then player0x = 0
  if joy0up then player0y = player0y + 1
  if joy0down then player0y = player0y - 1
draw_the_screen
  drawscreen
  goto main_kernel_loop

Of course, our little sample program is complete crap (e.g., it will draw just a black screen, since no colors are being set, and the player0 movements don't really make much sense), and there are ways it might be optimized even more (e.g., by removing the lines involving the "d" variable that isn't actually being used for anything)-- but it does illustrate how a bB program written with an "old style BASIC" coding style can be made easier to read and understand, and can be optimized so that it takes up less ROM space and needs to use fewer bB user variables.

 

Educational! I'm fine with what you already did, but if I run into any thing else like that, at least I'll know what to do.

 

I guess I was saying that we should stop posting in this thread, and you should start a new thread with a better name to continue the discussion! :D

 

Hmm...sounds good. I think a good time to move would be around demo 5 (when I actually have something kind of interesting to show people!). However, for the move, should I keep this up in the Bb forum or move this to the "homebrew discussion" for more exposure?

 

I think that if you're going to have "guided missiles" or "SCUD missiles," then it makes sense to let the tank direct them in a "backwards" direction, too.

 

However, I think you should either have two different types of missiles in the game (i.e., guided SCUD missiles and non-guided-- but aimed-- tank artillery), or else have different game variations (some with SCUD missiles, and some with tank artillery).

 

I'm not sure how you could do both types of missiles at the same time in a game-- not in terms of the logic, which shouldn't be a problem, but rather in terms of the game controllers. For example, you could say that if the player fires a SCUD missile, and moves the joystick while pressing the fire button, then the tank doesn't move, but the movement of the SCUD missile can be controlled. But how would the player inform the program that he (or she) wants to fire a SCUD missile rather than tank artillery, or vice versa-- maybe by flipping the difficulty switch?

 

Both difficulty switches are being used by the soon-to-come AI so we can't do that, but I'm working on polishing up the missile physics right now, I'll send (or post) you a demo when I'm done.

 

I think that would be good, because the missiles do seem to move too slowly.

 

Already done, will come with the missile demo.

 

I understand the mirroring, but I'm not certain that I understand what you mean about linking player0 with player1. You *can* do something like that, but I'm not certain that you understand how to do it, so let me explain it. First of all, note that you *cannot* change the names of "player0" and "player1" in the statements that define their graphics. But you *can* manually set the pointers and height variables for player0 and player1 in your program, which lets you do what you're thinking of doing. I'll have to see if I can post a little sample program to illustrate this.

 

Exactly it. Tell me more.

 

I like the mushroom cloud idea, but you might want to try a variety of things for destroying the tanks. For example, if you have variables to store each tank's "hit points," plus variables to store each tank's "fire power," then you could let each tank's hit points go down as it's hit. If the tank still has more hit points, it survives the hit, but maybe (or maybe not) it gets knocked into a spin. If the tank loses all its hit points, then it blows up with a mushroom cloud. If you let the tanks get killed, then you could start each player with a certain number of tanks, and let them earn an extra tank every so many points (if they don't lose all of their tanks first). Then, bonus points could be awarded to the survivor at the end, maybe with additional bonus points awarded for each spare tank he has left. Then it could be up to the players to decide between themselves whether "winning the game" was determined by the number of points earned, or who survived. :D

 

Sounds good, but would probably require variables which don't exist right now. I'll think about it.

 

I think "Combat" is a fun game to play-- if you have someone to play it with you-- so it would be nice to see you do a "Combat"-like game that puts a new "spin" on things. I think you should probably add some landmarks or terrain to give the tanks something to hide behind, and it would be cool if you could somehow let the tanks move around from one screen to another. The problem with that is, it's hard to let one player move around from screen to screen while there's supposed to be another player in the game. I just had an idea, though-- a split screen, with the left half for player0, and the right half for player1. You could let the players move around independently of each other, but if they find each other (i.e., are in the same "room" or screen), then they see each other and can fire at each other. I'll have to work up a little test to see if or how that works.

 

Michael

 

Nicely said. I like to think of this, in a way, as the "people's combat" (within reason ;)). I'd also like to think that this program widely demonstrates the flexability of Bb (to date, not one line was written in assembly). About the terrain, I've been thinking about that for quite some time. My first idea was to just use the multisprite kernel for one stationary object per line, but would require flickering when both players touched a line where, for example, a tree was, which would get annoying after a while and would require some serious coding. My second approach (currently) is that of Gosub's, just with the traditional "sandy rock" color topping the playfield. All I am certain of now is that, for sure, demo 6 will be the playfield. However, I'm completely open to any ideas (which includes your "little test", no seriously, that sounds pretty good) that you, or anyone else, may have.

Link to comment
Share on other sites

I guess I was saying that we should stop posting in this thread, and you should start a new thread with a better name to continue the discussion! :D

 

Hmm...sounds good. I think a good time to move would be around demo 5 (when I actually have something kind of interesting to show people!). However, for the move, should I keep this up in the Bb forum or move this to the "homebrew discussion" for more exposure?

How about both? You could post the bB code and the .BINs in the bB forum, especially if you want to discuss the bB code, but you could also post the .BINs in the homebrews forum, without the bB code and bB discussions. Or something like that.

 

I understand the mirroring, but I'm not certain that I understand what you mean about linking player0 with player1. You *can* do something like that, but I'm not certain that you understand how to do it, so let me explain it. First of all, note that you *cannot* change the names of "player0" and "player1" in the statements that define their graphics. But you *can* manually set the pointers and height variables for player0 and player1 in your program, which lets you do what you're thinking of doing. I'll have to see if I can post a little sample program to illustrate this.

 

Exactly it. Tell me more.

Well, I've just found out that defining the shapes as simple data tables, and then setting the player graphics pointers manually, has a few things you need to be careful of, otherwise it doesn't work! :)

 

Here is an example demo I wrote that displays two sprites, which cycle between 8 different shapes (arrows pointing in 8 directions), using only 5 shape tables. I defined the shape tables using inline assembly, but you could also use bB's data statement. The code in this example isn't optimized; for one thing, I keep setting the heights, even though in this example the heights are always 8. :)

 

I'm not going to try explaining the code line-by-line, but the general procedure is to define the shape tables somewhere in your code. Note that none of the shape tables should cross a page boundary, or there could be problems displaying the shapes correctly. In this example, I got lucky and didn't have to worry about it, because all of the shape tables fell within the same page (block of 256 bytes). But there's a way you can automatically ensure that the shape tables are positioned safely, which is how bB does it when you use the player0 command. (I'm not going to try to explain it right now, but I can explain it tomorrow night if you wish.) You also need to define some equates for the lo and hi bytes of the addresses for the shape tables. Then you set the lo and hi bytes of bB's player pointers to the lo and high bytes of the shape tables, using the equates. (There might be a way to do this without using inline assembly, but I'm not going to try it tonight.) You also need to set the player's height, as well as the player's reflection flag.

 

Note that you won't be able to quarter the ROM space needed for the player shapes, as you thought, because the tank shapes that are facing northward and southward are not reflections of each other. If you want tank shapes that can face in 16 directions, then you'll need 9 shape tables-- half of the number of directions, plus 1. So instead of 32 shape tables (16 for player0, and 16 for player1), you will have 9.

 

Another thing you'll need to be careful of is that reflecting a player's shape can affect its horizontal position on the screen, depending on if there are any blank pixel columns on the left or right sides of the player shape, as illustrated below:

 

%11110000
%11000000
%10100000
%10010000
%00001000

normal:
XXXX
XX
X X
X  X
X

reflected:
XXXX
  XX
 X X
X  X
  X

What this means is that you might need to adjust the x position of the sprite to nudge it a little bit left or right (1 pixel for each blank column), in order to keep its position the same, when you reflect the shape. This might not be an issue in your case, because I think maybe the only shapes you'll be reflecting are 8 pixels wide anyway (I didn't doublecheck to verify this).

 

it would be cool if you could somehow let the tanks move around from one screen to another. The problem with that is, it's hard to let one player move around from screen to screen while there's supposed to be another player in the game. I just had an idea, though-- a split screen, with the left half for player0, and the right half for player1. You could let the players move around independently of each other, but if they find each other (i.e., are in the same "room" or screen), then they see each other and can fire at each other. I'll have to work up a little test to see if or how that works.

I'm not going to try to post a split screen test tonight, but I will start on one. I think it could work-- a maze of "rooms" that the two players can move around in, with the left side of the screen showing the room that player 1 is in, and the right half showing the room that player 2 is in. If I remember correctly, the old "Spy vs. Spy" game did something similar, except the screen was split into a top half and bottom half. The idea is the same, though-- let the two players move around a maze of multiple screens independently of each other, and if they happen to be in the same room then they are both displayed in both windows.

 

Michael

Reusable_Players_Demo.bas

Reusable_Players_Demo.bas.bin

Link to comment
Share on other sites

How about both? You could post the bB code and the .BINs in the bB forum, especially if you want to discuss the bB code, but you could also post the .BINs in the homebrews forum, without the bB code and bB discussions. Or something like that.

Sure. May I suggest we keep this forum for the Bb portion? (because of all the discussion/contributed work that's on here?)

 

Well, I've just found out that defining the shapes as simple data tables, and then setting the player graphics pointers manually, has a few things you need to be careful of, otherwise it doesn't work! :)

 

Here is an example demo I wrote that displays two sprites, which cycle between 8 different shapes (arrows pointing in 8 directions), using only 5 shape tables. I defined the shape tables using inline assembly, but you could also use bB's data statement. The code in this example isn't optimized; for one thing, I keep setting the heights, even though in this example the heights are always 8. :)

 

I'm not going to try explaining the code line-by-line, but the general procedure is to define the shape tables somewhere in your code. Note that none of the shape tables should cross a page boundary, or there could be problems displaying the shapes correctly. In this example, I got lucky and didn't have to worry about it, because all of the shape tables fell within the same page (block of 256 bytes). But there's a way you can automatically ensure that the shape tables are positioned safely, which is how bB does it when you use the player0 command. (I'm not going to try to explain it right now, but I can explain it tomorrow night if you wish.) You also need to define some equates for the lo and hi bytes of the addresses for the shape tables. Then you set the lo and hi bytes of bB's player pointers to the lo and high bytes of the shape tables, using the equates. (There might be a way to do this without using inline assembly, but I'm not going to try it tonight.) You also need to set the player's height, as well as the player's reflection flag.

 

Note that you won't be able to quarter the ROM space needed for the player shapes, as you thought, because the tank shapes that are facing northward and southward are not reflections of each other. If you want tank shapes that can face in 16 directions, then you'll need 9 shape tables-- half of the number of directions, plus 1. So instead of 32 shape tables (16 for player0, and 16 for player1), you will have 9.

 

Another thing you'll need to be careful of is that reflecting a player's shape can affect its horizontal position on the screen, depending on if there are any blank pixel columns on the left or right sides of the player shape, as illustrated below:

 

%11110000
%11000000
%10100000
%10010000
%00001000

normal:
XXXX
XX
X X
X  X
X

reflected:
XXXX
  XX
 X X
X  X
  X

What this means is that you might need to adjust the x position of the sprite to nudge it a little bit left or right (1 pixel for each blank column), in order to keep its position the same, when you reflect the shape. This might not be an issue in your case, because I think maybe the only shapes you'll be reflecting are 8 pixels wide anyway (I didn't doublecheck to verify this).

 

Definetly something to look into. I, like you said, may have to adjust a few values to get it to work, but... once I'm done setting up the missiles and all, I'll see what I can do.

 

I'm not going to try to post a split screen test tonight, but I will start on one. I think it could work-- a maze of "rooms" that the two players can move around in, with the left side of the screen showing the room that player 1 is in, and the right half showing the room that player 2 is in. If I remember correctly, the old "Spy vs. Spy" game did something similar, except the screen was split into a top half and bottom half. The idea is the same, though-- let the two players move around a maze of multiple screens independently of each other, and if they happen to be in the same room then they are both displayed in both windows.

 

Michael

 

Could be a little hard to do, none-the-less, I'll take a look at that Spy vs. Spy game a bit tonight to see what your getting at exactly, but more importantly, I can't wait to see the demo!

 

BTW: The missiles are becoming very annoying, however, I'm trying my best to get most everything I mentioned yesterday into the game (I'm really thinking about eliminating the "butt firing" as I call it, but I can't really find a suitable approach). Like I said before, though, as soon as I'm done, I'll post it.

Link to comment
Share on other sites

I'll take a look at that Spy vs. Spy game a bit tonight to see what your getting at exactly, but more importantly, I can't wait to see the demo!

Here's a link to a Wikipedia article, which includes a screenshot of the game.

 

http://en.wikipedia.org/wiki/Spy_vs._Spy_%28computer_game%29

 

BTW: The missiles are becoming very annoying, however, I'm trying my best to get most everything I mentioned yesterday into the game (I'm really thinking about eliminating the "butt firing" as I call it, but I can't really find a suitable approach).

If the "guided SCUD missiles" (which, after all, were actually a bug) are too annoying, then just do away with them-- at least until you can add an option for the player to choose either non-guided or guided missiles. To have the missiles travel in a continuing straight line (in the same direction the tank was facing when it fired), you just need to have two variables to hold the x and y values for the missile's motion, and freeze them whenever the tank fires a new missile. The problem you had with the missiles not moving unless the fire button was kept depressed, was because you kept resetting the flags (s and r, I think they were) during each frame, and then setting them if the fire button was pressed. Once the flags are turned on, they should stay on so the missiles keep moving, until they either hit something or go off the screen. Likewise with the missiles' directional variables-- when the fire button is first pressed, thus turning on the missile's flag, you should set the missile's directional variables to whatever the tank's directional variables are at that time, and then leave them at those values as long as the missile's flag is still set, no matter how the tank's firectional variables change.

 

Michael

Link to comment
Share on other sites

If the "guided SCUD missiles" (which, after all, were actually a bug) are too annoying, then just do away with them-- at least until you can add an option for the player to choose either non-guided or guided missiles. To have the missiles travel in a continuing straight line (in the same direction the tank was facing when it fired), you just need to have two variables to hold the x and y values for the missile's motion, and freeze them whenever the tank fires a new missile. The problem you had with the missiles not moving unless the fire button was kept depressed, was because you kept resetting the flags (s and r, I think they were) during each frame, and then setting them if the fire button was pressed. Once the flags are turned on, they should stay on so the missiles keep moving, until they either hit something or go off the screen. Likewise with the missiles' directional variables-- when the fire button is first pressed, thus turning on the missile's flag, you should set the missile's directional variables to whatever the tank's directional variables are at that time, and then leave them at those values as long as the missile's flag is still set, no matter how the tank's firectional variables change.

 

Michael

 

I guess I should try that then! :)

Link to comment
Share on other sites

Finally! I have not only gotten the missiles to fire straight, but I have also stopped the "butt firing"!!!

 

:cool:

 

...with one catch22. :ponder:

 

You can't fire when in "reverse". It shouldn't be too big of a problem (heck, it might even add to the challenge :D) , but I thought I'd just let you know first.

 

Here's your "missile demo".

 

Combat_DX.bas

 

Combat_DX.bas.bin

 

Note: This demo is not "demo 5", so to speak. It may show some (if not most) of the main concepts of demo 5, but there are still a few features I want to add (like tank-death) before I'm done working on the firing. However, this should give you a good taste of what's to come.

Link to comment
Share on other sites

You can't fire when in "reverse".

You should be able to fix that easily. Since you must be using separate variables to keep track of the direction the tank is pointing in, as well as the direction it's moving in, then if the tank fires while it's in reverse, have the missile move in the direction the tank is pointing in, rather than the direction the tank is moving in.

 

Of course, in the real world, a tank can spin its barrel around in 360 degrees and fire in any direction regardless of which way it's moving-- but that would be very difficult to do on the Atari 2600, due to the limitations of the sprites. It's already tricky to draw the tank pointing in 16 directions, using only 8 (or fewer) pixels across.

 

Michael

Link to comment
Share on other sites

You can't fire when in "reverse".

You should be able to fix that easily. Since you must be using separate variables to keep track of the direction the tank is pointing in, as well as the direction it's moving in, then if the tank fires while it's in reverse, have the missile move in the direction the tank is pointing in, rather than the direction the tank is moving in.

 

Of course, in the real world, a tank can spin its barrel around in 360 degrees and fire in any direction regardless of which way it's moving-- but that would be very difficult to do on the Atari 2600, due to the limitations of the sprites. It's already tricky to draw the tank pointing in 16 directions, using only 8 (or fewer) pixels across.

 

Michael

 

That just gave me an idea on how to fix it! :)

 

You see, the reason it was firing in reverse in the first place was because when you back up the tank, I "tricked" the game into keeping the player sprite the same, but reversing the physics (includes missiles). My earlier soluition was to get rid of the firing all together, but since the tank and firing now operate on seperate variables I could just "tweak" the firing 180 degrees, when in reverse, to compensate.

Link to comment
Share on other sites

Of course, in the real world, a tank can spin its barrel around in 360 degrees and fire in any direction regardless of which way it's moving-- but that would be very difficult to do on the Atari 2600, due to the limitations of the sprites. It's already tricky to draw the tank pointing in 16 directions, using only 8 (or fewer) pixels across.

 

I wonder how it would work if pressing and holding the fire button locked the tank's motion until the button was released, and the direction of the joystick when releasing the fire button determined the angle to fire relative to the tank? It might take some getting used to, but allowing tanks to shoot in multiple directions could make the game interesting.

 

I was also pondering a twist for an airplane version of Combat: guided missiles plus Gorf-style firing. Either player would probably be able to chase down the other with a missile and blow him up, except of course that the other player would be trying to do the same to him.

Link to comment
Share on other sites

I wonder how it would work if pressing and holding the fire button locked the tank's motion until the button was released, and the direction of the joystick when releasing the fire button determined the angle to fire relative to the tank? It might take some getting used to, but allowing tanks to shoot in multiple directions could make the game interesting.

I agree. Even though the directional changes in the first version of the missiles was caused by a programming oversight, I thought it was cool in that it turned the artillery into SCUD missiles. :) I'd still like to see that implemented as an option in the final game. Likewise with being able to rotate the turret(?) while the main body of the tank remains pointed in another direction. And I think the turret *should* rotate if the player can shoot in other directions. Then, if you rotate (steer) the tank as it's moving, the turret could stay locked in the same direction relative to the tank (e.g., 90 degrees left of whichever direction the tank is moving), until the turret is rotated again. Aside from the logistics of the game controls, the only other issue is drawing all the graphics for the tank, in all its variations.

 

I was also pondering a twist for an airplane version of Combat: guided missiles plus Gorf-style firing. Either player would probably be able to chase down the other with a missile and blow him up, except of course that the other player would be trying to do the same to him.

That sounds good, too! :)

 

Michael

Link to comment
Share on other sites

Aside from the logistics of the game controls, the only other issue is drawing all the graphics for the tank, in all its variations.

 

For that, it would probably be necessary to use 16 bytes of RAM to hold the tank graphics (8 bytes each) and generate combination sprites with a turret XOR'ed with the rotating tank shape. That would in turn require having a kernel that takes the playfield data out of ROM. I think such an option exists, but I have no idea how one would go about it.

Link to comment
Share on other sites

Aside from the logistics of the game controls, the only other issue is drawing all the graphics for the tank, in all its variations.

 

For that, it would probably be necessary to use 16 bytes of RAM to hold the tank graphics (8 bytes each) and generate combination sprites with a turret XOR'ed with the rotating tank shape. That would in turn require having a kernel that takes the playfield data out of ROM. I think such an option exists, but I have no idea how one would go about it.

I thought about that, too, but I was thinking more in terms of using Superchip RAM. That would eat up 256 bytes from the beginning of each bank, but it would add a lot more variables. A sizable chunk of bank 2 is used for the tank graphics, and you couldn't get rid of all of it, because it's hard to copy something into RAM if you don't have a copy of it in ROM first. ;) But the ROM for the tank graphics could be nearly quartered, which would free up some ROM in bank 2. There's already over 256 bytes free in each bank, but some of it will need to be used for additional routines, plus playfield graphics. And it ought to be possible to free up more ROM space by optimizing some code.

 

Michael

Link to comment
Share on other sites

Almost done. I've got a working routine, but not enough rom to support it. Any suggestions on how I could crunch this code down a bit?

 

(the e = statements need to be in there somehow.)

 

  if t = 1 && a = 1 && e = 0 then v = 1
  if t = 1 && a = 2 && e = 0 then v = 2
  if t = 1 && a = 3 && e = 0 then v = 3
  if t = 1 && a = 4 && e = 0 then v = 4 
  if t = 1 && a = 5 && e = 0 then v = 5
  if t = 1 && a = 6 && e = 0 then v = 6 
  if t = 1 && a = 7 && e = 0 then v = 7
  if t = 1 && a = 8 && e = 0 then v = 8
  if t = 1 && a = 9 && e = 0 then v = 9
  if t = 1 && a = 10 && e = 0 then v = 10
  if t = 1 && a = 11 && e = 0 then v = 11
  if t = 1 && a = 12 && e = 0 then v = 12
  if t = 1 && a = 13 && e = 0 then v = 13
  if t = 1 && a = 14 && e = 0 then v = 14
  if t = 1 && a = 15 && e = 0 then v = 15
  if t = 1 && a = 16 && e = 0 then v = 16 
  if t = 1 && a = 1 && e = 1 then v = 9
  if t = 1 && a = 2 && e = 1 then v = 10
  if t = 1 && a = 3 && e = 1 then v = 11
  if t = 1 && a = 4 && e = 1 then v = 12
  if t = 1 && a = 5 && e = 1 then v = 13
  if t = 1 && a = 6 && e = 1 then v = 14
  if t = 1 && a = 7 && e = 1 then v = 15
  if t = 1 && a = 8 && e = 1 then v = 16
  if t = 1 && a = 9 && e = 1 then v = 1
  if t = 1 && a = 10 && e = 1 then v = 2
  if t = 1 && a = 11 && e = 1 then v = 3
  if t = 1 && a = 12 && e = 1 then v = 4
  if t = 1 && a = 13 && e = 1 then v = 5
  if t = 1 && a = 14 && e = 1 then v = 6
  if t = 1 && a = 15 && e = 1 then v = 7
  if t = 1 && a = 16 && e = 1 then v = 8 

 

Combat_DX.bas

Link to comment
Share on other sites

Any suggestions on how I could crunch this code down a bit?

Here are three suggestions. I presume that the third would take up the smallest ROM space.

 

  if t <> 1 then goto line_1
  if e <> 0 then goto line_2
  v = a
  goto line_1
line_2
  if e <> 1 then goto line_1
  v = a + 8
  if v > 17 then v = v - 16
line_1

  if t = 1 && e = 0 then v = a
  if t = 1 && e = 1 then v = a + 8 : if v > 17 then v = v - 16

  if t = 1 then v = a + 8 * e : if v > 17 then v = v - 16

By the way, if you ever have a long series of ifs that contain similar ands or ors (&& or ||), you can almost always simplify (and optimize) them by taking out the similar portions and making them separate ifs, and have it jump over the other ifs if the condition isn't met (e.g., all of your original ifs had "if t = 1," so use "if t <> 1" to jump over the other ifs). And once you start simplifying in these ways, you can generally end up with something even simpler-- the way you can take a very complicated equation, start to simplify it in different ways, with each simplification giving rise to further possible simplifications, until you end up with something that looks much simpler than the original and yet says exactly the same thing!

 

Michael

Link to comment
Share on other sites

  if t = 1 then v = a + 8 * e : if v > 17 then v = v - 16

I should add that this simplified version isn't *exactly* equivalent as the original, because it doesn't check the values of a and e, but rather assumes that a will always be between 1 and 16 inclusive, and e will always be either 0 or 1.

 

Michael

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