Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Katsesuuntaan kulkeminen

Sivun loppuun

mika132 [30.09.2010 20:00:58]

#

Olen tässä jo säätänyt hetken kaiken näköistä ja lukenut matopelin opasta, mutta en saa autoa liikkumaan katse suuntaan. Tämän hetken yritys:

kuski_1_x+=std::cos(kulma) * nopeus;
kuski_1_y+=std::sin(kulma) * nopeus;
kuski_1_x+=std::cos(kulma) * nopeus;
kuski_1_y+=std::cos(kulma) * nopeus;
kuski_1_x+=std::sin(kulma) * nopeus;
kuski_1_y+=std::sin(kulma) * nopeus;
kuski_1_x+=x_jana / nopeus;
kuski_1_y+=y_jana / nopeus;

Koitin lukea tuota putkan "ohjelmoitsian matematiikka" mutta en sieltäkään ymmärtänyt miten saisin sen liikkumaan katse suuntaan.

Metabolix [30.09.2010 20:33:20]

#

Mihin suuntaan se sitten liikkuu? Ensimmäinen tapa on ihan oikea, mutta kulman pitää tietenkin olla radiaaneina ja suunta 0 on suoraan oikealle.

mika132 [30.09.2010 22:16:22]

#

Eikun ongelma näyttäs ratkenneen sillä, että muutin x akselin vaihtamisen negatiiviseksi eli:

kuski_1_x-=std::cos(kulma) * nopeus;
kuski_1_y+=std::sin(kulma) * nopeus;

Mistä mahtaa johtua, että noin toimii?

jalski [30.09.2010 22:35:35]

#

mika132 kirjoitti:

Mistä mahtaa johtua, että noin toimii?

Villi arvaus: sprite kuvassa auton nokka osoittaa vakiona vasemmalle?

Jos sprite kuvassa nokka osoittaa jonnekin muualle, kuin oikealle täytyy tämä tietenkin kompensoida jotenkin.

esim. jos nokka osoittaisi vakiona sprite kuvassa ylöspäin pitäisi tämä tietenkin kompensoida laskuissa.

; Hollywood syntaksilla ja kulmat taulukosta asteina.
player.x = player.x + costable[player.angle + 90] * player.speed
player.y = player.y + sintable[player.angle - 90] * player.speed

Grez [30.09.2010 22:37:17]

#

lainaus:

Mistä mahtaa johtua, että noin toimii?

Sulla on varmaankin X-suunnassa käänteinen koordinaatisto..

Matemaattinen koordinaatistohan kasvaa oikealle ja ylös. Tietokonegrafiikassa koordinaatisto kasvaa usein oikealle ja alas. Sulla on sitten ilmeisesti 180° käännetty versio tietokonegrafiikan koordinaatistosta.

Tai sitten niinkuin Jalski arvasi, että autosi menee oikeasti päinvastaiseen suuntaan kuin mihin kulma osoittaa.

Metabolix [30.09.2010 23:16:49]

#

Tuolla tavalla menet kyllä vain sekaisin. Yksinkertaisempi korjaus olisi kääntää kulma vastakkaiseksi eli vaihtaa kääntymisnapit keskenään. Kun auton saa pyörimään oikeaan suuntaan, tarvitsee enää kääntää alkuperäinen kuva niin päin, että nokka osoittaa menosuuntaan.

Jalskin ehdottama kompensointi koodin puolella ei ole kovin viisas ratkaisu, koska se sekavoittaa koodia ja aiheuttaa enemmän työtä kuin kuvatiedoston kääntäminen valmiiksi oikein päin.

mika132 [01.10.2010 01:47:19]

#

Juu. Auto ei ollut väärinpäin eikä mitään, mutta ei siitä sen enempää, kun sain sen kuitenkin korjattua.

Tätä on vaikea selittää.

Kun AI kuski ajaa "pisteisiin" eli kohtiin joita radassa on joissa se pyrkii pysymään tarpeeksi hyvin kurssissa, niin miksiköhän auto tekee joka pisteessä ylimääräisen kiepsahduksen? Eli se ajaa pisteeseen pyörähtää ympäri ja ajaa toiseen pisteeseen ja tekee saman.

Jos ette tästä ymmärtäneet niin kertokaa katson jos saisin jonkun videon vaikka fraspilla aikaan.

int KuskinAlyX(int Ajotaito, int Hepat, int Hermot, int kurvi) {
    if (Hermot >= 80) {
        if (kurvi == 1)
        {
            return 70;
        }
        if (kurvi == 2)
        {
            return 180;
        }
        if (kurvi == 3)
        {
            return 275;
        }
        if (kurvi == 4)
        {
            return 250;
        }
    }
}
int KuskinAlyY(int Ajotaito, int Hepat, int Hermot, int kurvi) {
    if (Hermot >= 80) {
        if (kurvi == 1)
        {
            return 120;
        }
        if (kurvi == 2)
        {
            return 72;
        }
        if (kurvi == 3)
        {
            return 130;
        }
        if (kurvi == 4)
        {
            return 250;
        }
    }
}

//Nämä siis ovat ihan erillisessä funktiossa
        piirra_kuva(kuvat::rata_1, 0,0);
        int kaantymis_pisteX = KuskinAlyX(Ajotaito, Hepat, Hermot, Kurvi);
        int kaantymis_pisteY = KuskinAlyY(Ajotaito, Hepat, Hermot, Kurvi);
        x_jana = (kaantymis_pisteX - kuski_1_x);
        y_jana = (kaantymis_pisteY - kuski_1_y);
        double kulma = std::atan2((double)x_jana, (double)y_jana);
        kulma += 90;
        kuvat::temp = rotozoomSurface(kuvat::auto_1, rad2deg(kulma), 1, 1);
        piirra_kuva(kuvat::temp, kuski_1_x, kuski_1_y);
        kuski_1_x-=std::cos(kulma) * nopeus;
        kuski_1_y+=std::sin(kulma) * nopeus;
        if (x_jana <= 4) {
            if (y_jana <= 4) {
                Kurvi += 1;
            }
        }
        SDL_FreeSurface(kuvat::temp);

tuohon jossa Kurvi+=1 tulee niin noissa IF ehdoissa on tuo neljä siksi, että ajattelin sen auttavan, mutta ei auttanut. Muussa tapauksessa loppu on siis:

if (x_jana == 4) {
    if (y_jana == 4) {
        Kurvi += 1;
    }
}

Enkä kaipaa nyt tekoälystä mitään mainintaa, kun se on vasta kehitteillä ensin haluan nähdä, että auto pyörähtää radan ympäri ongelmitta. =)

Metabolix [01.10.2010 09:16:10]

#

Koodissasi on ihan käsittämättömiä viritelmiä – korjaa ne! Miksi atan2-funktion parametrit ovat väärin päin? Miksi radiaaneina olevaan kulmaan lisätään 90, joka on noin 5157 astetta eli 117 astetta yli täyden kierroksen? Tuo ongelma, josta tämäkin keskustelu alkoi, johtuu takuulla näistä kahdesta virheestä.

Lopuksi hieman matematiikkaa:

jos kohde = (70, 120), niin

      x_jana <= 4
<=>   70 - kuski_x <= 4
<=>   kuski_x >= 66

      y_jana <= 4
<=>   120 - kuski_y <= 4
<=>   kuski_y >= 116

Ymmärrätkö, mitä tämä tulos tarkoittaa? Jos et ymmärrä, olet ohjelmoinnin kanssa pahassa pulassa, nimittäin yhtälöiden ja epäyhtälöiden ymmärtäminen ja niissä esiintyvien lukujen ja erityisesti muuttujien ymmärtäminen ovat ohjelmoinnin peruskiviä.

Löytyisiköhän matematiikkaoppaasta järkevämpi ratkaisu? Älä kopioi vaan opettele!

mika132 [01.10.2010 12:12:20]

#

Juu se tarkottaa, et jos x_jana on lähempänä ko 4 ja y_jana on lähempänä ko 4 suoritetaan toiminto (tai siis mun koodista ko siin oli if)

120 - kuski_y <= 4
Jos 120 - kuski_y on vähemmän ko 4 nii tehdään jotain jos siis etuliitteenä on if.
ja perjaatteen mukaa se tarkottaa sitä, et jos kuski_y on <= 116 Eikä enemmän. Eikös y pienen ylemmäs mentäessä. =)

Luin tuota matematiikka opasta, mutta en silti saanut mitään järkevää vastausta siihen, miten muka eri kaava lopettaisi sen ylimääräsien pyörähdyksen. Enkä kyllä saanut tolkkua tuosta miten tuo kaava toimisi C++? Mitä koodeja tarvitaan, että tuollainen toteutuu... Siis neliöjuuri.

ja jos ymmärsin oikein halusit rad2deg koodin:

double rad2deg(double rad){
    return ((rad * 180) / 3.1415927);
}

Torgo [01.10.2010 14:39:10]

#

mika132 kirjoitti:

Juu se tarkottaa, et jos x_jana on lähempänä ko 4 ja y_jana on lähempänä ko 4 suoritetaan toiminto (tai siis mun koodista ko siin oli if)

120 - kuski_y <= 4
Jos 120 - kuski_y on vähemmän ko 4 nii tehdään jotain jos siis etuliitteenä on if.
ja perjaatteen mukaa se tarkottaa sitä, et jos kuski_y on <= 116 Eikä enemmän.

Ei, vaan juuri toisinpäin. Eli ts. et ymmärtänyt mitä Metabolixin lausekkeet tarkoittivat. Opettele lisää yhtälöitä.

Lyhyesti sanottuna se tarkoittaa että koodissa oleva lausekkeesi (y_jana <= 4) on yhtäpitävä lausekkeen (kuski_y >= 116) kanssa, kun kääntymispiste on 120.

Metabolix [01.10.2010 16:07:45]

#

mika132 kirjoitti:

ja jos ymmärsin oikein halusit rad2deg koodin

Aika jännästi ymmärretty. Sopiiko tiedustella, mistä ihmeestä tuollainen ajatus päähäsi pälkähti?

mika132 kirjoitti:

Mitä koodeja tarvitaan, että tuollainen toteutuu... Siis neliöjuuri.

Onko hakua todella niin vaikea käyttää?

mika132 kirjoitti:

(virheellistä matematiikkaa)

Nyt vikkelästi lukemaan sitä matematiikkaa! Jos x_jana on alle 4, se voi olla esimerkiksi -123456789, mikä ei todellakaan ole "lähempänä kuin neljä", jos vertailukohde on ruudulla. Ja epäyhtälöistä voit varmaan itsekin todeta helposti seuraavaa:

120 - kuski_y           <= 4
120 - kuski_y + kuski_y <= 4 + kuski_y
120                     <= 4 + kuski_y
120 - 4                 <=     kuski_y
116                     <=     kuski_y

    116 <= kuski_y,  esim.  116 <= 456
kuski_y >= 116,      esim.  456 >= 116

Jos tällaisissa perusasioissa on epäselvyyksiä, pitää opetella niitä perusasioita eikä yrittää koodata peliä, jossa nämä ovat äärimmäisen tärkeitä eivätkä saa mennä pieleen.

Yhtälöt eivät muutu miksikään, oli y sitten ruudulla ylös tai alas. Noista yhtälöistä seuraa, että autosi tulkitsee päässeensä perille aina, kun sen sijainti on kohdepisteestä positiiviseen x- ja y-suuntaan, SDL:n koordinaatistossa siis alaoikealle. (Lisäksi neljä pikseliä ylös tai vasemmallekin vielä kelpaa.) Käytännössä tästä seuraa, että autosi "on perillä" suurimman osan ajasta ja Kurvi-muuttuja kasvaa. (Tuossakin on muuten virhe: muuttujan olisi varmaan tarkoitus pyörähtää jossain vaiheessa takaisin alkuun.)

mika132 [02.10.2010 14:32:26]

#

Ei ole vielä, kun ensin pitäisi saada se menemään edes puoli rataa jotakuinkin oikein.

Suunnittelen ja mietin vielä tota, mutta tässä on eilinen 8-12h hommani jota mietin.

Tein pelaajalle ohjattavaa autoa ja mietin hetken miten sen toteuttaisi. Yhtäkkiä mieleeni välähti se, että teen "pisteen" joka liikkuu auton ohjausnapeista ja jota auto "yrittää" saada kiinni, mutta toteutus tyylini on suoraan sanoen aivan hanurista.

Tässä kuva:
Kuva

Se enemmän vasemmalla oleva "auto" on pelaajan ohjattava siis.

Ja tässä ohjaukseen liittyvät koodit:

//tein erilliseen tiedostoon ohjaukset. AI.hpp. Siellä on tuo AI pelaajan pisteiden haku (ei tule tässä mukana) minkä arvo palautetaan ja sitten taas pelaajan ohjaukset jotta ohjelma.cpp pysyisi hieman siistimpänä.


int PelaajanLiikkeetX(int PelaajanX, double kulma_oma, int PelaajanX1, int PelaajanY1) {
    Uint8* nappi;
    nappi = SDL_GetKeyState(NULL);
    if (nappi[SDLK_UP]) {
        PelaajanX-=std::cos(kulma_oma) * 3;
    }
    if (nappi[SDLK_DOWN]) {
        //PelaajanX+=1;
        //Ei vielä pakki käytössä
    }
    return PelaajanX;

}

int PelaajanLiikkeetY(int PelaajanY, double kulma_oma, int PelaajanX1, int PelaajanY1) {
    Uint8* nappi;
    nappi = SDL_GetKeyState(NULL);
    if (nappi[SDLK_UP]) {
        PelaajanY+=std::sin(kulma_oma) * 3;
    }
    if (nappi[SDLK_DOWN]) {
        //PelaajanX-=1;
        //Ei vielä pakki käytössä
    }
    return PelaajanY;

}

int PelaajanLiikkeetX1(int PelaajanX, double kulma_oma, int PelaajanX1, int PelaajanY1, int x_jana_oma, int y_jana_oma) {
    Uint8* nappi;
    nappi = SDL_GetKeyState(NULL);
    if (kulma_oma >= 5180 && kulma_oma <= 5294.999999999999999)
    {
        PelaajanX1=PelaajanX + 100;
    }
    if (nappi[SDLK_RIGHT]) {
        if (kulma_oma >= 5294 && kulma_oma <= 5331.99999999999)
        {
            PelaajanX1+=2;
        }
        if (kulma_oma >= 5050 && kulma_oma <= 5210.99999999999)
        {
            PelaajanX1-=2;
        }
    }
    if (nappi[SDLK_LEFT]) {
        if (kulma_oma >= 5294 && kulma_oma <= 5331.99999999999)
        {
            PelaajanX1-=2;
        }
        if (kulma_oma >= 5050 && kulma_oma <= 5210.99999999999)
        {
            PelaajanX1+=2;
        }
    }
    return PelaajanX1;

}

int PelaajanLiikkeetY1(int PelaajanY, double kulma_oma, int PelaajanX1, int PelaajanY1, int x_jana_oma, int y_jana_oma) {
    Uint8* nappi;
    nappi = SDL_GetKeyState(NULL);
    if (kulma_oma >= 5295 && kulma_oma <= 5331.99999999999)
    {
        PelaajanY1=PelaajanY - 100;
    }
    if (kulma_oma >= 5050 && kulma_oma <= 5210.99999999999)
    {
        PelaajanY1=PelaajanY + 100;
    }
    if (nappi[SDLK_RIGHT]) {
        if (kulma_oma >= 5208 && kulma_oma <= 5293.99999999999)
        {
            PelaajanY1+=2;
        }
    }
    if (nappi[SDLK_LEFT]) {
        if (kulma_oma >= 5208 && kulma_oma <= 5293.99999999999)
        {
            PelaajanY1-=2;
        }
    }
    return PelaajanY1;

}
//Ja täällä on ohjelma.cpp:stä se ohjaus kohta:
        PlayerX = PelaajanLiikkeetX(PlayerX, kulma_oma, PlayerX1, PlayerY1);
        PlayerY = PelaajanLiikkeetY(PlayerY, kulma_oma, PlayerX1, PlayerY1);
        PlayerX1 = PelaajanLiikkeetX1(PlayerX, rad2deg(kulma_oma), PlayerX1, PlayerY1, x_jana_oma, y_jana_oma);
        PlayerY1 = PelaajanLiikkeetY1(PlayerY, rad2deg(kulma_oma), PlayerX1, PlayerY1, x_jana_oma, y_jana_oma);
        piirra_kuva(kuvat::temp_oma, PlayerX, PlayerY);
        piirra_kuva(kuvat::ruksi, PlayerX1, PlayerY1);

Tiedän, että toteutus on huono, mutta en keksinyt muutakaan tapaa saada kulmaa laskettua. Kuitenkaan tämä ei toimi millään tavalla. Se ei liikuta autoa kuten pitäisi. Ensinnäkin se pysää pisteeseen 5019 vaikka sen mielestäni pitäisi alkaa tuossa kohtaa käyttämään X akselia pitkin liikkumista.

Uskon varmasti, että tähän on helpompikin toteutus tapa joten olisin kiitollinen jos valaisisitte hieman.

jalski [03.10.2010 00:11:46]

#

Mikset pelaajan auton ohjausta toteuta vain yksinkertaisesti siten, että ylös -ja alasnuolinapit säätelevät nopeutta ja sivunuolinapeilla voi vaihtaa auton ohjauksen kulmaa? Tuolloin kulman laskemisen ei kai pitäisi tuottaa ongelmia (yhteen -ja vähennyslaskua)?


Esim. Hollywoodilla muutamassa minuutissa tehdyn avaruusalus lentelypelin pelilooppi.

Function p_MainLoop()

	If IsKeyDown("LEFT")
		player.angle = (player.angle + 360) % 360 + 4
	ElseIf	IsKeyDown("RIGHT")
		player.angle = (player.angle + 360) % 360 - 4
	EndIf

	Local xd! = costable[player.angle + 90]
	Local yd! = sintable[player.angle - 90]

	If IsKeyDown("UP")
		player.speed! = player.speed! + 0.35
		If player.speed! > 3 Then player.speed! = 3

		If Rnd(100) > (100 - player.speed! * 2.5) Then flames:add(player.x! - 40 *xd!, player.y! - 40 * yd!, 0.5, 128)

	Else
		player.speed! = player.speed! - 0.25
		If player.speed! < 0 Then player.speed! = 0
	EndIf

	Local xs! = xd! * player.speed!
	Local ys! = yd! * player.speed!

	If IsKeyDown("LCONTROL")
		Local time = GetTimer(1)
		If time > 500
			shots:add(player.x! + 32 * xd!, player.y! + 32 * yd!, 20 * xd!, 20 * yd!)
			ResetTimer(1)
		EndIf

	EndIf

	DisplayBrush(1, #CENTER, #CENTER)

	player:move(xs!, ys!)
	player:rotate(player.angle)
	baddies:move()
	shots:move()

	shots:collision()
	baddies:collision()

	flames:animate()
	explosions:animate()

	starfield:draw()
	player:draw()
	baddies:draw()
	flames:draw()
	explosions:draw()
	shots:draw()

	TextOut(#LEFT, #TOP, AddStr(pointinfo$, points))

	Flip

EndFunction

Edellisessä siis kulmat asteina taulukosta ja toteutus siis Hollywoodilla, mutta ei luulisi olevan kamalan vaikea soveltaa...

mika132 [03.10.2010 15:43:15]

#

No joo näyttää ihan yksinkertaiselta, mutta silti en saa toimimaan.

Yritin kaikkea mahdollista, mutta ei niin ei. Mielestäni ainut looginen mahdollisuus on se, että asettamani "ruksi" kulkee 100px päässä autosta ja ruksi pyörii autoa ympäri, mutta en vain tiedä miten sen toteuttaisin. En osaa liikuttaa rustia kuin neliömäisesti ja sekin niin purkalla, että oksat pois. Edes itse en ymmärrä omaa purkka viritelmääni.

Eli miten saan ruksin jota auton on tarkoitus seurata pysymään 100px päässä autosta ja pyörimään ympyrää auton ympärillä ja auto seuraa tätä (no tuon seuraamisen osaan ehkä tehdä)

x_jana_oma = (PlayerX1 + 10 - PlayerX);
y_jana_oma = (PlayerY1 - 10 - PlayerY);
double kulma_oma = std::atan2((double)x_jana_oma, (double)y_jana_oma);
kuvat::temp_oma = rotozoomSurface(kuvat::auto_1, rad2deg(kulma_oma), 1, 1);
piirra_kuva(kuvat::ruksi, PlayerX1, PlayerY1);

Eikös tuollaisella viritelmällä saada auton kulma olemaan kohti ruksia ja sitten vain cosineilla ja sinineillä (vai mikä se oli) pistetään se menemään sinneppäin (eli jos noin toteutetaan sen osaan) mutta sitä en osaa, että miten saan ruksin eli "kiintopisteen" kulkemaan autoa ympäri ympyrää ja suuntana riippuu painikkeistä Vasemmalle vai oikealle.

Ps. Kiitos jos autatte.

Metabolix [03.10.2010 15:49:12]

#

Lähestymistapasi on aivan nurinkurinen. Ei pidä laskea mitään kiintopistettä, vaan ohjausnappien pitää muuttaa suoraan auton kulmaa.

Torgo [03.10.2010 15:49:17]

#

mika132 kirjoitti:

Mielestäni ainut looginen mahdollisuus on se, että asettamani "ruksi" kulkee 100px päässä autosta ja ruksi pyörii autoa ympäri

Mitä siinä logiikassa on vikana että auto kääntyy oikealle, kun painaa oikealle ja vasemmalle, kun painaa vasemmalle?

mika132 [03.10.2010 15:55:01]

#

Sitä, että itselläni auto ei kääntynyt mihinkään. Vaikka kuinka painoi oikealle tai vasemmalle (voi olla, että sovelsin koodia väärin C++).

Metabolix [03.10.2010 15:58:30]

#

Debuggauksen alkeet: tulosta muuttujien arvoja näkyviin eri kohdissa ohjelmaa, niin näet, missä kohti ne alkavat mennä pieleen.

mika132 [03.10.2010 16:05:47]

#

No juu consoliini tulostuu koko ajan tietoa auton kulmasta, mutta ne ovat koko ajan pielessä ja näyttävät samaa:

92.84...


Lisäksi en ymmärrä sitä, kun tulostin silloin kun auto "kääntyi" ja se kääntyi ihan päin hanuria niin tulostukset olivat jopa 90 asteen muutoksen jälkeen jotakuinkin näin:
92.84 ja käännöksen jälkeen
91.55

Siis en muista tarkkoja lukemia, mutta ihmettelin vain, miksi niin pieni muutos. Sitten hoksasin, että taitaa johtua x_janasta ja y_janasta ja tulostin rad2deg kulman ja arvot olivat 4900-5500 en muista tarkkaan. Eli miten saisin sopusuhtaiset asteluvut. Sitten saisin purkkani toimimaan ja mietittyä miten saan siitä paremman.

Vai onko nyt jokin mennyt täysin ohi minulta. Matikka oppaita luettu kyllä. C++ oppaita luettu tässä vkl aikana useasti ja kaikkea. Nyt on pää tyhjä. En keksi muuta kuin, että jotain on mennyt ohitse.

Metabolix [03.10.2010 16:22:55]

#

Yritä nyt tajuta se asteiden ja radiaanien ero. Ilmeisesti ainakin se on mennyt ohitse. Esimerkiksi 90 asteen muunnos ei todellakaan synny sillä, että lisäät kulmaan luvun 90, kuten tuolla pari viestiä aiemmin yritit.

Alkajaisiksi voit aina kulman muuttamisen jälkeen poistaa kulmasta ylimääräiset kokonaiset kierrokset (jotka näköjään myös ovat menneet ajatustesi ohitse) vaikka näin:

double korjaa_kulma(double kulma) {
  return std::atan2(std::sin(kulma), std::cos(kulma));
}

mika132 [03.10.2010 22:15:33]

#

Aivan! En muistanut ollenkaan atan2.

Tässä hetken säädeltyäni totesin, että nykyinen systeemi ei pelaa. Onko siis olemassa jotain "funktiota" tai nopeaa tapaa saada se niin, että "kiintopiste" kulkee auton edessä ympyrää. Eikä neliömäistä liike rataa.

Tässä se mitä tarkotian

Tässä se miten minulla nyt menee


Neliömäisessä auto alkaa kulkmemaan ns. Ohitse kiintopisteen, mutta loogisesti ajateltuna tuota ei pitäisi tapahtua ympyrämäisessä liikeradassa, koska kiintopiste on aina samalla etäisyydellä.

Metabolix [03.10.2010 22:23:53]

#

Kuten jo useammalta taholta todettiin, koko kiintopisteviritelmäsi on aivan järjetön. Et tarvitse sellaista. Voit muuttaa suoraan auton kulkusuuntaa. Joka tapauksessa tarvitsisit tuohon kiintopisteasiaan ihan täsmälleen samanlaisia laskuja.

Torgo [03.10.2010 22:30:32]

#

mika132 kirjoitti:

Vai onko nyt jokin mennyt täysin ohi minulta.

http://fi.wikipedia.org/wiki/Radiaani

mika132 kirjoitti:

Nyt on pää tyhjä. En keksi muuta kuin, että jotain on mennyt ohitse.

No edellisen lisäksi, ainakin 5 viestiä, missä kehotettiin luopumaan järjettömästä kiintopisteideasta.

mika132 [04.10.2010 02:03:13]

#

No nyt taisin ymmärtää. Edelleen ongelmana on se, että auto kulkee ihan hitusen poikittain.

Olisi siis kaksi kysymystä.
Miten voin asettaa kuvalle origon. Että auto siis taittuisi tietystä pisteestä (joskus GameMakerissä tähän tutustuin kun sai asettaa keskipisteen ja ihmiset pyörivät kivasti)
toinen. Miten saan sen asteen kahden poikittais liikkeen pois.

static double kulma_oma = korjaa_kulma(kulma_oma);
//Tuo on namespacessä alustuksessa, mutta varmaan ihan hyödytön siellä. Tuo on siis se atan 2 viritelmä


double ohjelma::korjaa_kulma(double kulma) {
    return std::atan2(std::sin(kulma), std::cos(kulma));
}
kuvat::temp_oma = rotozoomSurface(kuvat::auto_1, rad2deg(kulma_oma), 1, 1);
        if (nappi[SDLK_LEFT]) {
            if (nopeus_oma >= 0.01 && nopeus_oma <= 2) {
                kulma_oma+=0.08;
            }
            if (nopeus_oma >= 2 && nopeus_oma <= 4) {
                kulma_oma+=0.06;
            }
            if (nopeus_oma >= 4 && nopeus_oma <= 10) {
                kulma_oma+=0.04;
            }
        }
        if (nappi[SDLK_RIGHT]) {
            if (nopeus_oma >= 0.01 && nopeus_oma <= 2) {
                kulma_oma-=0.08;
            }
            if (nopeus_oma >= 2 && nopeus_oma <= 4) {
                kulma_oma-=0.06;
            }
            if (nopeus_oma >= 4 && nopeus_oma <= 10) {
                kulma_oma-=0.04;
            }
        }

Metabolix [04.10.2010 02:12:30]

#

mika132 kirjoitti:

Miten voin asettaa kuvalle origon

Vähennä kuvan piirtokohdasta aina puolet kuvan leveydestä ja korkeudesta, niin saat kuvan keskikohdan pysymään keskellä. Matopelioppaassa on tämäkin, katso sieltä. Muun kohdan asettaminen keskelle vaatii enemmän matematiikkaa, ja koska et osaa sitä, ei kannata yrittää.

mika132 kirjoitti:

Miten saan sen asteen kahden poikittais liikkeen pois.

Ei siellä pitäisi mitään tuollaista olla, jos kuvatiedosto on suorassa etkä lisäile ohjelmassa kulmaan mitään outoja lukuja.

Torgo [04.10.2010 13:39:46]

#

mika132 kirjoitti:

Miten saan sen asteen kahden poikittais liikkeen pois.

Siten että käytät auton liikuttamiseen samaa kulmaa, kuin millä pyörität sen kuvaakin, etkä muuttele sitä siinä välissä.

mika132 kirjoitti:

if (nopeus_oma >= 0.01 && nopeus_oma <= 2) {
    kulma_oma+=0.08;
}
if (nopeus_oma >= 2 && nopeus_oma <= 4) {
    kulma_oma+=0.06;
}
// ...

Näissä iffeissäsi ei ole alun alkaenkaan paljoa järkeä, mutta sanohan ainakin se, että mitä mielestäsi pitäisi tapahtua kun nopeus_oma == 2?

Teuro [04.10.2010 14:12:37]

#

Kulman pitäisi tosiaan olla 0.14, joka ei varmaankaan ole tarkoitus. Ilmeisesti tässä on tavoiteltu ominaisuutta, jossa nopeuden lisäys hidastaisi ohjausta.

mika132 [05.10.2010 02:07:54]

#

Juu. Se oli vahinkossa mennyt noin. Muutin iffit oikeiksi. :P

hmm... Ilmeisesti AI pelaajallekkaan ei ole hyvä systeemi tuo kiintopisteitten asettaminen tielle. Eli onko mitään hyviä ideoita?

jalski [05.10.2010 10:46:01]

#

En halua mitenkään masentaa, mutta et kyllä hirveän helppoa aihetta valinnut harjoitus projektiksesi. ;-) Jos nimittäin haluat edes suhteellisen realistisesti käyttäytyvät autot, niin joudut kyllä opiskelemaan hiukan fysiikkaa ja matematiikkaa. Tuo tekstikään ei sitten välttämättä ole kovin helppolukuista ainakaan, jos matemaattiset notaatiot, trigonometria, integrointi, derivointi, vektorit ja fysiikan lähtötiedot eivät ole hallussa.

Oppimateriaalia löydät kyllä paljon netistä. Aloita opiskelu vaikka hakusanalla: rigid body dynamics

Grez [05.10.2010 14:29:44]

#

Veikkaan kyllä vahvasti, että tarkoituskaan ei ole ollut tehdä realistista fysiikkamallinnusta. Kysyjälle varmasti riittäisi tässä vaiheessa, että saisi ne tekoälyautot edes kiertämään sitä rataa..

Lisäksi väittäisin että Slicks'n'Slide henkiseen autopeliin saa ihan riittävän hyvät "fysiikat" tehtyä ilman minkäänlaista todellisen fysiikan osaamista, kunhan nyt trigonometrian perusteet on hallussa.

Metabolix [05.10.2010 14:58:40]

#

mika132 kirjoitti:

Eli onko mitään hyviä ideoita?

Minulla on yksi aika hyvä idea: opettele ohjelmoimaan!

Pystyisin tekemään toimivan tekoälyn helposti ainakin kymmenellä tavalla – myös noilla yrittämilläsi kiintopisteviritelmillä. Sinä taas et näköjään pysty tekemään tekoälyä edes yhdellä tavalla, eikä ero johdu mistään mullistavasta erosta ideassa vaan siitä, että sinun ohjelmointitaitosi (ja matematiikkasi) ei riitä edes yksinkertaisen idean toteuttamiseen. Tähän ei ole kuin yksi ratkaisu: ohjelmoinnin ja matematiikan opetteleminen.

Lähdetään nyt ideasta, että radalla on ennalta asetetut pisteet, jotka auto pyrkii käymään läpi. Tarkoitus on siis saada auto liikkumaan aina seuraavan kohdepisteen suuntaan. Seuraavien vaiheiden avulla saat ratkaistua ongelman:

Torgo [05.10.2010 17:03:13]

#

mika132 kirjoitti:

hmm... Ilmeisesti AI pelaajallekkaan ei ole hyvä systeemi tuo kiintopisteitten asettaminen tielle. Eli onko mitään hyviä ideoita?

Pelaajan tapauksessa asian voisi ajatella näin, että kiintopiste on hinausauto ja nappien painamisella ohjaat tuota hinausautoa. Auton tehtävä on sitten kulkea hinausauton perässä vakioetäisyydellä. Näet varmaan mikä siinä on ongelmana? Joudut joka tapauksessa toteuttamaan ohjauksen, niin kumpaa on mielestäsi parempi ohjata: kilpa-autoa vai hinausautoa?

Ei se ole hyvä systeemi AI:llekaan, mutta siinä se toimii paremmin. Nythän niitä kiintopisteitä ei tarvitse ohjata, vaan voit ripotella niitä tielle ja ajaa aina suorinta reittiä seuraavaan. Eihän se mitään nättiä tai kovin järkevää ole, mutta se on riittävän yksinkertaista että pääset hommassa eteenpäin. Voit siis aivan hyvin näin aluksi toteuttaa ai:lle tuon kiintopisteidean, kunhan teet sen kiinteinä waypointteina, etkä yritäkään mitään rataa seuraavaa hinaajaa tehdä. Waypointtien etuna olisi sekin, että esim. jo aiemmin mainitsemani pid-säätö ohjaukseen olisi hyvin helppo toteuttaa, koska virhekulman saa suoraan auton kulman ja sijainnin ja waypointin välisen kulman erotuksesta. Mutta yritä nyt ensin saada auto kulkemaan suoraan pisteestä a pisteeseen b, ennenkuin alat sen kummempaa säätöä miettimään.

Kaikkein tärkeintä olisi, kuten Metabolix neuvoi, opetella ohjelmoimaan. Tämä tarkoittaa mm. sitä, että yrität ymmärtää rajapintojen merkityksen. Sitten suunnittelet pelillesi järkevän rajapinnan. Jos sinulla on järkevä rajapinta suunniteltuna, niin voit myöhemmin, taitojen karttuessa, helposti lisätä koodiisi fysiikan mallinusta tai vaihtaa AI:n tai ohjauksen parempaan.

mika132 [05.10.2010 18:25:23]

#

Juu. Minulla on noita waypointteja 12kpl radalla, mutta AI:n ongelma miksi mietin, että ei toimi kiintopiste AIllakaan niin on tässä:

Video youtubessa
Tein pienen videon tuosta AI:n ajamisesta radalla. Näette varmasti itsekkin mikä siinä tulee heti ensimmäisen kurvin kohdalla ongelmaksi.

Eikä minulla ole mitään tietoa, miten korjata se.

Lisäksi jostain syystä kiintopiseessä 9 (eli videon lopussa) AI lisää kurvi laskuriin itselleen lisää niin paljon, että tulee 12 ja palauttaa arvon yhteen kuten pitääkin ja lisää vielä kurvi arvoon 7 lisää. Eli AI kääntyy kurvissa ympäri ja menee hetkellisesti väärään suuntaan.

Kohdassa. 14sek - 20sek näkyy se, kun auto menee kiintopisteeseen ja menee tökkäsemällä kohti seuraavaa kiintopistettä. Ja siinä onkin ongelma. Auto meinaa mennä ohi kiintopisteen, mutta ns. Juuri ja juuri tajuaa kääntää auton kohti nurmikkoa ja taas auton suunta pamahtaa suoraan seuraavaa kiintopistettä kohti.


Koodia se on purkkaa tiedetään, mutta tarkoitus olisi saada tämä toimimaan ja katsoa miten saisin nipistettyä pienemmäksi, kuten monesti olette itsekkin maininneet, että opettelee tekemään ja sitten katsoo miten siitä saisi kätevämmän:

//AI.hpp
//TÄällä on siis funktiot joita kutsutaan sitten ohjelma.cpp:ssä
int KuskinAlyX(int Ajotaito, int Hepat, int Hermot, int kurvi) {
    if (Hermot >= 80) {
        if (kurvi == 1)
        {
            return 70;
        }
        if (kurvi == 2)
        {
            return 180;
        }
        if (kurvi == 3)
        {
            return 275;
        }
        if (kurvi == 4)
        {
            return 250;
        }
        if (kurvi == 5)
        {
            return 330;
        }
        if (kurvi == 6)
        {
            return 460;
        }
        if (kurvi == 7)
        {
            return 500;
        }
        if (kurvi == 8)
        {
            return 600;
        }
        if (kurvi == 9)
        {
            return 760;
        }
        if (kurvi == 10)
        {
            return 620;
        }
        if (kurvi == 11)
        {
            return 200;
        }
        if (kurvi == 12)
        {
            return 60;
        }
    }
}
int KuskinAlyY(int Ajotaito, int Hepat, int Hermot, int kurvi) {
    if (Hermot >= 80) {
        if (kurvi == 1)
        {
            return 120;
        }
        if (kurvi == 2)
        {
            return 72;
        }
        if (kurvi == 3)
        {
            return 130;
        }
        if (kurvi == 4)
        {
            return 250;
        }
        if (kurvi == 5)
        {
            return 330;
        }
        if (kurvi == 6)
        {
            return 300;
        }
        if (kurvi == 7)
        {
            return 170;
        }
        if (kurvi == 8)
        {
            return 90;
        }
        if (kurvi == 9)
        {
            return 270;
        }
        if (kurvi == 10)
        {
            return 520;
        }
        if (kurvi == 11)
        {
            return 500;
        }
        if (kurvi == 12)
        {
            return 260;
        }
    }
}
//Ohjelma.cpp
        int kaantymis_pisteX = KuskinAlyX(Ajotaito, Hepat, Hermot, Kurvi);
        int kaantymis_pisteY = KuskinAlyY(Ajotaito, Hepat, Hermot, Kurvi);
        x_jana = (kaantymis_pisteX - kuski_1_x);
        y_jana = (kaantymis_pisteY - kuski_1_y);
        double kulma = std::atan2((double)x_jana, (double)y_jana);
        kulma+=90;
        kuvat::temp = rotozoomSurface(kuvat::auto_1, rad2deg(kulma), 1, 1);
        kuski_1_x-=std::cos(kulma) * nopeus;
        kuski_1_y+=std::sin(kulma) * nopeus;

        if (x_jana <= 1) { //tässä on ollut kaikkea x_jana == 0 x_jana <= 12 jne.
            if (y_jana <= 1) {
//Nämä tein siksi, että ajattelin hahmon ottavan uudet pisteet itselleen heti ettei se tekisi pyörähdystä, mutta ei auttanut.
                std::clog << "Kurvi = " << Kurvi << std::endl;
                Kurvi+=1;
                kaantymis_pisteX = KuskinAlyX(Ajotaito, Hepat, Hermot, Kurvi);
                kaantymis_pisteY = KuskinAlyY(Ajotaito, Hepat, Hermot, Kurvi);
                x_jana = (kaantymis_pisteX - kuski_1_x);
                y_jana = (kaantymis_pisteY - kuski_1_y);
                kulma = std::atan2((double)x_jana, (double)y_jana);
                kulma+=90;
            }
        }

Ps. Toivottavasti tämä riittää informaatioksi, koska tarvitsisin oikeasti ja suuresti apua. Neljäs vai viides päivä jo kun olen tätä toimimaan yrittänyt saada, mutta aina menee samalla tavalla.

Olen todella kiitollinen jos vielä hieman viitsitte olla kärsivällisiä ja opastaa.

Metabolix [05.10.2010 18:31:42]

#

Metabolix kirjoitti:

Koodissasi on ihan käsittämättömiä viritelmiä – korjaa ne! ...

Lue tuo kyseinen viesti uudelleen ja korjaa mainitut virheet koodistasi. Onko tässä jotain epäselvää?

Vielä kertauksena:

mika132 [05.10.2010 23:27:44]

#

Ehdein tekemään pisteen välimatka laskun erillaisella systeemillä kun Pythagooralla. Se on hieman monimutkainen laskukaava enkä osannut tehdä siitä lyhyempää, mutta asian ydin on se, että mitä consoliin olevia tulostuksia katsoin se toimii täysin oikein ja kaava on:

etaisyys_ensimmainen_1 = kaantymis_pisteX - kuski_1_x;
etaisyys_ensimmainen = pow(etaisyys_ensimmainen_1, 2);
etaisyys_toinen_1 = kaantymis_pisteY - kuski_1_y;
etaisyys_toinen=pow(etaisyys_toinen_1, 2);
etaisyys = etaisyys_ensimmainen + etaisyys_toinen;
etaisyys_lopulta = sqrt(etaisyys);

Nyt kuitenkin auto kulkee poikittain. Se menee melkein muuten oikein, mutta kulkee poikittain. Olen tallentanut kuvan kyllä niin että etupää osoittaa oikealle.

Lisäksi jos muutan x akselin muuttumis kulmaan += niin auto menee väärään suuntaan. Yrittäessään tähdätä kiintopisteeseen yksi kääntämällä autoa oikealle se ajaakin vasemmalle ja eikä tule koskaan takaisin öö...??

Sen sijaan Y akseli ei ole enää += vaan -= öö??

Lisäksi kun seurasin auton poikittain ajoa huomasin, että se meinaa edelleen ajaa jokaisesta pisteestä ohitse ja näin joutuu kääntymään "takaisin päin" eli se mikä videossani oli siinä 15-20sek kohdilla.

Lisäksi saavuttuaan pisteeseen yksi auton kulma vaihtuu nykäyksellä eikä tasaisesti.
Tähän taas heitin sellaisen loogisen päätöksen että se johtuu tämän hetken kiintopiste systeemistä. Se saa uuden pisteen itselleen, mutta ei ymmärrä sitä, että sinne pitäisi kääntyä rauhallisesti eikä nykäyksellä

Korjaus ehdotus:
Pitäisikö siis tähän tehdä se hinaus auto juttu. Eli Auton edessä menisi piste mikä hakeutuisi kiintopisteisiin... Eikös sen pitäisi tasoittaa kääntyminen pois nykäyksistä? Mites nuo muut ongelmat sitten.

Koodi:

int kaantymis_pisteX = KuskinAlyX(Ajotaito, Hepat, Hermot, Kurvi);
int kaantymis_pisteY = KuskinAlyY(Ajotaito, Hepat, Hermot, Kurvi);
x_jana = (kuski_1_x - kaantymis_pisteX);
y_jana = (kuski_1_y - kaantymis_pisteY);
double kulma = std::atan2((double)y_jana, (double)x_jana);
etaisyys_ensimmainen_1 = kaantymis_pisteX - kuski_1_x;
etaisyys_ensimmainen = pow(etaisyys_ensimmainen_1, 2);
etaisyys_toinen_1 = kaantymis_pisteY - kuski_1_y;
etaisyys_toinen=pow(etaisyys_toinen_1, 2);
etaisyys = etaisyys_ensimmainen + etaisyys_toinen;
etaisyys_lopulta = sqrt(etaisyys);
kuvat::temp = rotozoomSurface(kuvat::auto_1, rad2deg(kulma), 1, 1);
piirra_kuva(kuvat::temp, kuski_1_x, kuski_1_y);
kuski_1_x-=std::cos(kulma) * nopeus;
kuski_1_y-=std::sin(kulma) * nopeus;

if (etaisyys_lopulta <= 1) {
    Kurvi+=1;
    int kaantymis_pisteX = KuskinAlyX(Ajotaito, Hepat, Hermot, Kurvi);
    int kaantymis_pisteY = KuskinAlyY(Ajotaito, Hepat, Hermot, Kurvi);
    x_jana = (kuski_1_x - kaantymis_pisteX);
    y_jana = (kuski_1_y - kaantymis_pisteY);
    double kulma = std::atan2((double)y_jana, (double)x_jana);

    etaisyys_ensimmainen_1 = kaantymis_pisteX - kuski_1_x;
    etaisyys_ensimmainen = pow(etaisyys_ensimmainen_1, 2);
    etaisyys_toinen_1 = kaantymis_pisteY - kuski_1_y;
    etaisyys_toinen=pow(etaisyys_toinen_1, 2);
    etaisyys = etaisyys_ensimmainen + etaisyys_toinen;
    etaisyys_2 = etaisyys;
    etaisyys_lopulta = sqrt(etaisyys_2);
    kuvat::temp = rotozoomSurface(kuvat::auto_1, rad2deg(kulma), 1, 1);
}

jalski [06.10.2010 02:59:18]

#

Tee tuo etäisyyden laskenta nyt kuitenkin ihan vaan sillä Pythagoraan lauseella ja muutenkin kannattaisi kyllä toimia saamiesi ohjeiden mukaan.

Kokeilepas tuota: http://www.zshare.net/download/811696250cca82d7/

Vasemmalla hiiren napilla voit lisätä suuntapisteitä ja oikea hiiren nappi pohjassa raketti liikkuu suuntapisteiden mukaan.

Tuolla on sen Hollywood-koodi: http://www.zshare.net/download/811698320a62ed1b/

Tutustu, siellä on käytetty ihan niitä samoja perusjuttuja, joiden käytössä on yritetty neuvoa.

Grez [06.10.2010 03:45:29]

#

mika132 kirjoitti:

Ehdein tekemään pisteen välimatka laskun erillaisella systeemillä kun Pythagooralla. ... kaava on:

... Pythagoras ...

LOL.

Tietty voisi auttaa jos edes tietäisi mistä puhutaan ja/tai mitä kaavaa itse asiassa käyttääkään...

Spongi [06.10.2010 09:04:35]

#

Haiskahtaa kyllä hitusen purkalta koko touhu. Itse suosittelisin että siirryt hieman pienempään projektiin ja opettelet vielä sitä C++:aa. Lukaisin pikasesti tämän ketjun läpi ja vaikuttaa että sinulla on vieläkin nuo otsikkotiedostot hukassa (.h, .hpp), niihin tulee vain esittelyt, älä vain satunnaisesti sisällytä niitä pitkin cpp-filujasi. Voisit vaikka aluksi tehdä joitakin pieniä testejä luokilla ja laittaa ne toimimaan muutamassa cpp-filussa, ja mieluusti ihan ajatuksen kanssa.

Tuosta viimeisimmästäkin koodistasi tulisi paljon selvempää jos tekisit esimerkiksi tuosta etäisyyden laskemisesta funktion, etkä vain vetelisi copypastella.

float distance(float x1, float y1, float x2, float y2)
{
 float xd = x2 - x1;
 float yd = y2 - y1;
 return sqrtf(xd*xd + yd*yd);
}

Torgo [06.10.2010 10:38:42]

#

mika132 kirjoitti:

Ehdein tekemään pisteen välimatka laskun erillaisella systeemillä kun Pythagooralla.

Kadun varmaan vielä että kysyin, mutta kysynpä kuitenkin. Mikähän se Pythagoraan kaava mielestäsi on, jos se ei ole tuo minkä annoit?

mika132 kirjoitti:

Korjaus ehdotus:
Pitäisikö siis tähän tehdä se hinaus auto juttu. Eli Auton edessä menisi piste mikä hakeutuisi kiintopisteisiin...

No juuri tätä sinulle on yritetty takoa, että älä missään nimessä tee mitään sellaista. Liikkuvan kiintopisteen vertaus hinausautoon oli tarkoitettu osoittamaan, miten typerä koko ajatus on.

mika132 kirjoitti:

Eikös sen pitäisi tasoittaa kääntyminen pois nykäyksistä?

Öö... ei. Jos et saa yhtä autoa ajamaan kiintopisteeseen, niin miten se onnistuisi paremmin että sinulla menee sinne jono autoja samalla viallisella koodilla? Eiköhän sen auton olisi parempi seurata tietä (eli tässä tapauksessa niitä kiintopisteitä), kuin jotain epämääräisesti heittelehtivää autoa siinä edessä. Vai miten itse ajaisit oikeassa liikenteessä? Seuraisitko mieluummin tietä, vai edessäsi heittelehtivää rattijuoppoa?

Metabolix [06.10.2010 12:09:48]

#

mika132 kirjoitti:

Nyt kuitenkin auto kulkee poikittain. Se menee melkein muuten oikein, mutta kulkee poikittain.

Voihan älynväläys sentään. Miksi muutit jana-muuttujien laskukaavaa? Nyt janasi osoittaa kiintopisteestä autoon eikä toisin päin. Tietenkin autokin liikkuu tällöin väärään suuntaan.

mika132 kirjoitti:

Sen sijaan Y akseli ei ole enää += vaan -= öö??

Älä muuta sitä! Vikoja ei korjata muuttamalla satunnaisesti muutamaa laskulauseketta.

Kulma 0 osoittaa x-akselin suuntaan ja kulma π/2 eli 90° osoittaa y-akselin suuntaan. Tämä on matematiikkaa, joten tämän kanssa ei kannata tapella. Tarkista, että auto liikkuu näiden sääntöjen mukaan (eli sekä x- että y-suunnassa on +=). Sitten tarkista, että muuttujat x_jana ja y_jana osoittavat nimenomaan autosta kohteeseen päin. Kummin päin vähennyslaskun tällöin pitäisi olla? (Vinkki: ajattele tilannetta, jossa auto on kohdassa (0, 0).)


Sivun alkuun

Vastaus

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

Tietoa sivustosta