Koodia on vähän kommentoitu, mutta kyselkää, jos jotain outoa ilmenee:
Code: Select all
Const SCRW = 950 //Ikkunan mitat
Const SCRH = 550 //|
Const FPSLIMIT = 40 //FPS-maksimi
Const PALLOJA = 25 //Pallojen määrä
Const COR_SEINA = 1.0 //Seinän kimmokerroin
SCREEN SCRW, SCRH, 0, 1
Type PALLO
Field obj% //ruudulla näkyvä objekti
Field posX# //x-sijainti
Field posY# //y-sijainti
Field velX# //x-nopuse
Field velY# //y-nopeus
Field rad# //pallon säde
Field mass# //pallon massa
Field cor# //pallon kimmokerroin
EndType
//Luodaan pallot
For i = 1 To PALLOJA
p.PALLO = New(PALLO)
p\obj = MakeObject() //tehdään tyhjä objekti
tmpVel# = Rnd(1, 5) //Arvotaan kappaleelle sopiva nopeus
tmpAng# = Rnd(0, 360)
p\velX = tmpVel*Cos(tmpAng)
p\velY = tmpVel*Sin(tmpAng)
//Arvotaan pallon kimmokerroin ja säde, ja lasketaan sen massa
p\cor = 1 //Rnd(0.99, 0.995)
p\rad = Sqrt(Rnd(100, 1000))
p\mass = p\rad*p\rad*p\rad
//Arvotaan pallolle sijainti ikkunan sisäpuolelta
p\posX = Rnd(-SCRW/2 + p\rad, SCRW/2 - p\rad)
p\posY = Rnd(-SCRH/2 + p\rad, SCRH/2 - p\rad)
PositionObject p\obj, p\posX, p\posY
//Tässä teksturoidaan pallo-objekti
tmpTex = MakeImage(Int(2*p\rad), Int(2*p\rad))
DrawToImage tmpTex
Color 255, 255, 255
Circle 0, 0, 2*p\rad, 0
//Numero
Color Rand(100, 255), Rand(100, 255), Rand(100, 255)
Text Int(p\rad - 0.5 - 0.5*TextWidth(Str(i))), -Int(p\rad - 0.5 - 0.5*TextHeight(Str(i))), Str(i)
DrawToScreen
//Teksturoidaan ja poistetaan turha tekstuuri
PaintObject p\obj, -tmpTex
DeleteImage tmpTex
Next i
Repeat
kEnergia# = 0 //Liike-energia
//Päivitetään pallot
For p.PALLO = Each PALLO
p\posX = p\posX + p\velX
p\posY = p\posY + p\velY
PositionObject p\obj, p\posX, p\posY
//Nämä If-lausekkeet tarkistavat, että pallo pysyy ikkunan sisäpuolella
//Mikäli pallo osuu seinään, sen vastaava nopeuden komponentti käännetään päinvastaiseen suuntaan
If p\posX - p\rad <= -SCRW/2 And p\velX < 0 Then
p\velX = -p\velX*p\cor*COR_SEINA
p\posX = -SCRW/2 + p\rad
EndIf
If p\posX + p\rad >= SCRW/2 And p\velX > 0 Then
p\velX = -p\velX*p\cor*COR_SEINA
p\posX = SCRW/2 - p\rad
EndIf
If p\posY - p\rad <= -SCRH/2 And p\velY < 0 Then
p\velY = -p\velY*p\cor*COR_SEINA
p\posY = -SCRH/2 + p\rad
EndIf
If p\posY + p\rad >= SCRH/2 And p\velY > 0 Then
p\velY = -p\velY*p\cor*COR_SEINA
p\posY = SCRH/2 - p\rad
EndIf
//Summataan kokonaisenergia
kEnergia = kEnergia + 0.5*p\mass*(p\velX*p\velX + p\velY*p\velY)
Next p
testeja% = 0
torm1% = 0
torm2% = 0
//Törmäystarkistus
For p1.PALLO = Each PALLO
For p2.PALLO = Each PALLO
If p1 <> p2 Then
testeja = testeja + 1
x12# = p2\posX - p1\posX //Pallojen keskipisteiden yhdysjanavektori
y12# = p2\posY - p1\posY //|
rsum# = p1\rad + p2\rad //Pallojen säteiden summa
cdotc# = x12*x12 + y12*y12 //Pallojen etäisyyden neliö (kierretään raskas neliöjuuri)
//Tarkistetaan törmäävätkö pallot
If cdotc <= rsum*rsum Then
torm1 = torm1 + 1
cLen# = Sqrt(cdotc) //yhdysjanan pituus aka pallojen etäisyys
v1# = (p1\velX*x12 + p1\velY*y12)/cLen //Pallojen nopeudet projisoituna yhdysjanavektorille
v2# = (p2\velX*x12 + p2\velY*y12)/cLen
vdiff# = v1 - v2 //Pallojen suhteellisen nopeuden yhdysjanan suuntainen komponentti
//Tarkistetaan, liikkuvatko pallot toisiaan kohti (suhteellinen nopeus positiivinen)
If vdiff > 0 Then
torm2 = torm2 + 1
cr# = p1\cor*p2\cor //Pallojen yhdistetty kimmokerroin
vn1# = (p1\mass*v1 + p2\mass*v2 - p2\mass*cr*vdiff)/(p1\mass + p2\mass) //Uusi nopeus laskettuna liikemäärän säilymislain ja restituutiokertoimen avulla
vn2# = (p1\mass*v1 + p2\mass*v2 + p1\mass*cr*vdiff)/(p1\mass + p2\mass)
unitX# = x12/cLen //Yhdysjanan suuntainen yksikkövektori
unitY# = y12/cLen
v1diff# = vn1 - v1 //Noepuksien erotus ennen ja jälkeen törmäyksen (skalaari)
v2diff# = vn2 - v2
v1dx# = (v1diff)*unitX //Pallojen nopeuksien muutokset (vektori)
v1dy# = (v1diff)*unitY
v2dx# = (v2diff)*unitX
v2dy# = (v2diff)*unitY
p1\velX = p1\velX + v1dx //Pivitetään pallojen nopeudet
p1\velY = p1\velY + v1dy
p2\velX = p2\velX + v2dx
p2\velY = p2\velY + v2dy
EndIf
EndIf
EndIf
Next p2
Next p1
//Piirretään objektit, että teksti näkyy
DrawGame
//Tulostetaan vähän infoa
Color 150, 0, 0
Text 5, 5, "Systeemin kokonaisliike-energia: " + kEnergia
Text 5, 20, "Törmäystarkistuksia: " + testeja
Text 5, 35, "Päällekkäisiä palloja: " + torm1
Text 5, 50, "Törmääviä palloja: " + torm2
DrawScreen
SetWindow Str(FPS())
ftc = LimitFPS(ftc)
Forever
//Rajoittaa Pelin pyörimisnopeutta ja lepuuttaa prosessoria yli jäävän ajan
Function LimitFPS(FrameTime%)
If Timer()-FrameTime<1000/FPSLIMIT Then Wait 1000/FPSLIMIT-(Timer()-FrameTime)
Return Timer()
EndFunction
EDIT:
Jos jotakuta kiinnostaa itse fysiikka koodin ja vektorimatematiikan takana, kannattaa tsekata tämä Wikipedia-artikkeli.