Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: VB6: Apua törmäystarkistukseen

Sivun loppuun

platypus [30.08.2006 09:02:18]

#

Olen tekemässä tasohyppelypeliä VB6.0:lla, ja kohtasin ongelman, jota en meinaa saada millään ratkaistuksi. Kuten jo otsikosta jo huomaakin, on ongelmani törmäystarkistuksissa.

Pelialue piirretään tekstiasiatiedoston mukaan, 50x37 ruudukkoon (palikat ovat 16x16 kokoisia).Pelialueella on kahdenlaista palikkaa: estettä ja vapaata. ja pelihahmo taas liikkuu "portaattomasti" 800x592 koordinaatistossa. Pelihahmon liikutus tapahtuu timerissa, suuntanappin ollessa pohjassa.

Mielestäni ongelman siis tuottavat nimenomaan nämä eri koordinaatistot.

Googlasin hetken ja löysin API-funktion:

Declare Function IntersectRect Lib "user32" Alias "IntersectRect" (lpDestRect As RECT, lpSrc1Rect As RECT, lpSrc2Rect As RECT) As Long

Tämä funktio voisi olla toimiva, mutta ohjelman käynnistyksissä VB ei tunnista tuota RECT-sanaa.

Kysymykseni siis kiteytettynä:
Kuinka saisin tehtyä törmäystarkistuksen ukon ja palikan välillä?

En tarvitse välttämättä valmista koodia, (vaikka tietysti sellainenkin kelpaa), vaan lähinnä neuvoa siitä, millainen lähestymistapa asiaan kannattaa ottaa, ja jos olen jo tehnyt jotain typerästi, asian korjausta.

Jos jokin asia jäi epäselväksi, (ja varmasti jäikin), kysykää.

(Pahoittelen etten voinut pistää mitään koodinpätkää esille, mutta omalla koneellani ei ole internet yhteyttä, joten kirjoitin tämän koulun koneelta).

Blaze [30.08.2006 09:55:42]

#

[platypus] kirjoitti:

Tämä funktio voisi olla toimiva, mutta ohjelman käynnistyksissä VB ei tunnista tuota RECT-sanaa.

RECT ei ole VB:n sisäänrakennettu tyyppi, vaan se pitää itse määritellä. WinApin käyttämät funktio-, tyyppi- ym. määritelmät löytyy kätevästi esim. ApiViewer 2004 -ohjelmalla

Antti Laaksonen [30.08.2006 12:21:32]

#

RECT-tyyppi näyttää tältä:

Private Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type

Tuossa siis on tallennettuna suorakulmion koordinaatit, ja WinAPIn funktiot käyttävät tätä tyyppiä. Kuitenkaan tämän ongelman ratkaisussa ei tarvita WinAPIn funktiota.

Yksi helppo tapa on laskea, minkä palikoiden kohdalle pelihahmo osuu, ja tarkistaa, onko näiden palikoiden kohdalla estettä. Kun tiedetään pelihahmon sijainti ja koko sekä palikan koko, laskeminen on helppoa.

Tämä kuva selventää tilannetta:
https://www.ohjelmointiputka.net/kuvat/patorm.png

Nyt esim. pelihahmon vasen ylänurkka on kohdassa (58, 44) ja oikea alanurkka on kohdassa (94, 100). Vastaavat ruudut saa laskettua jakamalla koordinaatit ruudun koolla ja pyöristämällä alaspäin. Vasen yläruutu on siis (58 / 16, 44 / 16) eli (3, 2) ja oikea alaruutu on (94 / 16, 100 / 16) eli (5, 6).

Kun ruudut ovat tiedossa, ne täytyy enää käydä läpi kahdella silmukalla ja tarkistaa, onko jossain ruuduista este.

platypus [30.08.2006 13:18:43]

#

Kiitos Antti, olen taas hieman viisaampi. Itsekkin koitin jos jonkinlaista If-lauseketta, mutta epäonnistuin. Kunhan kotiin kerkiän, niin testaan toimiiko tarkistus näillä neuvoilla.

Myös toinen ongelma on edessäpäin, jonka kimppuun en ole vielä edes kerennyt käymään.

Hyppy nimittäin toimii loogisesti ylöspäin-napin ollessa pohjassa, mutta täytyyhän hyppyä jotenkin rajoittaakin. kuinka siis saan hypyn (? napinpainalluksen pituuden ?), rajoitettua johonkin tiettyyn aikaan tai korkeuteen? Ja lisäksi kuinka estän hyppy-napin toiminnan ennen kuin ollaan taas maassa?

Antti Laaksonen [30.08.2006 13:34:14]

#

Paras ratkaisu on toteuttaa peliin painovoima. Pelihahmolla on aina tietty pystysuuntainen nopeus. Jos pelihahmo on maassa, tämä nopeus on nolla. Kun pelihahmo hyppää, nopeus muutetaan osoittamaan ylöspäin. Painovoiman takia nopeus kuitenkin pienentyy koko ajan ja muuttuu lopulta vastakkaissuuntaiseksi.

Pelihahmoa liikutetaan tietyin aikavälein sen nopeuden mukaisesti. Nyt hyppy näyttää luonnolliselta ja pelihahmo ei pääse korkeammalle kuin se "ponnistaa". Kun pelihahmo on palannut maahan, nopeus muutetaan jälleen nollaksi. Hyppynappi taas on toiminnassa vain, kun pelihahmo on maassa.

platypus [31.08.2006 08:23:05]

#

Tällä hetkellä tuo hahmon "ponnistusvoima" on samassa komennossa hypyn kanssa, eli ukko "ponnistaa" aina uudestaan kun hyppyä tarkistetaan. Tietysti ponnistusvoima siis kannattaa pistää yhden Boolean lauseen taakse, kuten hypyn mahdollistaminenkin.

Jos vielä jaksatte vastata ongelmiini, niin vielä olisi yksi:

Kun aloitin tämän pelin teon, pistin Formille 2 timeria; 1. vaihtoi animaatiokuvia, 2. hoitaa melkein kaiken muun johon tarvitsee ajastinta. Kuitenkin ennen hahmon piirtoa oli komento (picturebox->) Pelialue.Cls. Nyt kun kentänpiirtokin on tullut mukaan, en voi enää käyttää tätä käskyä.
Jos Pelialue.cls on päällä, vilkkuu ruutu hirveästi kun koko kartta piirretään uusiksi, jos taas ei, niin hahmo jättää jälkeensä ruman "hännän".
Hahmo on piirretty TransparentBlt-funktiolla.

M2tias [31.08.2006 19:07:20]

#

Ruudun vilkkuminen johtuu siitä, että Pelialus.Cls päivittää koko piirtoalueen ja tausta joudutaan piirtämään kokonaan uudestaan, mikä vie paljon aikaa. Nopeampi tapa päivittää ruutu on piirtää tausta vain niihin kohtiin, jotka muuttuvat edellisestä framesta. Toisin sanoen piirrä ukon kokoinen alue taustaa ukon entisen sijainnin päälle Pelialue.Cls:n sijaan.

platypus [01.09.2006 08:21:57]

#

Kiitos, tiesin kyllä mistä vilkkuminen johtuu, en vaan keksinyt miten saisin sen pois. Aluksi olin ajattelin timer.intervalin muuttamista suuremmaksi, jolloin kuvanpäivitys ei olisi tullut niin tiheään tahtiin, mutta samalla olisi kärsinyt hahmon animaationopeus. Olisi aika typerää, jos ukko juoksisi tuhatta ja sataa, mutta kuva näyttää siltä että kyseessä on vain kevyt hölkkä :).

Näiden vinkkien jälkeen pärjään jo varmaan aika pitkälle omillani. Kiitos kaikille "opettajille".


Sivun alkuun

Vastaus

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

Tietoa sivustosta