INHOUDSOPGAWE:

Arduino-beheerde platformspeletjie met joystick en IR-ontvanger: 3 stappe (met foto's)
Arduino-beheerde platformspeletjie met joystick en IR-ontvanger: 3 stappe (met foto's)

Video: Arduino-beheerde platformspeletjie met joystick en IR-ontvanger: 3 stappe (met foto's)

Video: Arduino-beheerde platformspeletjie met joystick en IR-ontvanger: 3 stappe (met foto's)
Video: Leap Motion SDK 2024, Julie
Anonim
Arduino-beheerde platformspeletjie met joystick en IR-ontvanger
Arduino-beheerde platformspeletjie met joystick en IR-ontvanger

Vandag gaan ons 'n Arduino-mikrokontroleerder gebruik om 'n eenvoudige C#-gebaseerde platformspeletjie te beheer. Ek gebruik die Arduino om insette uit 'n joystick -module te neem, en stuur die invoer na die C# -toepassing wat insette oor 'n seriële verbinding luister en dekodeer. Alhoewel u geen vorige ondervinding in die bou van videospeletjies nodig het om die projek te voltooi nie, kan dit 'n rukkie neem om 'n paar dinge wat in die 'speletjielus' aangaan, op te neem, wat ons later sal bespreek.

Om hierdie projek te voltooi, benodig u:

  • Visual Studio -gemeenskap
  • 'N Arduino Uno (of soortgelyk)
  • 'N Joystick -beheermodule
  • Geduld

As u gereed is om te begin, gaan voort!

Stap 1: Sluit die joystick en IR -LED aan

Sluit die joystick en die IR -LED aan
Sluit die joystick en die IR -LED aan
Sluit die joystick en IR -LED aan
Sluit die joystick en IR -LED aan

Hier is die aansluiting redelik eenvoudig. Ek het diagramme ingesluit wat slegs die aansluiting van die joystick bevat, asook die opstelling wat ek gebruik, wat die joystick plus 'n infrarooi LED insluit om die spel te beheer met 'n afstandsbediening, wat saam met baie Arduino -kits kom. Dit is opsioneel, maar dit was 'n goeie idee om draadloos te speel.

Die penne wat in die opstelling gebruik word, is:

  • A0 (analoog) <- Horisontaal of X-as
  • A1 (analoog) <- Vertikaal of Y-as
  • Speld 2 <- Invoer van joystick-skakelaar
  • Speld 2 <- Infrarooi LED-invoer
  • VCC <- 5V
  • Grond
  • Grond #2

Stap 2: Skep 'n nuwe skets

Skep 'n nuwe skets
Skep 'n nuwe skets

Ons begin met die skep van ons Arduino -sketslêer. Dit ondersoek die joystick vir veranderinge en stuur die veranderinge elke paar millisekondes na die C# -program. In 'n werklike videospeletjie sou ons die seriële poort in 'n speletjielus kontroleer vir invoer, maar ek het die speletjie as 'n eksperiment begin, dus die framerate is eintlik gebaseer op die aantal gebeurtenisse op die seriële poort. Ek het eintlik met die projek begin in die Arduino -susterprojek, Processing, maar dit blyk dat dit baie, baie stadiger was en die aantal bokse op die skerm nie kon hanteer nie.

Maak dus eers 'n nuwe skets in die Arduino -kode -redakteurprogram. Ek sal my kode wys en dan verduidelik wat dit doen:

#sluit "IRremote.h" in

// IR veranderlikes int ontvanger = 3; // Signaalpen van IR -ontvanger IRrecv irrecv (ontvanger); // skep 'n voorbeeld van 'irrecv' decode_results -resultate; // skep 'n voorbeeld van 'decode_results' // Joystick/game variables int xPos = 507; int yPos = 507; byte joyXPin = A0; byte joyYPin = A1; byte joySwitch = 2; vlugtige byte clickCounter = -1; int minMoveHigh = 530; int minMoveLow = 490; int currentSpeed = 550; // Standaard = 'n gemiddelde spoed int speedIncrement = 25; // Bedrag om spoed te verhoog/verlaag met Y -insette ongetekende langstroom = 0; // Hou huidige tydstempel int wag = 40; // ms om tussen boodskappe te wag [Let wel: laer wag = vinniger framerate] vlugtige bool buttonPressed = false; // Gauge as die knoppie ingedruk word leegstelling () {Serial.begin (9600); pinMode (joySwitch, INPUT_PULLUP); attachInterrupt (0, spring, VAL); stroom = millis (); // Stel die huidige tyd in // Stel infrarooi ontvanger op: irrecv.enableIRIn (); // Begin die ontvanger} // setup void loop () {int xMovement = analogRead (joyXPin); int yPos = analogRead (joyYPin); // Behandel die joystick X -beweging, ongeag die tydsberekening: as (xMovement> minMoveHigh || xMovement current + wait) {currentSpeed = yPos> minMoveLow && yPos <minMoveHigh // As net 'n bietjie beweeg …? currentSpeed // … gee net die huidige snelheid terug: getSpeed (yPos); // Verander slegs yPos as die joystick aansienlik beweeg het // int distance =; Serial.print ((String) xPos + "," + (String) yPos + ',' + (String) currentSpeed + '\ n'); stroom = millis (); }} // loop int getSpeed (int yPos) {// Negatiewe waardes dui aan dat die joystick omhoog beweeg as (yPos 1023? 1023: currentSpeed + speedIncrement;} anders as (yPos> minMoveHigh) // Interpreteer "af" {// Beskerm teen onder 0 terugkeer currentSpeed - speedIncrement <0? 0: currentSpeed - speedIncrement;}}} // getSpeed leemte spring () {buttonPressed = true; // Dui aan dat knoppie ingedruk is.} // spring // As 'n knoppie op die afgeleë, hanteer die korrekte reaksie leegte translateIR (resultate van dekode_resultate) // neem aksie gebaseer op ontvangde IR -kode {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 (" ander knoppie "); breek;} // Eindskakelaar} // EINDE translateIR

Ek het probeer om die kode meestal selfverduidelikend te maak, maar daar is 'n paar dinge wat die moeite werd is om te noem. Een ding waaroor ek probeer rekenskap gee, was in die volgende reëls:

int minYMoveUp = 520;

int minYMoveDown = 500;

As die program aan die gang is, is die analoog insette van die joystick geneig om rond te spring, gewoonlik ongeveer 507. Om dit reg te stel, verander die invoer nie tensy dit groter is as minYMoveUp, of kleiner as minYMoveDown.

pinMode (joySwitch, INPUT_PULLUP);

attachInterrupt (0, spring, VAL);

Met die attachInterrupt () -metode kan ons die normale lus te eniger tyd onderbreek, sodat ons insette kan neem, soos die druk op die knoppie as u op die joystick -knoppie klik. Hier het ons die onderbreking in die lyn voor dit vasgemaak met die pinMode () -metode. 'N Belangrike opmerking hier is dat u 'n onderbreking op die Arduino Uno moet heg, óf pen 2 óf 3. Ander modelle gebruik verskillende onderbrekingspenne, sodat u moontlik moet kyk watter penne u model op die Arduino -webwerf gebruik. Die tweede parameter is vir die terugbelmetode, hier 'n ISR of 'n 'Onderbrekingsroetine' genoem. Dit behoort geen parameters te neem of iets terug te gee nie.

Serial.print (…)

Dit is die lyn wat ons data na die C# spel stuur. Hier stuur ons die X-as-lesing, die Y-as-lesing en 'n snelheidsveranderlike na die spel. Hierdie lesings kan uitgebrei word met ander insette en lesings om die spel interessanter te maak, maar hier gebruik ons slegs 'n paar.

As u gereed is om u kode te toets, laai dit dan op na die Arduino en druk op [Shift] + [Ctrl] + [M] om die seriële monitor oop te maak om te sien of u uitvoer kry. As u data van die Arduino ontvang, is ons gereed om na die C# -gedeelte van die kode te gaan …

Stap 3: Skep die C# -projek

Om ons grafika te vertoon, het ek aanvanklik 'n projek in Verwerking begin, maar later besluit dat dit te stadig sal wees om al die voorwerpe wat ons moet vertoon, te wys. Daarom het ek gekies om C#te gebruik, wat baie gladder en meer reageerbaar was toe ons ons insette hanteer.

Vir die C# -gedeelte van die projek is dit die beste om die.zip -lêer eenvoudig af te laai en dit na sy eie gids te onttrek en dit dan te verander. Daar is twee vouers in die zip -lêer. Om die projek in Visual Studio oop te maak, voer die gids RunnerGame_CSharp in Windows Explorer in. Dubbelklik hier op die.sln (oplossing) lêer, en VS laai die projek.

Daar is 'n paar verskillende klasse wat ek vir die spel geskep het. Ek gaan nie in op die besonderhede van elke klas nie, maar ek gee 'n oorsig van wat die hoofklasse is.

Die boksklas

Ek het die boksklas geskep sodat u eenvoudige reghoekige voorwerpe kan skep wat op die skerm in 'n venstersvorm geteken kan word. Die idee is om 'n klas te skep wat uitgebrei kan word met ander klasse wat 'n soort grafika wil teken. Die "virtuele" sleutelwoord word gebruik sodat ander klasse dit kan oorheers (met behulp van die "oorheers" sleutelwoord). Op hierdie manier kan ons dieselfde gedrag vir die Player -klas en die Platform -klas kry as ons dit nodig het, en kan ons ook die voorwerpe verander soos ons moet.

Moenie te veel bekommerd wees oor al die eiendomme nie en maak oproepe. Ek het hierdie klas geskryf sodat ek dit kon uitbrei vir enige speletjie of grafiese program wat ek in die toekoms sou wou maak. As u eenvoudig 'n reghoek moet teken, hoef u nie 'n groot klas soos hierdie uit te skryf nie. Die C# -dokumentasie het goeie voorbeelde van hoe u dit moet doen.

Ek sal egter 'n paar van die logika van my "Box" -klas uiteensit:

openbare virtuele bool IsCollidedX (Box otherObject) {…}

Hier kyk ons na botsings met voorwerpe in die X-rigting, want die speler hoef net te kyk of daar in die Y-rigting bots (op en af) as hy daarmee op die skerm staan.

openbare virtuele bool IsCollidedY (Box otherObject) {…}

As ons oor of onder 'n ander spelvoorwerp is, kyk ons na Y -botsings.

openbare virtuele bool IsCollided (Box otherObject) {…}

Dit kombineer X- en Y -botsings, om terug te keer of 'n voorwerp hiermee bots.

openbare virtuele leemte OnPaint (grafiese grafika) {…}

Deur die bogenoemde metode te gebruik, gee ons enige grafiese voorwerp deur en gebruik dit terwyl die program aan die gang is. Ons maak enige reghoeke wat moontlik geteken moet word. Dit kan egter vir 'n verskeidenheid animasies gebruik word. Vir ons doeleindes sal reghoeke goed wees vir beide die platforms en die speler.

Die karakterklas

Die karakterklas brei my Box -klas uit, so ons het sekere fisika uit die boks. Ek het die 'CheckForCollisions' -metode geskep om vinnig al die platforms wat ons geskep het, te kontroleer vir 'n botsing. Die "Jump" -metode stel die speler se opwaartse snelheid in op die JumpSpeed-veranderlike, wat dan raam-vir-raam in die MainWindow-klas gewysig word.

Botsings word hier effens anders hanteer as in die Box -klas. Ek het in hierdie wedstryd besluit dat as ons opwaarts spring, ons deur 'n platform kan spring, maar dit sal ons speler onderweg vang as ons daarmee bots.

Die platformklas

In hierdie speletjie gebruik ek slegs die konstruktor van hierdie klas, wat 'n X-koördinaat as invoer neem, wat al die X-liggings van die platforms in die MainWindow-klas bereken. Elke platform is ingestel op 'n ewekansige Y-koördinaat van 1/2 van die skerm tot 3/4 van die skerm se hoogte. Die hoogte, breedte en kleur word ook lukraak gegenereer.

Die MainWindow -klas

Dit is waar ons al die logika gebruik wat gebruik moet word terwyl die spel aan die gang is. Eerstens druk ons in die konstruktor al die COM -poorte wat vir die program beskikbaar is.

foreach (string poort in SerialPort. GetPortNames ())

Console. WriteLine ("BESKIKBAAR PORTE:" + poort);

Ons kies watter kommunikasie ons sal aanvaar, volgens die poort wat u Arduino reeds gebruik:

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

Gee aandag aan die opdrag: SerialPort. GetPortNames () [2]. Die [2] dui aan watter seriële poort u moet gebruik. As die program byvoorbeeld 'COM1, COM2, COM3' uitdruk, luister ons na COM3 omdat die nommering by 0 in die skikking begin.

Ook in die konstruktor skep ons al die platforms met semi-ewekansige afstand en plasing in die Y-rigting op die skerm. Al die platforms word by 'n lys-voorwerp gevoeg, wat in C# eenvoudig 'n baie gebruikersvriendelike en doeltreffende manier is om 'n skikkingagtige datastruktuur te bestuur. Ons skep dan die speler, wat ons karaktervoorwerp is, stel die telling op 0 en stel GameOver op onwaar.

private statiese leegte DataReceived (voorwerp sender, SerialDataReceivedEventArgs e)

Dit is die metode wat genoem word wanneer data op die seriële poort ontvang word. Dit is waar ons al ons fisika toepas, besluit of ons die spel wil vertoon, die platforms wil skuif, ens. As u ooit 'n speletjie gebou het, het u gewoonlik 'n 'game loop', wat elke keer as die raam genoem word, genoem word. verfris. In hierdie speletjie dien die DataReceived -metode as die spellus, en manipuleer slegs die fisika namate data van die beheerder ontvang word. Dit sou miskien beter gewerk het om 'n timer in die hoofvenster op te stel en die voorwerpe te verfris op grond van die ontvangde data, maar aangesien dit 'n Arduino -projek is, wou ek 'n speletjie maak wat eintlik uitgevoer is, gebaseer op die data wat daaruit kom..

Kortom, hierdie opset bied 'n goeie basis om die spel uit te brei tot iets bruikbaars. Alhoewel die fisika nie heeltemal perfek is nie, werk dit goed genoeg vir ons doeleindes, om die Arduino te gebruik vir iets waarvan almal hou: speletjies speel!

Aanbeveel: