Πίνακας περιεχομένων:

Arduino OLED Snake Game: 3 Βήματα
Arduino OLED Snake Game: 3 Βήματα

Βίντεο: Arduino OLED Snake Game: 3 Βήματα

Βίντεο: Arduino OLED Snake Game: 3 Βήματα
Βίντεο: Arduino Snake Game on an OLED display. 2024, Νοέμβριος
Anonim
Arduino OLED Snake Game
Arduino OLED Snake Game

Γεια και καλώς ήρθατε, στις οδηγίες μας για το πώς να φτιάξετε και να κάνετε arduino OLED Game, αυτό το έργο προέκυψε καθώς προσπαθούσαμε να κάνουμε το πρώτο μας παιχνίδι με ένα arduino, έτσι, σκεφτήκαμε από πού καλύτερα να ξεκινήσουμε από το κλασικό φίδι της Nokia (καλά τουλάχιστον κλώνος φιδιού:)).

Αυτό που θα χρειαστείτε

Προμήθειες

Arduino UNO ή κλώνος

Οθόνη OLED

4 Δίοδοι

Αντίσταση 500-1k

4 κουμπιά χειριστηρίου

Παθητικός βομβητής Piezo

προαιρετικός

Solderless BreadBoard

Λάβετε υπόψη ότι αυτοί οι σύνδεσμοι είναι μόνο για παράδειγμα

Βήμα 1: Το κύκλωμα

Το Κύκλωμα
Το Κύκλωμα

Στην παραπάνω εικόνα μπορείτε να δείτε το κύκλωμά μας, χρησιμοποιούμε τον πείρο d3 στο arduino ως ακίδα αιτήματος διακοπής, έτσι ώστε το arduino να δίνει προτεραιότητα στην ανάγνωση των εισόδων του ελεγκτή που είναι d4 d5 d6 d7. Τα βασικά του κυκλώματος είναι ότι πιέζεται ένα κουμπί κατεύθυνσης που ανεβαίνει ψηλά 5v αυτό ενεργοποιεί τον πείρο αιτήματος διακοπής (d3 μοβ σύρμα) και έναν αντίστοιχο πείρο κατεύθυνσης, η λειτουργία διακοπής καλεί μια λειτουργία κατεύθυνσης ενημέρωσης και αυτός ο κώδικας μετακινεί ανάλογα το φίδι. Ο ακροδέκτης 9 χρησιμοποιείται ως ηχητική ακίδα καθώς είναι ένα PWM (ulation διαμόρφωση πλάτους παλμού) το οποίο συνδέεται απευθείας με ένα πιεζό 5v στο + pin και το - επιστρέφει στο 0v/γείωση.

(FYI στο arduino uno και κλωνοποιεί μόνο τα d2 και d3 μπορούν να λειτουργήσουν ως ακίδες αιτήματος διακοπής).

Καρφίτσες κατεύθυνσης:

d4 Πάνω ΠΟΡΤΟΚΑΛΙ

d5 Κάτω ροζ

d6 Αριστερά ΜΠΛΕ

d7 Δεξιά ΚΑΦΕ

d9 ήχος ΓΚΡΙ

Κάθε κουμπί έχει είσοδο σύνδεσης 5v και έξοδο που συνδέεται πρώτα με την αντίστοιχη ψηφιακή είσοδο στο arduino, η ίδια έξοδος κάθε κουμπιού συνδέεται στη συνέχεια με τη δική του δίοδο, χρησιμοποιούμε τις διόδους για να σταματήσουμε την επαναφορά της τάσης στο άλλα κουμπιά και ενεργοποίησή τους. Στο άκρο καθόδου (-) και των 4 διόδων τις ενώνουμε για να δημιουργήσουμε μια διασταύρωση εξόδου η οποία συνδέεται με το d3 και στη συνέχεια μέσω μιας αντίστασης στα 0v/γη για να τραβήξει τους πείρους arduino χαμηλά για να μην αφήσει αιωρούμενους πείρους όταν δεν είναι ενεργοποιημένο.

(FYI ένας πλωτός πείρος μπορεί να λάβει φανταστική τάση και να προκαλέσει ασυνήθιστη συμπεριφορά)

2 αναλογικές ακίδες χρησιμοποιούνται για την οδήγηση της οθόνης, αυτές είναι οι ακίδες i2c του υλικού arduino.

Το A5 είναι συνδεδεμένο στο SCL YELLOW

Το A4 συνδέεται με το SDA GREEN

Η έξοδος +5v και 0v (γη) από το arduino χρησιμοποιείται ως πηγή ισχύος για ολόκληρο το κύκλωμα που μπορεί να τροφοδοτηθεί από usb ή φορτιστή τηλεφώνου.

Βήμα 2: Ο κώδικας

// ------------------------ Παιχνίδια ANJAWARE SNAKE Με βοήθεια από τους καθαρούς λαούς --------------- -------

#περιλαμβάνω

#include // https://github.com/adafruit/Adafruit-GFX-Library #include // https://github.com/adafruit/Adafruit-GFX-Library // set display (πλάτος, ύψος) Adafruit_SSD1306 display (128, 64); // καθορίστε τις καρφίτσες εισόδου αυτές είναι οι ακίδες στο arduino που δεν αλλάζουν ποτέ, έτσι #define #define INTPIN 3 // μόνο οι ακίδες 2 και 3 μπορούν να διασταυρωθούν σε UNO #define UPPIN 4 // αυτές είναι ακίδες συνδεδεμένες tp σχετικός διακόπτης #define DWNPIN 5 #define LFTPIN 6 #define RHTPIN 7 #define SND 9 // καθορίστε οδηγίες #define DIRUP 1 // αυτές οι τιμές είναι αυτό που κοιτάζει το «φίδι» για να αποφασίσει- #define DIRDOWN 2 // την κατεύθυνση που θα ταξιδέψει το φίδι # define DIRLEFT 3 #define DIRRIGHT 4

// ορίστε μεταβλητές κουμπιών

// volitile cos το χρειαζόμαστε για να το ενημερώσουμε με το interupt ώστε να μπορεί να έχει οποιοδήποτε κομμάτι αξίας κύκλου

// δεν είναι ποτέ υψηλότερο από 4, οπότε χρειάζεστε μόνο 8bit int για να εξοικονομήσετε πόρους volatile uint8_t buttonpressed = 0; bool butup = 0; bool butdown = 0; // το χρησιμοποιούμε για να ορίσουμε true για να "ανιχνεύσει" ποια κατεύθυνση πάτησε bool butleft = 0; bool butright = 0;

// snake ints

byte snakePosX [30]; // array to make body of snake byte snakePosY [30];

int snakeX = 30; // θέση κεφαλιού φιδιού

int snakeY = 30; int snakeSize = 1; // ο αριθμός των φιδιών περιορίζεται στο μέγεθος του πίνακα

// ints κόσμου

uint8_t worldMinX = 0; // αυτά θέτουν τα όρια της περιοχής παιχνιδιού

uint8_t worldMaxX = 128; uint8_t worldMinY = 10; uint8_t worldMaxY = 63;

// συλλέξτε scran (φαγητό) και θέση scran

bool scranAte = 0; uint8_t scranPosX = 0; uint8_t scranPosY = 0;

// βαθμολογεί μεταβλητές

longcore = 0; μακρύ υψηλό σκορ = 30; // ορίστε υψηλή βαθμολογία σε 3 συλλογή ως σημείο εκκίνησης

// --------------------------- αυτό εκτελεί η διακοπή κατά την άνοδο της τάσης ------------ -------------

void interruptpressed () {καθυστέρηση (150); // μικρή καθυστέρηση για την πρόσθετη προστασία "bounce" updatedirection (); } // ------------------ ενημέρωση της τιμής κατεύθυνσης από το πάτημα του κουμπιού ----------------- άκυρη ενημέρωση κατεύθυνσης () { // Serial.println ("updatingdirection"); butup = digitalRead (UPPIN); // ελέγξτε ποια είσοδος πήγε ψηλά και ορίστε το σχετικό bool true butdown = digitalRead (DWNPIN); butleft = digitalRead (LFTPIN); butright = digitalRead (RHTPIN); // αυτά εάν τα άτομα που κοιτάζουν κοιτάζουν ποια είσοδος ανέβηκε και εισάγει τη σχετική τιμή στη μεταβλητή "buttonpressed" //, αυτή η μεταβλητή υπαγορεύει την κατεύθυνση της κίνησης εάν (butup == true) {buttonpressed = DIRUP; // Serial.println ("UP pressed"); // Serial.println (πατημένο με κουμπί); butup = false? τόνος (SND, 1500, 10). } if (butdown == true) {buttonpressed = DIRDOWN; // Serial.println ("ΚΑΤΩ πατημένο"); // Serial.println (πατημένο με κουμπί); butdown = false? τόνος (SND, 1500, 10). }

αν (butleft == true)

{buttonpressed = DIRLEFT; // Serial.println ("ΑΡΙΣΤΕΡΑ πατημένο"); // Serial.println (πατημένο με κουμπί); butleft = false? τόνος (SND, 1500, 10). } if (butright == true) {buttonpressed = DIRRIGHT; // Serial.println ("RIGHT pressed"); // Serial.println (πατημένο με κουμπί); σωστό = ψευδές? τόνος (SND, 1500, 10). }}

// -------------------------- σχεδιάστε τις ρουτίνες εμφάνισης ------------------ -----------------

void updateDisplay () // σχεδιάζει βαθμολογίες και περιγράμματα

{// Serial.println ("Ενημέρωση οθόνης");

display.fillRect (0, 0, display.width ()-1, 8, ΜΑΥΡΟ);

display.setTextSize (0); display.setTextColor (ΛΕΥΚΟ); // κλήρωση αποτελεσμάτων display.setCursor (2, 1); display.print ("Βαθμολογία:"); display.print (String (playcore, DEC)); display.setCursor (66, 1); display.print ("Υψηλό:"); display.print (String (highscore, DEC)); // σχεδίαση περιοχής αναπαραγωγής // pos 1x, 1y, 2x, 2y, έγχρωμη εμφάνιση. drawLine (0, 0, 127, 0, ΛΕΥΚΟ); // πολύ πάνω περίγραμμα display.drawLine (63, 0, 63, 9, ΛΕΥΚΟ); // βαθμολογία seperator display.drawLine (0, 9, 127, 9, ΛΕΥΚΟ); // κάτω από το περίγραμμα κειμένου display.drawLine (0, 63, 127, 63, ΛΕΥΚΟ); // κάτω περίγραμμα display.drawLine (0, 0, 0, 63, ΛΕΥΚΟ); // αριστερό περίγραμμα display.drawLine (127, 0, 127, 63, ΛΕΥΚΟ); // δεξί περίγραμμα

}

// --------------------------------------- ενημέρωση περιοχής αναπαραγωγής ---------- --------------------

void updateGame () // αυτό ενημερώνει την εμφάνιση της περιοχής παιχνιδιού

{display.clearDisplay ();

display.drawPixel (scranPosX, scranPosY, ΛΕΥΚΟ);

scranAte = scranFood ();

// ελέγξτε τις ρουτίνες των φιδιών

if (outOfArea () || selfCollision ())

{ τέλος παιχνιδιού(); }

// εμφάνιση φιδιού

για (int i = 0; i0; i--) {snakePosX = snakePosX [i-1]; snakePosY = snakePosY [i-1]; } // προσθέστε ένα επιπλέον pixel στο φίδι εάν (scranAte) {snakeSize+= 1; snakePosX [snakeSize-1] = snakeX; snakePosY [snakeSize-1] = snakeY; }

διακόπτης (πατημένος με κουμπί) // ήταν snakeDirection

{case DIRUP: snakeY- = 1; Διακοπή; θήκη DIRDOWN: snakeY+= 1; Διακοπή; θήκη DIRLEFT: snakeX- = 1; Διακοπή; θήκη DIRRIGHT: snakeX+= 1; Διακοπή; } snakePosX [0] = snakeX; snakePosY [0] = snakeY; updateDisplay (); display.display (); // --------------------- τοποθετήστε το scran -------------------

void placeScran ()

{scranPosX = τυχαίο (worldMinX+1, worldMaxX-1); scranPosY = τυχαίο (worldMinY+1, worldMaxY-1); } // ------------------------ ΣΚΡΑΤΗΣΤΕ ΣΗΜΕΙΩΣΗ ---------------- bool scranFood () {if (snakeX == scranPosX && snakeY == scranPosY) {playcore = livescore+10; τόνος (SND, 2000, 10). updateDisplay (); placeScran (); επιστροφή 1? } else {επιστροφή 0; }} // --------------------- εκτός περιοχής ---------------------- bool outOfArea () {return snakeX = worldMaxX || snakeY = worldMaxY; } //---------------------- τέλος παιχνιδιού----------------------- --- void gameOver () {uint8_t rectX1, rectY1, rectX2, rectY2; rectX1 = 38; rectY1 = 28; rectX2 = 58; rectY2 = 12; display.clearDisplay (); display.setCursor (40, 30); display.setTextSize (1); τόνος (SND, 2000, 50). display.print ("ΠΑΙΧΝΙΔΙ"); τόνος (SND, 1000, 50). display.print ("OVER"); εάν (βαθμολογία παιχνιδιού> = υψηλό σκορ) // ελέγξτε για να δείτε αν σκοράρει υψηλότερη από την υψηλή βαθμολογία {highscore = βαθμολογία παιχνιδιού · // single if statment για ενημέρωση υψηλής βαθμολογίας} για (int i = 0; i <= 16; i ++) // αυτό είναι για να τραβήξει ορθογώνια γύρω από το παιχνίδι πάνω από το {display.drawRect (rectX1, rectY1, rectX2, rectY2, WHITE); Serial.println ("εάν βρόχος"); display.display (); rectX1- = 2; // μετατόπιση κατά 2 εικονοστοιχεία rectY1- = 2; rectX2+= 4; // μετατόπιση πάνω από 2 εικονοστοιχεία από το τελευταίο σημείο rectY2+= 4; τόνος (SND, i*200, 3). } display.display (); // Screen Wipe after fame over rectX1 = 0; // ορίστε τη θέση έναρξης της γραμμής rectY1 = 0; rectX2 = 0; rectY2 = 63; για (int i = 0; i <= 127; i ++) {uint8_t cnt = 0; display.drawLine (rectX1, rectY1, rectX2, rectY2, BLACK); rectX1 ++; rectX2 ++; display.display (); } display.clearDisplay (); scorecore = 0; // επαναφορά στοιχείων φιδιού και παίκτη snakeSize = 1; snakeX = display.width ()/2; snakeY = display.height ()/2; waitForPress (); // περιμένετε να ξεκινήσει ο παίκτης το παιχνίδι} // ------------------------- περιμένετε για βρόχο πιέσεων ---------- --------------- void waitForPress () {bool αναμονή = 0; // Ο βρόχος τελειώνει όταν αυτό είναι πραγματικό display.clearDisplay (); while (αναμονή == 0) {drawALineForMe (ΛΕΥΚΟ); // σχεδιάστε μια τυχαία λευκή γραμμή drawALineForMe (ΜΑΥΡΟ); // σχεδιάστε μια τυχαία μαύρη γραμμή έτσι ώστε η οθόνη να μην γεμίζει εντελώς λευκή οθόνη.fillRect (19, 20, 90, 32, ΜΑΥΡΟ). // κενό φόντο για εμφάνιση κειμένου.setTextColor (ΛΕΥΚΟ); display.setCursor (35, 25); display.setTextSize (2); // μεγαλύτερη γραμματοσειρά display.println ("SNAKE"); // x y w h r col display.drawRoundRect (33, 22, 62, 20, 4, ΛΕΥΚΟ); // περίγραμμα Snake display.drawRect (19, 20, 90, 32, ΛΕΥΚΟ); // πλαίσιο περιγράμματος - 3 display.setCursor (28, 42); display.setTextSize (0); // γραμματοσειρά πίσω στην κανονική οθόνη.println ("πατήστε οποιοδήποτε πλήκτρο"); display.display (); αναμονή = digitalRead (INTPIN); // ελέγξτε για να δείτε αν το πλήκτρο αναμονής θα αλλάξει σε 1 που τελειώνει ενώ πατάτε το κουμπί = 0; // κουμπί επαναφοράς πατήστε}} // -------------------- ΣΧΕΔΙΖΕΤΕ ένα τυχαίο χρώμα εισαγωγής γραμμής uint8_t -------------- ----- άκυρο drawALineForMe (uint8_t clr) {uint8_t line1X, line1Y, line2X, line2Y = 0; // ορίστε τυχαίες συντεταγμένες για μια γραμμή και στη συνέχεια σχεδιάστε την // μεταβλητή όχι λιγότερο ούτε άλλη γραμμή1X = τυχαία (worldMinX+1, worldMaxX-1); line1Y = τυχαία (worldMinY+1, worldMaxY-1); line2X = τυχαία (worldMinX+1, worldMaxX-1); line2Y = τυχαία (worldMinY+1, worldMaxY-1); display.drawLine (line1X, line1Y, line2X, line2Y, clr); } // ----------------------------------------- ανίχνευση σύγκρουσης -------- -----------------------

για (byte i = 4; i <snakeSize; i ++) {if (snakeX == snakePosX && snakeY == snakePosy ) {επιστροφή 1; τόνος (SND, 2000, 20). τόνος (SND, 1000, 20). } επιστροφή 0; }

// --------------------------------- ΡΥΘΜΙΣΗ --------------- -----------------------------------

void setup () {καθυστέρηση (100); // απλώς δώστε στα πράγματα την ευκαιρία να "εκκινήσουν" // Serial.begin (9600). // αποεπιλέξτε αυτό εάν θέλετε να δείτε τις σειριακές εξόδους display.begin (SSD1306_SWITCHCAPVCC, 0x3C); display.clearDisplay (); // ξεκινήστε με καθαρή οθόνη display.setTextColor (ΛΕΥΚΟ); // ρυθμίστε το μέγεθος περιστροφής χρώματος κειμένου κ.λπ. display.setRotation (0); display.setTextWrap (false); display.dim (0); // ρυθμίστε το pinMode της οθόνης (INTPIN, INPUT). // ορίστε τις σωστές θύρες στις εισόδους pinMode (UPPIN, INPUT). pinMode (DWNPIN, INPUT); pinMode (LFTPIN, INPUT); pinMode (RHTPIN, INPUT); // αυτή είναι η εντολή interupt που "σταματά" το arduino για να διαβάσει τις εισόδους // command- function- pin-function to execute-condition on pin attachInterrupt (digitalPinToInterrupt (INTPIN), interruptpressed, RISING)? // Serial.println ("Setup Passed"); waitForPress (); // εμφάνιση της οθόνης εκκίνησης φιδιού placeScran (); // τοποθετήστε το πρώτο κομμάτι φαγητού} // --------------------- ΚΥΡΙΟ ΒΛΕΜΑ ----------------- ---------------------- void loop () {updateGame (); // αυτή η συνάρτηση είναι αυτή που φέρει τον κύριο κωδικό}

Βήμα 3:

Συνιστάται: