Obsah:

Platformová hra ovládaná Arduinem s joystickem a IR přijímačem: 3 kroky (s obrázky)
Platformová hra ovládaná Arduinem s joystickem a IR přijímačem: 3 kroky (s obrázky)

Video: Platformová hra ovládaná Arduinem s joystickem a IR přijímačem: 3 kroky (s obrázky)

Video: Platformová hra ovládaná Arduinem s joystickem a IR přijímačem: 3 kroky (s obrázky)
Video: CS50 2013 - Week 9 2024, Červenec
Anonim
Platformová hra ovládaná Arduinem s joystickem a IR přijímačem
Platformová hra ovládaná Arduinem s joystickem a IR přijímačem

Dnes použijeme mikrokontrolér Arduino k ovládání jednoduché plošinovky založené na C#. Používám Arduino k přijímání vstupu z modulu joysticku a odesílání tohoto vstupu do aplikace C#, která poslouchá a dekóduje vstup přes sériové připojení. Přestože k dokončení projektu nepotřebujete žádné předchozí zkušenosti s vytvářením videoher, může nějakou dobu trvat, než absorbujete některé věci, které se odehrávají v „herní smyčce“, o které budeme diskutovat později.

K dokončení tohoto projektu budete potřebovat:

  • Komunita Visual Studio
  • Arduino Uno (nebo podobné)
  • Modul ovladače joysticku
  • Trpělivost

Pokud jste připraveni začít, pokračujte!

Krok 1: Připojte joystick a IR LED

Zapojte joystick a IR LED
Zapojte joystick a IR LED
Zapojte joystick a IR LED
Zapojte joystick a IR LED

Zde je zapojení poměrně jednoduché. Zahrnul jsem diagramy zobrazující pouze připojený joystick a také nastavení, které používám, včetně joysticku a infračervené diody LED pro ovládání hry pomocí dálkového ovladače, který je dodáván s mnoha sadami Arduino. Toto je volitelné, ale zdálo se, že je skvělé mít možnost bezdrátového hraní.

Kolíky použité v nastavení jsou:

  • A0 (analogový) <- Horizontální nebo osa X
  • A1 (analogový) <- Svislý nebo osa Y
  • Pin 2 <- Joystick Přepnout vstup
  • Pin 2 <- infračervený LED vstup
  • VCC <- 5V
  • Přízemní
  • Ground #2

Krok 2: Vytvořte novou skicu

Vytvořte novou skicu
Vytvořte novou skicu

Začneme vytvořením souboru skici Arduino. To vyvolá změny na joysticku a odešle tyto změny do programu C# každých několik milisekund. Ve skutečné videohře bychom zkontrolovali vstup sériového portu v herní smyčce, ale hru jsem zahájil jako experiment, takže snímková frekvence je ve skutečnosti založena na počtu událostí na sériovém portu. Ve skutečnosti jsem projekt zahájil v sesterském projektu Arduino, Zpracování, ale ukázalo se, že byl mnohem, mnohem pomalejší a nezvládl počet políček na obrazovce.

Nejprve tedy vytvořte nový Sketch v programu editoru kódu Arduino. Ukážu svůj kód a poté vysvětlím, co dělá:

#include "IRremote.h"

// IR proměnné int receiver = 3; // Signální pin IR přijímače IRrecv ircc (přijímač); // vytvořit instanci výsledků 'unbcv' decode_results; // vytvoření instance 'decode_results' // Joystick/herní proměnné int xPos = 507; int yPos = 507; byte joyXPin = A0; byte joyYPin = A1; byte joySwitch = 2; volatile byte clickCounter = -1; int minMoveHigh = 530; int minMoveLow = 490; int currentSpeed = 550; // Výchozí = průměrná rychlost int speedIncrement = 25; // Částka pro zvýšení/snížení rychlosti s Y vstupem bez znaménka dlouhý proud = 0; // Zachová aktuální časové razítko int wait = 40; // ms na čekání mezi zprávami [Poznámka: nižší čekání = rychlejší framerate] volatile bool buttonPressed = false; // Ukazatel, pokud je tlačítko stisknuto, neplatné setup () {Serial.begin (9600); pinMode (joySwitch, INPUT_PULLUP); attachInterrupt (0, jump, FALLING); aktuální = milis (); // Nastavit aktuální čas // Nastavit infračervený přijímač: unbcv.enableIRIn (); // Spusťte přijímač} // nastavení void loop () {int xMovement = analogRead (joyXPin); int yPos = analogRead (joyYPin); // Ovládejte pohyb joysticku X bez ohledu na načasování: if (xMovement> minMoveHigh || xMovement current + wait) {currentSpeed = yPos> minMoveLow && yPos <minMoveHigh // If only moving a little…? currentSpeed //… stačí vrátit aktuální rychlost: getSpeed (yPos); // Změňte yPos pouze v případě, že se joystick výrazně pohybuje // int vzdálenost =; Serial.print ((String) xPos + "," + (String) yPos + ',' + (String) currentSpeed + '\ n'); aktuální = milis (); }} // smyčka int getSpeed (int yPos) {// Záporné hodnoty označují, že joystick se posunul nahoru, pokud (yPos 1023? 1023: currentSpeed + speedIncrement;} else if (yPos> minMoveHigh) // Interpretováno „dolů“{// Ochrana před jít pod 0 zpětný proudSpeed - speedIncrement <0? 0: currentSpeed - speedIncrement;}} // getSpeed void jump () {buttonPressed = true; // Indikace tlačítka bylo stisknuto.} // skok // Když je stisknuto tlačítko na vzdáleně, zpracovat správnou odpověď void translateIR (decode_results results) // provede akci na základě přijatého IR kódu {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: // Serial. println ("6"); xPos = 900; break; case 0xFF4AB5: //Serial.println("8 "); currentSpeed -= speedIncrement * 2; break; default: //Serial.println (" jiné tlačítko "); break;} // Koncový přepínač} // END translateIR

Pokusil jsem se vytvořit kód tak, aby byl většinou samovysvětlující, ale stojí za zmínku několik věcí. Jedna věc, kterou jsem se snažil vysvětlit, byla v následujících řádcích:

int minYMoveUp = 520;

int minYMoveDown = 500;

Když je program spuštěn, analogový vstup z joysticku má tendenci přeskakovat, obvykle se pohybuje kolem 507. K opravě se vstup nemění, pokud není větší než minYMoveUp nebo menší než minYMoveDown.

pinMode (joySwitch, INPUT_PULLUP);

attachInterrupt (0, jump, FALLING);

Metoda attachInterrupt () nám umožňuje kdykoli přerušit normální smyčku, abychom mohli přijímat vstup, jako je stisknutí tlačítka při kliknutí na tlačítko joysticku. Zde jsme připojili přerušení v řádku před ním pomocí metody pinMode (). Důležitou poznámkou je, že pro připojení přerušení na Arduino Uno musíte použít buď pin 2 nebo 3. Jiné modely používají jiné piny přerušení, takže možná budete muset zkontrolovat, které piny váš model používá na webových stránkách Arduino. Druhý parametr je pro metodu zpětného volání, zde nazývanou ISR nebo „rutina přerušení služby“. Nemělo by mít žádné parametry ani nic vracet.

Serial.print (…)

Toto je řádek, který odešle naše data do hry C#. Zde odešleme do hry čtení osy X, čtení osy Y a proměnnou rychlosti. Tyto hodnoty lze rozšířit o další vstupy a hodnoty, aby byla hra zajímavější, ale zde použijeme pouze pár.

Pokud jste připraveni otestovat svůj kód, nahrajte jej do Arduina a stisknutím [Shift] + [Ctrl] + [M] otevřete sériový monitor a zjistěte, zda získáváte nějaký výstup. Pokud přijímáte data z Arduina, jsme připraveni přejít k části C# kódu…

Krok 3: Vytvořte projekt C#

Abychom mohli zobrazit naši grafiku, původně jsem zahájil projekt ve Zpracování, ale později jsem se rozhodl, že bude příliš pomalé zobrazovat všechny objekty, které potřebujeme zobrazit. Takže jsem se rozhodl použít C#, který se ukázal být mnohem plynulejší a citlivější při zpracování našeho vstupu.

Pro část projektu C# je nejlepší jednoduše stáhnout soubor.zip, rozbalit jej do vlastní složky a poté upravit. V souboru zip jsou dvě složky. Chcete -li projekt otevřít v sadě Visual Studio, zadejte do Průzkumníka Windows složku RunnerGame_CSharp. Zde poklepejte na soubor.sln (řešení) a VS načte projekt.

Pro hru jsem vytvořil několik různých tříd. Nebudu zacházet do všech podrobností o každé třídě, ale uvedu přehled toho, k čemu slouží hlavní třídy.

Třída Box

Vytvořil jsem třídu box, která vám umožní vytvářet jednoduché obdélníkové objekty, které lze kreslit na obrazovce ve formě oken. Cílem je vytvořit třídu, kterou lze rozšířit o další třídy, které mohou chtít nakreslit nějaký druh grafiky. Klíčové slovo „virtuální“se používá tak, že je mohou přepsat jiné třídy (pomocí klíčového slova „přepsat“). Tímto způsobem můžeme získat stejné chování pro třídu Player a třídu Platform, když potřebujeme, a také upravit objekty, jakkoli potřebujeme.

Nedělejte si příliš starosti se všemi vlastnostmi a čerpejte hovory. Napsal jsem tuto třídu, abych ji mohl rozšířit o jakoukoli hru nebo grafický program, který bych chtěl v budoucnu vyrábět. Pokud potřebujete jednoduše nakreslit obdélník za běhu, nemusíte takto vypisovat velkou třídu. Dokumentace C# obsahuje dobré příklady, jak to provést.

Ukážu však část logiky své třídy „Box“:

veřejný virtuální bool IsCollidedX (Box otherObject) {…}

Zde kontrolujeme kolize s objekty ve směru X, protože hráč potřebuje kontrolovat kolize pouze ve směru Y (nahoru a dolů), pokud je s ním seřazen na obrazovce.

public virtual bool IsCollidedY (Box otherObject) {…}

Když jsme nad nebo pod jiným herním objektem, kontrolujeme, zda nedošlo ke kolizi Y.

public virtual bool IsCollided (Box otherObject) {…}

To kombinuje kolize X a Y a vrací, zda je s tímto objektem kolidován jakýkoli objekt.

public virtual void OnPaint (grafická grafika) {…}

Pomocí výše uvedené metody předáme jakýkoli grafický objekt a použijeme jej, když program běží. Vytvoříme všechny obdélníky, které bude třeba nakreslit. Dalo by se to však použít pro různé animace. Pro naše účely se obdélníky budou hodit jak pro platformy, tak pro hráče.

Třída postav

Třída Character rozšiřuje moji třídu Box, takže máme jistou fyziku z krabice. Vytvořil jsem metodu "CheckForCollisions" pro rychlou kontrolu všech platforem, které jsme vytvořili, kvůli kolizi. Metoda „Jump“nastaví rychlost hráče směrem nahoru na proměnnou JumpSpeed, která se poté ve třídě MainWindow upravuje snímek po snímku.

Kolize jsou zde řešeny mírně odlišně než ve třídě Box. V této hře jsem se rozhodl, že když vyskočíme nahoru, můžeme skočit přes plošinu, ale pokud se s ní srazí, zachytí našeho hráče na cestě dolů.

Platformová třída

V této hře používám pouze konstruktor této třídy, který jako vstup bere souřadnici X a vypočítává všechna umístění X platforem ve třídě MainWindow. Každá platforma je nastavena na náhodných souřadnicích Y od 1/2 obrazovky do 3/4 výšky obrazovky. Výška, šířka a barva jsou také generovány náhodně.

Třída MainWindow

Zde jsme vložili veškerou logiku, která se má použít, když je hra spuštěna. Nejprve v konstruktoru vytiskneme všechny COM porty dostupné programu.

foreach (řetězcový port v SerialPort. GetPortNames ())

Console. WriteLine ("DOSTUPNÉ PORTY:" + port);

Vybereme si, na kterém budeme přijímat komunikaci, podle toho, jaký port vaše Arduino již používá:

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

Věnujte velkou pozornost příkazu: SerialPort. GetPortNames () [2]. [2] označuje, který sériový port použít. Pokud by například program vytiskl „COM1, COM2, COM3“, poslouchali bychom na COM3, protože číslování začíná na 0 v poli.

Také v konstruktoru vytvoříme všechny platformy s semi-random mezerami a umístěním ve směru Y na obrazovce. Všechny platformy jsou přidány do objektu List, což je v C# jednoduše uživatelsky přívětivý a efektivní způsob správy datové struktury podobné poli. Poté vytvoříme Player, což je náš objekt Character, nastavíme skóre na 0 a nastavíme GameOver na false.

private static void DataReceived (odesílatel objektů, SerialDataReceivedEventArgs e)

Toto je metoda, která se nazývá při příjmu dat na sériový port. Zde uplatníme veškerou naši fyziku, rozhodneme se, zda hru zobrazit, přesunout platformy atd. Pokud jste někdy hru vytvořili, obvykle máte něco, co se nazývá „herní smyčka“, která se nazývá pokaždé v rámci osvěží. V této hře metoda DataReceived funguje jako herní smyčka, pouze manipuluje s fyzikou, když jsou data přijímána z ovladače. Možná by lépe fungovalo nastavení časovače v hlavním okně a obnovení objektů na základě přijatých dat, ale jelikož se jedná o projekt Arduino, chtěl jsem vytvořit hru, která by ve skutečnosti běžela na základě dat, která z něj přicházejí.

Na závěr toto nastavení dává dobrý základ pro rozšíření hry na něco použitelného. Ačkoli fyzika není úplně dokonalá, funguje dostatečně dobře pro naše účely, což je využití Arduina pro něco, co má každý rád: hraní her!

Doporučuje: