' 3D Bouncing Balls Using _MAPTRIANGLE by QWERKEY (Richard Notley) 21/04/18
' Cyperium method for sphere image
CONST True
= -1`
, False
= 0`
CONST NoBalls%%
= 10, Uscreen%
= 1000, Vscreen%
= 800, NoPhis%%
= 16, NoAlphas%%
= 6, XBright!
= 0.5 CONST Pi!
= 4 * ATN(1), Rad1%%
= 25, PerspDist%
= 550, DeltaSepn!
= 0.25 'small offset to stop balls sticking CONST Alpha!
= Pi!
/ (2 * NoAlphas%%
), Phi!
= 2 * Pi!
/ NoPhis%%
DIM BallStats!
(NoBalls%%
- 1, 9), ViewOrder%%
(NoBalls%%
- 1), Cyperium&
(NoBalls%%
- 1) DIM MapConv%
(NoPhis%%
, NoAlphas%%
, 1, 2)
'Conversion from 2D
FOR M%%
= 0 TO NoAlphas%%
MapConv%
(N%%
, M%%
, 0, 0) = 128 + CINT(127 * SIN((Pi!
/ 2) - M%%
* Alpha!
) * COS(N%%
* Phi!
)) MapConv%
(N%%
, M%%
, 0, 1) = 128 + CINT(127 * SIN((Pi!
/ 2) - M%%
* Alpha!
) * SIN(N%%
* Phi!
)) MapConv%
(N%%
, M%%
, 1, 0) = CINT(Rad1%%
* SIN((Pi!
/ 2) - M%%
* Alpha!
) * COS(N%%
* Phi!
)) MapConv%
(N%%
, M%%
, 1, 1) = CINT(Rad1%%
* SIN((Pi!
/ 2) - M%%
* Alpha!
) * SIN(N%%
* Phi!
)) MapConv%
(N%%
, M%%
, 1, 2) = CINT(Rad1%%
* COS((Pi!
/ 2) - M%%
* Alpha!
))
'Screen Background
TempImage&
= _NEWIMAGE(Uscreen%
, Vscreen%
, 32)FOR UCol%
= 0 TO Uscreen%
- 1 FOR VCol%
= 0 TO Vscreen%
- 1 PSET (UCol%
, VCol%
), _RGB(100, INT(180 * UCol%
/ Uscreen%
), INT(180 * VCol%
/ Vscreen%
)) Background& = MakeHardware&(TempImage&)
'Set array for depth order
JumpStart%% = 1
WHILE JumpStart%%
<= NoBalls%%: JumpStart%%
= JumpStart%%
* 2:
WEND FOR N%%
= 0 TO NoBalls%%
- 1 ViewOrder%%(N%%) = N%%
' Define characteristics of balls
FOR N%%
= 0 TO NoBalls%%
- 1 'Ball mass
BallStats!(N%%, 0) = 0.1 + (0.8 * N%% / (NoBalls%% - 1))
IF BallStats!
(N%%
, 0) = 0 THEN BallStats!
(N%%
, 0) = 0.000001 'Ball colours (temporarily use (N%%,1,2,3)
READ BallStats!
(N%%
, P%%
) COLOR _RGB(BallStats!
(N%%
, 1), BallStats!
(N%%
, 2), BallStats!
(N%%
, 3)), _RGBA(0, 0, 0, 0) 'Image data goes from 1 to 255 (not 0 to 255)
DeltaX% = X% - 127
DeltaY% = Y% - 127
DeltaZ% = Z% - 127
Dist!
= SQR((DeltaX%
* DeltaX%
) + (DeltaY%
* DeltaY%
) + (DeltaZ%
* DeltaZ%
)) IF Dist!
> 125 AND Dist!
< 127 THEN PSET (X%
, Y%
), _RGB(CINT(Z%
* BallStats!
(N%%
, 1) * (1 - (XBright!
* X%
/ 255)) / 255), CINT(Z%
* BallStats!
(N%%
, 2) * (1 - (XBright!
* X%
/ 255)) / 255), CINT(Z%
* BallStats!
(N%%
, 3) * (1 - (XBright!
* X%
/ 255)) / 255)) Cyperium&(N%%) = MakeHardware&(TempImage&)
'Ball positions/velocities
BallStats!
(N%%
, P%%
) = (0.5 - RND) * 1000 Velocity! = Velocity! - 0.5
Velocity! = Velocity! + 0.5
BallStats!(N%%, P%%) = Velocity! * 3
'Create screen
'Initialise axes and rotations
ZRot!
= (RND - 0.5) * 0.0011: YRot!
= (RND - 0.5) * 0.0011: XRot!
= (RND - 0.5) * 0.0011Zaxis! = 0: Yaxis! = 0: Xaxis! = 0
Stereo` = True
_LIMIT 120 'Game Frames/Second Rate
'Calculate moves
FOR N%%
= 0 TO NoBalls%%
- 1 BallStats!(N%%, 3 + P%%) = BallStats!(N%%, 3 + P%%) + BallStats!(N%%, 6 + P%%)
'Check for collsions
FOR N%%
= 0 TO NoBalls%%
- 2 FOR M%%
= N%%
+ 1 TO NoBalls%%
- 1 SepnSqd! = (BallStats!(N%%, 4) - BallStats!(M%%, 4)) * (BallStats!(N%%, 4) - BallStats!(M%%, 4)) + (BallStats!(N%%, 5) - BallStats!(M%%, 5)) * (BallStats!(N%%, 5) - BallStats!(M%%, 5)) + (BallStats!(N%%, 6) - BallStats!(M%%, 6)) * (BallStats!(N%%, 6) - BallStats!(M%%, 6))
IF SepnSqd!
<= 4 * Rad1%%
* Rad1%%
THEN ' Set new velocities
Multiplier! = 0: NDist! = 0: MDist! = 0
Multiplier! = Multiplier! + (BallStats!(N%%, 6 + P%%) - BallStats!(M%%, 6 + P%%)) * (BallStats!(N%%, 3 + P%%) - BallStats!(M%%, 3 + P%%))
NDist! = NDist! + BallStats!(N%%, 3 + P%%) * BallStats!(N%%, 3 + P%%)
MDist! = MDist! + BallStats!(M%%, 3 + P%%) * BallStats!(M%%, 3 + P%%)
Multiplier! = 2 * Multiplier! / (SepnSqd! * (BallStats!(N%%, 0) + BallStats!(M%%, 0)))
SepnVect! = BallStats!(N%%, 3 + P%%) - BallStats!(M%%, 3 + P%%)
BallStats!(N%%, 6 + P%%) = BallStats!(N%%, 6 + P%%) - (Multiplier! * BallStats!(M%%, 0) * SepnVect!)
BallStats!(M%%, 6 + P%%) = BallStats!(M%%, 6 + P%%) + (Multiplier! * BallStats!(N%%, 0) * SepnVect!)
BallStats!
(M%%
, 3 + P%%
) = BallStats!
(M%%
, 3 + P%%
) - (DeltaSepn!
* (BallStats!
(N%%
, 3 + P%%
) - BallStats!
(M%%
, 3 + P%%
)) / SQR(SepnSqd!
)) BallStats!
(N%%
, 3 + P%%
) = BallStats!
(N%%
, 3 + P%%
) + (DeltaSepn!
* (BallStats!
(N%%
, 3 + P%%
) - BallStats!
(M%%
, 3 + P%%
)) / SQR(SepnSqd!
))
'Look for reflection off sides
FOR N%%
= 0 TO NoBalls%%
- 1 IF BallStats!
(N%%
, 3 + P%%
) > 500 - Rad1%%
THEN BallStats!(N%%, 6 + P%%) = -BallStats!(N%%, 6 + P%%)
IF BallStats!
(N%%
, 3 + P%%
) + BallStats!
(N%%
, 6 + P%%
) > 500 - Rad1%%
THEN BallStats!(N%%, 3 + P%%) = BallStats!(N%%, 3 + P%%) - DeltaSepn!
ELSEIF BallStats!
(N%%
, 3 + P%%
) < -500 + Rad1%%
THEN BallStats!(N%%, 6 + P%%) = -BallStats!(N%%, 6 + P%%)
IF BallStats!
(N%%
, 3 + P%%
) + BallStats!
(N%%
, 6 + P%%
) < -500 + Rad1%%
THEN BallStats!(N%%, 3 + P%%) = BallStats!(N%%, 3 + P%%) + DeltaSepn!
'Adjust for angle of rotation
FOR N%%
= 0 TO NoBalls%%
- 1 R2!
= SQR(BallStats!
(N%%
, 4) * BallStats!
(N%%
, 4) + BallStats!
(N%%
, 5) * BallStats!
(N%%
, 5) + BallStats!
(N%%
, 6) * BallStats!
(N%%
, 6)) Theta2!
= _ACOS(BallStats!
(N%%
, 6) / R2!
) Phi2!
= _ATAN2(BallStats!
(N%%
, 5), BallStats!
(N%%
, 4)) + Zaxis!
BallStats!
(N%%
, 1) = R2!
* SIN(Theta2!
) * COS(Phi2!
) BallStats!
(N%%
, 2) = R2!
* SIN(Theta2!
) * SIN(Phi2!
) BallStats!
(N%%
, 3) = R2!
* COS(Theta2!
) R2!
= SQR(BallStats!
(N%%
, 1) * BallStats!
(N%%
, 1) + BallStats!
(N%%
, 2) * BallStats!
(N%%
, 2) + BallStats!
(N%%
, 3) * BallStats!
(N%%
, 3)) Theta2!
= _ACOS(BallStats!
(N%%
, 1) / R2!
) Phi2!
= _ATAN2(BallStats!
(N%%
, 3), BallStats!
(N%%
, 2)) + Xaxis!
BallStats!
(N%%
, 2) = R2!
* SIN(Theta2!
) * COS(Phi2!
) BallStats!
(N%%
, 3) = R2!
* SIN(Theta2!
) * SIN(Phi2!
) BallStats!
(N%%
, 1) = R2!
* COS(Theta2!
) R2!
= SQR(BallStats!
(N%%
, 1) * BallStats!
(N%%
, 1) + BallStats!
(N%%
, 2) * BallStats!
(N%%
, 2) + BallStats!
(N%%
, 3) * BallStats!
(N%%
, 3)) Theta2!
= _ACOS(BallStats!
(N%%
, 2) / R2!
) Phi2!
= _ATAN2(BallStats!
(N%%
, 1), BallStats!
(N%%
, 3)) + Yaxis!
BallStats!
(N%%
, 3) = CINT(R2!
* SIN(Theta2!
) * COS(Phi2!
)) BallStats!
(N%%
, 1) = CINT(R2!
* SIN(Theta2!
) * SIN(Phi2!
)) BallStats!
(N%%
, 2) = CINT(R2!
* COS(Theta2!
))
'Change display order: furthest first
Jump%% = JumpStart%%
Jump%% = (Jump%% - 1) \ 2
DoneHere` = False
DoneHere` = True
FOR Upper%%
= 1 TO NoBalls%%
- Jump%%
Lower%% = Upper%% + Jump%%
'BallStats! z-dim
IF BallStats!
(ViewOrder%%
(Upper%%
- 1), 3) > BallStats!
(ViewOrder%%
(Lower%%
- 1), 3) THEN SWAP ViewOrder%%
(Upper%%
- 1), ViewOrder%%
(Lower%%
- 1) DoneHere` = False
'Display balls
P%% = ViewOrder%%(N1%%)
'_PUTIMAGE (BallStats!(P%%, 1) + 500, BallStats!(P%%, 2) + 400), Cyperium&(P%%)
'Ball views done with _MAPTRIANGLE 3D
FOR N%%
= 0 TO NoPhis%%
- 1 FOR M%%
= 0 TO NoAlphas%%
- 2 Ax% = MapConv%(N%%, M%%, 1, 0) + BallStats!(P%%, 1)
Ay% = MapConv%(N%%, M%%, 1, 1) + BallStats!(P%%, 2)
Az% = MapConv%(N%%, M%%, 1, 2) + BallStats!(P%%, 3) - PerspDist%
Bx% = MapConv%(N%%, M%% + 1, 1, 0) + BallStats!(P%%, 1)
By% = MapConv%(N%%, M%% + 1, 1, 1) + BallStats!(P%%, 2)
Bz% = MapConv%(N%%, M%% + 1, 1, 2) + BallStats!(P%%, 3) - PerspDist%
Cx% = MapConv%(N%% + 1, M%% + 1, 1, 0) + BallStats!(P%%, 1)
Cy% = MapConv%(N%% + 1, M%% + 1, 1, 1) + BallStats!(P%%, 2)
Cz% = MapConv%(N%% + 1, M%% + 1, 1, 2) + BallStats!(P%%, 3) - PerspDist%
_MAPTRIANGLE (MapConv%
(N%%
, M%%
, 0, 0), MapConv%
(N%%
, M%%
, 0, 1))-(MapConv%
(N%%
, M%%
+ 1, 0, 0), MapConv%
(N%%
, M%%
+ 1, 0, 1))-(MapConv%
(N%%
+ 1, M%%
+ 1, 0, 0), MapConv%
(N%%
+ 1, M%%
+ 1, 0, 1)), Cyperium&
(P%%
) TO(Ax%
, Ay%
, Az%
)-(Bx%
, By%
, Bz%
)-(Cx%
, Cy%
, Cz%
) _MAPTRIANGLE (MapConv%
(N%%
+ 1, M%%
+ 1, 0, 0), MapConv%
(N%%
+ 1, M%%
+ 1, 0, 1))-(MapConv%
(N%%
+ 1, M%%
, 0, 0), MapConv%
(N%%
+ 1, M%%
, 0, 1))-(MapConv%
(N%%
, M%%
, 0, 0), MapConv%
(N%%
, M%%
, 0, 1)), Cyperium&
(P%%
) TO(Cx%
, Cy%
, Cz%
)-(MapConv%
(N%%
+ 1, M%%
, 1, 0) + BallStats!
(P%%
, 1), MapConv%
(N%%
+ 1, M%%
, 1, 1) + BallStats!
(P%%
, 2), MapConv%
(N%%
+ 1, M%%
, 1, 2) + BallStats!
(P%%
, 3) - PerspDist%
)-(Ax%
, Ay%
, Az%
) '_MAPTRIANGLE (MapConv%(N%%, M%%, 0, 0), MapConv%(N%%, M%%, 0, 1))-(MapConv%(N%%, M%% + 1, 0, 0), MapConv%(N%%, M%% + 1, 0, 1))-(MapConv%(N%% + 1, M%% + 1, 0, 0), MapConv%(N%% + 1, M%% + 1, 0, 1)), Cyperium&(P%%) TO(MapConv%(N%%, M%%, 1, 0) + BallStats!(P%%, 1), MapConv%(N%%, M%%, 1, 1) + BallStats!(P%%, 2), MapConv%(N%%, M%%, 1, 2) + BallStats!(P%%, 3) - PerspDist%)-(MapConv%(N%%, M%% + 1, 1, 0) + BallStats!(P%%, 1), MapConv%(N%%, M%% + 1, 1, 1) + BallStats!(P%%, 2), MapConv%(N%%, M%% + 1, 1, 2) + BallStats!(P%%, 3) - PerspDist%)-(MapConv%(N%% + 1, M%% + 1, 1, 0) + BallStats!(P%%, 1), MapConv%(N%% + 1, M%% + 1, 1, 1) + BallStats!(P%%, 2), MapConv%(N%% + 1, M%% + 1, 1, 2) + BallStats!(P%%, 3) - PerspDist%)
'_MAPTRIANGLE (MapConv%(N%% + 1, M%% + 1, 0, 0), MapConv%(N%% + 1, M%% + 1, 0, 1))-(MapConv%(N%% + 1, M%%, 0, 0), MapConv%(N%% + 1, M%%, 0, 1))-(MapConv%(N%%, M%%, 0, 0), MapConv%(N%%, M%%, 0, 1)), Cyperium&(P%%) TO(MapConv%(N%% + 1, M%% + 1, 1, 0) + BallStats!(P%%, 1), MapConv%(N%% + 1, M%% + 1, 1, 1) + BallStats!(P%%, 2), MapConv%(N%% + 1, M%% + 1, 1, 2) + BallStats!(P%%, 3) - PerspDist%)-(MapConv%(N%% + 1, M%%, 1, 0) + BallStats!(P%%, 1), MapConv%(N%% + 1, M%%, 1, 1) + BallStats!(P%%, 2), MapConv%(N%% + 1, M%%, 1, 2) + BallStats!(P%%, 3) - PerspDist%)-(MapConv%(N%%, M%%, 1, 0) + BallStats!(P%%, 1), MapConv%(N%%, M%%, 1, 1) + BallStats!(P%%, 2), MapConv%(N%%, M%%, 1, 2) + BallStats!(P%%, 3) - PerspDist%)
_MAPTRIANGLE (MapConv%
(N%%
, NoAlphas%%
- 1, 0, 0), MapConv%
(N%%
, NoAlphas%%
- 1, 0, 1))-(128, 128)-(MapConv%
(N%%
+ 1, NoAlphas%%
- 1, 0, 0), MapConv%
(N%%
+ 1, NoAlphas%%
- 1, 0, 1)), Cyperium&
(P%%
) TO(Bx%
, By%
, Bz%
)-(BallStats!
(P%%
, 1), BallStats!
(P%%
, 2), BallStats!
(P%%
, 3) + Rad1%%
- PerspDist%
)-(Cx%
, Cy%
, Cz%
) '_MAPTRIANGLE (MapConv%(N%%, NoAlphas%% - 1, 0, 0), MapConv%(N%%, NoAlphas%% - 1, 0, 1))-(128, 128)-(MapConv%(N%% + 1, NoAlphas%% - 1, 0, 0), MapConv%(N%% + 1, NoAlphas%% - 1, 0, 1)), Cyperium&(P%%) TO(MapConv%(N%%, NoAlphas%% - 1, 1, 0) + BallStats!(P%%, 1), MapConv%(N%%, NoAlphas%% - 1, 1, 1) + BallStats!(P%%, 2), MapConv%(N%%, NoAlphas%% - 1, 1, 2) + BallStats!(P%%, 3) - PerspDist%)-(BallStats!(P%%, 1), BallStats!(P%%, 2), BallStats!(P%%, 3) + Rad1%% - PerspDist%)-(MapConv%(N%% + 1, NoAlphas%% - 1, 1, 0) + BallStats!(P%%, 1), MapConv%(N%% + 1, NoAlphas%% - 1, 1, 1) + BallStats!(P%%, 2), MapConv%(N%% + 1, NoAlphas%% - 1, 1, 2) + BallStats!(P%%, 3) - PerspDist%)
'rotate around z- axis
Zaxis! = Zaxis! + ZRot!
Zaxis! = Zaxis! - 2 * Pi!
Zaxis! = Zaxis! + 2 * Pi!
'rotate around y- axis
Yaxis! = Yaxis! + YRot!
Yaxis! = Yaxis! - 2 * Pi!
Yaxis! = Yaxis! + 2 * Pi!
'rotate around x- axis
Xaxis! = Xaxis! + XRot!
Xaxis! = Xaxis! - 2 * Pi!
Xaxis! = Xaxis! + 2 * Pi!
ZRot!
= (RND - 0.5) * 0.0011 YRot!
= (RND - 0.5) * 0.0011 XRot!
= (RND - 0.5) * 0.0011