'*************** Zom-B's famous (at least on [abandoned, outdated and now likely malicious qb64 dot net website - don’t go there]) screen mode selector!
DIM SHARED maxscreenx
, maxscreeny
, maxscreenz
ncolors = 32
_TITLE "Rotating Polys Using Gradient Triangle And Lines From Center of screen to object centroid * rendered in real-time no get or put. press mouse button or space bar for cool effect, esc to exit"
'************************ for experimental collision detection algo
DIM SHARED DivSecX
, DivSecY
, DivSecZ
, NumXSegs
, NumYSegs
, NumZSegs
, MinObjectRotateXYZ%
, MaxObjectRotateRateXYZ%
, MaxR
DIM SHARED currentplayerx
, currentplayery
, currentplayerz
NumYSegs = 16
NumXSegs = 16
NumZSegs = 16
maxscreenz = 1024
DivSecZ = maxscreenz / NumZSegs
'* this is just an arbitrary formula i came up with that keeps counts() and polysinregion() from having array bounds errors
'* there is probably a better one available, but this involves a lot of probability theory
ProbableMax = 2 * MaxPolys / ((NumXSegs + 1) ^ (1 / 8))
DIM SHARED Counts
(NumXSegs
, NumYSegs
, NumZSegs
), PolysInRegion
(NumXSegs
, NumYSegs
, NumZSegs
, ProbableMax
)
'*************************
k! = 2520
'2^3 * 3^2 * 5 * 7 = 2520, a number dividable by all numbers between 1 and 10.
DIM SHARED SinTable!
(0 TO k!
- 1), CosTable!
(0 TO k!
- 1), UpBoundTrigTables%
, mybulletmin
, mybulletmax
, myship
, points&
UpBoundTrigTables%
= UBOUND(SinTable!
)MaxObjectRotateRateXYZ% = (UpBoundTrigTables% + 1) / 8
MinObJectRotateRateXYZ% = (UpBoundTrigTables% + 1) / 15
'* use precalculated trig tables for speed, especially doing rotations!
'* this program does a ton of them
FOR i
= 0 TO UpBoundTrigTables%
a! = i * 3.141592653589793 / ((UpBoundTrigTables% + 1) / 2)
keystepx = maxscreenx / 10
keystepy = maxscreeny / 10
keystepz = maxscreenz / 10
DIM Polys
(MaxPolys
) AS PolyRec
MaxR = DivSecX
MaxR = DivSecY
MaxR = DivSecZ
'* user-controlled poly -- still a bit jumpy to say the least, even with loop-unrolled (formerly the for/next with index i on polygons)
'* program a faster way to handle this and add some shooting/effects, you got yourself a game!
myship = 0
numbullets = 32
mybulletmin = myship + 1
mybulletmax = mybulletmin + numbullets
'* set default values for stuff flying around on-screen
'* must pass i as this determines the classification of the polygon
'* far easier to do this than creating individual polygon records for the ship, its weapons (laserbombs) and each asteroid (polyoid)
setPolyParams Polys(), i
nframes% = 0
frames& = 0
Bytes% = (DivSecX * DivSecY * (32 / 8) + 4) / 2
DIM RestoreScreen%
(DivSecX
, DivSecY
, 1 TO Bytes%
) oldpx = -1
oldpy = -1
asteroidhit = 0
'* change this to 0 for making into game
testing = -1
down$
= CHR$(0) + CHR$(80) '* down arrow rght$
= CHR$(0) + CHR$(77) '* right arrow forward$
= CHR$(0) + CHR$(145) '*ctrl-down fire$ = " "
fdx$ = "X"
fdy$ = "Y"
fdz$ = "Z"
fdxn$ = "^X"
fdyn$ = "^Y"
fdzn$ = "^Z"
cutthatcrapout$
= CHR$(27) GetKey "Up", up$
GetKey "Down", down$
GetKey "Left", lft$
GetKey "Right", rght$
GetKey "forward", forward$
GetKey "Back", back$
GetKey "Fire", fire$
GetKey "Stop this infernal madness", cutthatcrapout$
GetKey "Fire Direction X+", fdx$
GetKey "Fire Direction Y+", fdy$
GetKey "Fire Direction Z+", fdz$
GetKey "Fire Direction X-", fdxn$
GetKey "Fire Direction Y-", fdyn$
GetKey "Fire Direction Z-", fdzn$
'_FULLSCREEN
points& = 0
asteroidhit = 0
asteroidhitmax = 256
i = MaxPolys + 1
missilesactive% = 0
nframes% = 0
frames& = frames& + 1
k$ = fire$
IF rb%
THEN '* function not yet implemented currentplayerx = SetToMinMax(currentplayerx - keystepx, Polys(myship).radius, maxscreenx - Polys(myship).radius)
currentplayerx = SetToMinMax(currentplayerx + keystepx, Polys(myship).radius, maxscreenx - Polys(myship).radius)
currentplayery = SetToMinMax(currentplayery - keystepy, Polys(myship).radius, maxscreeny - Polys(myship).radius)
currentplayery = SetToMinMax(currentplayery + keystepy, Polys(myship).radius, maxscreeny - Polys(myship).radius)
CASE forward$
'* into the screen -- increasing z values move away from player currentplayerz = SetToMinMax(currentplayerz + keystepz, Polys(myship).radius, maxscreenz - Polys(myship).radius)
currentplayerz = SetToMinMax(currentplayerz - keystepz, Polys(myship).radius, maxscreenz - Polys(myship).radius)
'* the laserbombs start in a cluster and spread out fairly evenly along x,y and z planes
'* don't fire off too many at once or my collision-checking program might scream
'* i have fired off 64 at once without failure. for a cool effect, hold down the spacebar
'* or whatever key you select for your fire button and then release it.
missilesactive% = -1
nframes% = 0
count% = 0
FOR h
= mybulletmin
TO mybulletmax
Polys(h).active = -1
Polys(h).px = currentplayerx + Polys(myship).radius
Polys(h).py = currentplayery + Polys(myship).radius
Polys(h).pz = currentplayerz + Polys(myship).radius
Polys
(h
).incz
= (CINT(RND) * 2 - 1) * (INT(RND * (maxscreenz \
32)) + 1) 'Polys(h).incx = 7 + INT(RND * 9)
'Polys(h).incy = 7 + INT(RND * 9)
'Polys(h).incz = 7 + INT(RND * 9)
fdx = 1
fdy = 1
fdz = 1
fdx = fdx + 1
fdy = fdy + 1
fdz = fdz + 1
fdx = fdx - 1
fdy = fdy - 1
fdz = fdz - 1
mk = 0
mk = mk + 1
IF oldpx
<> currentplayerx
OR oldpy
<> currentplayery
OR currentplayerz
<> oldpz
THEN 'drawpolySimple PlayerRect, _RGB32(PlayerRect.cr, playerrrect.cg, PlayerRect.cb)
oldpy = currentplayery
oldpx = currentplayerx
oldpz = currentplayerz
'PlayerRect.px = CurrentPlayerx
'PlayerRect.py = CurrentPlayerY
'PlayerRect.pz = CurrentPlayerZ
PrintLocate
3, 1, MID$(STR$(points&
), 2), 1, 0, 0, dummy$
oldpx = currentplayerx - 1
oldpy = currentplayery - 1
i = 0
FOR a
= 0 TO Counts
(X
, y
, z
) - 1 Polys(PolysInRegion(X, y, z, a)).alreadychecked = 0
Counts(X, y, z) = 0
'drawpoly Polys(i), 0
Polys(i).px = currentplayerx
Polys(i).py = currentplayery
Polys(i).pz = currentplayerz
IF Polys
(i
).px
> maxscreenx
- Polys
(i
).incx
- Polys
(i
).radius
THEN Polys(i).incx = -Polys(i).incx
Polys
(i
).incrotate
= -SGN(Polys
(i
).incy
) * RandRange%
(MinObJectRotateRateXYZ%
, MaxObjectRotateRateXYZ%
) ELSEIF Polys
(i
).px
< Polys
(i
).radius
- Polys
(i
).incx
THEN Polys(i).incx = -Polys(i).incx
Polys
(i
).incrotate
= SGN(Polys
(i
).incy
) * RandRange%
(MinObJectRotateRateXYZ%
, MaxObjectRotateRateXYZ%
)
IF Polys
(i
).py
> maxscreeny
- Polys
(i
).incy
- Polys
(i
).radius
THEN Polys(i).incy = -Polys(i).incy
Polys
(i
).incrotate
= SGN(Polys
(i
).incx
) * RandRange%
(MinObJectRotateRateXYZ%
, MaxObjectRotateRateXYZ%
) ELSEIF Polys
(i
).py
< Polys
(i
).radius
- Polys
(i
).incy
THEN Polys(i).incy = -Polys(i).incy
Polys
(i
).incrotate
= -SGN(Polys
(i
).incx
) * RandRange%
(MinObJectRotateRateXYZ%
, MaxObjectRotateRateXYZ%
)
IF Polys
(i
).pz
> maxscreenz
- Polys
(i
).incz
- Polys
(i
).radius
THEN Polys(i).incz = -Polys(i).incz
Polys
(i
).incrotate
= SGN(Polys
(i
).incx
) * RandRange%
(MinObJectRotateRateXYZ%
, MaxObjectRotateRateXYZ%
) ELSEIF Polys
(i
).pz
< Polys
(i
).radius
- Polys
(i
).incz
THEN Polys(i).incz = -Polys(i).incz
Polys
(i
).incrotate
= -SGN(Polys
(i
).incz
) * RandRange%
(MinObJectRotateRateXYZ%
, MaxObjectRotateRateXYZ%
) '* SetIncrementers Polys(i).px, Polys(i).incx, Polys(i).radius, Maxscreenx - Polys(i).radius
'* SetIncrementers Polys(i).py, Polys(i).incy, Polys(i).radius, Maxscreeny - Polys(i).radius
'* SetIncrementers Polys(i).pz, Polys(i).incz, Polys(i).radius, MaxScreenZ - Polys(i).radius
SetIncrementers Polys(i).cr, Polys(i).crs, 0, 255
SetIncrementers Polys(i).cg, Polys(i).cgs, 0, 255
SetIncrementers Polys(i).cb, Polys(i).cbs, 0, 255
Polys(i).horizontal = MapToTrigTables%(Polys(i).horizontal + Polys(i).horizontalinc)
Polys(i).vertical = MapToTrigTables%(Polys(i).vertical + Polys(i).verticalinc)
Polys(i).rotateangle = MapToTrigTables%(Polys(i).rotateangle + Polys(i).incrotate)
Polys(i).px = Polys(i).px + Polys(i).incx
Polys(i).py = Polys(i).py + Polys(i).incy
Polys(i).pz = Polys(i).pz + Polys(i).incz
Polys(i).cr = Polys(i).cr + Polys(i).crs
Polys(i).cg = Polys(i).cg + Polys(i).cgs
Polys(i).cb = Polys(i).cb + Polys(i).cbs
drawpoly Polys(i), 1
getsegminmax Polys(i).px, StartX, EndX, Polys(i).radius, IndexX, DivSecX, NumXSegs
getsegminmax Polys(i).py, StartY, EndY, Polys(i).radius, IndexY, DivSecY, NumYSegs
getsegminmax Polys(i).pz, StartZ, EndZ, Polys(i).radius, IndexZ, DivSecZ, NumZSegs
PolysInRegion(IndexX, IndexY, IndexZ, Counts(IndexX, IndexY, IndexZ)) = i
Polys(PolysInRegion(IndexX, IndexY, IndexZ, i)).alreadychecked = -1
FOR z
= 0 TO Counts
(sx
, sy
, sz
) - 1 Counts(IndexX, IndexY, IndexZ) = Counts(IndexX, IndexY, IndexZ) + 1
'PutRegion Polys(i), IndexX, IndexY, RestoreScreen%()
'drawpoly Polys(i), 0
i = i + 1
nframes% = nframes% + 1
'* LOCATE 2, 1
'* PRINT "Ha! You missed us, James T Kirk -- you suck!";
FOR h
= mybulletmin
TO mybulletmax
'* drawpoly Polys(h), 0
Polys(h).active = 0
count% = 0
nframes% = 0
missilesactive% = 0
count% = count% + 1
'_LIMIT 60
'CLS
'_TITLE STR$(frames& / 1000) + STR$(frames& / (TIMER - tstart#))
'saveimage _DEST, "ScreenShot" + STR$(frame& / 1000)
'SYSTEM
PRINT frames&
/ (tend#
- tstart#
)
MainCollider:
IF PolysInRegion
(sx
, sy
, sz
, i
) <> PolysInRegion
(sx
, sy
, sz
, z
) THEN collide Polys(), PolysInRegion(sx, sy, sz, i), PolysInRegion(sx, sy, sz, z)
IF Distance
(Polys
(PolysInRegion
(sx
, sy
, sz
, i
)), Polys
(PolysInRegion
(sx
, sy
, sz
, z
))) <= 0 THEN SELECT CASE Polys
(PolysInRegion
(sx
, sy
, sz
, i
)).kind
IF Polys
(PolysInRegion
(sx
, sy
, sz
, z
)).kind
= laserbomb
THEN '* asteroid smacked bomb
Polys(PolysInRegion(sx, sy, sz, z)).active = 0
Polys(PolysInRegion(sx, sy, sz, i)).active = 0
points& = points& + 1
IF Polys
(PolysInRegion
(sx
, sy
, sz
, z
)).kind
= asteroid
THEN '* bomb smacked asteroid
Polys(PolysInRegion(sx, sy, sz, z)).active = 0
Polys(PolysInRegion(sx, sy, sz, i)).active = 0
points& = points& + 1
IF Polys
(PolysInRegion
(sx
, sy
, sz
, z
)).kind
= asteroid
THEN '* asteroid smacked my ship
IF asteroidhit
< asteroidhitmax
THEN asteroidhit = asteroidhit + 1
points& = points& - 1
asteroidhit = 0
SUB setPolyParams
(p
() AS PolyRec
, i
) p
(i
).radius
= INT(((MaxR
- 2) / 1.28) * RND) + 2 p
(i
).px
= INT(RND * (maxscreenx
- 2 * p
(i
).radius
)) + p
(i
).radius
p
(i
).py
= INT(RND * (maxscreeny
- 2 * p
(i
).radius
)) + p
(i
).radius
p
(i
).pz
= INT(RND * (maxscreenz
- 2 * p
(i
).radius
)) + p
(i
).radius
p
(i
).nsides
= INT(RND * 7) + 2 IF p
(i
).nsides
= 2 THEN p
(i
).nsides
= 40 'approximate circle p
(i
).incz
= (CINT(RND) * 2 - 1) * (INT(RND * (maxscreenz \
32)) + 1) p(i).rotateangle = RangeNum%(MinObjectRotateXYZ%, MaxObjectRotateRateXYZ%)
p
(i
).incrotate
= (CINT(RND) * 2 - 1) * RandRange%
(MinObJectRotateRateXYZ%
, MaxObjectRotateRateXYZ%
)
'* these are used by drawpolySimple
p
(i
).fillstep
= INT(RND * MaxR
) + 1 p
(i
).dosectorlines
= INT(1 - RND * 2) p
(i
).vertical
= (CINT(RND) * 2 - 1) * RangeNum%
(MinObjectRotateXYZ%
, MaxObjectRotateRateXYZ%
) p
(i
).horizontal
= (CINT(RND) * 2 - 1) * RangeNum%
(MinObjectRotateXYZ%
, MaxObjectRotateRateXYZ%
) p
(i
).verticalinc
= (CINT(RND) * 2 - 1) * RangeNum%
(MinObjectRotateXYZ%
, MaxObjectRotateRateXYZ%
) p
(i
).horizontalinc
= (CINT(RND) * 2 - 1) * RangeNum%
(MinObjectRotateXYZ%
, MaxObjectRotateRateXYZ%
) 'Color cycling
'* these are used by collision checker
p(i).mass = 1 '(Polys(i).radius ^ 3) / 4
p(i).alreadychecked = 0
p(i).active = -1
p(i).kind = ismyship
p(i).incx = 0
p(i).incy = 0
p(i).incz = 0
p(i).radius = MaxR
p(i).pz = currentplayerx
p(i).py = currentplayery
p(i).px = currentplayerz
p(i).incrotate = (UpBoundTrigTables% + 1) / (p(i).nsides + 1)
CASE mybulletmin
TO mybulletmax
p(i).kind = laserbomb
p(i).active = 0
p
(i
).nsides
= INT(RND * 7) + 3 p(i).kind = asteroid
PRINT "Press the key to go "; p$
SUB getsegminmax
(ptcheck
, sxy
, exy
, radius
, Index
, divider
, NumSegs
) Index = SetToMinMax(ptcheck \ divider, 0, NumSegs)
sxy = (ptcheck - radius) \ divider
sxy = Index
IF (ptcheck
+ radius
) \ divider
> NumSegs
THEN exy = NumSegs
exy = (ptcheck + radius) \ divider
FUNCTION SetToMinMax
(calcvalue
, minval
, maxval
) '* used to calculate rotating values, namely color variations used for shading/coloring polygons and increments used for moving asteroids/laserbombs
'* whose values are not mouse/user input dependent
SetToMinMax = minval
SetToMinMax = maxval
SetToMinMax = calcvalue
SUB SetIncrementers
(a
, addv
, min
, max
) a = SetToMinMax(a + addv, min, max)
addv = -addv
addv = -addv
SUB collide
(p
() AS PolyRec
, x
, y
) calcmethod = 1
IF Distance
(p
(x
), p
(y
)) > 0 THEN CalcVelocities p(), x, y
p(x).alreadychecked = -1
p(y).alreadychecked = -1
IF ABS(p
(x
).pz
- p
(y
).pz
) < p
(x
).radius
+ p
(y
).radius
THEN d = ((p(x).px - p(y).px) ^ 2 + (p(x).py - p(y).py) ^ 2)
IF d
<= (p
(x
).radius
+ p
(y
).radius
) ^ 2 THEN CalcVelocities p(), x, y
p(x).alreadychecked = -1
p(y).alreadychecked = -1
'* calculates distance using pythagorean formula for (x1,y1), (x2,y2) and relative distance betweenz Z
dx! = (p.px - q.px) ^ 2
dy! = (p.py - q.py) ^ 2
IF hyp!
> p.radius
+ q.radius
THEN s! = hyp! - (p.radius + q.radius)
IF ABS(p.pz
- q.pz
) > p.radius
+ q.radius
THEN s! = hyp! - (p.radius + q.radius)
Distance = s!
'* generates random number from min% to max% inclusive
RangeNum%
= min%
+ INT(RND * (max%
- min%
+ 1))
GetPx = p.px
GetPx = p.py
GetPx = p.pz
GetPx = 0
SUB CalcVelocities
(b
() AS PolyRec
, i&
, j&
) temp1 = b(i&).incx
temp2 = b(j&).incx
totalMass = (b(i&).mass + b(j&).mass)
b(i&).incx = (temp1 * (b(i&).mass - b(j&).mass) + (2 * b(j&).mass * temp2)) / totalMass
b(j&).incx = (temp2 * (b(j&).mass - b(i&).mass) + (2 * b(i&).mass * temp1)) / totalMass
temp1 = b(i&).incy
temp2 = b(j&).incy
b(i&).incy = (temp1 * (b(i&).mass - b(j&).mass) + (2 * b(j&).mass * temp2)) / totalMass
b(j&).incy = (temp2 * (b(j&).mass - b(i&).mass) + (2 * b(i&).mass * temp1)) / totalMass
temp1 = b(i&).incz
temp2 = b(j&).incz
b(i&).incz = (temp1 * (b(i&).mass - b(j&).mass) + (2 * b(j&).mass * temp2)) / totalMass
b(j&).incz = (temp2 * (b(j&).mass - b(i&).mass) + (2 * b(i&).mass * temp1)) / totalMass
SUB drawpoly
(p
AS PolyRec
, intensity
) REDIM x
(p.nsides
), y
(p.nsides
) cr0 = 255 * intensity
cg0 = 255 * intensity
cb0 = 255 * intensity
cr1 = p.cr * intensity
cg1 = p.cg * intensity
cb1 = p.cb * intensity
x = p.px
y = p.py
z = p.pz
r = p.radius
a!
= p.rotateangle
- INT(p.rotateangle
/ (UpBoundTrigTables%
+ 1)) * (UpBoundTrigTables%
+ 1) sa! = (UpBoundTrigTables% + 1) / p.nsides
x1! = CosTable!(b) * CosTable!(p.horizontal)
y1! = SinTable!(b) * SinTable!(p.vertical)
zscale! = (z / maxscreenz)
rzscale! = r * zscale!
fx = x + rzscale! / 3
fx = x - rzscale! / 3
fy = y - rzscale! / 3
fy = y + rzscale! / 3
a! = a! + sa!
a! = a! + (UpBoundTrigTables% + 1) * (a! >= (UpBoundTrigTables% + 1))
x2! = CosTable!(b) * CosTable!(p.horizontal): x(a) = x2!
y2! = SinTable!(b) * SinTable!(p.vertical): y(a) = y2!
gTriangle fx
, fy
, x
+ (x1!
* rzscale!
), y
+ (y1!
* rzscale!
), x
+ (x2!
* rzscale!
), y
+ (y2!
* rzscale!
), _RGB32(cr0
, cg0
, cb0
), _RGB32(cr1
, cg1
, cb1
), RGBToNum
(cr1
, cg1
, cb1
) gTriangle fx
, fy
, x
+ (x1!
* r
), y
+ (y1!
* r
), x
+ (x2!
* r
), y
+ (y2!
* r
), _RGB32(cr0
, cg0
, cb0
), _RGB32(cr1
, cg1
, cb1
), _RGB32(cr1
, cg1
, cb1
) drawpolySimple p
, _RGB32(cr0
, cg0
, cb0
) gTriangle fx
, fy
, x
+ (x1!
* rzscale!
), y
+ (y1!
* rzscale!
), x
+ (x2!
* rzscale!
), y
+ (y2!
* rzscale!
), _RGB32(cr0
, cg0
, cb0
), _RGB32(cr1
, cg1
, cb1
), RGBToNum
(cr1
, cg1
, cb1
) gTriangle fx
, fy
, x
+ (x1!
* r
), y
+ (y1!
* r
), x
+ (x2!
* r
), y
+ (y2!
* r
), _RGB32(cr0
, cg0
, cb0
), _RGB32(cr1
, cg1
, cb1
), _RGB32(cr1
, cg1
, cb1
) drawpolySimple p
, _RGB32(cr0
, cg0
, cb0
) x1! = x2!
y1! = y2!
RGBToNum& = cr * 65536 + cg * 256 + cb
SUB NewPolyDraw
(p
AS PolyRec
) ang = 0
stp = 360 / p.nsides
r = p.radius
x = p.px
y = p.py
x1
= y
+ COS(ang
* deg
) * r
y1
= y
+ SIN(ang
* deg
) * r
x2
= y
+ COS((ang
+ 5) * deg
) * r
y2
= y
+ SIN((ang
+ 5) * deg
) * r
gTriangle x, y, x1, y1, x2, y2, c1&, c2&, c2&
ang = ang + stp
SUB drawpolySimple
(p
AS PolyRec
, c
) fc& = 0
fc&
= _RGB32(p.cr
, p.cg
, p.cb
) Zfactor! = p.pz / maxscreenz
yx = (UpBoundTrigTables% + 1) / p.nsides
angle2 = MapToTrigTables%(p.rotateangle)
FOR i
= 0 TO (UpBoundTrigTables%
+ 1) STEP yx
angle = angle2
angle2 = MapToTrigTables%(angle + yx)
x1 = p.px + Zfactor! * (cr * CosTable!(angle)) * CosTable!(MapToTrigTables%(p.horizontal))
y1 = p.py + Zfactor! * (cr * SinTable!((angle))) * SinTable!(MapToTrigTables%(p.vertical))
x2 = p.px + Zfactor! * (cr * CosTable!(((angle2)))) * CosTable!(MapToTrigTables%(p.horizontal))
y2 = p.py + Zfactor! * (cr * SinTable!(((angle2)))) * SinTable!(MapToTrigTables%(p.vertical))
LINE (x1
, y1
)-(x2
, y2
), fc&
LINE (p.px
, p.py
)-(x1
, y1
), fc&
x1 = p.px + Zfactor! * (p.radius * CosTable!((angle)))
y1 = p.py + Zfactor! * (p.radius * SinTable!((angle)))
x2 = p.px + Zfactor! * (p.radius * CosTable!(((angle2))))
y2 = p.py + Zfactor! * (p.radius * SinTable!(((angle2))))
LINE (x1
, y1
)-(x2
, y2
), fc&
LINE (p.px
, p.py
)-(x1
, y1
), fc&
a
= angle
MOD (UpBoundTrigTables%
+ 1) a = a + (UpBoundTrigTables% + 1)
MapToTrigTables% = a
'* not used
CosToSinMap = MapToTrigTables%(angle - (UpBoundTrigTables% + 1) / 4)
RandRange%
= min%
+ INT(RND * (max%
- min%
+ 1))
'=== Make a linear gradient along the vertical axis of an edge ===
SUB gTriangle
(x1%
, y1%
, x2%
, y2%
, x3%
, y3%
, c1&
, c2&
, c3&
)
minY% = y1%
maxY% = y1%
IF minY%
> y2%
THEN minY%
= y2%
IF maxY%
< y2%
THEN maxY%
= y2%
IF minY%
> y3%
THEN minY%
= y3%
IF maxY%
< y3%
THEN maxY%
= y3%
' Create a vertical gradient along each side of the triangle
maxX%(y%) = -1
gMark x1%, y1%, x2%, y2%, cr1%, cg1%, cb1%, cr2%, cg2%, cb2%
gMark x2%, y2%, x3%, y3%, cr2%, cg2%, cb2%, cr3%, cg3%, cb3%
gMark x3%, y3%, x1%, y1%, cr3%, cg3%, cb3%, cr1%, cg1%, cb1%
x% = minX%(y%)
maxX% = maxX%(y%)
cr! = minR!(y%)
cg! = minG!(y%)
cb! = minB!(y%)
D% = maxX% - x%
crs! = (maxR!(y%) - cr!) / D%
cgs! = (maxG!(y%) - cg!) / D%
cbs! = (maxB!(y%) - cb!) / D%
cr! = cr! - crs! * x%
cg! = cg! - cgs! * x%
cb! = cb! - cbs! * x%
x% = 0
x% = x% + 1
cr! = cr! + crs!
cg! = cg! + cgs!
cb! = cb! + cbs!
'=== Make a linear gradient along the vertical axis of an edge ===
SUB gMark
(x1%
, y1%
, x2%
, y2%
, cr1%
, cg1%
, cb1%
, cr2%
, cg2%
, cb2%
) D% = y2% - y1%
x! = x1%
y% = y1%
cr! = cr1%
cg! = cg1%
cb! = cb1%
maxY% = y2%
x! = x2%
y% = y2%
cr! = cr2%
cg! = cg2%
cb! = cb2%
maxY% = y1%
sx! = (x2% - x1%) / D%
crs! = (cr2% - cr1%) / D%
cgs! = (cg2% - cg1%) / D%
cbs! = (cb2% - cb1%) / D%
x! = x! - sx! * y%
cr! = cr! - crs! * y%
cg! = cg! - cgs! * y%
cb! = cb! - cbs! * y%
y% = 0
minX%(y%) = x%
minR!(y%) = cr!
minG!(y%) = cg!
minB!(y%) = cb!
maxX%(y%) = x%
maxR!(y%) = cr!
maxG!(y%) = cg!
maxB!(y%) = cb!
y% = y% + 1
x! = x! + sx!
cr! = cr! + crs!
cg! = cg! + cgs!
cb! = cb! + cbs!
SUB GetRegion
(p
AS PolyRec
, ix
, iy
, pic%
()) '* my failed attempt at capturing a screen region so only regions of screen have to be redrawn
x1
= SetToMinMax
(p.px
- p.radius
, p.radius
, _WIDTH - p.radius
) y1
= SetToMinMax
(p.py
- p.radius
, p.radius
, _HEIGHT - p.radius
) x2
= SetToMinMax
(p.px
+ p.radius
, x1
+ p.radius
, _WIDTH - p.radius
) y2
= SetToMinMax
(p.py
+ p.radius
, y1
+ p.radius
, _HEIGHT - p.radius
) GET (x
, y
)-(x
+ p.radius
, y
+ p.radius
), pic%
(ix
, iy
, 1) 'GET (x, y)-STEP(2 * p.radius, 2 * p.radius), pic%(ix,iy,1)
SUB PutRegion
(p
AS PolyRec
, ix
, iy
, pic%
()) '* my failed attempt at redrawing a screen region so only regions of screen have to be redrawn
x1
= SetToMinMax
(p.px
- p.radius
, p.radius
, _WIDTH - p.radius
) y1
= SetToMinMax
(p.py
- p.radius
, p.radius
, _HEIGHT - p.radius
) x2
= SetToMinMax
(p.px
+ p.radius
, x1
+ p.radius
, _WIDTH - p.radius
) y2
= SetToMinMax
(p.py
+ p.radius
, y1
+ p.radius
, _HEIGHT - p.radius
) PUT (x1
, y1
), pic%
(ix
, iy
, 1), PSET
SUB PrintLocate
(row
, col
, what$
, whatcolor
, gotonextline
, doinput
, ret$
)