Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Törmäys pyörivään kohteeseen

Sivun loppuun

mika132 [25.01.2011 23:24:26]

#

Eli olen tässä väsännyt laskenut miettinyt ja piirrellyt törmäystä kahdella kappaleella (eli autoilla). Autothan eivät törmää tietyssä kulmassa aina joten pitää laskea kuvan koko ja kulma. Tein tälläisen toteutuksen:

if (kisaa->x - std::sin(auton_kulma_oma) * 60 >= x_oma + std::sin(auton_kulma_oma) * 20 && kisaa->x + std::sin(auton_kulma_oma) * 20 <= x_oma - std::sin(auton_kulma_oma) * 60) {
    if (kisaa->y + std::cos(auton_kulma_oma) * 80 >= y_oma - std::cos(auton_kulma_oma) * 20 && kisaa->y - std::cos(auton_kulma_oma) * 20 <= y_oma + std::cos(auton_kulma_oma) * 80) {
        kisaa->tormaa_autoon=true;
        tormaa_autoon=true;
    }
}

autot kyllä törmäävät mutta erittäin paljon liian kaukaa ja tietyissä kulmissa ei ollenkaan.

Lisäksi koodi on sekava eikä mitään logiikkaa ja tiedän, että helpompikin tapa tuo olisi tehdä, että olisiko vinkkejä?

Metabolix [25.01.2011 23:55:27]

#

Mitä ihmettä nuo maagiset luvut (20, 60, 80) tuolla tekevät?

Kun koko asia on sinulle noin vaikea, laske törmäys vain ympyröille Pythagoraan lauseella.

if (std::hypot(x2 - x1, y2 - y1) < haluamasi_tormaysetaisyys) {
  tormaa = true;
}

Tämä riittää peliisi ihan hyvin. Turha sinun on mitään hienompaa yrittää, ennen kuin koko peli on muilta osin toimiva kokonaisuus. Ja kun alat yrittää, älä sähellä vaan opettele kunnolla matematiikkaa. Opettele, kunnes oikeasti osaat, ja tee vasta sitten.

mika132 [26.01.2011 14:33:34]

#

hmm.. olen nyt sitten pistänyt miettien, että saako tuota samaa koodia sovellettua seiniin? Minulla on seinät tallennettu vectoreihin joista katson tällä hetkellä erittäin monimutkaisesti törmääkö ja yleinen ongelma törmätessä on, että auto jää seinään sisälle ja sen jälkeen auto liikkuu seinän ohjauskomennoilla eli "väärinpäin"

//tässä tuo törmäystarkistus
                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;
                        seinan_tyyppi=seinaa->tyyppi;
                    }
                }
//Tässä törmäystarkistyksen poisto
                if (x_oma >= seinaa->seinan_x+seinaa->poisx && x_oma <= seinaa->seinan_x + seinaa->seinan_leveys+50) {
                    if (y_oma >= seinaa->seinan_y+seinaa->poisy && y_oma <= seinaa->seinan_y + seinaa->seinan_korkeus+50) {
                        tormaa=false;
                    }
                }

sitten tämä törmäys hetken ohjaus joka ei tosiaan ole hyvä vaan melkoinen purkka ja sekasorto.

if (!tormaa and !tormaa_autoon) {
    x_oma+=std::cos(kulma_oma) * nopeus_oma;
    y_oma+=std::sin(kulma_oma) * nopeus_oma;
}
else if (tormaa_autoon) {
    x_oma-=std::cos(kulma_oma) * 4;
    y_oma-=std::sin(kulma_oma) * 4;
    tormaa_autoon=false;
} else {
    if (seinan_tyyppi==1) {
        x_oma-=std::cos(kulma_oma) * 4;
        y_oma-=std::sin(kulma_oma) * 4;
        if (!auton_kulma_oma <= kulma_oma) {
            auton_kulma_oma += 0.04;
        }
    }
}

User137 [26.01.2011 14:39:34]

#

Yksinkertainen tapa siirtää auto törmäyksen sattuessa on joka kierroksen lopussa tallentaa auton sijainti vara-muuttujaan. Jos törmäys tapahtuu niin yksinkertaisesti siirtää auton siihen paikkaan jossa se oli edellisellä kierroksella, eli kopioi auton sijainti = vanha_sijainti.

Se mikä törmäyksessä muuttuu on liikevektori joka pitää peilata vastakkaiseen suuntaan kohteen tangentin suhteen.

mika132 [26.01.2011 15:25:30]

#

Onkos heijastus vectoriin C++ jotai yksinkertaistettua funktiota? Luin ohjelmointiputkan matikka oppaasta tuosta aiheesta ja tuntuu melko ongelmalliselta laittaa ne vain perätysten (tai pikemminkin pitkältä) joten uskoisin, että tuohon on jokin oma funktiokin?

Metabolix [26.01.2011 16:26:47]

#

Ei, C++ ei sisällä juurikaan yksittäisiä laskutoimituksia edistyneempää matematiikkaa. Jos haluat valmista matematiikkaa, opettele käyttämään jotain kirjastoa tai vaihda C++ johonkin pelinteko-ohjelmaan.

Kuitenkin jos olet sitä mieltä, että pystyt toteuttamaan C++:lla pelin, sinun pitäisi ehdottomasti pystyä tekemään myös oma funktio, joka laskee tuollaisen triviaalin laskutoimituksen. Kannattaa tehdä 2d-vektorista luokka ja siihen peruslaskutoimituksille operaattorit, niin laskut helpottuvat huomattavasti.

mika132 [26.01.2011 17:03:00]

#

No yritinpä lähteä tekemään tuolle kaavalle mikä tuolla on funktiota, mutta löinkin pääni seinään heti.

Koodi todella löytää seinän, mutta vauhti jää 0. Eli ei ihan oikein toimi.

double Tracks::LaskeKimpoaminenSeinasta(float vauhti, double auton_kulma, float seinan_kimmoke_voima) {
    double neliojuuren_tulos = sqrt(13);
    double N = 1 / neliojuuren_tulos * (2-3);
    float v2 = vauhti - 2 * (vauhti * N) * N;
    return v2;
}

seinan_kimmoke_voima muuttuja on eräällä tavalla ylimääräinen, koska tarkoitus olisi vielä sukelluttaa myöhemmin tuohon kaiteiden ja heikkavallien erot.

sitten en ole ihan varma mistä nuo kirjaimet tuonne kaavaan tulee oppaassa:
v · N = (3i - j) · 1/√13 (2i - 3j) = 1/√13 * (3*2 - 1*(-3)) = 9/√13 ≈ 2,5

esim (3i - j)

ja sen tiedän, että kaavani on aivan väärin, mutta olisiko jotain pientä vinkkiä oikeeseen suuntaan laittamisesta?

eq [26.01.2011 17:19:49]

#

Onko tämä nyt joku vitsi?

mika132 kirjoitti:

ja sen tiedän, että kaavani on aivan väärin, mutta olisiko jotain pientä vinkkiä oikeeseen suuntaan laittamisesta?

Yksi vaihtoehto olisi odotella, että sitten joskus kun yläasteelle menet, ja siellä puhutaan kulmista ja mahdollisesti vektoreistakin, niin kuuntelet. Sitten sovellat oppimaasi ohjelmoinnissa.

Jos sen sijaan ajattelit käydä läpi kaikki mahdolliset koodinpätkät, joista joku oikean vastauksen tuottaisi .. no, monta koodinpätkää on vielä jäljellä. Itse funktiossasi ei ole päätä eikä häntää; tiedätköhän itsekään mitä edes yrität funktiossa laskea? Uutta vauhtiako?

mika132 [26.01.2011 17:42:26]

#

peilikuva vauhtia. Eli päinvastaiseen suuntaan seinästä. Eli kimmoketta.

No joo tosiaan tuota olen ylä-asteen käynyt ja ikääkin 18, mutta ylä-asteeni matikan tunnit olivat enimmäkseen nukkumista kuten monetmuutkin.

Silti matematiikka on ollut vahvin alani koskaan, vaikkakin välillä on päiviä, kun ei tahdo ymmärtää siitä mitään.

Lahha [26.01.2011 18:10:56]

#

R = V - 2 * (V · N) * N

V on auton vanha nopeusvektori, N on osumapinnan normaalivektori(pitää olla yksikkövektori eli siis pituudeltaan 1) ja R on auton uusi nopeusvektori.

Metabolix [26.01.2011 18:20:21]

#

mika132 kirjoitti:

No joo tosiaan tuota olen ylä-asteen käynyt ja ikääkin 18... Matematiikka on ollut vahvin alani koskaan...

Hassua, juttujesi perusteella olen aina luuullut, että olisit ala-asteella tai enintään yläasteen alkupuolella. Pelottaa edes kuvitella, miten ne muut alat sitten sujuvat, jos matematiikka on noin pahasti hukassa.

Siis tajuatko, että siinä oppaassa on yksi esimerkkitapaus ja että tuo kopioimasi rimpsu on kyseisen esimerkin ratkaisu? Yrität laskea laskua a+b, kopioit oppaasta lausekkeen 1+1, kirjoitat sitten vielä senkin ohjelmaasi väärin ja lopuksi ihmettelet, miksi tulee väärä tulos. Järkevää toimintaa ei myöskään ole se, että poistat lausekkeesta ne osat, joita et ymmärrä. Esimerkiksi ihmettelemäsi kirjaimet selitetään jo oppaan alkupuolella, ja kun kerran on vektorioppaasta kyse ja vektori-sana vilisee selostuksessakin joka välissä, luulisi tyhmemmänkin tajuavan, että kyse on vektoreista ja niiden laskutoimituksista (kuten vektorien pistetulosta) eikä yksittäisistä float- tai double-luvuista.

Hanki jostakin vaikka lukion pitkän matematiikan ensimmäisten kurssien kirjoja. Lue niistä asiat ja tee tehtäviä. Viides kurssi käsittelee vektoreita, mutta luonnollisesti edellisten kurssien asiat ovat myös tarpeen, joten älä hyppää mitään yli.

On aika turhaa kysellä keskustelussa matematiikan perusasioista. Koulussa ne opetetaan ja koulussa muutkin ovat niitä oppineet. Jos koulu ei kiinnosta etkä pysty lukemaan kirjoja omin avuin, palkkaa jostain yksityisopettaja. Silloinkin muista, että ei se opettaja voi opettaa, jos oppilas ei opi eikä edes yritä tosissaan opetella.

mika132 kirjoitti:

double Tracks::LaskeKimpoaminenSeinasta(float vauhti, double auton_kulma, float seinan_kimmoke_voima)

Miten ihmeessä tämä funktio voisi laskea mitään hyödyllistä? Jos kerron sinulle, että auto kulkee nopeudella 60 km/h viistosti itäkoilliseen ja törmää kumiseinään, osaatko näiden tietojen perusteella sanoa edes suunnilleen, mihin päin auto kimpoaa? Keksitkö itse, mikä tärkeä tieto tästä siis puuttuu?

User137 [27.01.2011 12:45:59]

#

Vaaka-pystysuorien seinien kanssa ei myöskään sitten edes tarvita suurempia kaavoja. Jos auto tulee nopeudella (-1, 0.5) loivasti ylös vasempaan päin ja törmää pystysuuntaiseen seinään niin peilattu nopeus on (1, 0.5). Eli nopeusX = -nopeusX. Vastaavasti vaakasuuntaisella seinällä käännetään vain nopeusY toisinpäin.

Eri asia on sitten ottaa huomioon törmäyksessä häviävä liikevoima. Sen voi vaikka tehdä tuon laskun jälkeen jotenkin

nopeusX = nopeusX*0.2;
nopeusY = nopeusY*0.2;

Muttei tuo ole realistinen joka tilanteessa. Siihen voi tarvita siniä ja kosinia, ja tarkemmin ajateltuna sinulla pitäisi olla melko hyvin sisäistettynä lukion pitkä fysiikka.

Mutta tarvitset Lahhan mainitsemaa kaavaa jos teet törmäyksiä autojen kesken.

XYZ [28.01.2011 21:03:30]

#

http://www.box2d.org/
http://www.miata.net/sport/Physics/
http://physics.hardwire.cz/index.php?action=show­&parent_id=42&sortby=order
http://web.archive.org/web/20050901072440/http://home.planet.nl/~monstrous/tutcar.html
http://www.codeproject.com/KB/GDI-plus/PolygonCollision.aspx
http://www.metanetsoftware.com/technique/tutorialA.html
http://www.rodedev.com/tutorials/gamephysics/
http://code.google.com/p/chipmunk-physics/


Sivun alkuun

Vastaus

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

Tietoa sivustosta