// Uses cursorT to target a square and send that "attack" to the other // arduino. Waits to receive the result and updates the local info. bool Fire(int8_t* Array) { // Select a square int8_t target = CursorT(Array); // write that square to the other arduino. Serial3.write(target); // waits for a result. while( !Serial3.available() ) {} // reads the result. int8_t result = Serial3.read(); // if the result is greater than 10, we know we sunk a ship. if( result/10 ) { Write_Message("You sunk a ship!"); } // %10 ensures that a 12 (ship sunk) becomes a 2 (hit), otherwise, has // no effect (nothing else greater than 10 should be read). Array[target] = result%10; // draws the resulting image patch to the target square. lcd_image_draw(&Images[Array[target]%10], &tft, 0, 0, (12*(target%10))+8, (12*(target/10))+8, 12, 12); // return a 1 if a ship was sunk, in order to decrement the counter // of the other players remaining ships. return 0 otherwise. delay(3000); // This delay allows a player to view the result of their // shot, and also makes an approximate synchronization // with the other player's delay from the sound effect. return result/10; }
void AP_Logger::Write_MessageF(const char *fmt, ...) { char msg[65] {}; // sizeof(log_Message.msg) + null-termination va_list ap; va_start(ap, fmt); hal.util->vsnprintf(msg, sizeof(msg), fmt, ap); va_end(ap); Write_Message(msg); }
int main() { // Initialize arduino, serial communication, lcd screen, buttons (and // internal pull-up resistors), LED pins, and SD card. init(); Serial.begin(9600); Serial3.begin(9600); while(Serial3.available()) {Serial3.read();} // Clean the Serial line tft.initR(INITR_BLACKTAB); pinMode(SEL, INPUT); digitalWrite(SEL, HIGH); pinMode(Button1, INPUT); digitalWrite(Button1, HIGH); for (int i = 0; i < 10; ++i) { pinMode(i + 22, OUTPUT); } int click; // This will be used to continue from the Title Screen Serial.print("Initializing SD card..."); if (!SD.begin(SD_CS)) { Serial.println("failed!"); } Serial.println("OK!"); // do the auto calibration of the cursor (found in Cursor.cpp) Initialize_Cursor(); while(true) { // draw the title screen, and set the turn pin to neutral (blue) lcd_image_draw(&Images[title], &tft, 0, 0, 0, 0, 128, 160 ); digitalWrite(bluePin, HIGH); while (true) { // leave the title page with a joystick button press. click = digitalRead(SEL); if (!click) {break;} } // draw a black screen tft.fillScreen(0); // draw the border image (note that the numbers (0-9) and // letters (A-J) are just for appearance and aren't actually used by // the program). lcd_image_draw(&Images[border], &tft, 0, 0, 0, 0, 128, 128 ); // initialize My_Ocean so that each value is 0 (water) for( int i=0; i<100; i++ ) { My_Ocean[i] = 0; } // initialize Their_Ocean so that each value is 1 (miss). This needs to // be nonzero for the first drawing of the screen (occurs on line 47 // of Place_Ships.cpp) and will be set to 0 after. for( int i=0; i<100; i++ ) { Their_Ocean[i] = 1; } //==================== Initialization complete ================= // Allows a player to place their ships My_Ships = Place_Ships(My_Ocean, Their_Ocean); // set Their_Ocean so that each value is 0 (water). for( int i=0; i<100; i++ ) { Their_Ocean[i] = 0; } // One arduino should read high, and the other should read low // (see wiring instructions for more detail). This determines who // gets the first turn. bool Turn = digitalRead(13); // Initialize the number of ships remaining for each player to 5. // can be set to 1 for a "debug" mode to see the victory/reset more // quickly. int Mine_Alive = 5; int Their_Alive = 5; // Turn on all the LED's initially (because all 10 ships should be // alive). for (int i = 0; i < 10; i++) { digitalWrite(22+i , HIGH); } // Connect to opponent. One arduino writes 'R' for ready, then waits // to receive a response. The other waits to read 'R' first, then // writes it. Write_Message("Connecting..."); if( Turn == 1 ) { Serial3.write('R'); while( Serial3.read() !='R' ) {} } else { while( Serial3.read() !='R' ) {} Serial3.write('R'); } //==================== Ready to communicate/play =============== // Loop until either player has no ships left. while((Mine_Alive != 0) && (Their_Alive != 0)) { // My turn if( Turn == 1 ) { // draw a red square in the top left corner (because we will // view what we know of Their_Ocean). tft.fillRect(0, 0, 8, 8, 0xF800); // Make the LED green because it is our turn. digitalWrite(redPin, LOW); digitalWrite(greenPin, HIGH); digitalWrite(bluePin, LOW); // Draw Their_Ocean Draw_Screen(Their_Ocean, My_Ocean); // Indicate our turn at the bottom of the screen Write_Message("Your Turn"); // Call Fire. It will return one (decrementing Their_Alive) // if it sinks a ship. Their_Alive = Their_Alive - Fire(Their_Ocean); // change turns Turn = 0; } else if( Turn == 0 ) { // draw a green square in the top left corner (because we will // view our own ships (My_Ocean). tft.fillRect(0, 0, 8, 8, 0x07E0); // Make the LED red because it is their turn. digitalWrite(redPin, HIGH); digitalWrite(greenPin, LOW); digitalWrite(bluePin, LOW); // draw My_Ocean Draw_Screen(My_Ocean, Their_Ocean); // Indicate their turn at the bottom of the screen Write_Message("Opponent's turn"); // Call Get_Shot_At. It will return one (and will decrement // Mine_Alive) if a ship is sunk. Mine_Alive = Mine_Alive-Get_Shot_At(My_Ocean, My_Ships); // change turns Turn = 1; } // update the LEDs based on the number of ships left alive. The // Green LEDS represent the number of ships you have alive while // the Red ones do the same for the other players ships. for (int i = 5; i > 0; i--) { if (Their_Alive >= i) { digitalWrite(21 + 2*i , HIGH); } else { digitalWrite(21 + 2*i , LOW); } } for (int i = 5; i > 0; i--) { if (Mine_Alive >= i) { digitalWrite(20 + 2*i , HIGH); } else { digitalWrite(20 + 2*i , LOW); } } } // The delays help everything to sync up with the sound effects. delay(2000); if( Mine_Alive > 0 ) { // The number sent to the 'Victory_Cascade()' is to indicate which // set of LEDS are to be cascaded based on which player is the // winner of the game. The spaces in the message are in place to // avoid the word in the messages being cut off Write_Message("You won! Please hold joystick button to play again."); Sound_Victory(); Victory_Cascade(22); } else { delay(3000); Write_Message("You lost! Please holdjoystick button to play again."); Victory_Cascade(23); } } Serial3.end(); Serial.end(); return 0; // End of function }
// Waits for an "attack" then calculates its result and write the result // arduino. Also updates our own information with the result. bool Get_Shot_At(int8_t* Array, Ship* Ships) { // Waits for an "attack" through serial3. while( !Serial3.available() ) {} // reads which square has been targeted. int8_t target = Serial3.read(); // If that square has 0 or 1 (water or miss). if( Array[target] <=1 ) { // set its value to 1 (miss) Array[target] = 1; // Write a 1 (miss) to other arduino. Serial3.write(1); // draw a miss square lcd_image_draw(&Images[miss], &tft, 0, 0, (12*(target%10))+8, (12*(target/10))+8, 12, 12); // play a miss sound effect. Sound_Miss(); } // If that square has 2 (already been hit) else if( Array[target] == 2) { // Write a 2 (so that other arduino still has the correct data) Serial3.write(2); // But, play a miss sound effect. Sound_Miss(); } // By elimination, a ship must have been hit. Calls Hit_My_Ship else{ // If Hit_My_Ship returns 1, a ship has been sunk. if( Hit_My_Ship(Array, target, Ships) ) { Write_Message("They sunk a ship!"); // The two represents a hit (for the image patch), the 10 denotes // that a ship has been sunk. Serial3.write(12); // set our array to 2 (hit) Array[target] = 2; // draw a hit square lcd_image_draw(&Images[Array[target]%10], &tft, 0, 0, (12*(target%10))+8, (12*(target/10))+8, 12, 12); // play a hit sound effect. Sound_Hit(); // return 1 to decrement our counter of how many ships are alive. return(1); } else { // A ship was not sunk. // Write back a 2 (hit) Serial3.write(2); // set our array to 2 (hit) Array[target] = 2; // draw a hit square lcd_image_draw(&Images[Array[target]%10], &tft, 0, 0, (12*(target%10))+8, (12*(target/10))+8, 12, 12); // play a hit sound effect. Sound_Hit(); } } // Note that the playing of the sound effects creates an adequate // delay to allow a player to view the effects of the shot. // (about 4 seconds). // if a ship has not been sunk, return 0. return 0; }
void AP_Logger::Write_Message(const char *message) { FOR_EACH_BACKEND(Write_Message(message)); }