Jump to content

Photo

Plot a Circle


5 replies to this topic

#1 boski OFFLINE  

boski

    Space Invader

  • 26 posts
  • Location:Janesville, WI

Posted Sat Mar 18, 2017 4:34 PM

I want my sprites to essentially orbit the center of the screen. That means I need to be able to plot a circle to calculate the sprite's x,y coordinates, which will be constantly changing. Does anyone know how to do this?



#2 bogax OFFLINE  

bogax

    Dragonstomper

  • 704 posts

Posted Mon Mar 20, 2017 6:55 PM

here's one that uses a sine table
 
 
 
 
  dim angle = a.c
  dim tangle = temp1
 
 
 
  angle = 0
 
  gosub su
 
loop
 
 
 
  temp3 = sine(angle)
  temp3 = scl(temp3)
 
  player0x = temp3 + 37
 
  temp3 = angle - 64
  temp3 = sine(temp3)
  temp3 = scl(temp3)
  player0y = temp3 + 7
 
  angle = angle + 1.0
 
  COLUP0 = $3A
  COLUP1 = $14
  drawscreen
  goto loop
 
 
 
 
  ;  multiply by .328125 so scales 255 -> 83
  function scl
  asm
  lda temp1
  lsr
  lsr
  adc temp1
  ror
  lsr
  adc temp1
  ror
  lsr
  rts
end
 
 
 
 
 
  function sine
  temp2 = tangle
  if tangle{6} then temp2 = temp2 ^ %00111111  ; if its an odd quadrant complement the angle in 64 (64 is one quadrant)
  temp2 = (temp2 & %00111111)                  ; scale to index table 0..63 /2 for 32 elements /4 for 16 elements
  temp2 = sinetbl[temp2]/2
  if tangle{7} then temp2 = 255 - temp2        ; if the angle is greater than 128 then complement the sine in 128
  temp2 = temp2 + 128                          ; add an offset so the sine is 0..255 no negatives  
  return
 
 ;  data sinetbl
 ;    0,  50,  74,  98, 121, 142, 162, 181
 ;  198, 213, 226, 237, 245, 251, 255, 255
 ;end
 
 ;  data sinetbl
 ;    0,  25,  37,  50,  62,  74,  86,  98
 ;  109, 120, 131, 142, 152, 162, 171, 180
 ;  189, 197, 205, 212, 219, 225, 231, 236
 ;  240, 244, 247, 250, 252, 254, 255, 255
 ;end
 
  data sinetbl
    0,  13,  19,  25,  31,  38,  44,  50
   56,  62,  68,  74,  80,  86,  92,  98
  104, 109, 115, 121, 126, 132, 137, 142
  147, 152, 157, 162, 167, 172, 177, 181
  185, 190, 194, 198, 202, 206, 209, 213
  216, 220, 223, 226, 229, 231, 234, 237
  238, 241, 243, 245, 247, 248, 250, 251
  252, 253, 254, 255, 255, 255, 255, 255
end
 
su
 
  player0:
  %00000000
  %00000000
  %00011000
  %00111100
  %00111100
  %00011000
  %00000000
  %00000000
end
 
  player1:
  %00111100
  %01111110
  %11111111
  %11111111
  %11111111
  %11111111
  %01111110
  %00111100
end
 
 
  COLUPF = $48
 
  player1x = 80
  player1y = 48
 
  return
 
 
 
here's one that uses a smaller sine table to form a circle from a set of line segments
 
 
 
  dim angle = a.c
  dim tangle = temp1
 
 
 
  angle = 0
 
  gosub su
 
loop
 
  temp3 = sine(angle)
  x = x + temp3
  player0x = scl(x)
  player0x = player0x + 39
 
  temp3 = angle + 64
  temp3 = sine(temp3)
  y = y + temp3
  player0y = scl(y)
  player0y = player0y + 6
 
  angle = angle + 1.0
 
  COLUP0 = $3A
  COLUP1 = $14
  drawscreen
  goto loop
 
 
  ;  multiply by .328125 so scales 255 -> 83
  function scl
  asm
  lda temp1
  lsr
  lsr
  adc temp1
  ror
  lsr
  adc temp1
  ror
  lsr
  rts
end
 
 
 
 
 
  function sine
  temp2 = tangle & %00111111
  if tangle{6} then temp2 = 64 - temp2         ; if its an odd quadrant complement the angle in 64 (64 is one quadrant)
  temp2 = (temp2 & %00111111)/8                ; scale to index table 0..63 -> 0..7
  temp2 = sinetbl[temp2]
  if tangle{7} then temp2 = 0 - temp2          ; if the angle is greater than 128 then negate
  temp2 = temp2
  return
 
  data sinetbl
    0,   1,  1,  2,  2,  3,  3,  3
end
 
 
su
 
  player0:
  %00000000
  %00000000
  %00011000
  %00111100
  %00111100
  %00011000
  %00000000
  %00000000
end
 
  player1:
  %00111100
  %01111110
  %11111111
  %11111111
  %11111111
  %11111111
  %01111110
  %00111100
end
 
 
  COLUPF = $48
 
  x = 0 : y = 128 : angle = 0
 
  player1x = 80
  player1y = 48
 
  return
 
 
 
here's one that uses a parabolic aproximation of sines-cosines
if you look closely you'll see it's actually sort of elliptical
 
 
  dim dx = v
  dim dy = w
 
 
  gosub su
 
loop
 
  c = c + 1
 
  if c & 7 then skip
 
  if x{7} then dx = dx - 1 else dx = dx + 1 
  x = x + dx
 
   player0x = scl(x)
   player0x = player0x + 34
 
  if y{7} then dy = dy - 1 else dy = dy + 1
  y = y + dy
 
  player0y = scl(y)
  player0y = player0y + 2
 
 
skip
 
  COLUP0 = $3A
  COLUP1 = $14
  drawscreen
  goto loop
 
 
 
  ;  multiply by .34375 so scales 247 -> 84
  function scl
  asm
  lda temp1
  lsr
  adc temp1
  ror
  lsr
  adc temp1
  ror
  lsr
  rts
end
 
 
su
 
  player0:
  %00000000
  %00000000
  %00011000
  %00111100
  %00111100
  %00011000
  %00000000
  %00000000
end
 
  player1:
  %00111100
  %01111110
  %11111111
  %11111111
  %11111111
  %11111111
  %01111110
  %00111100
end
 
 
  COLUPF = $48
 
  dx = $0E : x = $7F
  dy = $00 : y = $F7
 
 
 
 
  player1x = 80
  player1y = 46
 
  return
 
 
 

Attached Files



#3 bogax OFFLINE  

bogax

    Dragonstomper

  • 704 posts

Posted Tue Mar 21, 2017 6:22 PM

I forgot to mention that in the case of the line segment circle

the table is matched to the number of steps in the circle so if you change the number of steps

the circle changes

it will get larger or smaller and if things don't add up just right it will probably wobble



#4 boski OFFLINE  

boski

    Space Invader

  • Topic Starter
  • 26 posts
  • Location:Janesville, WI

Posted Tue Mar 21, 2017 7:05 PM

Thank you very much for your help! I've already learned a lot just playing around with the code. I'm sure this will help a lot of other people too. Just one more question - how can I change the radius in circle one? It seems like I'd need to change the code in more than one spot to keep it even.



#5 bogax OFFLINE  

bogax

    Dragonstomper

  • 704 posts

Posted Sat Mar 25, 2017 11:33 AM

 
the sine table is built on the (possibly) spurious theory
that it's good to start with the best accuracy and then
throw away what you don't need
so the sines are 0..255 and which would give you
sines -255..255
the sine function immediately throws some of that away and
returns sines that range 0..255 
those values are scaled to fit by multiplying by the
reciprocal of the scale factor
that's what the scl function does
 
if you just want a different radius that can be baked into 
the sine table
 
 
 
  dim angle = a.c
  dim tangle = temp1
 
 
 
  angle = 0
 
  gosub su
 
 
loop
 
  temp1 = angle/4
  player0x = sinetbl[temp1] + 42
 
  temp1 = (angle - 64)/4
  player0y = sinetbl[temp1] + 7
 
  angle = angle + 0.5
 
  COLUP0 = $3A
  COLUP1 = $14
  drawscreen
  goto loop
 
 
   data sinetbl
   38,  42,  45,  49,  53,  56,  59,  62
   65,  67,  70,  72,  73,  74,  75,  76
   76,  76,  75,  74,  73,  72,  70,  67
   65,  62,  59,  56,  53,  49,  45,  42
   38,  34,  31,  27,  23,  20,  17,  14
   11,   9,   6,   4,   3,   2,   1,   0
    0,   0,   1,   2,   3,   4,   6,   9
   11,  14,  17,  20,  23,  27,  31,  34
end
 
 
su
 
  player0:
  %00000000
  %00000000
  %00011000
  %00111100
  %00111100
  %00011000
  %00000000
  %00000000
end
 
  player1:
  %00111100
  %01111110
  %11111111
  %11111111
  %11111111
  %11111111
  %01111110
  %00111100
end
 
 
  COLUPF = $48
 
  player1x = 80
  player1y = 48
 
  return
 
 
 
if you want to vary the radius on the fly probably the easiest way is to
scale the sines to suit
 
here the sines are scaled using an approximate reciprocal calulated from
the radius
 
you can vary the radius from 4..40 using joy0 up-down
 
none of it is very accurate
the sine table is not very accurate
the scl function is not very accurate
and the reciprocal approximation is not very accurate
 
 
 
  dim angle = a.c
  dim tangle = temp1
 
 
 
  angle = 0
 
  gosub su
 
  dim num = temp1
  dim mul = temp2
 
  r = 20
 
loop
 
  f = (SWCHA ^ $FF) & f
  if f{4} then r = r + 1 : if r > 40 then r =  4
  if f{5} then r = r - 1 : if r <  4 then r = 40
  f = SWCHA
 
  temp1 = angle/4
  temp1 = sinetbl[temp1] 
  temp2 = r * 2
  temp1 = scl(temp1,temp2) 
  player0x = temp1 + 80 - r
 
  temp1 = (angle - 64)/4
  temp1 = sinetbl[temp1] 
  temp2 = r * 2
  temp1 = scl(temp1,temp2) 
  player0y = temp1 + 48 - r
 
  angle = angle + 0.5
 
  COLUP0 = $3A
  COLUP1 = $14
  drawscreen
  goto loop
 
 
 
 
  ;  multiply by .328125 so scales 255 -> 83
  function scl
  asm
  lda #$00
  sec
  ror mul
loop
  bcc shift
  adc num
shift
  ror
enter
  lsr mul
  bne loop
  rts    
end
 
 
   data sinetbl
  127, 139, 151, 163, 175, 186, 197, 207
  216, 225, 232, 239, 244, 248, 251, 253
  253, 253, 251, 248, 244, 239, 232, 225
  216, 207, 197, 186, 175, 163, 151, 139
  126, 114, 102,  90,  78,  67,  56,  46
   37,  28,  21,  14,   9,   5,   2,   0
    0,   0,   2,   5,   9,  14,  21,  28
   37,  46,  56,  67,  78,  90, 102, 114
end
 
 
 
su
 
  player0:
  %00000000
  %00000000
  %00011000
  %00111100
  %00111100
  %00011000
  %00000000
  %00000000
end
 
  player1:
  %00111100
  %01111110
  %11111111
  %11111111
  %11111111
  %11111111
  %01111110
  %00111100
end
 
 
  COLUPF = $48
 
  player1x = 80
  player1y = 48
 
  return
 

Attached Files


Edited by bogax, Sat Mar 25, 2017 11:35 AM.


#6 boski OFFLINE  

boski

    Space Invader

  • Topic Starter
  • 26 posts
  • Location:Janesville, WI

Posted Sun Mar 26, 2017 6:33 PM

Thank you very much! This will keep me busy for a while!






0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users