Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- OPTION BASE 0
- RANDOMIZE TIMER
- ' screen related stuff
- ' find out current screen resolution
- screenhandle = _SCREENIMAGE
- userresowidth = _WIDTH(screenhandle)
- userresoheight = _HEIGHT(screenhandle)
- ' make a fullscreen window, or actually don't. make a quarter-screen window.
- DIM SHARED screenwidth, screenheight
- screenwidth = userresowidth / 2
- screenheight = userresoheight / 2
- SCREEN _NEWIMAGE(screenwidth, screenheight, 32), , 0, 1
- '_FULLSCREEN _STRETCH
- _MOUSEHIDE
- ' load the first font from a predetermined list that exists in the windows' font directory
- ' if none is found, then use qbasic/qb64 default
- windowsdir$ = ENVIRON$("SYSTEMROOT")
- fontchoices = 2
- DIM fontchoice$(fontchoices)
- fontchoice$(0) = "segoeuib.ttf"
- fontchoice$(1) = "ARIALBD.TTF"
- fontsize = 12
- FOR i = 0 TO fontchoices - 1
- fontpath$ = windowsdir$ + "\Fonts\" + fontchoice$(i)
- IF _FILEEXISTS(fontpath$) THEN
- _FONT _LOADFONT(fontpath$, fontsize)
- EXIT FOR
- END IF
- NEXT i
- _PRINTMODE _KEEPBACKGROUND
- totalcircles = 256
- maxvx = 0 ' randomize initial velocities in the range -max/2 -> max/2
- maxvy = 0
- borders = 1
- friction = 0.92
- bordercoefficient = friction
- stictionthreshold = 0.4
- particlegravity = 0 ' 0, 1
- downwardsgravity = 0.0008
- DIM SHARED scancode(128) AS DOUBLE, oldscancode(128) AS DOUBLE, downscancode(128) AS DOUBLE, keyboardrepeat AS DOUBLE
- DIM SHARED sqrlookup(32768) AS SINGLE: FOR i = 0 TO 32768: sqrlookup(i) = SQR(i / 32768): NEXT i
- DIM circleactive(totalcircles), circletouched(totalcircles)
- DIM circleposx(totalcircles) AS DOUBLE, circleposy(totalcircles) AS DOUBLE
- DIM circlevx(totalcircles) AS DOUBLE, circlevy(totalcircles) AS DOUBLE
- DIM circlemass(totalcircles) AS DOUBLE, circlegravity(totalcircles) AS DOUBLE, circlesize(totalcircles) AS DOUBLE
- DIM circletolinecontacts(totalcircles) AS _UNSIGNED INTEGER
- DIM tempcirclevix AS DOUBLE, tempcircleviy AS DOUBLE, tempcirclevjx AS DOUBLE, tempcirclevjy AS DOUBLE
- DIM radii AS DOUBLE, radius AS DOUBLE
- DIM vx AS DOUBLE, vy AS DOUBLE, newvx AS DOUBLE, newvy AS DOUBLE, newvix AS DOUBLE, newviy AS DOUBLE, newvjx AS DOUBLE, newvjy AS DOUBLE
- DIM tempivx AS DOUBLE, tempivy AS DOUBLE, tempjvx AS DOUBLE, tempjvy AS DOUBLE, tempvelocity AS DOUBLE, maxvelocity AS DOUBLE
- DIM collisionx AS DOUBLE, collisiony AS DOUBLE
- DIM diffxi AS DOUBLE, diffyi AS DOUBLE, diffxj AS DOUBLE, diffyj AS DOUBLE
- DIM sqrradi AS DOUBLE, sqrradj AS DOUBLE, sqrdiffi AS DOUBLE, sqrdiffj AS DOUBLE, normi AS DOUBLE, normj AS DOUBLE
- DIM distance AS DOUBLE, distx AS DOUBLE, disty AS DOUBLE, distxji AS DOUBLE, distyji AS DOUBLE, distp AS DOUBLE, distv AS DOUBLE
- DIM dist AS DOUBLE, distpow AS DOUBLE, unitx AS DOUBLE, unity AS DOUBLE, accx AS DOUBLE, accy AS DOUBLE
- DIM particlecolor AS LONG, linecolor AS LONG, pixelcol AS LONG, colred AS LONG, colgre AS LONG, colblu AS LONG, color.black AS LONG
- particlecolor = _RGB(240, 240, 240)
- linecolor = _RGB(180, 180, 180)
- color.black = _RGB(0, 0, 0)
- hilightcells = 0
- fpslimit = 60
- physperframe = 16
- levselectorfadertimer = TIMER(0.001)
- levselectorvisibletime = 4 ' in seconds
- levselectorfadetime = 2 ' in seconds
- totalvertices = 10000
- DIM linep1x(totalvertices), linep1y(totalvertices), linep2x(totalvertices), linep2y(totalvertices)
- DIM gridcircle(256, 256, 200) ' why the fuck this needs to be done when i'm gonna redim it later anyway
- DIM gridline(256, 256, 1000)
- DIM listoffiles$(131072)
- elmalevdir$ = "" '"E:\Program Files\eol\lev\"
- GOSUB getdirectorycontents
- GOSUB importelmalevel
- GOSUB initcircles
- GOSUB initlinegrid
- ON TIMER(1) GOSUB updatefps
- TIMER ON
- 'selectedline = 3
- DO
- ' highlight cells that are occupied with circles and lines
- IF hilightcells THEN
- FOR y = 0 TO gridcellsy
- FOR x = 0 TO gridcellsx
- IF gridcircle(x, y, 0) OR gridline(x, y, 0) THEN
- x1 = x * gridsizex
- y1 = y * gridsizey
- x2 = (x + 1) * gridsizex - 2
- y2 = (y + 1) * gridsizey - 2
- cc = gridcircle(x, y, 0) * 10
- cl = gridline(x, y, 0) * 2 + 16
- IF cl > 160 THEN cl = 160
- c = cc + cl
- IF c > 240 THEN c = 240
- LINE (x1, y1)-(x2, y2), _RGB(c, c, c), BF
- END IF
- NEXT x
- NEXT y
- END IF
- ' show level selector (or don't)
- IF TIMER(0.001) < (levselectorfadertimer + levselectorvisibletime + levselectorfadetime) THEN
- GOSUB showlevelselector
- END IF
- ' draw lines
- FOR l = 0 TO totalvertices - 1
- aaLine linep1x(l) + 0.1, linep1y(l) + 0.1, linep2x(l) + 0.1, linep2y(l) + 0.1, linecolor, 0 ' ...wtf
- 'LINE (linep1x(l), linep1y(l))-(linep2x(l), linep2y(l)), linecolor
- NEXT l
- ' check which is the fastest bacircle
- maxvelocity = 0
- FOR i = 0 TO totalcircles - 1
- IF circleactive(i) THEN
- tempvelocity = circlevx(i) * circlevx(i) + circlevy(i) * circlevy(i)
- IF tempvelocity > maxvelocity THEN
- maxvelocity = tempvelocity
- maxvelocitybacircle = i
- END IF
- END IF
- NEXT i
- ' draw circles
- FOR i = 0 TO totalcircles - 1
- IF circleactive(i) THEN
- IF i = maxvelocitybacircle THEN
- aaFilledCircle circleposx(i), circleposy(i), circlesize(i), _RGB(0, 255, 0)
- 'CIRCLE (circleposx(i), circleposy(i)), circlesize(i) - 2, _RGB(0, 255, 0)
- 'PAINT (circleposx(i), circleposy(i)), _RGB(0, 255, 0)
- ELSE
- 'aaFilledCircle circleposx(i), circleposy(i), circlesize(i), particlecolor
- aaCircle circleposx(i), circleposy(i), circlesize(i), particlecolor, 0
- 'CIRCLE (circleposx(i), circleposy(i)), circlesize(i), particlecolor
- 'PAINT (circleposx(i), circleposy(i)), particlecolor
- 'PSET (circleposx(i) + drawoffsetx, circleposy(i) + drawoffsety), particlecolor
- END IF
- END IF
- NEXT i
- ' calculate physics
- FOR physicsframe = 1 TO physperframe
- GOSUB keyboardroutine ' keep it responsive
- ' reset circle grid
- FOR y = 0 TO gridcellsy
- FOR x = 0 TO gridcellsx
- gridcircle(x, y, 0) = 0
- NEXT x
- NEXT y
- ' populate circle grid (retarded, make one that is only updated if there's any change (BUT MOOOM IT'S HARDER))
- FOR i = 0 TO totalcircles - 1
- IF circleactive(i) THEN
- pos1x = (circleposx(i) - circlesize(i)) \ gridsizex
- pos1y = (circleposy(i) - circlesize(i)) \ gridsizey
- pos2x = (circleposx(i) + circlesize(i)) \ gridsizex
- pos2y = (circleposy(i) + circlesize(i)) \ gridsizey
- IF pos1x < 0 THEN pos1x = 0
- IF pos1y < 0 THEN pos1y = 0
- IF pos2x < 0 THEN pos2x = 0
- IF pos2y < 0 THEN pos2y = 0
- IF pos1x >= gridcellsx THEN pos1x = gridcellsx
- IF pos1y >= gridcellsy THEN pos1y = gridcellsy
- IF pos2x >= gridcellsx THEN pos2x = gridcellsx
- IF pos2y >= gridcellsy THEN pos2y = gridcellsy
- FOR gy = pos1y TO pos2y
- FOR gx = pos1x TO pos2x
- gridcircle(gx, gy, 0) = gridcircle(gx, gy, 0) + 1 ' there's now one more circle in the current cell
- gridcircle(gx, gy, gridcircle(gx, gy, 0)) = i ' add that circle's id to that cell
- NEXT gx
- NEXT gy
- END IF
- NEXT i
- ' loop through circles
- FOR i = 0 TO totalcircles - 1
- IF circleactive(i) THEN
- ' move circles
- circleposx(i) = circleposx(i) + circlevx(i)
- circleposy(i) = circleposy(i) + circlevy(i)
- ' bounce off screen boundaries
- IF borders THEN
- IF circleposx(i) < circlesize(i) AND circlevx(i) < 0 THEN
- circleposx(i) = circlesize(i)
- circlevx(i) = -circlevx(i) * bordercoefficient
- circlevy(i) = circlevy(i) * bordercoefficient
- ELSEIF circleposx(i) > (screenwidth - circlesize(i) - 1) AND circlevx(i) > 0 THEN
- circleposx(i) = screenwidth - circlesize(i) - 1
- circlevx(i) = -circlevx(i) * bordercoefficient
- circlevy(i) = circlevy(i) * bordercoefficient
- ELSEIF circleposy(i) < circlesize(i) AND circlevy(i) < 0 THEN
- circleposy(i) = circlesize(i)
- circlevx(i) = circlevx(i) * bordercoefficient
- circlevy(i) = -circlevy(i) * bordercoefficient
- ELSEIF circleposy(i) > (screenheight - circlesize(i) - 1) AND circlevy(i) > 0 THEN
- circleposy(i) = screenheight - circlesize(i) - 1
- circlevx(i) = circlevx(i) * bordercoefficient
- circlevy(i) = -circlevy(i) * bordercoefficient
- IF circletouched(i) = 0 THEN circleactive(i) = 0
- END IF
- END IF
- ' gravity between circle-particles
- IF particlegravity THEN
- accx = 0
- accy = 0
- FOR j = 0 TO totalcircles - 1
- IF circleactive(j) THEN
- IF (i <> j) THEN
- dist = SQR((circleposx(i) - circleposx(j)) * (circleposx(i) - circleposx(j)) + (circleposy(i) - circleposy(j)) * (circleposy(i) - circleposy(j))) + 2
- unitx = (circleposx(j) - circleposx(i)) / dist
- unity = (circleposy(j) - circleposy(i)) / dist
- distpow = dist ^ 2
- accx = accx + 1 / distpow * circlegravity(j) * unitx
- accy = accy + 1 / distpow * circlegravity(j) * unity
- END IF
- END IF
- NEXT j
- circlevx(i) = circlevx(i) + accx
- circlevy(i) = circlevy(i) + accy
- END IF
- ' circle to line collision
- ' get grid cells occupied by the bacircle for checking if any line segment is also in any of the same cells for potential collision
- circlegridpos1x = (circleposx(i) - circlesize(i)) \ gridsizex
- circlegridpos1y = (circleposy(i) - circlesize(i)) \ gridsizey
- circlegridpos2x = (circleposx(i) + circlesize(i)) \ gridsizex
- circlegridpos2y = (circleposy(i) + circlesize(i)) \ gridsizey
- IF circlegridpos1x < 0 THEN circlegridpos1x = 0
- IF circlegridpos1y < 0 THEN circlegridpos1y = 0
- IF circlegridpos2x < 0 THEN circlegridpos2x = 0
- IF circlegridpos2y < 0 THEN circlegridpos2y = 0
- IF circlegridpos1x >= gridcellsx THEN circlegridpos1x = gridcellsx
- IF circlegridpos1y >= gridcellsy THEN circlegridpos1y = gridcellsy
- IF circlegridpos2x >= gridcellsx THEN circlegridpos2x = gridcellsx
- IF circlegridpos2y >= gridcellsy THEN circlegridpos2y = gridcellsy
- collision = 0 ' we shall assumeth teh initial wanderance
- circletolinecontacts(i) = 0 ' also reset the counter
- FOR gy = circlegridpos1y TO circlegridpos2y
- FOR gx = circlegridpos1x TO circlegridpos2x
- FOR gridlineid = 1 TO gridline(gx, gy, 0)
- l = gridline(gx, gy, gridlineid)
- ' make a bounding box of the line
- bound1x = linep1x(l)
- bound2x = linep2x(l)
- IF bound2x < bound1x THEN SWAP bound1x, bound2x
- bound1y = linep1y(l)
- bound2y = linep2y(l)
- IF bound2y < bound1y THEN SWAP bound1y, bound2y
- ' check if circle is inside line's bounding box + its radius
- IF circleposx(i) > bound1x - circlesize(i) AND circleposx(i) < bound2x + circlesize(i) AND circleposy(i) > bound1y - circlesize(i) AND circleposy(i) < bound2y + circlesize(i) THEN
- ' i guess, then calculate some local coordinates
- circleradiuspov = circlesize(i) * circlesize(i)
- localp1x = linep1x(l) - circleposx(i)
- localp1y = linep1y(l) - circleposy(i)
- localp2x = linep2x(l) - circleposx(i)
- localp2y = linep2y(l) - circleposy(i)
- p2minusp1x = localp2x - localp1x
- p2minusp1y = localp2y - localp1y
- a = (p2minusp1x) * (p2minusp1x) + (p2minusp1y) * (p2minusp1y)
- b = 2 * ((p2minusp1x * localp1x) + (p2minusp1y * localp1y))
- c = (localp1x * localp1x) + (localp1y * localp1y) - (circleradiuspov)
- delta = b * b - (4 * a * c)
- ' is a circle intersecting the infinite line?
- IF (delta >= 0) THEN
- collision = 1 ' could actually collide with the segment ?!?!?
- u = -b / (2 * a)
- intersectx = linep1x(l) + (u * p2minusp1x)
- intersecty = linep1y(l) + (u * p2minusp1y)
- ' debug
- 'kakkax = intersectx
- 'kakkay = intersecty
- 'fauxradius = 3
- 'pyllymakkara = 0 ' show debug gfx
- 'kaurakeksi = 0
- ' is a circle outside of the axxual line segment?
- IF (intersectx < bound1x OR intersectx > bound2x) AND (intersecty < bound1y OR intersecty > bound2y) THEN
- tempax = ABS(intersectx - linep1x(l))
- tempbx = ABS(intersectx - linep2x(l))
- tempay = ABS(intersecty - linep1y(l))
- tempby = ABS(intersecty - linep2y(l))
- endpointx = linep1x(l)
- endpointy = linep1y(l)
- IF tempbx < tempax THEN endpointx = linep2x(l)
- IF tempby < tempay THEN endpointy = linep2y(l)
- ' check if we are close enough to hit an endpoint
- distx = endpointx - circleposx(i)
- disty = endpointy - circleposy(i)
- distance = (distx * distx) + (disty * disty)
- IF (distance > circleradiuspov) THEN
- ' nope, too far.
- collision = 0
- ELSE
- ' yeap, close enough.
- intersectx = endpointx
- intersecty = endpointy
- END IF
- END IF
- IF collision THEN
- circletolinecontacts(i) = circletolinecontacts(i) + 1
- ' does teh bacircle move towards teh line?
- distx = intersectx - circleposx(i)
- disty = intersecty - circleposy(i)
- distp = distx * circlevx(i) + disty * circlevy(i)
- IF (distp >= 0) THEN
- distv = (distx * distx) + (disty * disty)
- ' move circle tangent to the line, prevents bacircles slowly flowing through a line
- ' also prevents bacircles from hitting line endpoints while rolling along a line, maybe.
- ' getting stuck between 2 almost parallel lines: how to fix poppage?
- norm = circleradiuspov / distv
- circleposx(i) = intersectx - distx * norm
- circleposy(i) = intersecty - disty * norm
- ' yes, let's calculate the new velocity vector
- newvx = distp / distv * distx
- newvy = distp / distv * disty
- circlevx(i) = circlevx(i) + 2 * -newvx * friction
- circlevy(i) = circlevy(i) + 2 * -newvy * friction
- circletouched(i) = 1
- END IF
- END IF
- END IF
- END IF
- NEXT gridlineid
- NEXT gx
- NEXT gy
- ' downwards gravity
- 'IF NOT collision THEN
- circlevy(i) = circlevy(i) + downwardsgravity
- 'END IF
- ' circle to circle collision detection
- ' get grid cells occupied by the bacircle again, since its position might have changed (line tangent)
- circlegridpos1x = (circleposx(i) - circlesize(i)) \ gridsizex
- circlegridpos1y = (circleposy(i) - circlesize(i)) \ gridsizey
- circlegridpos2x = (circleposx(i) + circlesize(i)) \ gridsizex
- circlegridpos2y = (circleposy(i) + circlesize(i)) \ gridsizey
- IF circlegridpos1x < 0 THEN circlegridpos1x = 0
- IF circlegridpos1y < 0 THEN circlegridpos1y = 0
- IF circlegridpos2x < 0 THEN circlegridpos2x = 0
- IF circlegridpos2y < 0 THEN circlegridpos2y = 0
- IF circlegridpos1x >= gridcellsx THEN circlegridpos1x = gridcellsx
- IF circlegridpos1y >= gridcellsy THEN circlegridpos1y = gridcellsy
- IF circlegridpos2x >= gridcellsx THEN circlegridpos2x = gridcellsx
- IF circlegridpos2y >= gridcellsy THEN circlegridpos2y = gridcellsy
- FOR gy = circlegridpos1y TO circlegridpos2y
- FOR gx = circlegridpos1x TO circlegridpos2x
- FOR gridcircleid = 1 TO gridcircle(gx, gy, 0)
- j = gridcircle(gx, gy, gridcircleid)
- 'FOR j = i + 1 TO totalcircles - 1 ' old slow loop
- IF circleactive(j) THEN
- IF i <> j THEN
- ' check for bounding box
- IF (circleposx(i) + circlesize(i) + circlesize(j) > circleposx(j) AND circleposx(i) < circleposx(j) + circlesize(i) + circlesize(j) AND circleposy(i) + circlesize(i) + circlesize(j) > circleposy(j) AND circleposy(i) < circleposy(j) + circlesize(i) + circlesize(j)) THEN
- ' check if circles axxualli collide
- distx = circleposx(j) - circleposx(i)
- disty = circleposy(j) - circleposy(i)
- distance = (distx * distx) + (disty * disty)
- radii = circlesize(i) + circlesize(j)
- IF (distance <= radii * radii) THEN
- ' yes. but do they move towards each other?
- vx = circlevx(i) - circlevx(j)
- vy = circlevy(i) - circlevy(j)
- IF (distx * vx + disty * vy > 0) THEN
- IF 1 THEN
- ' if circles have enough combined velocity, move them iteratively (vitun hidas) closer to the actual collision
- IF totalvelocity#(circlevx(i), circlevy(i), circlevx(j), circlevy(j)) > 1 THEN
- ' copy velocities
- tempcirclevix = circlevx(i)
- tempcircleviy = circlevy(i)
- tempcirclevjx = circlevx(j)
- tempcirclevjy = circlevy(j)
- ' move balls back and forth to an appropriate degree of precision
- velocityfactor = -0.5
- collision = 1
- oldcollision = 0
- move = 0
- DO
- move = move + 1
- ' check if collision status has changed
- distx = circleposx(j) - circleposx(i)
- disty = circleposy(j) - circleposy(i)
- distance = (distx * distx) + (disty * disty)
- radii = circlesize(i) + circlesize(j)
- IF collision = 0 THEN
- IF (distance <= radii * radii) THEN
- collision = 1
- END IF
- ELSEIF collision = 1 THEN
- IF (distance > radii * radii) THEN
- collision = 0
- END IF
- END IF
- IF collision <> oldcollision THEN
- tempcirclevix = tempcirclevix * velocityfactor
- tempcircleviy = tempcircleviy * velocityfactor
- tempcirclevjx = tempcirclevjx * velocityfactor
- tempcirclevjy = tempcirclevjy * velocityfactor
- END IF
- oldcollision = collision
- circleposx(i) = circleposx(i) + tempcirclevix
- circleposy(i) = circleposy(i) + tempcircleviy
- circleposx(j) = circleposx(j) + tempcirclevjx
- circleposy(j) = circleposy(j) + tempcirclevjy
- ' debug gfx
- IF 0 THEN
- CLS
- PSET (circleposx(i), circleposy(i)), _RGB(255, 255, 0)
- PSET (circleposx(j), circleposy(j)), _RGB(0, 255, 0)
- CIRCLE (circleposx(i), circleposy(i)), circlesize(i), _RGB(200, 200, 200)
- CIRCLE (circleposx(j), circleposy(j)), circlesize(j), _RGB(200, 200, 200)
- PRINT move; ":"; totalvelocity#(tempcirclevix, tempcircleviy, tempcirclevjx, tempcirclevjy)
- PCOPY 0, 1
- _DELAY 0.03
- 'x$ = INPUT$(1)
- END IF
- LOOP UNTIL totalvelocity#(tempcirclevix, tempcircleviy, tempcirclevjx, tempcirclevjy) < 0.5
- END IF
- END IF
- ' compare distance differences and calculate the correct factor of the new velocity vector for the first timestep after collision
- ' todo. =(
- ' new velocities
- distxji = circleposx(j) - circleposx(i)
- distyji = circleposy(j) - circleposy(i)
- distance = (distxji * distxji) + (distyji * distyji)
- newvix = (circlevx(i) * distxji + circlevy(i) * distyji) / distance * distxji
- newviy = (circlevx(i) * distxji + circlevy(i) * distyji) / distance * distyji
- newvjx = (circlevx(j) * -(distxji) + circlevy(j) * -(distyji)) / distance * -(distxji)
- newvjy = (circlevx(j) * -(distxji) + circlevy(j) * -(distyji)) / distance * -(distyji)
- tempivx = circlevx(i) + ((2 * circlemass(j)) / (circlemass(i) + circlemass(j))) * (newvjx - newvix)
- tempivy = circlevy(i) + ((2 * circlemass(j)) / (circlemass(i) + circlemass(j))) * (newvjy - newviy)
- tempjvx = circlevx(j) + ((2 * circlemass(i)) / (circlemass(j) + circlemass(i))) * (newvix - newvjx)
- tempjvy = circlevy(j) + ((2 * circlemass(i)) / (circlemass(j) + circlemass(i))) * (newviy - newvjy)
- ' if the combined velocity of the bacircles is too low, don't apply friction
- velocitycoefficient = friction
- IF totalvelocity(tempivx, tempivy, tempjvx, tempjvy) < stictionthreshold THEN velocitycoefficient = 1
- 'IF circletolinecontacts(i) < 1 THEN
- circlevx(i) = tempivx * velocitycoefficient
- circlevy(i) = tempivy * velocitycoefficient
- 'END IF
- circlevx(j) = tempjvx * velocitycoefficient
- circlevy(j) = tempjvy * velocitycoefficient
- ' make sure the bacircles aren't overlapping
- collisionx = ((circleposx(i) * circlesize(j)) + (circleposx(j) * circlesize(i))) / radii
- collisiony = ((circleposy(i) * circlesize(j)) + (circleposy(j) * circlesize(i))) / radii
- diffxi = collisionx - circleposx(i)
- diffyi = collisiony - circleposy(i)
- diffxj = collisionx - circleposx(j)
- diffyj = collisiony - circleposy(j)
- sqrdiffi = SQR(diffxi * diffxi + diffyi * diffyi)
- sqrdiffj = SQR(diffxj * diffxj + diffyj * diffyj)
- normi = circlesize(i) / sqrdiffi
- normj = circlesize(j) / sqrdiffj
- ' don't fix the position of the first bacircle if it's in contact with at least one line
- ' might need balancing for the second bacircle mutta hyp„t„„n nyt ensin
- IF circletolinecontacts(i) < 1 THEN
- circleposx(i) = collisionx - diffxi * normi
- circleposy(i) = collisiony - diffyi * normi
- END IF
- circleposx(j) = collisionx - diffxj * normj
- circleposy(j) = collisiony - diffyj * normj
- END IF
- END IF
- END IF
- END IF
- END IF
- NEXT gridcircleid
- NEXT gx
- NEXT gy
- END IF
- NEXT i
- physcalcframe = physcalcframe + 1
- NEXT physicsframe
- frame = frame + 1
- GOSUB keyboardroutine ' in case we don't calculate physics at all
- ' debug gfx for shared endpoint collision
- IF pyllymakkara = 1 THEN
- kaurakeksi = kaurakeksi + 1
- IF kaurakeksi = 100 THEN
- kaurakeksi = 0
- pyllymakkara = 0
- END IF
- CIRCLE (kakkax, kakkay), fauxradius
- END IF
- intphys = INT(physperframe)
- fpsstring1$ = fps$ + " fps"
- fpsstring2$ = "x" + trim$(STR$(intphys)) + " (" + pfps$ + ")"
- fpsstringoffset1 = _PRINTWIDTH(fpsstring1$)
- fpsstringoffset2 = _PRINTWIDTH(fpsstring2$)
- COLOR _RGB(255, 255, 255)
- _PRINTSTRING (screenwidth - fpsstringoffset1 - 1, screenheight - 26), fpsstring1$
- _PRINTSTRING (screenwidth - fpsstringoffset2 - 1, screenheight - 14), fpsstring2$
- ' show inp(96) output
- 'FOR k = 0 TO 127
- ' IF scancode(k) THEN PRINT k; scancode(k)
- 'NEXT k
- PCOPY 0, 1
- LINE (0, 0)-(screenwidth - 1, screenheight - 1), color.black, BF
- _LIMIT fpslimit
- LOOP
- 'SYSTEM
- showlevelselector:
- fadefactor = 1
- IF TIMER(0.001) > (levselectorfadertimer + levselectorvisibletime) THEN
- fadefactor = (levselectorfadetime - (TIMER(0.001) - (levselectorfadertimer + levselectorvisibletime))) / levselectorfadetime
- END IF
- FOR i = -levelrange TO levelrange
- colorfactor = (levelrange - ABS(i) + 3) / (levelrange * 2 + 3)
- IF i = 0 THEN colorfactor = 1
- c = 255 * (colorfactor * fadefactor)
- COLOR _RGB(c, c, c)
- IF listoffiles$(leveldiroffset + i + levelrange) = currentlevel$ THEN
- vertices$ = " (" + trim$(STR$(totalvertices)) + ")"
- ELSE
- vertices$ = ""
- END IF
- IF leveldiroffset + i >= 0 THEN _PRINTSTRING (2, textyoffset + (i + levelrange) * fontsize), listoffiles$(leveldiroffset + i + levelrange) + vertices$
- NEXT i
- 'colorfactor = 0.9
- 'c = 255 * (colorfactor * fadefactor)
- 'COLOR _RGB(c, c, c)
- '_PRINTSTRING (2, textyoffset - 2 * fontsize), "vertices: " + trim$(STR$(totalvertices))
- RETURN
- keyboardroutine:
- tempscancode = 0
- dummy$ = INKEY$
- keyboard = INP(96)
- IF keyboard < 128 THEN
- scancode(keyboard) = TIMER(0.001)
- IF downscancode(keyboard) = 0 THEN downscancode(keyboard) = TIMER(0.001)
- ELSE
- scancode(keyboard - 128) = 0
- downscancode(keyboard - 128) = 0
- END IF
- FOR i = 1 TO 127
- IF scancode(i) > 0 AND oldscancode(i) = 0 THEN tempscancode = i
- NEXT i
- IF tempscancode > 0 THEN scancode(tempscancode) = TIMER(0.001)
- ' randomize circles
- IF oncekeypress(19) THEN ' r
- GOSUB initcircles
- GOSUB initlinegrid ' grid size might have changed because the cell size is calculated according to the average bacircle radius
- END IF
- ' toggle cell highlighting
- IF oncekeypress(35) THEN ' h
- hilightcells = hilightcells + 1
- IF hilightcells = 2 THEN hilightcells = 0
- END IF
- ' change number of physics calculations per frame
- IF oncekeypress(12) THEN IF INT(physperframe) > 0 THEN physperframe = physperframe / 2
- IF oncekeypress(13) THEN physperframe = physperframe * 2
- IF oncekeypress(30) THEN selectedline = selectedline + 1
- IF oncekeypress(31) THEN selectedline = selectedline - 1
- IF selectedline = totalvertices THEN selectedline = 0
- IF selectedline < 0 THEN selectedline = totalvertices - 1
- levselectornavigation = 0
- ' select new level
- IF oncekeypress(28) THEN
- GOSUB importelmalevel
- GOSUB initcircles
- GOSUB initlinegrid
- levselectornavigation = 1
- END IF
- ' change level selector offset
- levlistscroll = 1
- IF keypress(42) OR keypress(54) THEN levlistscroll = 8
- IF repeatedkeypress(72) THEN ' arrow up
- leveldiroffset = leveldiroffset - levlistscroll
- IF leveldiroffset < 0 THEN leveldiroffset = 0
- levselectornavigation = 1
- END IF
- IF repeatedkeypress(80) THEN ' arrow down
- leveldiroffset = leveldiroffset + levlistscroll
- IF leveldiroffset > numberoflevels - levelrange - 1 THEN leveldiroffset = numberoflevels - levelrange - 1
- levselectornavigation = 1
- END IF
- IF repeatedkeypress(73) THEN ' page up
- leveldiroffset = leveldiroffset - numberoflevelsshown * levlistscroll
- IF leveldiroffset < 0 THEN leveldiroffset = 0
- levselectornavigation = 1
- END IF
- IF repeatedkeypress(81) THEN ' page down
- leveldiroffset = leveldiroffset + numberoflevelsshown * levlistscroll
- IF leveldiroffset > numberoflevels - levelrange - 1 THEN leveldiroffset = numberoflevels - levelrange - 1
- levselectornavigation = 1
- END IF
- IF levselectornavigation = 1 THEN levselectorfadertimer = TIMER(0.001)
- IF keypress(1) THEN SYSTEM
- FOR i = 0 TO 127
- oldscancode(i) = scancode(i)
- NEXT i
- RETURN
- updatefps:
- fps = INT(physcalcframe / physperframe * 10) / 10 'frame
- fps$ = trim$(STR$(fps))
- IF fps = INT(fps) THEN fps$ = fps$ + ".0"
- IF fps < 1 THEN fps$ = "0" + fps$
- IF fps < 0.1 THEN fps$ = "0.0"
- pfps = physcalcframe
- pfps$ = trim$(STR$(pfps))
- frame = 0
- physcalcframe = 0
- 'IF levselectornavigation = 0 THEN
- ' levselectorfade = levselectorfade + 1
- 'END IF
- RETURN
- getdirectorycontents:
- SHELL _HIDE "dir " + CHR$(34) + elmalevdir$ + "*.lev" + CHR$(34) + " /b /on > bacirclineshelloutput.tmp"
- OPEN "bacirclineshelloutput.tmp" FOR INPUT AS #1
- numberoflevels = 0
- WHILE NOT EOF(1)
- INPUT #1, listoffiles$(numberoflevels)
- numberoflevels = numberoflevels + 1
- WEND
- CLOSE #1
- KILL "bacirclineshelloutput.tmp"
- IF numberoflevels = 0 THEN
- _PRINTSTRING (4, 4), "wateh no levels found =( put me in lev folder pls"
- PCOPY 0, 1
- x$ = INPUT$(1)
- SYSTEM
- END IF
- levelrange = 5 ' how many previous and next levels shown
- IF numberoflevels < (levelrange * 2 + 1) THEN levelrange = 0
- numberoflevelsshown = levelrange * 2 + 1 ' and the one currently selected
- textyoffset = screenheight - (fontsize * numberoflevelsshown) - 4
- leveldiroffset = INT(numberoflevels * RND) ' start at nth file
- RETURN
- importelmalevel:
- ' open elma .lev
- REDIM numberofpolys AS DOUBLE
- filename$ = elmalevdir$ + listoffiles$(leveldiroffset + levelrange)
- OPEN filename$ FOR BINARY AS #1
- GET #1, 131, numberofpolys
- numberofpolys = INT(numberofpolys)
- REDIM numberofvertices(numberofpolys) AS LONG
- REDIM vertexx(numberofpolys, 8000) AS DOUBLE, vertexy(numberofpolys, 8000) AS DOUBLE, grassflag(numberofpolys) AS LONG
- minvertexx = 1000000
- minvertexy = 1000000
- maxvertexx = -1000000
- maxvertexy = -1000000
- v = 0
- FOR poly = 0 TO numberofpolys - 1
- GET #1, , grassflag(poly)
- GET #1, , numberofvertices(poly)
- FOR vert = 0 TO numberofvertices(poly) - 1
- GET #1, , vertexx(poly, vert)
- GET #1, , vertexy(poly, vert)
- IF vertexx(poly, vert) < minvertexx THEN minvertexx = vertexx(poly, vert)
- IF vertexy(poly, vert) < minvertexy THEN minvertexy = vertexy(poly, vert)
- IF vertexx(poly, vert) > maxvertexx THEN maxvertexx = vertexx(poly, vert)
- IF vertexy(poly, vert) > maxvertexy THEN maxvertexy = vertexy(poly, vert)
- v = v + 1
- NEXT vert
- NEXT poly
- CLOSE #1
- ' scale level to fit screen
- factorvertexx = (screenwidth - 1) / (maxvertexx - minvertexx)
- factorvertexy = (screenheight - 1) / (maxvertexy - minvertexy)
- scalefactor = factorvertexx
- xoffset = 0
- IF factorvertexy < scalefactor THEN
- scalefactor = factorvertexy
- xoffset = (screenwidth - scalefactor * (maxvertexx - minvertexx)) / 2
- END IF
- FOR poly = 0 TO numberofpolys - 1
- IF grassflag(poly) = 0 THEN
- FOR vert = 0 TO numberofvertices(poly) - 1
- vertexx(poly, vert) = (vertexx(poly, vert) - minvertexx) * scalefactor + xoffset
- vertexy(poly, vert) = (vertexy(poly, vert) - minvertexy) * scalefactor
- NEXT vert
- END IF
- NEXT poly
- l = 0
- FOR poly = 0 TO numberofpolys - 1
- IF grassflag(poly) = 0 THEN
- FOR vert = 0 TO numberofvertices(poly) - 1
- nextvert = vert + 1
- IF nextvert = numberofvertices(poly) THEN nextvert = 0
- linep1x(l) = vertexx(poly, vert)
- linep1y(l) = vertexy(poly, vert)
- linep2x(l) = vertexx(poly, nextvert)
- linep2y(l) = vertexy(poly, nextvert)
- IF ABS(linep2x(l) - linep1x(l)) < 0.01 THEN linep2x(l) = linep2x(l) + 0.001 ' to prevent zero-sized
- IF ABS(linep2y(l) - linep1y(l)) < 0.01 THEN linep2y(l) = linep2y(l) + 0.001 ' bounding box
- l = l + 1
- ' LINE (vertexx(poly, vert), vertexy(poly, vert))-(vertexx(poly, nextvert), vertexy(poly, nextvert))
- NEXT vert
- END IF
- NEXT poly
- totalvertices = l
- RETURN
- initlinegrid:
- ' reset the line grid
- FOR y = 0 TO gridcellsy
- FOR x = 0 TO gridcellsx
- FOR i = 1 TO gridline(x, y, 0)
- gridline(x, y, i) = 0
- NEXT i
- gridline(x, y, 0) = 0
- NEXT x
- NEXT y
- ' populate the line grid
- FOR l = 0 TO totalvertices - 1
- length = INT(SQR((linep2x(l) - linep1x(l)) * (linep2x(l) - linep1x(l)) + (linep2y(l) - linep1y(l)) * (linep2y(l) - linep1y(l))))
- lengthdiv = length
- IF lengthdiv = 0 THEN lengthdiv = 1
- FOR c = 0 TO length
- cellx = (linep1x(l) + (linep2x(l) - linep1x(l)) * (c / lengthdiv)) \ gridsizex
- celly = (linep1y(l) + (linep2y(l) - linep1y(l)) * (c / lengthdiv)) \ gridsizey
- IF gridline(cellx, celly, gridline(cellx, celly, 0)) <> l OR gridline(cellx, celly, 0) = 0 THEN
- gridline(cellx, celly, 0) = gridline(cellx, celly, 0) + 1 ' the cell has one more line in it
- gridline(cellx, celly, gridline(cellx, celly, 0)) = l ' add that line's id to that cell
- END IF
- NEXT c
- NEXT l
- RETURN
- initcircles:
- circlecolumns = 128
- FOR i = 0 TO totalcircles - 1
- circlemass(i) = 4 * RND + 4
- circleposx(i) = ((i MOD circlecolumns) + 2) * (screenwidth / (circlecolumns + 3))
- circleposy(i) = (i \ circlecolumns) * 20 + 120
- circlevx(i) = maxvx * RND - maxvx / 2
- circlevy(i) = maxvy * RND - maxvy / 2
- IF filename$ <> currentlevel$ THEN
- circleactive(i) = 1
- circletouched(i) = 0
- END IF
- NEXT i
- drawoffsetx = 0
- drawoffsety = 0
- IF 0 THEN
- circleposx(0) = 320
- circleposy(0) = 200
- circlemass(0) = 3000
- circlevx(0) = 0.5
- circlevy(0) = 0.8
- END IF
- FOR i = 0 TO totalcircles - 1
- circlegravity(i) = circlemass(i) / 1280
- circlesize(i) = SQR(circlemass(i))
- NEXT i
- currentlevel$ = filename$
- avgcirclesize = 0
- FOR i = 0 TO totalcircles - 1: avgcirclesize = avgcirclesize + circlesize(i): NEXT i
- avgcirclesize = avgcirclesize / totalcircles
- IF avgcirclesize < 4 THEN avgcirclesize = 4
- gridsizex = FIX(avgcirclesize * 4)
- gridsizey = FIX(avgcirclesize * 4)
- gridcellsx = FIX(screenwidth / gridsizex)
- gridcellsy = FIX(screenheight / gridsizey)
- REDIM gridcircle(gridcellsx, gridcellsy, totalcircles) AS INTEGER ' work, bitch
- RETURN
- ' obsolete
- initlines:
- FOR l = 1 TO numberoflines - 1
- 'linep1x(l) = linep2x(l - 1)
- 'linep1y(l) = linep2y(l - 1)
- 'linep2x(l) = linep1x(l) + 200 * RND - 100
- 'linep2y(l) = linep1y(l) + 200 * RND - 100
- linep1x(l) = screenwidth * RND
- linep1y(l) = screenheight * RND
- linep2x(l) = linep1x(l) + 400 * RND - 200
- linep2y(l) = linep1y(l) + 400 * RND - 200
- NEXT l
- IF 0 THEN
- linep1x(0) = 290
- linep1y(0) = 170
- linep2x(0) = 340
- linep2y(0) = 220
- linep1x(1) = 290
- linep1y(1) = 170
- linep2x(1) = 340
- linep2y(1) = 223
- END IF
- IF 1 THEN
- linep1x(0) = 20
- linep1y(0) = 310
- linep2x(0) = 150
- linep2y(0) = 305
- linep1x(1) = 150
- linep1y(1) = 305
- linep2x(1) = 200
- linep2y(1) = 309
- linep1x(2) = 200
- linep1y(2) = 309
- linep2x(2) = 400
- linep2y(2) = 300 '291.1
- linep1x(3) = 430
- linep1y(3) = 260
- linep2x(3) = 430.1
- linep2y(3) = 260.1
- linep1x(4) = 450
- linep1y(4) = 320
- linep2x(4) = 600
- linep2y(4) = 305
- linep1x(5) = 600
- linep1y(5) = 305
- linep2x(5) = 640
- linep2y(5) = 293
- linep1x(6) = 450 '0
- linep1y(6) = 320 '311
- linep2x(6) = 400 '50
- linep2y(6) = 300 '290
- END IF
- RETURN
- SUB aaLine (x0, y0, x1, y1, rgbcol AS LONG, settype)
- ox0 = x0
- oy0 = y0
- ox1 = x1
- oy1 = y1
- steep = 0
- IF ABS(y1 - y0) > ABS(x1 - x0) THEN steep = 1
- IF steep THEN
- SWAP x0, y0
- SWAP x1, y1
- END IF
- IF x0 > x1 THEN
- SWAP x0, x1
- SWAP y0, y1
- END IF
- dx = x1 - x0
- dy = y1 - y0
- gradient = dy / dx
- ' koodirosmo's comment: these endpoints seem to be performing subpar-ly
- ' handle first endpoint
- xend = CINT(x0) ' this and CINT(x1) sometimes crashes if a circle drops from high enough onto a line (?)
- yend = y0 + gradient * (xend - x0)
- xgap = rfpart(x0 + 0.5)
- xpxl1 = xend ' this will be used in the main loop
- ypxl1 = FIX(yend)
- IF steep THEN
- plot ypxl1, xpxl1, rfpart(yend) * xgap, rgbcol, settype
- plot ypxl1 + 1, xpxl1, fpart(yend) * xgap, rgbcol, settype
- ELSE
- plot xpxl1, ypxl1, rfpart(yend) * xgap, rgbcol, settype
- plot xpxl1, ypxl1 + 1, fpart(yend) * xgap, rgbcol, settype
- END IF
- intery = yend + gradient ' first y-intersection for the main loop
- ' handle second endpoint
- xend = CINT(x1)
- yend = y1 + gradient * (xend - x1)
- xgap = fpart(x1 + 0.5)
- xpxl2 = xend ' this will be used in the main loop
- ypxl2 = FIX(yend)
- IF steep THEN
- plot ypxl2, xpxl2, rfpart(yend) * xgap, rgbcol, settype
- plot ypxl2 + 1, xpxl2, fpart(yend) * xgap, rbgcol, settype
- ELSE
- plot xpxl2, ypxl2, rfpart(yend) * xgap, rgbcol, settype
- plot xpxl2, ypxl2 + 1, fpart(yend) * xgap, rgbcol, settype
- END IF
- ' main loop
- FOR x = xpxl1 + 1 TO xpxl2 - 1
- IF steep THEN
- plot FIX(intery), x, rfpart(intery), rgbcol, settype
- plot FIX(intery) + 1, x, fpart(intery), rgbcol, settype
- ELSE
- plot x, FIX(intery), rfpart(intery), rgbcol, settype
- plot x, FIX(intery) + 1, fpart(intery), rgbcol, settype
- END IF
- intery = intery + gradient
- NEXT x
- ' kr”hh”m.
- plot ox0, oy0, 1, rgbcol, 0
- plot ox1, oy1, 1, rgbcol, 0
- END SUB
- SUB plot (x, y, c, rgbcol AS LONG, settype)
- ' draw antialiased pixel
- ' settype: 0 = draw if any of the color channels is brighter than in the current pixel
- ' 1 = add to the pixel color channels
- DIM p AS LONG
- 'PRINT c;
- 'PCOPY 0, 1
- IF c > 1 THEN c = 1
- IF c > 0 THEN c = sqrlookup(c * 32768) ' SQR(c)
- r = _RED(rgbcol) * c
- g = _GREEN(rgbcol) * c
- b = _BLUE(rgbcol) * c
- p = POINT(x, y)
- pr = _RED(p)
- pg = _GREEN(p)
- pb = _BLUE(p)
- IF settype = 0 THEN
- IF pr < r OR pg < g OR pb < b THEN PSET (x, y), _RGB(r, g, b)
- ELSEIF settype = 1 THEN
- PSET (x, y), _RGB(r + pr, g + pg, b + pb)
- END IF
- END SUB
- ' fractional part of x
- FUNCTION fpart (x)
- IF x < 0 THEN fpart = 1 - (x - FIX(x))
- fpart = x - FIX(x)
- END FUNCTION
- FUNCTION rfpart (x)
- rfpart = 1 - fpart(x)
- END FUNCTION
- SUB aaCircle (x, y, radius, rgbcol AS LONG, settype)
- 'CIRCLE (x, y), radius, rgbcol
- 'PAINT (x, y), rgbcol
- ci = radius * 2
- FOR i = 0 TO ci
- a0 = i * _PI / radius
- a1 = (i + 1) * _PI / radius
- x0 = x + COS(a0) * radius
- y0 = y + SIN(a0) * radius
- x1 = x + COS(a1) * radius
- y1 = y + SIN(a1) * radius
- aaLine x0, y0, x1, y1, rgbcol, settype
- NEXT i
- END SUB
- SUB aaFilledCircle (x, y, radius, rgbcol AS LONG)
- ' this is fuging idiotic
- aaCircle x, y, radius, rgbcol, 0
- aaCircle x, y, radius - 0.5, rgbcol, 0
- FOR c = 1 TO radius - 1 STEP 0.5
- aaCircle x, y, c, rgbcol, 1
- NEXT c
- END SUB
- FUNCTION acos (x AS DOUBLE) ' inverse cosine, not used anywhere
- IF x < 1 THEN
- acos = (2 * ATN(1)) - ATN(x / SQR(1 - x * x))
- END IF
- END FUNCTION
- ' combined velocities of two bacircles
- FUNCTION totalvelocity# (vix AS DOUBLE, viy AS DOUBLE, vjx AS DOUBLE, vjy AS DOUBLE)
- totalvelocity# = SQR(vix * vix + viy * viy) + SQR(vjx * vjx + vjy * vjy)
- END FUNCTION
- ' true if key is held down
- FUNCTION keypress (code)
- IF scancode(code) > 0 THEN keypress = scancode(code)
- END FUNCTION
- ' true only once when key was first pressed down
- FUNCTION oncekeypress (code)
- IF scancode(code) > 0 AND oldscancode(code) = 0 THEN oncekeypress = scancode(code)
- END FUNCTION
- ' mimics key repeat
- FUNCTION repeatedkeypress (code)
- pressed = oncekeypress(code)
- IF pressed OR scancode(code) > (downscancode(code) + 0.3) THEN
- IF (TIMER(0.001) > keyboardrepeat + 0.03) THEN
- repeatedkeypress = scancode(code)
- keyboardrepeat = TIMER(0.001)
- END IF
- END IF
- END FUNCTION
- FUNCTION trim$ (s$)
- trim$ = LTRIM$(RTRIM$(s$))
- END FUNCTION
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement