Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: muu kieli, Pascal: Pallotörmäilystä palikoihin

DumTom [29.11.2012 03:53:19]

#

Sain kyllä loistavasti edellisessä keskustelussa mainitun koodin toimimaan.
Nyt ongelmana on sellainen että pelissä on palikoita jotka eivät tavallisella pallolla lähde pois. Pallo saattaa jäädä kimpoilemaan ikuisesti kun se osuu ikipalikan kulmaan ja toisessa kohtaa toisen ikipalikan kulmaan.
Olen miettinyt ongelmaa ja minulla on kaksi vaihtoehtoa eli se että kulmaa säädettäisiin randomisti hieman joka kulmaosumalla tai sitten space napista tulisi tavallaan flipperin tönäisyä vastaava nappi.

Olisiko kellään kolmatta ideaa?:)

User137 [29.11.2012 05:42:43]

#

Ei sulla muuta ongelmaa ole kun ohjelmointivirhe... Koodia voipi näyttää.

Joskus kun tein näitä pallo-kimpoilu tyylisiä pelejä, niin käytin periaatetta että lasken mikä on palloa lähin seinäpiste. Joko vektorigrafiikasta tai ihan pikselikartasta. Sitten vaan lasket Reflect()-funktiolla mihin suuntaan pallon tulee siitä jatkaa. Esimerkki löytyy tähänkin mun pelimoottorista:
http://code.google.com/p/nxpascal/source/browse/trunk/src/nxMath.pas#282
Oli sitten tasainen seinä tai kulma, niin pallo kimpoaa aina oikeaan suuntaan. Kun koko törmäystapahtuma on yksinkertaistettu tuolle tasolle niin koodimäärällä päästään vähällä.

Eli siellä on 2 funktiota:

1. function Reflect(const rayStart, rayDir, wallPoint: TVector2f): TVector2f;
2. function Reflect(const rayDir, wallNormal: TVector2f): TVector2f;

Ensimmäinen ottaa parametreina 2d-vektoreina (x, y), pallon sijainnin, pallon liikesuunnan ja tuon lähimmän seinäpisteen. Käyttää sisäisesti toista funktiota.

Toinen funktio taas ottaisi pallon liikesuunnan ja seinän suunnan (tangentti). Tätä et tarvitse tässä ongelmassa suoraan käyttää, mutta joudut kuitenkin ohjelmointikielellesi kääntämään, jotta tuota ekaa voi käyttää.

Jos mietit vaikka ongelmaa että pallo liikkuu vasemmalta oikeaan yläviistoon juuri neliön yli, mutta kuitenkin hipaisten kulmaa. Mihin suuntaan pallo kääntyy? Sen tulee kääntyä vain hitusen ylöspäin, mutta tarkalleen sen kertoo tuo Reflect()-funktio.

DumTom [02.12.2012 11:19:59]

#

Kielenä BlitzBasic.
Tuossapa koodi:

Function BrickHits(b%)
vastaus=False
For y%=0 To 14
 For x%=0 To 10
 If BrickOn(y,x)=1 Then
 vastaus=Osuma(BrickLx(y,x),BrickLy(y,x),BrickLx(y,x)+45,BrickLy(y,x)+23,BallX(b),BallY(b), 5)
  If vastaus=True Then
  ty%=BrickType(y,x)
  If (BallSize(b)<10) Then
     If ty=12 OsumaRajahdys(x,y)
     If ty<>12 And ty<>7 And ty<>8 And ty<> 10 BrickMurtuu(y,x)=1
     If ty=7 Then
     BrickType(y,x)=8
     BrickFlash(y,x)=5
     End If
     If ty=8 Then
     BrickType(y,x)=9
     BrickFlash(y,x)=5
     End If
     If (HEAVYBALL=False) Then
     If (ty=10) Then BrickFlash(y,x)=10
     If (ty<>7 And ty<>8 And ty<>10) Then
     BrickOn(y,x)=0
     BrickType(y,x)=-1
     ArvoRulla(x,y)
     End If
     End If
     If (HEAVYBALL=True) Then
     BrickOn(y,x)=0
     BrickType(y,x)=-1
     ArvoRulla(x,y)
     End If
  End If

If (BallSize(b)=10) Then
If ty=12 OsumaRajahdys(x,y)
If ty>-1 And ty<>12 BrickMurtuu(y,x)=1
BrickOn(y,x)=0
BrickType(y,x)=-1
ArvoRulla(x,y)
End If

  If (HEAVYBALL=False) Then
  BallX(b)=BallEX(b)
  BallY(b)=BallEY(b)
  If (yhit=1) Then
  BallDir(b)=180-BallDir(b)
  If (BallDir(b)<0) BallDir(b)=BallDir(b)+360
  End If
  If (xhit=1) Then
  BallDir(b)=360-BallDir(b)
  End If

  End If
  End If
 End If
 Next
Next
End Function



Function Lahempana(dx, dy, r)
xhit=1
yhit=1
    Return dx * dx + dy * dy < r * r
End Function
Function Osuma(x0, y0, x1, y1, xk, yk, r)
xhit=0
yhit=0
    ; Sivujen suuntaiset tilanteet:
    If x0 <= xk And xk <= x1 Then
    xhit=1
    Return y0 - r < yk And yk < y1 + r
    End If
    If y0 <= yk And yk <= y1 Then
    yhit=1
    Return x0 - r < xk And xk < x1 + r
    End If
    ; Kulmittaiset tilanteet:
    If xk < x0 And yk < y0 Then Return Lahempana(x0 - xk, y0 - yk, r)
    If xk > x1 And yk < y0 Then Return Lahempana(x1 - xk, y0 - yk, r)
    If xk > x1 And yk > y1 Then Return Lahempana(x1 - xk, y1 - yk, r)
    If xk < x0 And yk > y1 Then Return Lahempana(x0 - xk, y1 - yk, r)
End Function

Mod. lisäsi kooditagit!

Metabolix [02.12.2012 12:49:51]

#

Pallo ehkä jää palikan sisään jumiin, jos tarkistat törmäyksen liian myöhään. Tämä ongelma ratkeaa niin, että jos pallo törmäisi, et liikuta sitä (tai siirrät sen takaisin).

Törmäyssysteemisi on muutenkin huonosti toteutettu: esimerkiksi jos palikat ovat rivissä ja pallo törmää täsmälleen kahden palikan rajalle, tarkistuksesi mukaan se törmää silloin molempien palikoiden kulmaan (totta sinänsä) ja kimpoaa samaan aikaan kaksi kertaa palikan kulmasta eli lopulta jatkaakin eteenpäin (väärin). Lisäksi on tilanteita, joissa kulmasta takaisin kimpoaminen on täysin fysiikan lakien vastaista, esim. silloin, kun pallo kulkee kulmittain ja on melkein menossa palikan ohi mutta vähän hipaiseekin nurkkaa.

Paras ratkaisu on tehdä tarkistukset niin, että tiedät, millaiseen kokonaisuuteen pallo oikeasti törmää ja miten sen siis pitää järkevästi kimmota. Nopea korjaus voi kuitenkin olla, että siirrät kimpoamiskoodin (ja tietenkin myös hitx- ja hity-muuttujien nollauksen) silmukoiden ulkopuolelle, jotta kaikkien tarkistusten jälkeen tehdään vain yksi kimpoaminen.

Lopuksi: Voisitko opetella käyttämään kooditageja viesteissäsi? Koodistasi puolet (palikoiden muuttuminen ja tuhoutuminen) on myös täysin epäolennaista ongelman kannalta, ja toisaalta siitä puuttuu pallon liikuttaminen, joka on hyvin tärkeä.

DumTom [03.12.2012 03:07:51]

#

Tässä nämä pallon liikutukset.

Function MoveBalls()
For t=0 To 50
If BallOn(t)=1 And BallStop(t)=0 Then
	Select BallCatch(t)
	Case 0
	BallMoveCalls(t)
	Case 1
	BallX(t)=paddle.MAILA\x+BallErox(t)
	Default
	End Select
End If
Next

End Function

Function BallMoveCalls(b%)
k%=SPEED/0.5
For t=0 To k


BallEX(b)=BallX(b)
BallEY(b)=BallY(b)


OSUMA=False

suu%=BallDir(b);
lx#=MCOS(suu)
ly#=MSIN(suu)
If (PAUSED=False) Then
BallX(b)=BallX(b)+lx
BallY(b)=BallY(b)+ly
End If
;ALAREUNA
If (BallY(b)>599) Then
BALLS=BALLS-1
If (BALLS=0) Then
PoistaLiikkuvat()
AlustaPalloJaMaila()

LIVES=LIVES-1
If LIVES<0 Then LIVES=0
End If
Return
End If



;YLÄREUNA
If BallY(b)<32+BallSize(b) Then
suu=360-suu;
If suu>359 Then suu=suu-360
If suu<0 Then suu=suu+360
BallDir(b)=suu
BallY(b)=BallEY(b)
BallX(b)=BallEX(b)
BallEiMailassa(b)=0

upflash=2
End If
;OIKEA REUNA
If BallX(b)>767-BallSize(b) Then
suu=180-suu;
If suu>359 Then suu=suu-360
If suu<0 Then suu=suu+360
BallDir(b)=suu
BallY(b)=BallEY(b)
BallX(b)=BallEX(b)
BallEiMailassa(b)=0

rightflash=2
End If
;VASEN REUNA
If BallX(b)<224+BallSize(b) Then
suu=180-suu;
If suu>359 Then suu=suu-360
If suu<0 Then suu=suu+360
BallDir(b)=suu
BallY(b)=BallEY(b)
BallX(b)=BallEX(b)
BallEiMailassa(b)=0
leftflash=2
End If
OSUMA=False
BrickHits(b)




;MAILA
BallEiMailassa(b)=0
MailaHits(b,suu)

Next

End Function

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta