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?:)
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/
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.
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!
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ä.
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
Aihe on jo aika vanha, joten et voi enää vastata siihen.