Olen tässä suunnitellut map editoria, mutta tulipa yhtäkkiä mieleen, että miten saan ne pelissä auki?
Eli olen tehnyt omallaista editoria jossa tietty layeri on seinä niin miten se pitäisi tallentaa ja miten sen voisi avata pelissäni? Onko esim
track_1.dat tekstitiedosto hyvä, johon sitten tallennetaan mitä ja miten?
Suunnitelet sopivan formaatin kartallesi, tallennat tässä formaatissa tekstitiedostoon kartan ja lataat pelissäsi, tai vaihtoehtoisesti tallennat binaarina ja luet pelissäsi binaarina.
Taasko on pakko yrittää perä edellä puuhun? Tee ensin pelisi niin, että se osaa ladata edes jotain. Ensimmäisen kartan voit luoda käsin. Tarkista, että lataus toimii kunnolla, ja tee vasta sitten karttaeditori, joka osaa tallentaa samassa muodossa.
No mitenkäs mahtaa sitten onnistua väriintörmäys?
ja toimiiko väriintörmäys esim jos piirto tehdään tässä järjestyksessä:
Tormays_kartta (Eli alueet joihin ei pääse seinät yms värjätty)
Rata (Rata itse)
eli siis silloinhan Tormays_kartta jäsii piiloon, mutta toimiiko se silti taustalla? Ja miten se tarkistus oikein tehdään, että onko x,y akselit tietyssä värissä.
huh huh taas mitä suunnittelua.
Hieman kannattaa opetella etukäteen, ennen kuin edes rupeat koko karttaeditoria tekemään.
Eli tee ihan pieniä testejä aluks, jossa testailet eri tekniikoita. Eli teet vaan pienen pieniä ohjelmia, jotka vaikka tulostavat ruudulle, kun kokeilet "törmäyskarttoja" ja tiedostoon tallennusta. Kun perusasiat ovat kunnossa, rupeat vasta vääntämään mitään oikeaa juttua.
Sikäli mikäli olen yhtään kartalla (heh! kartalla! tajusitko) niin koko törmäyskarttaa ei ole edes pakko piirtää mihinkään, vaan voit säilyttää sitä ihan "piilossa" muistissa. Kartan tekniikkakin riippuu hyvinkin paljon siitä, millaista peliä olet tekemässä, elikkäs yksinkertaisimpia karttaformaatteja on "ruutupohjaiset" (tilebased maps) kartat, joita voisi verrata ruutupaperiin. Jokaiseen ruutupaperin ruutuun voi piirtää yhdenlaisen määreen, esim. seinä, lattia, kivi, nurmi, vettä yms.
Esimerkin näet tässä:
http://www.youtube.com/watch?v=QvOoULhh5o0#t=2m0s
Vaikka ruutupohjainen muoto onkin yksinkertainen toteuttaa, sillä voi toteuttaa upeitakin karttoja kuten Bitmap Brotherssin luomassa God -pelissä (luomassa! jumala luo! hehehe)
http://www.stickhead.pwp.blueyonder.co.uk/top50/
Ruutupohjaisuus ei tietenkään tarkoita, että ruutujen pitää olla juuri neliöitä, vaan "ruutu" voi olla myös vaikkapa hexagonin muotoinen tai vaikkapa 3d-kuutio.
Tietenkin, kun osaamisesi edistyy, voit luoda karttoja, joissa on useita ruutupohjaisia karttoja päällekkäin, tai karttoja, jotka tukevat eri kokoisia ruutuja tai jopa asioita, joita ruutupohjaisuus ei koske.
Juu tuota olen käyttänyt tilemappi systeemiä aikoinaan RPG MAkerin sekä CoolBasicin kanssa.
Mutta jo en käytä mitään tilemap juttua vaan piirrän vaikka paintilla suoraan kaksi kuvaa joista toisee on värjätty seinä kohdat ja toiseen rata, niin miten voin tarkistaa koska auto on törmäys alueella? Siis esim värin avulla.
Lue se väri auton kohdalta (sopiva funktio on jo joskus annettu) ja tarkista, mitä tuli. Jos luet ratakuvasta, tarkista, että ei tullut seinäväriä, ja jos luet seinäkuvasta, tarkista, että tuli rataväriä.
Helpompi ja tehokkaampi ratkaisu olisi piirtää yksi kuva, jossa on ruudulle tuleva kuva, ja toinen, jossa on täysin mustalla seinät ja täysin valkoisella rata. Jos olet tosi fiksu, arvaat itsekin, kummasta kuvasta ja millaisella if-lauseella se törmääminen tarkistetaan.
Bonusvinkki: Kannattaa tarkistaa se seinä jo ennen liikutusta ja törmäystilanteessa jättää liikkumatta. Muuten auto joutuu seinän sisään eikä välttämättä voi edes pakittaa sieltä pois.
Metabolix kirjoitti:
Bonusvinkki: Kannattaa tarkistaa se seinä jo ennen liikutusta ja törmäystilanteessa jättää liikkumatta. Muuten auto joutuu seinän sisään eikä välttämättä voi edes pakittaa sieltä pois.
Tuon bonusvinkin huono puoli on se, että auton liikkuessa lujaa se todennäköisesti liikkuu ruudulla useamman pikselin kerrallansa. Jos törmäystesti tehdään tässä tapauksessa ennen liikutusta, niin auto luulee törmänneensä esteeseen liian aikaisin.
Perinteinen tapa taitaa olla se, että liikutaan ja sitten tarkistetaan objektin törmäyspisteiden avulla ollaanko osuttu ja tarvittaessa peruutetaan esim. puoli pikseliä kerrallansa pois esteen sisältä, kunnes ei enää osuta esteeseen.
jalski: Ajatuksenani oli vain antaa helpoin mahdollinen vastaus kysymykseen, joka hyvin todennäköisesti tulee heti, kun tuo törmäystarkistus toimii. Kysyjän koodaustaidot huomioon ottaen kannattanee toistaiseksi jättää käsittelemättä sellaiset vaikeat asiat kuin "silmukka" ja "laskeminen". Kunhan nyt saisi edes luettua oikeasta kuvasta oikean pikselin ja verrattua sitä oikeaan arvoon; edellinen yritys ei mennyt ihan nappiin.
Metabolix kirjoitti:
jalski: Ajatuksenani oli vain antaa helpoin mahdollinen vastaus kysymykseen, joka hyvin todennäköisesti tulee heti, kun tuo törmäystarkistus toimii.
Ymmärrän tuon kyllä. Omana ajatuksenani oli vain saada kysyjä itse hiukan pohtimaan asioita ja antaa miettimisen aihetta.
Alla Hollywood esimerkki simppelistä tasohyppelyn "mario-luokasta". Autopelissä törmäyspisteiden hallinta on hiukan monimutkaisempaa rotaatioiden takia, mutta idea ehkä selvinnee kuitenkin.
mario = {} mario.x = 32 ; aloitus x - koordinaatti mario.y = 400 + 32 ; aloitus y - koordinaatti mario.xs = 0 ; speed mario.vy = 0 ; velocity mario.frame = 0 ; animaatio frame mario.flipx = 0 ; onko sprite flipattu x-suunnassa. mario.jumping = False ; Hyppääkö mario? mario.scrollx = 0 ; missä mennään kartalla? mario.scrolling = False ; liikutetaanko mariota, vai scrollataanko karttaa? ; Seuraavana marion törmäyspisteet: cpx = x - pisteet ja cpy = y - pisteet ; Nämä löytyvät tietysti ylä-osalle, ala-osalle, vasemmalle puolelle ja oikealle puolelle. ; Ensimmäinen arvo aina normaalitila ja toinen, jos sprite on flipattu x-suunnassa. ; Arvot ovat siis siirroksia pelaajan x -ja y-koordinaatteihin (spriten keskipiste). mario.cpx = { bottom = { -11, 9 }, top = { 21, 41}, right = { 26, 30 }, left = { -30, -28 } } mario.cpy = { bottom = { 32, 32 }, top = { 0, 0 }, right = { -10, -17}, left = {-17, -10} } Function mario:move() ; liikutetaanko mariota, vai scrollataanko karttaa? If mario.scrolling = False Then self.x = self.x + self.xs If self.x < 32 Then self.x = 32 If self.x > 640 - 32 Then self.x = 640 - 32 ; Kuten yleensä elämässä, niin normaali suunta on aina alaspäin... self.vy = self.vy + #GRAVITY If self.vy <> 0 Then mario.jumping = True self.y = self.y + self.vy ; Kun on liikuttu, tarkastetaan ja käsitellään törmäykset pelikentän kanssa. self:CheckLevelCollision() EndFunction ; Arvaat ehkä, mitä tämä funktio tekee? Function mario:animate() Local time = GetTimer(3) If time > 1000/6 If self.jumping self.frame = 2 ElseIf self.xs <> 0 Or mario.scrolling = True self.frame = self.frame + 1 self.frame = Wrap(self.frame, 0, 2) Else self.frame = 0 EndIf ResetTimer(3) EndIf EndFunction ; Piirtää marion Function mario:draw() Local framesy = { 0, 65, 129 } ; animaatio framet allekkain samassa kuvassa, tässä niiden y-offsetit. DisplayBrushPart(9, 0, framesy[self.frame], self.x, self.y, 64, 64, {AnchorX = 0.5, AnchorY = 0.5}) EndFunction ; Tarkastaa törmäykset pelikentän kanssa Function mario:CheckLevelCollision() Local col SelectBrush(15) ; Törmäyskartta on brush 15, tästä luetaan pikseleitä nyt. ; Jos ollaan maan sisällä, niin pakitetaan. col = ReadPixel(self.scrollx + self.x + self.cpx.bottom[self.flipx], self.y + self.cpy.bottom[self.flipx]) While col = #RED self.y = self.y - 0.5 col = ReadPixel(self.scrollx + self.x + self.cpx.bottom[self.flipx], self.y + self.cpy.bottom[self.flipx]) Wend ; Jaahas, onkohan suoraan jalkojen alapuolella maata col = ReadPixel(self.scrollx + self.x + self.cpx.bottom[self.flipx], self.y + self.cpy.bottom[self.flipx] + 1) If col = #RED self.vy = 0 self.jumping = False EndIf ; Platformien läpi voi hypätä alapuolelta ylöspäin, mutta niiden läpi ei voi pudota If self.vy > 0 col = ReadPixel(self.scrollx + self.x + self.cpx.bottom[self.flipx], self.y + self.cpy.bottom[self.flipx]) While col = $26FF self.y = self.y - 0.5 col = ReadPixel(self.scrollx + self.x + self.cpx.bottom[self.flipx], self.y + self.cpy.bottom[self.flipx]) Wend ; Näyttääkös tutulta aiemmasta kohtaa? col = ReadPixel(self.scrollx + self.x + self.cpx.bottom[self.flipx], self.y + self.cpy.bottom[self.flipx] + 1) If col = $26FF self.vy = 0 self.jumping = False EndIf EndIf ; Pitäisiköhän vielä tarkastaa oikea puoli? col = ReadPixel(self.scrollx + self.x + self.cpx.right[self.flipx], self.y + self.cpy.right[self.flipx]) While col = #RED self.x = self.x - 1 col = ReadPixel(self.scrollx + self.x + self.cpx.right[self.flipx], self.y + self.cpy.right[self.flipx]) Wend ; Ja vasenkin puoli voisi ehkä olla fiksua vielä tsekata? col = ReadPixel(self.scrollx + self.x + self.cpx.left[self.flipx], self.y + self.cpy.left[self.flipx]) While col = #RED self.x = self.x + 1 col = ReadPixel(self.scrollx + self.x + self.cpx.left[self.flipx], self.y + self.cpy.left[self.flipx]) Wend EndSelect ; Brush 15 valinta ohi, käsitellään normaalisti näyttöä tämän jälkeen. EndFunction
Noniiin. Tein jotain systeemiä tuohon törmäämiseen. Tallennan vectoriin törmäys neliöitä (40x40) ja tarkistan että jos niihin törmätään muutetaan auton asentoa ja liikutetaan eri suuntaan, mutta eipäs ollutkaan niin helppo juttu. Sitten otin kulman muuttamisen kokonaan pois ja yritän saada auton liikkumaan eri suuntaan törmäyksestä.
Eli jos auto törmää oikealla etukulmallaan se kääntyy enemmän vasemmalle ja taas toisin päin. Viritin tälläistä systeemiä:
while(seinaa != Game::Seinat.end()){ if (x_oma >= seinaa->seinan_x && x_oma <= seinaa->seinan_x + seinaa->seinan_leveys) { if (y_oma >= seinaa->seinan_y && y_oma <= seinaa->seinan_y + seinaa->seinan_korkeus) { tormaa=true; } else { tormaa=false; } } seinaa++; } SDL_FreeSurface(Tekstit::text_19); Tekstit::text_19 = Tekstit::LoadText(" ", true, nopeus_oma, Fontit::font2, 255, 0, 0); if (!tormaa) { x_oma+=std::cos(kulma_oma) * nopeus_oma; y_oma+=std::sin(kulma_oma) * nopeus_oma; } else { x_oma-=std::sin(kulma_oma) * nopeus_oma; y_oma+=std::cos(kulma_oma) * nopeus_oma; }
Tuo systeemi toimii niin kauan kuin auto törmää vasemmalla etukulmallaan. Jos oikea etukulma osuu seinään menee auto seinästä läpi lujaa.
Olisikos mitään pikku vinkkejä?
Mikä tässä mun koodissa on vikana?
if (this->var_X > this->varY != this->varX < this->varY) varX = 1; else varY = 0; var_X++; ..... --> lisää random koodia
EDIT: http://lmgtfy.com/?q=polygon collision detection
Toinen EDIT:
Jos viitsisit edes yrittää keksiä mielekkäitä kysymyksiä. Omat yrityksesi ovat niin alkeellisia, että rupesin miettimään ymmärrätkö alkuunkaan koodiasi? Lainaa huvikseen jostain Päivi Hietasen C++ olio-ohjelmointi tai vastaava ja sisäistä kirja.
Yritäpä nyt ensin tehdä niin, että auto edes pysähtyy seinään.
Aihe on jo aika vanha, joten et voi enää vastata siihen.