Cześć
W dzisiejszym artykule chciałem Ci przedstawić projekt gry stworzonej za pomocą Arduino oraz języka Processing.
Przejdźmy do rzeczy.
Celem gry jest sterowanie małym samolocikiem oraz zbieranie kaczek.
A po co nam do tego Arduino?
Tutaj dopiero zaczyna się zabawa :-) Przy pomocy Arduino stworzymy swoisty kontroler dzięki, któremu będziemy mogli sterować naszym samolocikiem przy pomocy ruchów własnej ręki lub innych części ciała.
Co potrzebujemy do wykonania projektu:
–Arduino (ja wykorzystałem Arduino UNO) dostępne w sklepie botland KLIK
-Czujnik ultradźwiękowy HC-SR04
-Środowisko Processing oraz Arduino
-Opcjonalnie płytkę stykową
Gdy już skompletowaliśmy wszystkie części przejdźmy do uproszczonego omówienia zasady działania czujnika ultradźwiękowego. Czujnik ten wyposażony jest w nadajnik oraz odbiornik dzięki czemu wysyła impuls ultradźwiękowy, który “odbija” się od przeszkody (w tym wypadku od naszej ręki lub innej części ciała) a odbity sygnał odbierany jest przez odbiornik. Odległość między czujnikiem a przeszkodą jest obliczana według wzoru
Podłączenie
Podłączenie jest bardzo proste ponieważ w podstawowej wersji wykorzystujemy tylko czujnik ultradźwiękowy.
KOD
Teraz przejdźmy do napisania kodu do Arduino zwracającego odległość od obiektu w centymetrach
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
int echoPin= 2; int triggerPin= 3; unsigned long czasimpulsu = 0; unsigned odleglosc =0; unsigned staraodleglosc =0; void setup (){ pinMode (echoPin, INPUT); pinMode (triggerPin, OUTPUT); Serial.begin(9600); } void loop(){ digitalWrite(triggerPin, LOW); delayMicroseconds(100); digitalWrite(triggerPin, HIGH); delayMicroseconds(100); digitalWrite(triggerPin, LOW); czasimpulsu = pulseIn(echoPin, HIGH); odleglosc = czasimpulsu / 58; delay(10); if (staraodleglosc != odleglosc) { Serial.println(odleglosc); staraodleglosc = odleglosc; } delay(50); } |
Teraz w Monitorze portu szeregowego mamy możliwość odczytu danych z czujnika
Przechodzimy do najbardziej skomplikowanej oraz najbardziej przyjemnej części naszego poradnika czyli do napisania kodu naszej gry w języku Processing.
Zadaniem kodu jest odbieranie danych z serial monitora, dzięki którym sterujemy naszym samolotem; losowe generowanie gwiazd oraz ptaków; zliczanie punktów. Tworzy to swoistą grę.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
int i, j; int punkty ; float odlegloscsamolotuptaka; float pol; float poz; int odlegloscu; int iodleglosc; float ptakX; float ptakY; float trawaX ; String DataIn; //dane szeregowego monitora float [] chmuraX = new float[6]; float [] chmuraY = new float[6]; PImage chmura; PImage ptak; PImage samolot; PImage trawa; //konfiguracja portu szeregowego import processing.serial.*; Serial myPort; void setup() { //inicjacja portu szeregowego myPort = new Serial(this, Serial.list()[0], 9600); myPort.bufferUntil(10); frameRate(30); //liczba klatek na sekunde size(800, 600);//rozdzielczość rectMode(CORNERS) ; noCursor(); textSize(16); pol = 300; //wstepna polozenie samolotu chmura = loadImage("chmura.png"); //Ladowanie obrazow ptak = loadImage("ptak.png"); samolot = loadImage("samolot.png"); trawa = loadImage("trawa.png"); //generowanie pozycji chmur for (int i = 1; i <= 5; i = i+1) { chmuraX[i]=random(1000); chmuraY[i]=random(400); } punkty = 0; } //dane wysyłane na port szeregowy void serialEvent(Serial p) { DataIn = p.readString(); iodleglosc = int(trim(DataIn)); println(iodleglosc); if (iodleglosc>1 && iodleglosc<100 ) { odlegloscu = iodleglosc; } } void draw() { background(0, 0, 0); Ciel(); //rysowanie nieba fill(5, 72, 0); for (int i = -2; i <= 4; i = i+1) { image(trawa, 224*i + trawaX, 550, 224, 58); } trawaX = trawaX - cos(radians(poz))*10; if (trawaX < -224) { trawaX=224; } //dane dotyczące pozycji text(poz, 10, 30); text(pol, 10, 60); //punkty odlegloscsamolotuptaka = sqrt(pow((400-ptakX), 2) + pow((pol-ptakY), 2)) ; if (odlegloscsamolotuptaka < 40) { punkty = punkty+ 1; ptakX = 900; ptakY = random(600); } //liczba punktow wyswietlana na ekranie text("punkty : ", 200, 30); text( punkty, 260, 30); poz = (18- odlegloscu)*4; pol = pol + sin(radians(poz))*10; //obliczenie wertykalnej pozycji samolot //sprawdzenie zakresu wysokosci if (pol < 0) { pol=0; } if (pol > 600) { pol=600; } tr(pol, poz); ptakX = ptakX - cos(radians(poz))*10; if (ptakX < -30) { ptakX=900; ptakY = random(600); } //rysowanie i ruch chmur for (int i = 1; i <= 5; i = i+1) { chmuraX[i] = chmuraX[i] - cos(radians(poz))*(10+2*i); image(chmura, chmuraX[i], chmuraY[i], 300, 200); if (chmuraX[i] < -300) { chmuraX[i]=1000; chmuraY[i] = random(400); } } image(ptak, ptakX, Y, 59, 38); } void Ciel() { noStroke(); rectMode(CORNERS); for (int i = 1; i < 600; i = i+10) { fill( 49 +i*0.165, 118 +i*0.118, 181 + i*0.075 ); rect(0, i, 800, i+10); } } void tr(float Y, float anti) { noStroke(); pushMatrix(); translate(400, Y); rotate(radians(anti)); scale(0.5); image(samolot, -111, -55, 223, 110); popMatrix(); } |
W kodzie pojawiają się cztery odniesienia do plików graficznych, są to obrazy tła, kaczuszki, chmur oraz samolotu.
Wszystkie grafiki wykonałem w programie Inkscape jednak niestety nie posiadam talentu artystycznego przez co nie są one zbyt ładne. Jednak ty możesz stworzyć swoje grafiki, niekoniecznie muszą one przedstawiać to samo.
Grafiki te musisz skopiować do folderu ze sketchem processing.
Gdy już wszystko masz podłączone wystarczy kliknąć przycisk uruchamiający nasz program Processing i zacząć zabawę.
WAŻNE!
Aby nasz projekt działał Arduino musi być cały czas podłączone do naszego komputera
Ta gra nie jest może zbyt efektowna jednak pomyśl jak wiele jest czujników, które możemy użyć w innych projektach tego typu. Pamiętaj, że Arduino może nie tylko wysyłać dane z czujników lecz może je także odbierać oraz przesyłać do aplikacji. Daje nam to prawie nieograniczone możliwości.
Na przykład gra zwiększająca poziom trudności wraz ze wzrostem lub coś w rodzaju wirtualnej rzeczywistości zapalanie/gaszenie światła w pomieszczeniu, zmienianie temperatury itp. Wszystko oczywiście dopasowane do tempa rozgrywki.
Jedyną barierą jest nasza wyobraźnia.
Więcej informacji dotyczących tego tematu przedstawię na blogu za jakiś czas w poradniku dotyczącym “połączenia” Unity oraz Arduino.
Jeżeli masz jakieś pytania dotyczące projektu pisz w komentarzach ;-)
Więcej artykułów tego typu znajdziesz na moim BLOGU
Fajnie ,że ktoś zrobił coś z Processingiem
Chciałem zobaczyć jak to działa, ale w Processing po naciśnięciu Run wyświetla się okno z szarym tłem.
Musisz przerobić kod na myszkę lub podłączyć Arduino.
Linie
myPort = new Serial(this, Serial.list()[0], 9600);
myPort.bufferUntil(10);
Daj jako komentarz
//myPort = new Serial(this, Serial.list()[0], 9600);
//myPort.bufferUntil(10);
Kod zadziała wtedy ale “nic nie zrobisz”
Całkiem fajne. Przyczepię się tylko, że Processing to środowisko, a nie język. ;-)
Nie jest to pełnoprawny język programowania wraz z zintegrowanym środowiskiem programistycznym.
Podoba mi się to połączenie, mimo że wkradły się dwa błędy:
image(ptak, ptakX, Y, 59, 38);
należy poprawić na:
image(ptak, ptakX, ptakY, 59, 38);
ponieważ wszystkie ptaki rysowały się przy górnej krawędzi a kolizja wykrywana prawidłowo (w zależności od wartości “ptakY” . Na początku nie wiedziałem dlaczego nie mogę złapać ptaków :D.
Pomysł super!
Monitor portu szeregowego wykrywa mi czujnik, aplikacja w processing włącza się prawidłowo, ale nie wykrywa czujnika i samolocik opada na duł, nie reagując na nic.
Jakaś podpowiedź ?
Mam tą samą sytuację co @grzechu Samolot nie reaguje na odczyty czujnika ultradźwięku