Sisällysluettelo:

Arduinon ohjaama tasohyppelypeli ohjaussauvalla ja IR-vastaanottimella: 3 vaihetta (kuvilla)
Arduinon ohjaama tasohyppelypeli ohjaussauvalla ja IR-vastaanottimella: 3 vaihetta (kuvilla)

Video: Arduinon ohjaama tasohyppelypeli ohjaussauvalla ja IR-vastaanottimella: 3 vaihetta (kuvilla)

Video: Arduinon ohjaama tasohyppelypeli ohjaussauvalla ja IR-vastaanottimella: 3 vaihetta (kuvilla)
Video: Kokemuksia Ohjaamo Helsingistä 2024, Heinäkuu
Anonim
Arduinon ohjaama tasohyppelypeli ohjaussauvalla ja IR-vastaanottimella
Arduinon ohjaama tasohyppelypeli ohjaussauvalla ja IR-vastaanottimella

Tänään aiomme käyttää Arduinon mikro-ohjainta yksinkertaisen C#-pohjaisen tasohyppelypelin ohjaamiseen. Käytän Arduinoa ottaaksesi syötteen joystick -moduulista ja lähettääksesi sen C# -sovellukseen, joka kuuntelee ja purkaa syötteen sarjayhteyden kautta. Vaikka et tarvitse aiempaa kokemusta videopelien rakentamisesta projektin loppuunsaattamiseksi, saattaa kestää jonkin aikaa, jotta osa "pelisilmukassa" tapahtuvista asioista imeytyy, josta keskustelemme myöhemmin.

Tämän projektin loppuun saattamiseksi tarvitset:

  • Visual Studio -yhteisö
  • Arduino Uno (tai vastaava)
  • Joystick -ohjainmoduuli
  • Kärsivällisyyttä

Jos olet valmis aloittamaan, jatka!

Vaihe 1: Liitä ohjaussauva ja IR -LED

Liitä ohjaussauva ja IR -LED
Liitä ohjaussauva ja IR -LED
Liitä ohjaussauva ja IR -LED
Liitä ohjaussauva ja IR -LED

Tässä kytkentä on melko yksinkertainen. Olen sisällyttänyt kaaviot, jotka osoittavat vain ohjaussauvan kytkettynä sekä käyttämäni asennuksen, joka sisältää ohjaussauvan ja infrapuna -LEDin pelin ohjaamiseen kauko -ohjaimella, joka tulee monien Arduino -sarjojen mukana. Tämä on valinnaista, mutta tuntui hienolta ajatukselta pelata langattomasti.

Asennuksessa käytetyt nastat ovat:

  • A0 (analoginen) <- Vaaka- tai X-akseli
  • A1 (analoginen) <- Pysty- tai Y-akseli
  • Nasta 2 <- Joystick-kytkimen tulo
  • Nasta 2 <- Infrapuna-LED-tulo
  • VCC <- 5V
  • Maa
  • Maa #2

Vaihe 2: Luo uusi luonnos

Luo uusi luonnos
Luo uusi luonnos

Aloitamme luomalla Arduino -luonnostiedostomme. Tämä kyselee muutoksia ohjaussauvasta ja lähettää muutokset C# -ohjelmaan muutaman millisekunnin välein. Todellisessa videopelissä tarkistamme syöttösilmukan sarjaportin, mutta aloitin pelin kokeiluna, joten kehysnopeus perustuu itse asiassa sarjaportin tapahtumien määrään. Olin itse aloittanut projektin Arduinon sisarprojektissa Processing, mutta kävi ilmi, että se oli paljon, paljon hitaampi eikä pystynyt käsittelemään ruutujen määrää.

Luo siis ensin uusi luonnos Arduino -koodieditoriohjelmassa. Näytän koodini ja selitän sitten, mitä se tekee:

#sisältää "IRremote.h"

// IR -muuttujat int vastaanotin = 3; // IR -vastaanottimen signaalitappi IRrecv irrecv (vastaanotin); // luo ilmentymä "irrecv" decode_results tulokset; // luo ilmentymä "decode_results" // Joystick/game muuttujat int xPos = 507; int yPos = 507; tavu joyXPin = A0; tavu joyYPin = A1; tavu joySwitch = 2; haihtuva tavu clickCounter = -1; int minMoveHigh = 530; int minMoveLow = 490; int currentSpeed = 550; // Oletus = keskimääräinen nopeus int speedIncrement = 25; // Määrä nopeuden lisäämiseksi/vähentämiseksi, kun Y -tulo on allekirjoittamaton pitkävirtainen = 0; // Pitää nykyisen aikaleiman int wait = 40; // ms odottamaan viestien välillä [Huomautus: alempi odotus = nopeampi kehysnopeus] haihtuva bool -painikePainettu = epätosi; // Mittari, jos painiketta painetaan void setup () {Serial.begin (9600); pinMode (joySwitch, INPUT_PULLUP); attachInterrupt (0, hyppy, FALLING); virta = millis (); // Aseta kellonaika // Aseta infrapunavastaanotin: irrecv.enableIRIn (); // Käynnistä vastaanotin} // setup void loop () {int xMovement = analogRead (joyXPin); int yPos = analoginenLue (joyYPin); // Käsittele ohjaussauvan X liikettä ajoituksesta riippumatta: if (xMovement> minMoveHigh || xMovement current + wait) {currentSpeed = yPos> minMoveLow && yPos <minMoveHigh // Jos vain vähän liikutetaan…? currentSpeed //… palauta vain nykyinen nopeus: getSpeed (yPos); // Vaihda yPos vain, jos ohjaussauva liikkui merkittävästi // int distance =; Serial.print ((String) xPos + "," + (String) yPos + ',' + (String) currentSpeed + '\ n'); virta = millis (); }} // silmukka int getSpeed (int yPos) {// Negatiiviset arvot osoittavat, että ohjaussauvaa siirrettiin ylös, jos (yPos 1023? 1023: currentSpeed + speedIncrement;} else if (yPos> minMoveHigh) // Tulkittu "alas" {// Suojaa menossa alle 0 return currentSpeed - speedIncrement <0? 0: currentSpeed - speedIncrement;}} // getSpeed void jump () {buttonPressed = true; // Ilmoita, että painiketta painettiin.} // hyppy // Kun painiketta painetaan etä, käsittele oikea vastaus void translateIR (decode_results results) // ryhtyy toimiin vastaanotetun IR -koodin perusteella {switch (results.value) {case 0xFF18E7: //Serial.println("2 "); currentSpeed += speedIncrement * 2; break; case 0xFF10EF: //Serial.println("4 "); xPos = -900; break; case 0xFF38C7: //Serial.println("5"); jump (); break; case 0xFF5AA5: // Sarja. println ("6"); xPos = 900; break; case 0xFF4AB5: //Serial.println("8 "); currentSpeed -= speedIncrement * 2; break; oletus: //Serial.println (" muu painike "); break;} // Lopetuskytkin} // END translateIR

Yritin luoda koodin enimmäkseen itsestään selväksi, mutta on muutamia mainitsemisen arvoisia asioita. Yksi asia, jonka yritin ottaa huomioon, oli seuraavilla riveillä:

int minYMoveUp = 520;

int minYMoveDown = 500;

Kun ohjelma on käynnissä, ohjaussauvan analogitulolla on taipumus hypätä ympäri, yleensä noin 507. Tämän korjaamiseksi tulo ei muutu, ellei se ole suurempi kuin minYMoveUp tai pienempi kuin minYMoveDown.

pinMode (joySwitch, INPUT_PULLUP);

attachInterrupt (0, hyppy, FALLING);

AttachInterrupt () -menetelmän avulla voimme keskeyttää normaalin silmukan milloin tahansa, jotta voimme syöttää tietoja, kuten painikkeen painaminen ohjaussauvan painiketta napsautettaessa. Tässä olemme liittäneet keskeytyksen ennen sitä olevalle riville käyttämällä pinMode () -menetelmää. Tärkeä huomautus on, että keskeytyksen liittämiseksi Arduino Unoon sinun on käytettävä joko tappia 2 tai 3. Muut mallit käyttävät erilaisia keskeytystappeja, joten sinun on ehkä tarkistettava, mitä nastajasi mallisi käyttää Arduinon verkkosivustolla. Toinen parametri koskee takaisinsoittomenetelmää, jota kutsutaan tässä ISR: ksi tai "Keskeytä palvelurutiiniksi". Sen ei pitäisi ottaa mitään parametreja tai palauttaa mitään.

Serial.print (…)

Tämä on linja, joka lähettää tietomme C# -peliin. Tässä lähetämme peliin X-akselin lukeman, Y-akselin lukeman ja nopeusmuuttujan. Näitä lukemia voidaan laajentaa sisältämään muita syötteitä ja lukemia, jotta peli olisi mielenkiintoisempi, mutta tässä käytämme vain paria.

Jos olet valmis testaamaan koodisi, lataa se Arduinolle ja avaa sarjamonitori painamalla [Vaihto] + [Ctrl] + [M] ja tarkista, saatko tulosta. Jos vastaanotat tietoja Arduinolta, olemme valmiita siirtymään koodin C# -osaan…

Vaihe 3: Luo C# -projekti

Grafiikkamme näyttämiseksi aloitin aluksi prosessin käsittelyn, mutta myöhemmin päätin, että olisi liian hidasta näyttää kaikki näytettävät objektit. Joten päätin käyttää C#: ta, joka osoittautui paljon tasaisemmaksi ja reagoivammaksi käsitellessämme panostamme.

Projektin C# -osaa varten on parasta ladata.zip -tiedosto ja purkaa se omaan kansioonsa ja muokata sitä. Zip -tiedostossa on kaksi kansiota. Avaa projekti Visual Studiossa kirjoittamalla RunnerGame_CSharp -kansio Windowsin Resurssienhallinnassa. Kaksoisnapsauta tässä.sln (ratkaisu) -tiedostoa, ja VS lataa projektin.

Pelille olen luonut muutamia erilaisia luokkia. En mene jokaisen luokan kaikkiin yksityiskohtiin, mutta annan yleiskuvan siitä, mitä pääluokat ovat.

Laatikkoluokka

Luin laatikkoluokan, jonka avulla voit luoda yksinkertaisia suorakulmio-objekteja, jotka voidaan piirtää näytölle Windows-muodossa. Ajatuksena on luoda luokka, jota voidaan laajentaa käyttämällä muita luokkia, jotka saattavat haluta piirtää jonkinlaista grafiikkaa. "Virtuaalista" avainsanaa käytetään siten, että muut luokat voivat ohittaa ne (käyttämällä "ohittaa" -avainsanaa). Näin voimme saada saman käyttäytymisen Player -luokalle ja Platform -luokalle, kun sitä tarvitaan, ja myös muokata objekteja tarpeen mukaan.

Älä huolehdi liikaa kaikista kiinteistöistä ja soita puheluita. Kirjoitin tämän luokan, jotta voisin laajentaa sitä mihin tahansa peliin tai grafiikkaohjelmaan, jonka haluaisin tehdä tulevaisuudessa. Jos sinun tarvitsee vain piirtää suorakulmio lennossa, sinun ei tarvitse kirjoittaa tällaista suurta luokkaa. C# -dokumentaatiossa on hyviä esimerkkejä tästä.

Esitän kuitenkin joitain "Box" -luokan logiikkaa:

julkinen virtuaalinen bool IsCollidedX (Box otherObject) {…}

Täällä tarkistamme törmäykset X-suunnan esineisiin, koska pelaajan tarvitsee vain tarkistaa törmäykset Y-suuntaan (ylös ja alas), jos hän on rivissä sen kanssa näytöllä.

julkinen virtuaalinen bool IsCollidedY (Box otherObject) {…}

Kun olemme toisen peliobjektin päällä tai alla, tarkistamme Y -törmäykset.

julkinen virtuaalinen bool IsCollided (Box otherObject) {…}

Tämä yhdistää X- ja Y -törmäykset ja palauttaa sen, törmääkö jokin esine tähän.

julkinen virtuaalinen tyhjä OnPaint (grafiikkagrafiikka) {…}

Yllä olevan menetelmän avulla välitämme kaikki grafiikkaobjektit ja käytämme niitä ohjelman ollessa käynnissä. Luomme kaikki suorakulmiot, jotka on ehkä piirrettävä. Tätä voitaisiin kuitenkin käyttää erilaisiin animaatioihin. Meidän tarkoituksemme mukaan suorakulmiot toimivat hyvin sekä alustoille että soittimelle.

Hahmoluokka

Character -luokka laajentaa Box -luokkaani, joten meillä on tietty fysiikka laatikosta. Luin "CheckForCollisions" -menetelmän tarkistaakseni nopeasti kaikki luomamme alustat törmäyksen varalta. "Jump" -menetelmä asettaa pelaajan ylöspäin suuntautuvan nopeuden JumpSpeed-muuttujalle, jota sitten muokataan MainWindow-luokassa kuva kerrallaan.

Törmäyksiä käsitellään täällä hieman eri tavalla kuin Box -luokassa. Päätin tässä pelissä, että jos hyppäämme ylöspäin, voimme hypätä alustan läpi, mutta se tarttuu pelaajamme matkalla alas, jos törmää siihen.

Platform -luokka

Tässä pelissä käytän vain tämän luokan konstruktoria, joka ottaa syötteeksi X-koordinaatin ja laskee kaikki alustojen X sijainnit MainWindow-luokassa. Jokainen alusta on asetettu satunnaisella Y-koordinaatilla 1/2 ruudusta 3/4 ruudun korkeuteen. Korkeus, leveys ja väri luodaan myös satunnaisesti.

MainWindow -luokka

Tässä laitamme kaiken logiikan käytettäväksi pelin ollessa käynnissä. Ensin tulostamme konstruktorissa kaikki ohjelman käytettävissä olevat COM -portit.

foreach (merkkijonoportti SerialPort. GetPortNames ())

Console. WriteLine ("AVAILABLE PORTS:" + portti);

Valitsemme, kummasta hyväksymme viestinnän, sen mukaan, mitä Arduino -porttiasi käyttää:

SerialPort = uusi SerialPort (SerialPort. GetPortNames () [2], 9600, Parity. None, 8, StopBits. One);

Kiinnitä erityistä huomiota komentoon: SerialPort. GetPortNames () [2]. [2] osoittaa, mitä sarjaporttia käytetään. Jos esimerkiksi ohjelma tulostaa "COM1, COM2, COM3", kuuntelemme COM3: lla, koska numerointi alkaa taulukossa 0.

Myös konstruktorissa luomme kaikki alustat puolittain satunnaisilla etäisyyksillä ja sijoittamalla näytön Y-suuntaan. Kaikki alustat lisätään List-objektiin, joka C#: ssa on yksinkertaisesti erittäin käyttäjäystävällinen ja tehokas tapa hallita taulukkomaista tietorakennetta. Luomme sitten Playerin, joka on Character -objektimme, asetamme pisteet 0: ksi ja GameOverin arvoksi false.

yksityinen staattinen tyhjä DataReceived (objektin lähettäjä, SerialDataReceivedEventArgs e)

Tätä menetelmää kutsutaan, kun tietoja vastaanotetaan sarjaporttiin. Tässä käytämme kaikkea fysiikkaamme, päätämme näyttää pelin, siirtää alustoja jne. Jos olet koskaan rakentanut pelin, sinulla on yleensä ns. "Pelisilmukka", joka kutsutaan joka kerta kehyksen yhteydessä virkistää. Tässä pelissä DataReceived -menetelmä toimii pelisilmukana manipuloimalla vain fysiikkaa, kun dataa vastaanotetaan ohjaimelta. Olisi ehkä toiminut paremmin asettamalla ajastin pääikkunaan ja päivittämään objektit vastaanotettujen tietojen perusteella, mutta koska tämä on Arduino -projekti, halusin tehdä pelin, joka todella juoksi sen sisältämien tietojen perusteella.

Yhteenvetona voidaan todeta, että tämä asetus antaa hyvän perustan pelin laajentamiseen käyttökelpoiseksi. Vaikka fysiikka ei ole aivan täydellinen, se toimii riittävän hyvin tarkoituksiimme, eli käyttää Arduinoa johonkin, mistä kaikki pitävät: pelaamiseen!

Suositeltava: