set display mode 1280, 1024, 32 sync on sync rate 0 randomize timer() backdrop on color backdrop 0 type psuedoPoint x# y# endtype type psuedoLine p as psuedoPoint endtype type Asteroid x# y# speedX# speedY# rotSpeed# angle# cX# cY# imgId size radiusSquared endtype #constant ASTEROID_POINTS 12 #constant ASTEROID_COUNT 6 #constant ASTEROID_MIN_RADIUS_FACTOR 0.40 #constant ASTEROID_MAX_RADIUS_FACTOR 0.99 Dim Asteroids(ASTEROID_COUNT) as Asteroid `Lines Dim psuedoLineArray(ASTEROID_COUNT, ASTEROID_POINTS) as psuedoLine `Make 'ASTEROID_COUNT' asteroids for j = 1 to ASTEROID_COUNT `Asteroid size (width and height) ASTEROID_SIZE = 128 + rnd(128) `Make a colour col as dword select rnd(7) case 0 : col = rgb(255, 128, 128) : endcase case 1 : col = rgb(128, 255, 128) : endcase case 2 : col = rgb(128, 128, 255) : endcase case 3 : col = rgb(255, 255, 128) : endcase case 4 : col = rgb(255, 128, 255) : endcase case 5 : col = rgb(128, 255, 255) : endcase case 6 : col = rgb(255, 255, 255) : endcase case 7 : col = rgb(128, 128, 128) : endcase endselect inc col,(128 << 24) && 0xFFFFFFFF for i = 0 to ASTEROID_POINTS if i < ASTEROID_POINTS `Get the angle angle# = 360.0 * i / (ASTEROID_POINTS * 1.0) `Distance is currently 95% of the radius (distance from edge to middle) - this SHOULD make a "circle" dist# = (ASTEROID_SIZE * ASTEROID_MIN_RADIUS_FACTOR) + (rnd(ASTEROID_SIZE * 100.0 * (ASTEROID_MAX_RADIUS_FACTOR - ASTEROID_MIN_RADIUS_FACTOR)) * 0.01) dist# = dist# * 0.5 `Create a point based on the current angle, above distance. This is from the origin; 0,0 psuedoLineArray(j, i).p.x# = (cos(angle#) * dist#) `+ cP# psuedoLineArray(j, i).p.y# = (sin(angle#) * dist#) `+ cP# else psuedoLineArray(j, ASTEROID_POINTS).p.x# = psuedoLineArray(j, 0).p.x# psuedoLineArray(j, ASTEROID_POINTS).p.y# = psuedoLineArray(j, 0).p.y# endif next i Asteroids(j).cX# = ASTEROID_SIZE * 0.5 Asteroids(j).cY# = ASTEROID_SIZE * 0.5 Asteroids(j).size = ASTEROID_SIZE Asteroids(j).radiusSquared = (ASTEROID_SIZE * 0.5) * (ASTEROID_SIZE * 0.5) make memblock 1, 12 + (ASTEROID_SIZE * ASTEROID_SIZE * 4) write memblock dword 1, 0, ASTEROID_SIZE write memblock dword 1, 4, ASTEROID_SIZE write memblock dword 1, 8, 32 p as psuedoPoint for y = 0 to ASTEROID_SIZE - 1 for x = 0 to ASTEROID_SIZE - 1 pos = 12 + ((y * ASTEROID_SIZE) + x) * 4 p.x# = x - (ASTEROID_SIZE * 0.5) p.y# = y - (ASTEROID_SIZE * 0.5) if PointInAsteroid(p, j, 0.0) = 0 `outside write memblock dword 1, pos, 0 else `inside write memblock dword 1, pos, col endif next x next y make image from memblock j, 1 delete memblock 1 sprite j, 0, 0, j offset sprite j, Asteroids(j).cX#, Asteroids(j).cY# Asteroids(j).x# = rnd(screen width()) Asteroids(j).y# = rnd(screen height()) Asteroids(j).speedX# = rnd(25) + 25 : if rnd(1) then Asteroids(j).speedX# = Asteroids(j).speedX# * -1 Asteroids(j).speedY# = rnd(25) + 25 : if rnd(1) then Asteroids(j).speedY# = Asteroids(j).speedY# * -1 Asteroids(j).rotSpeed# = rnd(40) + 20 : if rnd(1) then Asteroids(j).rotSpeed# = Asteroids(j).rotSpeed# * -1 Asteroids(j).angle# = 0.0 Asteroids(j).imgId = j : `Temp - will allow multiple asteroids for randomness next j global frameTime# frameTime# = 1.0 startTime = timer() do frameTime# = (frameTime# * 0.8) + ((timer() - startTime) * 0.2) startTime = timer() moveAsteroids() checkAsteroids() text 0, screen height() - 20, "FPS: " + str$(screen fps()) sync loop end exitfunction function checkAsteroids() for i = 1 to ASTEROID_COUNT for j = i+1 to ASTEROID_COUNT `Check squared distance between asteroids... Quicker check to see if we need to check points dx# = Asteroids(i).x# - Asteroids(j).x# dy# = Asteroids(i).y# - Asteroids(j).y# radiussum# = (Asteroids(i).size * 0.5) + (Asteroids(j).size * 0.5) if (dx#*dx#)+(dy#*dy#) <= radiussum#*radiussum# `Compare asteroid i to j. This loop structure should stop comparing A to B then B to A... ap as psuedoPoint angle# = Asteroids(i).angle# for k = 1 to ASTEROID_POINTS ap.x# = (psuedoLineArray(i, k).p.x# * cos(angle#)) - (psuedoLineArray(i, k).p.y# * sin(angle#)) ap.y# = (psuedoLineArray(i, k).p.x# * sin(angle#)) + (psuedoLineArray(i, k).p.y# * cos(angle#)) inc ap.x#, dx# inc ap.y#, dy# `Point p is now 1 vertice of asteroid 'i'. See if this point is in asteroid 'j' if PointInAsteroid(ap, j, Asteroids(j).angle#) = 1 then text 400, 400, "ASTEROID COLLISION!!!" next k endif next j next i endfunction `CODE HERE BASED ON: http://astronomy.swin.edu.au/~pbourke/geometry/insidepoly/ function PointInAsteroid(p as psuedoPoint, j, angle#) `Check if point p is within asteroid 'j' p1 as psuedoPoint p2 as psuedoPoint counter = 0 `Angle is zero, no need to rotate! if angle# = 0.0 p1 = psuedoLineArray(j, 0).p else p1.x# = (psuedoLineArray(j, 0).p.x# * cos(angle#)) - (psuedoLineArray(j, 0).p.y# * sin(angle#)) p1.y# = (psuedoLineArray(j, 0).p.x# * sin(angle#)) + (psuedoLineArray(j, 0).p.y# * cos(angle#)) endif for i = 1 to ASTEROID_POINTS if angle# = 0.0 p2 = psuedoLineArray(j, i MOD ASTEROID_POINTS).p else iMODap = i MOD ASTEROID_POINTS p2.x# = (psuedoLineArray(j, iMODap).p.x# * cos(angle#)) - (psuedoLineArray(j, iMODap).p.y# * sin(angle#)) p2.y# = (psuedoLineArray(j, iMODap).p.x# * sin(angle#)) + (psuedoLineArray(j, iMODap).p.y# * cos(angle#)) endif if p.y# > MIN(p1.y#, p2.y#) if p.y# <= MAX(p1.y#, p2.y#) if p.x# <= MAX(p1.x#, p2.x#) if p1.y# <> p2.y# xinters# = (p.y# - p1.y#) * (p2.x# - p1.x#) / (p2.y# - p1.y#) + p1.x# if p1.x# = p2.x# OR p.x# <= xinters# then inc counter endif endif endif endif p1 = p2 next i result = counter MOD 2 endfunction result function moveAsteroids() for j = 1 to ASTEROID_COUNT inc Asteroids(j).x#, Asteroids(j).speedX# * frameTime# * 0.001 inc Asteroids(j).y#, Asteroids(j).speedY# * frameTime# * 0.001 inc Asteroids(j).angle#, Asteroids(j).rotSpeed# * frameTime# * 0.001 rotate sprite j, Asteroids(j).angle# `Check for horizontal bounds if Asteroids(j).speedX# < 0 `going left, are we too far? if Asteroids(j).x# + Asteroids(j).Size * 0.5 < 0 then inc Asteroids(j).x#, screen width() + Asteroids(j).Size else `going right, are we too far? if Asteroids(j).x# - Asteroids(j).Size * 0.5 > screen width() then dec Asteroids(j).x#, screen width() + Asteroids(j).Size endif `Check for vertical bounds if Asteroids(j).speedY# < 0 `going up, are we too far? if Asteroids(j).y# + Asteroids(j).Size * 0.5 < 0 then inc Asteroids(j).y#, screen height() + Asteroids(j).Size else `going right, are we too far? if Asteroids(j).y# - Asteroids(j).Size * 0.5 > screen height() then dec Asteroids(j).y#, screen height() + Asteroids(j).Size endif sprite j, Asteroids(j).x#, Asteroids(j).y#, Asteroids(j).imgId next j endfunction function MIN(a#, b#) if a# < b# then r# = a# else r# = b# endfunction r# function MAX(a#, b#) if a# > b# then r# = a# else r# = b# endfunction r#