Jump to content



0

bB "target" practice - advice?


14 replies to this topic

#1 Snider-man OFFLINE  

Snider-man

    Stargunner

  • 1,987 posts
  • Doofenshmirtz Evil Incorporated

Posted Mon Aug 4, 2008 7:55 AM

Howdy!

I'm having a bit of a dilemma and I'm looking for the obvious solution that I'm missing.

Let's pretend you're designing a game based on the ice game of curling. Let's say you draw a simple open box with background elements:

*****
*----*
*----*
*****

And you slide a sprite in the direction of the "target". When the sprite eventually comes to a stop, I want to test whether the sprite falls outside of the box; on the box itself; or falls within the box. Testing for background element collision is straightforward, but how can I check for the other two (outside and inside) when there really are no elements for the sprite to "hit?" Is it a matter of mapping out the position of the interior of the box and everything that isn't there or "on the box" is "outside?"

This seemed simple enough, but I'm kind of going in circles here...

Edited by Snider-man, Mon Aug 4, 2008 7:56 AM.


#2 yuppicide OFFLINE  

yuppicide

    I am the Black Knight. Give me your money!

  • 6,933 posts
  • Location:New Jersey

Posted Mon Aug 4, 2008 9:41 AM

Now, keep in mind I'm only a beginner as well, but what about this. Let's say you're drawing the box out of Playfield.

How about making a multicolored playfield?

So your playfield will look like

....XXXXXXX....
....XXXXXXX....
....XX......XX....
....XX......XX....
....XX......XX....
....XXXXXXX....
....XXXXXXX....

Now, I don't know how multicolored playfields work since I've never done one so far. Anyway, the outerbox would be painted the same color as the background so it's invisible. The inside box would be colored to show the box. Then you would use a routine to check if your object landed on a certain spot.. if it landed on one of the outside the box totally you get no points. If you land on the outer invisible box you get less points, inside visible box more points, and fully inside the box you get even more points.

There's probably a better way to do things, but this is what I thought of.

Edited by yuppicide, Mon Aug 4, 2008 9:42 AM.


#3 Random Terrain ONLINE  

Random Terrain

    Visual batari Basic User

  • 20,911 posts
  • Controlled Randomness
    Replay Value
    Nonlinear
  • Location:North Carolina (USA)

Posted Mon Aug 4, 2008 1:55 PM

Someone better than all of us might use an array:

http://www.randomter...html#dataarrays

http://www.randomter...nds.html#pfread


Since I'm not a pro programmer, I'd probably try to use collision detection and if-then statements that checked the position. If I failed miserably, then I'd try an array.

#4 SeaGtGruff OFFLINE  

SeaGtGruff

    River Patroller

  • 4,543 posts
  • Location:Georgia, USA

Posted Mon Aug 4, 2008 2:18 PM

View PostSnider-man, on Mon Aug 4, 2008 8:55 AM, said:

When the sprite eventually comes to a stop, I want to test whether the sprite falls outside of the box; on the box itself; or falls within the box. Testing for background element collision is straightforward, but how can I check for the other two (outside and inside) when there really are no elements for the sprite to "hit?"
Convert the player's x and y position into a pfpixel position, and check it that way. The exact conversion formulas will vary depending on a few things. I'll assume you're using bB v1.0, standard kernel. Are you using no_blank_lines? How large is your player-- i.e., do you use all 8 pixels across, and how many lines tall is it? Also, what are the dimensions of the box, is it always the same size (width and height)?

Michael

#5 Snider-man OFFLINE  

Snider-man

    Stargunner

  • 1,987 posts
  • Doofenshmirtz Evil Incorporated

Posted Sat Sep 13, 2008 4:12 PM

Still working on the scoring/collision detection, as well as some other velocity/aiming issues. But here's a screenshot of the WIP.

Posted Image

Always wanted a dart sim for the ol' 2600.

#6 SeaGtGruff OFFLINE  

SeaGtGruff

    River Patroller

  • 4,543 posts
  • Location:Georgia, USA

Posted Sat Sep 13, 2008 8:24 PM

View PostSnider-man, on Sat Sep 13, 2008 6:12 PM, said:

Still working on the scoring/collision detection, as well as some other velocity/aiming issues. But here's a screenshot of the WIP.

Posted Image

Always wanted a dart sim for the ol' 2600.
It looks interesting! I have a few comments/suggestions/questions.

(1) It might be good to put more distance between the dart's initial position and the dartboard. I realize you've got the line as far to the right as you can get it, and the dartboard as far left as you can get it, given that the playfield is limited to just the 32 centermost pfpixels. But with a few simple changes to bB's standard kernel, you can trade PF2 for PF0-- i.e., you'll get a playfield that's split into two halves, with 12 pfpixels on the left (the left copies of PF0 and PF1), and 12 pfpixels on the right (the right copies of PF1 and PF0), and with a gap of 16 unused pfpixels in the center (the left and right copies of PF2). This is very easy to do, and I've already done it before for someone else, so I can make the same change for you if you're interested. Then you could move the dartboard a little further to the left, and move the line a little further to the right. I'm guessing you might want to leave at least 1 blank pfpixel column to the left of the dartboard, so the dart has a place to "hit the wall" if the player overshoots the dartboard. And I'd suggest leaving 2 blank pfpixel columns to the right of the line.

(2) You could also get more distance between the dart and the dartboard by moving the dart just behind the line (if there's no particular reason why you want it just in front of the line). That's why I suggested leaving 2 blank pfpixel columns to the right of the line-- to leave room for the dart. Or am I missing something because it's a still image? For example, does the dart start out right on the line, and then swing back and forth a little bit to either side of the line, to simulate someone who's standing on the line, moving their hand back and forth before releasing the dart?

(3) Have you worked out the collision-detection logic yet? I'd forget about checking for a collision between the player sprite and the playfield, and just use the coordinates for the tip of the dart once it comes to a stop. That is, you would convert the player's x coordinate into an equivalent pfpixel column number, and convert the player's y coordinate into an equivalent pfpixel row number. Then it would be easy to tell, based on those two values, whether the dart hit the dartboard or not, and which red or black circle it hit. Assuming you're going to have two darts, with two different colors (for competing players), you could even tell which dart is closest to the center of the bull's eye.

Michael

#7 Snider-man OFFLINE  

Snider-man

    Stargunner

  • 1,987 posts
  • Doofenshmirtz Evil Incorporated

Posted Mon Sep 15, 2008 5:52 AM

All very good comments and stuff I've considered/am working out.

1. A wider playfield would be preferable, but not sure if I want to go that way or not. I have some specific plans that require a playfield of this size. And the bar to the left is a "powerbar" (but it also marks the far left border for now as well). And if the player "overshoots" the board, it's just as easy to test for "off the screen" rather than a blank pfline behind it, so it should be fine where it is.

2. As explained, the line is a powerbar so it doesn't serve the same purpose as the official "stand behind this line" line in regulation darts.

3. Pretty much the very idea I had. Just working on the details now. Will post a BIN once I have the collision detection sort of working like I want it.

#8 yuppicide OFFLINE  

yuppicide

    I am the Black Knight. Give me your money!

  • 6,933 posts
  • Location:New Jersey

Posted Mon Sep 15, 2008 7:34 AM

I'm not really a darts fan, but it's looking good so far.

#9 SeaGtGruff OFFLINE  

SeaGtGruff

    River Patroller

  • 4,543 posts
  • Location:Georgia, USA

Posted Mon Sep 15, 2008 11:31 AM

View PostSnider-man, on Mon Sep 15, 2008 6:52 AM, said:

All very good comments and stuff I've considered/am working out.

1. A wider playfield would be preferable, but not sure if I want to go that way or not. I have some specific plans that require a playfield of this size. And the bar to the left is a "powerbar" (but it also marks the far left border for now as well). And if the player "overshoots" the board, it's just as easy to test for "off the screen" rather than a blank pfline behind it, so it should be fine where it is.

2. As explained, the line is a powerbar so it doesn't serve the same purpose as the official "stand behind this line" line in regulation darts.

3. Pretty much the very idea I had. Just working on the details now. Will post a BIN once I have the collision detection sort of working like I want it.
I fiddled with the playfield but it didn't work. Looking back at what I'd done last year, it was a change in the multisprite kernel. Apparently the playfield timing is either much tighter, or just plain different, in the standard kernel, so it would be a lot trickier (or maybe even impossible) to make that change.

OK, gotcha on the powerbar thing. I wonder if you could use the ball for the powerbar (because you could get a finer vertical resolution), and then let the playfield line be for the "don't stand beyond this point" line? Or vice versa, use the ball to draw a thin "stand here" line? That's assuming there would be any value in having such a line-- like, if the player could "step forward" or "step backward" before tossing the dart.

Later tonight I can post the X and Y values to convert the dart's final position into the equivalent dartboard positions. I did a list of them last night, but I need to put them into if statements. Also, how tall is your dart sprite? The image you posted needs only 5 lines for the player, but some bB programmers seem to think they need to define 8 lines even if the last few are completely blank (or first few), and the player's height will affect the conversion from player coordinates to playfield coordinates.

Michael

#10 SeaGtGruff OFFLINE  

SeaGtGruff

    River Patroller

  • 4,543 posts
  • Location:Georgia, USA

Posted Tue Sep 16, 2008 1:42 AM

Here's a little program I did using your dartboard display, to see how the player's X and Y positions relate to the playfield. The score shows the player's X and Y coordinates as you move the dart around with the joystick.

And here are the relationships between the dart's X and Y coordinates and the dartboard:

x < 17 : left of dartboard
x = 17 to 20 : outer red
x = 21 to 24 : middle black
x = 25 to 28 : middle red
x = 29 to 32 : inner black
x = 33 to 36 : center
x = 37 to 40 : inner black
x = 41 to 44 : middle red
x = 45 to 48 : middle black
x = 49 to 52 : outer red
x > 52 : right of dartboard

y < 9 : above dartboard
y = 9 to 17 (16?) : outer red
y = 17 to 25 (24?) : middle black
y = 25 to 33 (32?) : middle red
y = 33 to 41 (40?) : inner black
y = 41 to 49 : center
y = 49 (50?) to 57 : inner black
y = 57 (58?) to 65 : middle red
y = 65 (66?) to 73 : middle black
y = 73 (74?) to 81 : outer red
y > 81 : below dartboard

The Y positions are a little problematic, because the dart can hit "on the line" between a red zone and a black zone. So I'm assuming that if the dart lands on a line, it will be counted as having hit the higher-scoring portion of the dartboard. One way you might combine the X and Y positions is with the following code (change the variables to fit your program):

   dim board_x = a
   dim board_y = b
   dim circle = c

   if player0x > 52 then board_x = 0
   if player0x < 53 then board_x = 1
   if player0x < 49 then board_x = 2
   if player0x < 45 then board_x = 3
   if player0x < 41 then board_x = 4
   if player0x < 37 then board_x = 5
   if player0x < 33 then board_x = 4
   if player0x < 29 then board_x = 3
   if player0x < 25 then board_x = 2
   if player0x < 21 then board_x = 1
   if player0x < 17 then board_x = 0

   if player0y > 81 then board_y = 0
   if player0y < 82 then board_y = 1
   if player0y < 74 then board_y = 2
   if player0y < 66 then board_y = 3
   if player0y < 58 then board_y = 4
   if player0y < 50 then board_y = 5
   if player0y < 41 then board_y = 4
   if player0y < 33 then board_y = 3
   if player0y < 25 then board_y = 2
   if player0y < 17 then board_y = 1
   if player0y < 9 then board_y = 0

   circle = 0
   if board_y = 1 then if board_x > 2 then circle = 1
   if board_y = 2 then if board_x = 2 then circle = 1
   if board_y = 2 then if board_x > 2 then circle = 2
   if board_y = 3 then if board_x = 1 then circle = 1
   if board_y = 3 then if board_x > 1 then circle = 2
   if board_y = 3 then if board_x > 3 then circle = 3
   if board_y = 4 then if board_x = 1 then circle = 1
   if board_y = 4 then if board_x = 2 then circle = 2
   if board_y = 4 then if board_x = 3 then circle = 3
   if board_y = 4 then if board_x > 3 then circle = 4
   if board_y = 5 then circle = board_x
This will give you circle 0 through 5, with 0 being outside the dartboard, 1 being the outer red circle, 2 being the middle black circle, 3 being the middle red circle, 4 being the inner black circle, and 5 being the bull's eye.

There are other ways you could do it, but this is one of the best ones I can think of right now that doesn't involve a lot of logical operations.

Michael

Attached Files



#11 Snider-man OFFLINE  

Snider-man

    Stargunner

  • 1,987 posts
  • Doofenshmirtz Evil Incorporated

Posted Tue Sep 16, 2008 5:23 AM

Wow! Nice. I'll take a look and let you know how it works. I appreciate the help!

#12 SeaGtGruff OFFLINE  

SeaGtGruff

    River Patroller

  • 4,543 posts
  • Location:Georgia, USA

Posted Tue Sep 16, 2008 8:22 PM

View PostSnider-man, on Tue Sep 16, 2008 6:23 AM, said:

Wow! Nice. I'll take a look and let you know how it works. I appreciate the help!
I completely rewrote the conversion routine, and created a data table to look up the score. When you move the dart with the joystick, the score will display your score, based on which part of the dartboard the tip of the dart is touching. The outer red circle has a value of 1. The middle black circle has a value of 2. The middle red circle has a value of 3. The inner black circle has a value of 4. And the bull's eye has a value of 5. Anything outside the dartboard has a value of 0. But when the score is displayed, it essentially multiplies those values by 10 (e.g., so touching the bull's eye will display a score of 50).

   rem * Darts Simulator Screen Test

   include div_mul.asm

   set kernel_options no_blank_lines

   dim t1 = temp3
   dim t2 = temp4
   dim t3 = temp5

   playfield:
   ................................
   ..XXXXX........................X
   .X.....X.......................X
   X..XXX..X......................X
   X.X...X.X......................X
   X.X.X.X.X......................X
   X.X...X.X......................X
   X..XXX..X......................X
   .X.....X.......................X
   ..XXXXX........................X
   ...............................X
end

   player0:
   %00000001
   %00111010
   %11111111
   %00111010
   %00000001
end

   COLUBK = $00
   COLUPF = $44
   scorecolor = $0E

   player0x = 80
   player0y = 44

loop

   COLUP0 = $1A

   drawscreen

   if joy0up then player0y = player0y - 1
   if joy0down then player0y = player0y + 1
   if joy0left then player0x = player0x - 1
   if joy0right then player0x = player0x + 1

   t1 = (player0x - 17) / 4
   if t1 > 4 then t1 = 8 - t1
   if t1 > 4 then t1 = 255

   t2 = player0y - 9
   if player0y > 48 then t2 = t2 - 1
   t2 = t2 / 8
   if t2 > 4 then t2 = 8 - t2
   if t2 > 4 then t2 = 255

   if t1 < 5 && t2 < 5 then t3 = 5 * t1 + t2 else t3 = 25

   t1 = points[t3]

   score = 0
   if t1 > 0 then for t2 = 1 to t1 : score = score + 10 : next

   goto loop

   data points
   0, 0, 1, 1, 1
   0, 1, 2, 2, 2
   1, 2, 2, 3, 3
   1, 2, 3, 4, 4
   1, 2, 3, 4, 5, 0
end
Michael

Darts_Simulator_Screen_Test.png

Cool! I got a bull's eye! ;)

Attached Files



#13 Snider-man OFFLINE  

Snider-man

    Stargunner

  • 1,987 posts
  • Doofenshmirtz Evil Incorporated

Posted Wed Sep 17, 2008 10:52 AM

:cool: In one afternoon, you effectively solved two problems I was working on. Very nice and I *really* appreciate the help. I need to take a look at what you did and wrap my head around it (as well as incorporate it into the current gameplay).

I'm busy working on two other non-Atari related hobby projects, so I'm setting this aside for a week or so while I get that taken care of. Thanks again for giving me the assistance and some solid direction.

#14 SeaGtGruff OFFLINE  

SeaGtGruff

    River Patroller

  • 4,543 posts
  • Location:Georgia, USA

Posted Wed Sep 17, 2008 10:12 PM

View PostSnider-man, on Wed Sep 17, 2008 11:52 AM, said:

:cool: In one afternoon, you effectively solved two problems I was working on. Very nice and I *really* appreciate the help.
Two birds with one stone is always nice (well, unless you're a bird). Thanks for the thanks, and you're welcome. :)

View PostSnider-man, on Wed Sep 17, 2008 11:52 AM, said:

I need to take a look at what you did and wrap my head around it
First, I noted how the player's X and Y coordinates relate to the playfield pixels. This is fairly straightforward for the most part, but can be a little bit tricky because the width and height of the player affects it, as well as which kernel is being used, and the presence of any blank rows or columns within the sprite definition can also affect it (depending on where they are). That's why I used the program that displays the player's coordinates in the score while you move the sprite around.

View PostSeaGtGruff, on Tue Sep 16, 2008 2:42 AM, said:

x < 17 : left of dartboard
x = 17 to 20 : outer red
x = 21 to 24 : middle black
x = 25 to 28 : middle red
x = 29 to 32 : inner black
x = 33 to 36 : center
x = 37 to 40 : inner black
x = 41 to 44 : middle red
x = 45 to 48 : middle black
x = 49 to 52 : outer red
x > 52 : right of dartboard

y < 9 : above dartboard
y = 9 to 17 (16?) : outer red
y = 17 to 25 (24?) : middle black
y = 25 to 33 (32?) : middle red
y = 33 to 41 (40?) : inner black
y = 41 to 49 : center
y = 49 (50?) to 57 : inner black
y = 57 (58?) to 65 : middle red
y = 65 (66?) to 73 : middle black
y = 73 (74?) to 81 : outer red
y > 81 : below dartboard
Then I made a little grid for the dartboard, with the numbers 0 through 5 indicating the red and black circles:

00000000000
00011111000
00122222100
01223332210
01234443210
01234543210
01234443210
01223332210
00122222100
00011111000
00000000000

0 = outside the dartboard
1 = outer red circle
2 = middle black circle
3 = middle red circle
4 = inner black circle
5 = center (red bull's eye)

The nice thing about this particular playfield is that the dartboard is circular, so it's reflected around its horizontal axis, as well as around its vertical axis. This lets us simplify it down to about a quarter of its full size:

000000
000111
001222
012233
012344
012345

And we can also shave off the row and column that are all 0s:

00111
01222
12233
12344
12345

You'll notice that this is essentially the same as the data table I posted:

   data points
   0, 0, 1, 1, 1
   0, 1, 2, 2, 2
   1, 2, 2, 3, 3
   1, 2, 3, 4, 4
   1, 2, 3, 4, 5, 0
end
The only thing I did (aside from putting commas between the values) was to tack on an extra 0 at the end of the table, which I'll get to in a moment.

Going back to the original grid, we can assign column numbers and row numbers to it. For the benefit of the data table, we want the row and column numbers to begin with 0, since the index to the data table will also start with 0:

x012345678x

00000000000 -- x
00011111000 -- 0
00122222100 -- 1
01223332210 -- 2
01234443210 -- 3
01234543210 -- 4
01234443210 -- 5
01223332210 -- 6
00122222100 -- 7
00011111000 -- 8
00000000000 -- x

The "x" rows and columns are where the dart falls outside the dartboard, and they extend for some distance on all sides of the dartboard, so we're essentially taking all the empty space on the four sides of the dartboard and compressing it down into the "x" rows and columns.

Now we want a way to code which circle of the dartboard has been hit. We could use a bunch of IF statements with logical ANDs (&&s) and logical ORs (||s), but that would be kind of messy. It's simpler to use mathematical formulas to convert the dart's X and Y coordinates into the equivalent rows and columns of the dartboard.

Each playfield pixel spans four player pixel positions, so we can divide the player0x position by 4 to get the playfield column number-- except we need to take into account that the playfield doesn't start at the leftmost edge of the screen, and we also want to use the column numbers that we came up with for the grid. So we can start by listing which player0x positions map to which grid columns:

player0x = 0 through 16 ... Column x
player0x = 17 through 20 ... Column 0
player0x = 21 through 24 ... Column 1
player0x = 25 through 28 ... Column 2
player0x = 29 through 32 ... Column 3
player0x = 33 through 36 ... Column 4
player0x = 37 through 40 ... Column 5
player0x = 41 through 44 ... Column 6
player0x = 45 through 48 ... Column 7
player0x = 49 through 52 ... Column 8
player0x = 53 through 255 ... Column x

Now, some of these are technically incorrect-- i.e., for player0x = 0, the tip of the dart is to the right of the dartboard; and player0x = 161 through 255 is equivalent to player0x = 1 through 95-- but I'm assuming that you'll probably be keeping the dart's player0x position limited to 1 through 160.

When we divide in bB, we lose the remainder. (There's a way to keep the remainder, but in this case we don't care about it, anyway.) So what we want to end up with is the following:

player0x = 17 through 20 ... Column 0
Adjusted player0x position = 0 through 3 ... Divided by 4 ... Column 0
(i.e., 0/4 = 0, 1/4 = 0, 2/4 = 0, and 3/4 = 0)

player0x = 21 through 24 ... Column 1
Adjusted player0x position = 4 through 7 ... Divided by 4 ... Column 1
(i.e., 4/4 = 1, 5/4 = 1, 6/4 = 1, and 7/4 = 1)

player0x = 25 through 28 ... Column 2
Adjusted player0x position = 8 through 11 ... Divided by 4 ... Column 2
(i.e., 8/4 = 2, 9/4 = 2, 10/4 = 2, and 11/4 = 2)

etc.

Looking at that, we can see that we need to subtract 17 from player0x before we divide by 4. We don't want to change player0x (because we don't want the dart to move as a consequence of our computations), so we use a variable. Rather than use up one of the 26 user variables, we can use one or more temporary variables instead. Let's call them t1, t2, etc. (I like short variable names, unless there's a specific reason to use longer, more meaningful names-- and these are just temporary variables that we don't need to keep, so short names are fine.)

   t1 = (player0x - 17) / 4
This line converts the player0x position into one of our grid column numbers, 0 through whatever. Of course, subtracting 17 from player0x could give us a negative number-- specifically, 0 - 17 = -16, through 16 - 17 = -1-- but since we're working with bytes, those negative numbers will be equivalent to 240 (256 - 16 = 240) through 255 (256 - 1 = 255), which will fall outside of the dartboard, anyway, so we don't need to worry about them.

However, we're simplifying the dartboard's grid by taking just the upper left quarter of it, so we can adjust the results-- in other words, we're taking the "reflection" of some of the columns. If t1 (the column number) is 5, then we want to use 3 instead. If t1 is 6, we want to use 2. If t1 is 7, we want to use 1. And if t1 is 8, we want to use 0:

x012345678x -- original column numbers
x012343210x -- reflected column numbers

00000000000
00011111000
00122222100
01223332210
01234443210
01234543210
01234443210
01223332210
00122222100
00011111000
00000000000

That means 8 - t1 gives us the reflected column number (8 - 5 = 3, 8 - 6 = 2, 8 - 7 = 1, and 8 - 8 = 0), but we want to do this only when t1 is greater than 4:

   if t1 > 4 then t1 = 8 - t1
Finally, this is going to give us some more negative numbers (when t1 is greater than 8 ), but those will be values that fall outside of the dartboard, anyway-- and when we express the negative values as positive byte values, they'll always be greater than 4 (if we're going to restrict the dart's X position to 1 through 160). So rather than have a whole bunch of extra numbers where the dart has fallen outside of the dartboard, let's set all of those extra/unwanted values to 255:

   if t1 > 4 then t1 = 255
In other words, if t1 = 255 after all of this, then we know the dart is in "column x," or "outside the dartboard."

Putting that all together, we have the following:

   t1 = (player0x - 17) / 4
   if t1 > 4 then t1 = 8 - t1
   if t1 > 4 then t1 = 255
We can do exactly the same thing with the player0y position, as follows:

player0y = 0 through 8 ... Row x
player0y = 9 through 16 ... Row 0
player0y = 17 through 24 ... Row 1
player0y = 25 through 32 ... Row 2
player0y = 33 through 40 ... Row 3
player0y = 41 through 48 ... Row 4
player0y = 49 through 56 ... Row 5 (or row 3 after reflecting it)
player0y = 57 through 64 ... Row 6 (or row 2 after reflecting it)
player0y = 65 through 72 ... Row 7 (or row 1 after reflecting it)
player0y = 73 through 80 ... Row 8 (or row 0 after reflecting it)
player0y = 81 through 255 ... Row x

player0y = 9 through 16 ... Row 0
Adjusted player0y position = 0 through 7 ... Divided by 8 ... Row 0
(i.e., 0/8 = 0, 1/8 = 0, 2/8 = 0, 3/8 = 0, 4/8 = 0, 5/8 = 0, 6/8 = 0, and 7/8 = 0)

player0y = 17 through 24 ... Row 1
Adjusted player0y position = 8 through 15 ... Divided by 8 ... Row 1

player0y = 25 through 32 ... Row 2
Adjusted player0y position = 16 through 23 ... Divided by 8 ... Row 2

etc.

   t2 = (player0y - 9) / 8
   if t2 > 4 then t2 = 8 - t2
   if t2 > 4 then t2 = 255
However, there's a slight wrinkle, because the player0y positions don't line up exactly with the borders of the playfield pixels. In particular, for player0y = 9, the tip of the dart is halfway in row x (above the dartboard) and halfway in row 0. Similarly, player0y = 17 is half on row 0 and half on row 1; player0y = 25 is half on row 1 and half on row 2; etc. As I mentioned in an earlier post, I'm assuming that in these cases, the dart will be considered to be in the higher-scoring circle, to give the player "the benefit of the doubt" as it were. That means each row will be 8 player0y positions tall-- except for the centermost row (the red bull's eye), which will be 9 player0y positions tall (because *both* of the "iffy" positions will be assigned to the bull's eye). That gives us the following:

player0y = 0 through 8 ... Row x
player0y = 9 through 16 ... Row 0
player0y = 17 through 24 ... Row 1
player0y = 25 through 32 ... Row 2
player0y = 33 through 40 ... Row 3
player0y = 41 through 49* ... Row 4
player0y = 50* through 57* ... Row 5 (or row 3 after reflecting it)
player0y = 58* through 65* ... Row 6 (or row 2 after reflecting it)
player0y = 66* through 73* ... Row 7 (or row 1 after reflecting it)
player0y = 74* through 81* ... Row 8 (or row 0 after reflecting it)
player0y = 82* through 255 ... Row x

In this slightly-adjusted list, "*" indicates a value that we "bumped up" by 1 so each borderline player0y position will always be associated with the higher-scoring circle on the dartboard. To "bump up" the values in this way, we can simply subtract 1 whenever player0y is greater than 48, as follows:

   t2 = player0y - 9
   if player0y > 48 then t2 = t2 - 1
The reason we subtract 1 like this is so the results will conform to the desired pattern (for computational purposes):

player0y = 0 through 8 ... Subtract 9 ... t2 = -9 through -1 ... Divide by 8 ... Row x
player0y = 9 through 16 ... Subtract 9 ... t2 = 0 through 7 ... Divide by 8 ... Row 0
player0y = 17 through 24 ... Subtract 9 ... t2 = 8 through 15 ... Divide by 8 ... Row 1
player0y = 25 through 32 ... Subtract 9 ... t2 = 16 through 23 ... Divide by 8 ... Row 2
player0y = 33 through 40 ... Subtract 9 ... t2 = 24 through 31 ... Divide by 8 ... Row 3
player0y = 41 through 48** ... Subtract 9 ... t2 = 32 through 39 ... Divide by 8 ... Row 4
player0y = 49** through 56** ... Subtract 9 ... t2 = 40 through 47 ... Divide by 8 ... Row 5
player0y = 57** through 64** ... Subtract 9 ... t2 = 48 through 55 ... Divide by 8 ... Row 6
player0y = 65** through 72** ... Subtract 9 ... t2 = 56 through 63 ... Divide by 8 ... Row 7
player0y = 73** through 80** ... Subtract 9 ... t2 = 64 through 71 ... Divide by 8 ... Row 8
player0y = 81** through 254** ... Subtract 9 ... t2 = 72 through 245 ... Divide by 8 ... Row x

In this list, "**" indicates where we subtracted 1 as described above. So putting all of that together, including where we reflect the rows and then assign 255 to the rows that are outside the dartboard, we get the following:

   t2 = player0y - 9
   if player0y > 48 then t2 = t2 - 1
   t2 = t2 / 8
   if t2 > 4 then t2 = 8 - t2
   if t2 > 4 then t2 = 255
Now all we have to do is convert the t1 (column) and t2 (row) values into a single index, t3, which we'll use to read from our data table. Since the table is 5-by-5, we use t3 = 5 * t1 + t2. However, we don't want to do this when t1 or t2 is 255 (or outside the dartboard grid), so we exclude those cases:

   if t1 < 5 && t2 < 5 then t3 = 5 * t1 + t2
The "< 5" works for us, because t1 and t2 are each going to be 0, 1, 2, 3, 4, or 255, so the only "legal" values will be less than 5. But we still want to know when the dart has landed outside the dartboard, so we'll assign all the "outside" positions to t3 = 25, as follows:

   if t1 < 5 && t2 < 5 then t3 = 5 * t1 + t2 else t3 = 25
Then we just tack an extra byte onto the end of our data table, for when t3 = 25:

   data points
   0, 0, 1, 1, 1
   0, 1, 2, 2, 2
   1, 2, 2, 3, 3
   1, 2, 3, 4, 4
   1, 2, 3, 4, 5, 0
end
Now we can read the points from the table, and store them in a temporary variable. Rather than use a fourth temporary variable, I just reused t1, since it's already served its purpose as a column number and we don't need it for that anymore:

   t1 = points[t3]
Then the only thing we need to do is decide how many points each of these is really worth. I just decided to use 10, 20, 30, 40, and 50, but you can make them whatever you want them to be. And you can put the actual point values into the data table, as follows:

   data points
   0, 0, 10, 10, 10
   0, 10, 20, 20, 20
   10, 20, 20, 30, 30
   10, 20, 30, 40, 40
   10, 20, 30, 40, 50, 0
end
Unfortunately, right now bB doesn't work right when you try to assign a variable to the score, so I initialized the score to 0, then used a for...next loop to increment the score based on the points-- and that works best when there aren't too many iterations of the loop, otherwise it can take too long and cause the screen to scroll, so I stuck with 1 through 5:

   score = 0
   if t1 > 0 then for t2 = 1 to t1 : score = score + 10 : next
   rem * Or you could use score + 100, score + 50, etc.
This time, I reused t2 for the for...next loop counter, rather than wasting some other variable.

As far as the three temporary variables that I've used-- t1, t2, and t3-- we need to be careful in assigning them to bB's temporary variables, because the division and multiplication routines use temp1 and temp2. So I've assigned them to temp3, temp4, and temp5:

   dim t1 = temp3
   dim t2 = temp4
   dim t3 = temp5
I hope you were able to follow my explanation. Now you can focus on the *really* hard part-- coming up with the code for the dart's velocity and trajectory! :)

Michael

Edited by SeaGtGruff, Wed Sep 17, 2008 10:23 PM.


#15 SeaGtGruff OFFLINE  

SeaGtGruff

    River Patroller

  • 4,543 posts
  • Location:Georgia, USA

Posted Wed Sep 17, 2008 10:42 PM

One final comment: I was thinking the dart might look a little better if you make the player sprite twice as wide:

Darts.png

If you do, you'll need to make a minor adjustment in the formula that converts the player0x position to the column number, because the player0x positions range from 2 to 161 when you use a double-wide player:

   rem * Darts Simulator Screen Test

   include div_mul.asm

   set kernel_options no_blank_lines

   dim t1 = temp3
   dim t2 = temp4
   dim t3 = temp5

   playfield:
   ................................
   ..XXXXX........................X
   .X.....X.......................X
   X..XXX..X......................X
   X.X...X.X......................X
   X.X.X.X.X......................X
   X.X...X.X......................X
   X..XXX..X......................X
   .X.....X.......................X
   ..XXXXX........................X
   ...............................X
end

   player0:
   %00000001
   %00111010
   %11111111
   %00111010
   %00000001
end

   COLUBK = $00
   COLUPF = $44
   scorecolor = $0E

   player0x = 80
   player0y = 44

loop

   NUSIZ0 = 5 : rem * be sure to set the player's width *inside* the screen loop
   COLUP0 = $1A

   drawscreen

   if joy0up then player0y = player0y - 1
   if joy0down then player0y = player0y + 1
   if joy0left then player0x = player0x - 1
   if joy0right then player0x = player0x + 1

   t1 = (player0x - 16) / 4 : rem * instead of player0x - 17 as before
   if t1 > 4 then t1 = 8 - t1
   if t1 > 4 then t1 = 255

   t2 = player0y - 9
   if player0y > 48 then t2 = t2 - 1
   t2 = t2 / 8
   if t2 > 4 then t2 = 8 - t2
   if t2 > 4 then t2 = 255

   if t1 < 5 && t2 < 5 then t3 = 5 * t1 + t2 else t3 = 25

   t1 = points[t3]

   score = 0
   if t1 > 0 then for t2 = 1 to t1 : score = score + 10 : next

   goto loop

   data points
   0, 0, 1, 1, 1
   0, 1, 2, 2, 2
   1, 2, 2, 3, 3
   1, 2, 3, 4, 4
   1, 2, 3, 4, 5, 0
end
Michael




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users