├── LICENSE.txt ├── README.md ├── asteroids ├── Asteroid.png ├── Asteroid0.png ├── Asteroid1.png ├── Asteroid2.png ├── Rocket.png ├── asteroids.pde ├── laser.png └── processing.js ├── bombgame └── bombgame.ino ├── breakout ├── Ball.pde ├── Brick.pde ├── Paddle.pde ├── PowerUp.pde ├── breakout.pde └── data │ └── MicrosoftYaHei-48.vlw ├── follow_the_leader ├── follow_the_leader.pde └── sketch.properties ├── mechanical_sketching_toy └── mechanical_sketching_toy.pde ├── processing_getting_started ├── xbeegamecontroller.zip └── xbjlib.zip ├── quizshow ├── QuizShow.h └── quizshow.ino ├── racegame ├── racegame.pde └── sketch.properties ├── racegame_scalable ├── racegame_scalable.pde └── sketch.properties ├── rockpaperscissors └── rockpaperscissors.ino ├── rssi_seek └── rssi_seek.ino ├── spaceinvaders ├── Conf.pde ├── Invader.pde ├── Laser.pde ├── MotherShip.pde ├── Protection.pde ├── Ship.pde ├── data │ ├── CourierNew36.vlw │ ├── filtrejeu.gif │ └── filtrejeu.tga └── spaceinvaders.pde ├── stopit └── stopit.ino └── xbeegamecontroller ├── .gitignore ├── README.md ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library.properties ├── libs ├── slf4j-api-1.7.7.jar └── xbjlib.jar └── src └── xbeegamecontroller └── Controller.java /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | XBee®/Arduino Compatible Coding Platform 2 | === 3 | [Digi](http://www.digi.com) XBee/Arduino Compatible Coding Platform teaches you about XBees 4 | through building and playing some simple electronic projects. Each folder in the repository contains 5 | the code for one of the projects. To get started, check out the 6 | [User Guide](https://docs.digi.com/display/XBeeArduinoCodingPlatform). 7 | 8 | License 9 | --- 10 | This software is open-source. Copyright (c), Digi International Inc., 2015. 11 | 12 | This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 13 | If a copy of the MPL was not distributed with this file, you can obtain one at 14 | http://mozilla.org/MPL/2.0/. 15 | 16 | Licensing for Asteroids, SpaceInvaders, and Breakout 17 | --- 18 | The code in this repository was copied from [OpenProcessing](http://www.openprocessing.org) and 19 | modified to work with the XBee. All sketches and images from OpenProcessing are available under the 20 | [Creative Commons License](http://creativecommons.org/licenses/by-sa/3.0/) and the 21 | [GNU Public License version 2](http://creativecommons.org/licenses/GPL/2.0/). -------------------------------------------------------------------------------- /asteroids/Asteroid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/digidotcom/XBeeArduinoCodingPlatform/446208697f9cfb8c48feb1fe78a959365addb118/asteroids/Asteroid.png -------------------------------------------------------------------------------- /asteroids/Asteroid0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/digidotcom/XBeeArduinoCodingPlatform/446208697f9cfb8c48feb1fe78a959365addb118/asteroids/Asteroid0.png -------------------------------------------------------------------------------- /asteroids/Asteroid1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/digidotcom/XBeeArduinoCodingPlatform/446208697f9cfb8c48feb1fe78a959365addb118/asteroids/Asteroid1.png -------------------------------------------------------------------------------- /asteroids/Asteroid2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/digidotcom/XBeeArduinoCodingPlatform/446208697f9cfb8c48feb1fe78a959365addb118/asteroids/Asteroid2.png -------------------------------------------------------------------------------- /asteroids/Rocket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/digidotcom/XBeeArduinoCodingPlatform/446208697f9cfb8c48feb1fe78a959365addb118/asteroids/Rocket.png -------------------------------------------------------------------------------- /asteroids/asteroids.pde: -------------------------------------------------------------------------------- 1 | /* @pjs preload="Asteroid.png, Asteroid0.png, Asteroid1.png, Asteroid2.png, Rocket.png"; 2 | */ 3 | 4 | /* 5 | * "Asteroids" by Mark Gillespie, licensed under Creative Commons 6 | * Attribution-Share Alike 3.0 and GNU GPL license. 7 | * Work: http://openprocessing.org/visuals/?visualID=106239 8 | * License: 9 | * http://creativecommons.org/licenses/by-sa/3.0/ 10 | * http://creativecommons.org/licenses/GPL/2.0/ 11 | */ 12 | 13 | // Modified from source code at http://www.openprocessing.org/sketch/106239 for 14 | // use in Digi's XBee/Arduino Compatible Coding Platform. This game uses Digi's 15 | // XBee Game Controller library to handle user input by replacing the control 16 | // handling through setting the variables and calling the methods originally 17 | // done through mouse and keyboard input. See the buttonEvent and handleJoystick 18 | // methods below for more details. 19 | 20 | // Processing XBee Java Library must be installed 21 | import com.digi.xbee.api.*; 22 | // Digi XBee Game Controller library 23 | import xbeegamecontroller.*; 24 | 25 | Controller controller; 26 | 27 | // Change as necessary. Specifies how to address the XBee. 28 | final String XBEE_PORT = "COM5"; 29 | final int XBEE_BAUD = 9600; 30 | 31 | // Because the joystick included in the kit does not always spring back to 32 | // perfectly centered (~512), we effectively reduce the joystick sensitivity by 33 | // ignoring any values less than this far off of center. This means that, to 34 | // see the joystick as being pushed 'up', for example, the Y value needs to be 35 | // less than or equal to 412 (512 - 100). 36 | final int JOYSTICK_THRESHOLD = 100; 37 | 38 | Ship ship; 39 | boolean upPressed = false;//CHANGE LEFT AND RIGHT TO UP AND DOWN( IN SHIP TOO) 40 | boolean downPressed = false; 41 | boolean leftPressed = false; 42 | boolean rightPressed = false; 43 | 44 | float shipSpeed = 2; 45 | float rotationAngle = .2; 46 | float bulletSpeed = 10; 47 | int numAsteroids = 1; 48 | 49 | int startingRadius = 50; 50 | PImage[] asteroidPics = new PImage[3]; 51 | 52 | float bgColor = 0; 53 | 54 | PImage rocket; 55 | 56 | 57 | ArrayList exhaust; 58 | ArrayList fire; 59 | ArrayList bullets; 60 | ArrayList asteroids; 61 | 62 | PFont font; 63 | 64 | 65 | int darkCounter; 66 | int darkCounterLimit = 24*2; 67 | int MAX_LIVES = 3; 68 | int lives; 69 | int stage = -1; 70 | int diffCurve = 2; 71 | 72 | void setup() { 73 | textAlign(CENTER, CENTER); 74 | 75 | background(bgColor); 76 | size(800, 500); 77 | font = createFont("Cambria", 32); 78 | asteroidPics[0] = loadImage("Asteroid0.png"); 79 | asteroidPics[1] = loadImage("Asteroid1.png"); 80 | asteroidPics[2] = loadImage("Asteroid2.png"); 81 | rocket = loadImage("Rocket.png"); 82 | frameRate(24); 83 | lives = 3; 84 | asteroids = new ArrayList(0); 85 | 86 | // Connect to the XBee, treat it as an interface to the controller. 87 | try { 88 | controller = new Controller(this, XBEE_PORT, XBEE_BAUD); 89 | } catch (Exception e) { 90 | /* This would be unexpected. This will usually occur if the serial port 91 | * does not exist, or was already open. 92 | */ 93 | System.err.println("Failed to initialize XBee"); 94 | e.printStackTrace(); 95 | System.exit(1); 96 | } 97 | } 98 | 99 | // buttonEvent is automatically called by the XBee Game Controller library when 100 | // button states change. 101 | void buttonEvent(boolean leftButtonPushed, boolean rightButtonPushed) { 102 | if (leftButtonPushed && stage > -1 && asteroids.size() > 0) { 103 | // If the left button on the controller is pressed, and the game has begun, 104 | // try to fire a bullet. 105 | fireBullet(); 106 | } 107 | 108 | if (rightButtonPushed) { 109 | // We use the Right button as a replacement for clicking the mouse. 110 | mousePressed(); 111 | } 112 | } 113 | 114 | // Called in the draw() method. This method is used to convert the position of 115 | // the joystick into movement on-screen. 116 | void handleJoystick(int x, int y) { 117 | int middle = 512; 118 | 119 | // See the comment on the JOYSTICK_THRESHOLD variable at the top of this file 120 | // for more details on its use here. 121 | upPressed = (y <= middle - JOYSTICK_THRESHOLD); 122 | downPressed = (y >= middle + JOYSTICK_THRESHOLD); 123 | 124 | leftPressed = (x <= middle - JOYSTICK_THRESHOLD); 125 | rightPressed = (x >= middle + JOYSTICK_THRESHOLD); 126 | } 127 | 128 | void draw() { 129 | if (lives >= 0 && asteroids.size()>0) { 130 | // Handle the joystick position. 131 | handleJoystick(controller.getX(), controller.getY()); 132 | 133 | float theta = heading2D(ship.rotation)+PI/2; 134 | background(0); 135 | 136 | ship.update(exhaust, fire); 137 | ship.edges(); 138 | ship.render(); 139 | if (ship.checkCollision(asteroids)) { 140 | lives--; 141 | ship = new Ship(); 142 | } 143 | 144 | if (leftPressed) { 145 | rotate2D(ship.rotation, -rotationAngle); 146 | //ellipse(100,100,100,100); 147 | } 148 | if (rightPressed) { 149 | rotate2D(ship.rotation, rotationAngle); 150 | } 151 | 152 | if (upPressed) { 153 | ship.acceleration = new PVector(0, shipSpeed); 154 | rotate2D(ship.acceleration, theta); 155 | } else { 156 | ship.acceleration = new PVector(0, 0); 157 | } 158 | 159 | if (downPressed) { 160 | ship.acceleration = new PVector(0, 0); 161 | } 162 | 163 | for (Exhaust e : exhaust) { 164 | e.update(); 165 | e.render(); 166 | } 167 | 168 | for (Exhaust e : fire) { 169 | e.update(); 170 | e.render(); 171 | } 172 | 173 | for (int i = 0; i < bullets.size (); i++) { 174 | bullets.get(i).edges(); 175 | if (bullets.get(i).update()) { 176 | bullets.remove(i); 177 | i--; 178 | } 179 | if (i < 0) { 180 | break; 181 | } 182 | bullets.get(i).render(); 183 | if (bullets.get(i).checkCollision(asteroids)) { 184 | bullets.remove(i); 185 | i--; 186 | } 187 | } 188 | 189 | while (exhaust.size () > 20) { 190 | exhaust.remove(0); 191 | } 192 | 193 | while (fire.size ()>3) { 194 | fire.remove(0); 195 | } 196 | 197 | while (bullets.size () > 30) { 198 | bullets.remove(0); 199 | } 200 | 201 | for (Asteroid a : asteroids) { 202 | a.update(); 203 | a.edges(); 204 | a.render(); 205 | } 206 | 207 | 208 | for (int i = 0; i < lives; i++) { 209 | image(rocket, 40*i + 10, ship.r*1.5, 2*ship.r, 3*ship.r); 210 | } 211 | } else if (lives < 0) { 212 | if (darkCounter < darkCounterLimit) { 213 | background(0); 214 | darkCounter++; 215 | for (Asteroid a : asteroids) { 216 | a.update(); 217 | a.edges(); 218 | a.render(); 219 | } 220 | fill(0, 255-(darkCounterLimit-darkCounter)*3); 221 | rect(0, 0, width, height); 222 | } else { 223 | background(0); 224 | for (Asteroid a : asteroids) { 225 | a.update(); 226 | a.edges(); 227 | a.render(); 228 | } 229 | image(rocket, width/2 - 5 * ship.r, height/2-7.5*ship.r, 10*ship.r, 15*ship.r); 230 | textFont(font, 33); 231 | fill(0, 200); 232 | text("GAME OVER", width/2, height*.75-1); 233 | textFont(font, 32); 234 | fill(255); 235 | text("GAME OVER", width/2, height*.75); 236 | 237 | String playAgainText = "Click anywhere, or press the Right button, to play again."; 238 | textFont(font, 16); 239 | fill(0, 200); 240 | text(playAgainText, width/2, height*.9-1); 241 | textFont(font, 15); 242 | fill(255); 243 | text(playAgainText, width/2, height*.9); 244 | } 245 | } else { 246 | background(0); 247 | ship = new Ship(); 248 | ship.render(); 249 | 250 | textFont(font, 32); 251 | fill(255); 252 | if (stage > -1) { 253 | text("Stage " + (stage + 1) + " Complete", width/2, height/2); 254 | } else { 255 | text("Asteroids", width/2, height/2); 256 | } 257 | 258 | textFont(font, 15); 259 | fill(255); 260 | text("Click anywhere, or press the Right button, to start stage " + (stage + 2), width/2, height*.75); 261 | } 262 | } 263 | 264 | void mousePressed() { 265 | if (lives < 0) { 266 | stage = -1; 267 | lives = 3; 268 | asteroids = new ArrayList(0); 269 | } else if (asteroids.size()==0) { 270 | stage++; 271 | reset(); 272 | } 273 | } 274 | 275 | 276 | void reset() { 277 | ship = new Ship(); 278 | exhaust = new ArrayList(); 279 | fire = new ArrayList(); 280 | bullets = new ArrayList(); 281 | asteroids = new ArrayList(); 282 | for (int i = 0; i asteroids) { 341 | if (radius <= 30) { 342 | asteroids.remove(this); 343 | } else if (radius < 33) { 344 | for (int i = 0; i < 2; i++) { 345 | float angle = random(2*PI); 346 | PVector rand = new PVector(radius*sin(angle), radius*cos(angle)); 347 | rand.add(position); 348 | asteroids.add(new Asteroid(rand, radius*.8, pics, stage)); 349 | } 350 | asteroids.remove(this); 351 | } else { 352 | for (int i = 0; i < 3; i++) { 353 | float angle = random(2*PI); 354 | PVector rand = new PVector(radius*sin(angle), radius*cos(angle)); 355 | rand.add(position); 356 | asteroids.add(new Asteroid(rand, radius*.8, pics, stage)); 357 | } 358 | asteroids.remove(this); 359 | } 360 | } 361 | 362 | void update() { 363 | position.add(velocity); 364 | rotate2D(rotation, spin); 365 | } 366 | void render() { 367 | fill(col); 368 | circ(position.x, position.y); 369 | if (position.x < radius) { 370 | circ(position.x + width, position.y); 371 | } else if (position.x > width-radius) { 372 | circ( position.x-width, position.y); 373 | } 374 | if (position.y < radius) { 375 | circ(position.x, position.y + height); 376 | } else if (position.y > height-radius) { 377 | circ(position.x, position.y-height); 378 | } 379 | } 380 | 381 | void edges() { 382 | if (position.x < 0) { 383 | position.x = width; 384 | } 385 | if (position.y < 0) { 386 | position.y = height; 387 | } 388 | if (position.x > width) { 389 | position.x = 0; 390 | } 391 | if (position.y > height) { 392 | position.y = 0; 393 | } 394 | } 395 | 396 | 397 | void circ(float x, float y) { 398 | pushMatrix(); 399 | translate(x, y); 400 | rotate(heading2D(rotation)+PI/2); 401 | // ellipse(0,0,2.1*radius, 1.9*radius); 402 | image(pic, -radius, -radius, radius*2, radius*2); 403 | popMatrix(); 404 | } 405 | 406 | 407 | float heading2D(PVector pvect) { 408 | return (float)(Math.atan2(pvect.y, pvect.x)); 409 | } 410 | 411 | void rotate2D(PVector v, float theta) { 412 | float xTemp = v.x; 413 | v.x = v.x*cos(theta) - v.y*sin(theta); 414 | v.y = xTemp*sin(theta) + v.y*cos(theta); 415 | } 416 | } 417 | /* @pjs preload="laser.png"; 418 | */ 419 | 420 | class Bullet { 421 | PVector position; 422 | PVector velocity; 423 | int radius = 5; 424 | int counter = 0; 425 | int timeOut = 24 * 2; 426 | float alpha; 427 | PImage img = loadImage("laser.png"); 428 | 429 | public Bullet(PVector pos, PVector vel) { 430 | position = pos; 431 | velocity = vel; 432 | alpha = 255; 433 | } 434 | 435 | void edges() { 436 | if (position.x < 0) { 437 | position.x = width; 438 | } 439 | if (position.y < 0) { 440 | position.y = height; 441 | } 442 | if (position.x > width) { 443 | position.x = 0; 444 | } 445 | if (position.y > height) { 446 | position.y = 0; 447 | } 448 | } 449 | 450 | boolean checkCollision(ArrayList asteroids) { 451 | for (Asteroid a : asteroids) { 452 | PVector dist = PVector.sub(position, a.position); 453 | if (dist.mag() < a.radius) { 454 | a.breakUp(asteroids); 455 | return true; 456 | } 457 | } 458 | return false; 459 | } 460 | 461 | boolean update() { 462 | alpha *= .9; 463 | counter++; 464 | if (counter>=timeOut) { 465 | return true; 466 | } 467 | position.add(velocity); 468 | return false; 469 | } 470 | 471 | void render() { 472 | fill(255); 473 | pushMatrix(); 474 | translate(position.x, position.y); 475 | rotate(heading2D(velocity)+PI/2); 476 | //ellipse(0,0, radius, radius*5); 477 | image(img, -radius/2, -2*radius, radius, radius*5); 478 | popMatrix(); 479 | } 480 | 481 | float heading2D(PVector pvect) { 482 | return (float)(Math.atan2(pvect.y, pvect.x)); 483 | } 484 | } 485 | class Exhaust { 486 | PVector position; 487 | PVector velocity; 488 | float diameter; 489 | color hugh; 490 | 491 | public Exhaust(PVector pos, PVector vel, color col, int rad) { 492 | position = pos; 493 | velocity = vel; 494 | diameter = (float)(Math.random()*rad); 495 | hugh = col; 496 | } 497 | 498 | void render() { 499 | noStroke(); 500 | fill(hugh); 501 | ellipse(position.x, position.y, diameter, diameter); 502 | } 503 | 504 | void update() { 505 | position.add(velocity); 506 | velocity.mult(.9); 507 | } 508 | } 509 | /* @pjs preload="Rocket.png"; 510 | */ 511 | 512 | class Ship { 513 | PVector position; 514 | PVector velocity; 515 | PVector acceleration; 516 | PVector rotation; 517 | float drag = .9; 518 | float r = 15; 519 | PImage img = loadImage("Rocket.png"); 520 | 521 | public Ship() { 522 | position = new PVector(width/2, height-50); 523 | acceleration = new PVector(0, 0); 524 | velocity = new PVector(0, 0); 525 | rotation = new PVector(0, 1); 526 | } 527 | 528 | void update(ArrayList exhaust, ArrayList fire) { 529 | PVector below = new PVector(0, -2*r); 530 | rotate2D(below, heading2D(rotation)+PI/2); 531 | below.add(position); 532 | color grey = color(100, 75); 533 | 534 | int exhaustVolume = (int)(velocity.mag())+1; 535 | for (int i = 0; i width-r) { 565 | position.x = r; 566 | } 567 | if (position.y > height-r) { 568 | position.y = r; 569 | } 570 | } 571 | 572 | boolean checkCollision(ArrayList asteroids) { 573 | for (Asteroid a : asteroids) { 574 | PVector dist = PVector.sub(a.position, position); 575 | if (dist.mag() < a.radius + r/2) { 576 | a.breakUp(asteroids); 577 | return true; 578 | } 579 | } 580 | return false; 581 | } 582 | 583 | void render() { 584 | float theta = heading2D(rotation) + PI/2; 585 | theta += PI; 586 | 587 | pushMatrix(); 588 | translate(position.x, position.y); 589 | rotate(theta); 590 | fill(0); 591 | 592 | image(img, -r, -r*1.5, 2*r, 3*r); 593 | popMatrix(); 594 | } 595 | 596 | float heading2D(PVector pvect) { 597 | return (float)(Math.atan2(pvect.y, pvect.x)); 598 | } 599 | 600 | void rotate2D(PVector v, float theta) { 601 | float xTemp = v.x; 602 | v.x = v.x*cos(theta) - v.y*sin(theta); 603 | v.y = xTemp*sin(theta) + v.y*cos(theta); 604 | } 605 | } 606 | -------------------------------------------------------------------------------- /asteroids/laser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/digidotcom/XBeeArduinoCodingPlatform/446208697f9cfb8c48feb1fe78a959365addb118/asteroids/laser.png -------------------------------------------------------------------------------- /bombgame/bombgame.ino: -------------------------------------------------------------------------------- 1 | /* This program implements a simple multiplayer bomb defuser game. 2 | * An XBee will be attached to the Arduino on an XBee Shield. This 3 | * code will receive I/O packets from remote XBees when players pull 4 | * wires connecting digital inputs to ground. Each player only pulls 5 | * a single wire on their turn. If a player acts out-of-turn, their 6 | * bomb explodes (their LED lights up) and gameplay ends. If a player 7 | * pulls a wire which the other player has already pulled, their bomb 8 | * explodes and gameplay ends. To restart the game, reset the Arduino. 9 | * 10 | * Additional gameplay notes: 11 | * - Due to the fairly simple implementation here, a single game can 12 | * potentially continue indefinitely, if players begin reconnecting 13 | * wires. The game logic only checks for pins which are both high 14 | * at the same time, and so returning a pin to a low state will not 15 | * trigger any game-ending logic on its own. 16 | * 17 | * This code is written assuming using of an Arduino Leonardo and access 18 | * to the hardware serial port 'Serial1'. It will need to be modified 19 | * slightly if you choose to use a software serial port or another 20 | * variant of Arduino. 21 | */ 22 | 23 | // Uses the 'xbee-arduino' library. 24 | // https://code.google.com/p/xbee-arduino/ 25 | #include 26 | 27 | XBee xbee = XBee(); 28 | 29 | // Change as necessary 30 | uint16_t REMOTE_ADDR[] = { 0x1235, 0x1236 }; // MY parameter values of remote nodes 31 | int WIRE[] = { 0, 1, 2, 3 }; // Digital input pins used 32 | uint8_t LED_AT_COMMAND[] = {'D', '7'}; // Command used to change the status LED on each remote node 33 | 34 | // Set this to an array the same length as REMOTE_ADDR[]. 35 | int previous[] = { 0, 0 }; 36 | 37 | // How long to wait, in milliseconds, for a successful AT command response 38 | // (when changing remote LED state). 39 | const int AT_COMMAND_TIMEOUT = 2000; 40 | 41 | // Do not change. 42 | const int WIRE_COUNT = sizeof(WIRE) / sizeof(int); 43 | const int PLAYER_COUNT = sizeof(REMOTE_ADDR) / sizeof(uint16_t); 44 | Rx16IoSampleResponse response = Rx16IoSampleResponse(); 45 | 46 | int currentPlayer = 0; 47 | 48 | boolean firstLoop = true; 49 | boolean gameOver = false; 50 | 51 | void setup() { 52 | // Open the local serial port and tell the xbee-arduino library to 53 | // use it for XBee traffic. 54 | Serial1.begin(9600); 55 | xbee.begin(Serial1); 56 | 57 | // Record expected initial I/O state for each player. 58 | for (int i = 0; i < PLAYER_COUNT; i++) { 59 | previous[i] = 0; 60 | } 61 | } 62 | 63 | void loop() { 64 | // If the game has just begin, run through some initialization logic. 65 | if (firstLoop) { 66 | firstLoop = false; 67 | onFirstLoop(); 68 | } 69 | 70 | // If the game is over, delay for a moment to avoid wasting CPU time, 71 | // then restart the loop function. 72 | if (gameOver) { 73 | delay(1000); 74 | return; 75 | } 76 | 77 | // Read a packet in from the XBee, if one is available. 78 | xbee.readPacket(); 79 | 80 | if (xbee.getResponse().isAvailable() && xbee.getResponse().getApiId() == RX_16_IO_RESPONSE) { 81 | // It's an I/O sample. Parse the packet. 82 | xbee.getResponse().getRx16IoSampleResponse(response); 83 | 84 | // If this packet is from someone who is playing out of turn, signal their loss. 85 | if (response.getRemoteAddress16() != REMOTE_ADDR[currentPlayer]) { 86 | gameOver = true; 87 | signalExplosion(response.getRemoteAddress16()); 88 | return; 89 | } 90 | 91 | // For I/O comparison, we could use the `isDigitalOn` method of the response; however, 92 | // this game is concerned with tracking and comparing the overall I/O state of the 93 | // devices, and not any individual pin, and so it is easier to parse out the digital I/O 94 | // bitmask directly as done below than it would be to build that up using `isDigitalOn` 95 | // inside a for-loop, for example. 96 | 97 | // The xbee-arduino library presents the I/O data as the bytes contained in the packet. 98 | uint8_t *data = response.getData(); 99 | // The first byte is the number of sample, the next two bytes are the channel bitmask, 100 | // and the two bytes after that are the digital data. 101 | unsigned int io = (data[3] << 8) | data[4]; 102 | 103 | // If the current player is 0, the 'previous' is PLAYER_COUNT-1. Otherwise, subtract 1. 104 | int previousPlayer = (currentPlayer ? currentPlayer : PLAYER_COUNT) - 1; 105 | 106 | // If the pin that went high was already high on the other player's board, 107 | // then this player loses. 108 | unsigned int shared = io & previous[previousPlayer]; 109 | if (shared) { // shared != 0 110 | // Previous player already cut that wire. 111 | gameOver = true; 112 | signalExplosion(response.getRemoteAddress16()); 113 | return; 114 | } 115 | 116 | // Otherwise, record this player's new I/O state, and move on to the next player. 117 | previous[currentPlayer] = io; 118 | currentPlayer = (currentPlayer + 1) % PLAYER_COUNT; 119 | } 120 | } 121 | 122 | //============================================ 123 | // Game-specific functions. 124 | 125 | // Turn on the LED associated with the XBee at the given address. 126 | void signalExplosion(uint16_t address) { 127 | // Build a remote AT command to turn on the given player's LED. 128 | uint8_t value[] = {5}; 129 | RemoteAtCommandRequest request = RemoteAtCommandRequest(address, LED_AT_COMMAND, value, 1); 130 | 131 | // Send the command. 132 | xbee.send(request); 133 | } 134 | 135 | // Turn off the LED associated with the XBee at the given address. Used during 136 | // game initialization. 137 | void clearLed(uint16_t address) { 138 | // Build a remote AT command to turn off the given player's LED. 139 | uint8_t value[] = {4}; 140 | RemoteAtCommandRequest request = RemoteAtCommandRequest(address, LED_AT_COMMAND, value, 1); 141 | 142 | // Send the command. 143 | xbee.send(request); 144 | 145 | // Wait for a successful response, or time out after AT_COMMAND_TIMEOUT milliseconds. 146 | unsigned long start = millis(); 147 | while (1) { 148 | // Read a packet in from the XBee, if one is available. 149 | xbee.readPacket(); 150 | 151 | if (!xbee.getResponse().isAvailable()) { 152 | // No data. 153 | } else { 154 | if (xbee.getResponse().getApiId() == REMOTE_AT_COMMAND_RESPONSE) { 155 | // It's a response to an AT command. Parse the packet. 156 | RemoteAtCommandResponse response = RemoteAtCommandResponse(); 157 | xbee.getResponse().getRemoteAtCommandResponse(response); 158 | 159 | if (response.getRemoteAddress16() == address && response.isOk()) { 160 | // The command was successful. (Assumes these are the only AT commands 161 | // going out over the network.) 162 | break; 163 | } 164 | } 165 | } 166 | 167 | if (millis() > start + AT_COMMAND_TIMEOUT) { 168 | // We've waited for at least the specified timeout. Break out of the loop. 169 | break; 170 | } 171 | } 172 | } 173 | 174 | // Called when the game is about to begin. Clears all players' LEDs. 175 | void onFirstLoop() { 176 | // Sometimes these commands don't send successfully, so send them twice. 177 | for (int i = 0; i < 2; i++) { 178 | for (int i = 0; i < PLAYER_COUNT; i++) { 179 | // Clear the player's LED. 180 | clearLed(REMOTE_ADDR[i]); 181 | // Pause for a short moment. 182 | delay(500); 183 | } 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /breakout/Ball.pde: -------------------------------------------------------------------------------- 1 | class Ball { //The class for the ball 2 | 3 | //Initialization of the ball's variables 4 | PVector ballLocation; //The location of the ball 5 | PVector ballSpeed; //The speed of the ball 6 | color ballColor = color(255); //The color of the ball - defaults as white 7 | int canNextBallBeHitTimer = 0; //The time before the next hit is allowed - this is to stop a glitch that lets a ball hit more then one brick at a time 8 | 9 | Ball(float ballSpawnLocationX, float ballSpawnLocationY, float inputBallSpeedX, float inputBallSpeedY) { //Takes the nessessary inputs and creates a new ball with these properties 10 | 11 | //Declaration of the ball's variables 12 | this.ballLocation = new PVector(ballSpawnLocationX, ballSpawnLocationY); //Sets the inputed location to the new ball 13 | this.ballSpeed = new PVector(inputBallSpeedX, inputBallSpeedY); //Sets the speed of the ball 14 | } 15 | 16 | void renderBall(int ballNumber) { //Renders the ball 17 | 18 | //Movement of the ball 19 | if (!pauseState) { //If the game isn't paused 20 | this.ballLocation.x += this.ballSpeed.x; //Moves ball horizantally by the horizantal speed 21 | this.ballLocation.y += this.ballSpeed.y; //Moves ball vertically by the vertical speed 22 | } 23 | 24 | //Collision of the ball with the walls 25 | if (this.ballLocation.x < BALL_SIZE && this.ballSpeed.x < 0) this.ballSpeed.x = -this.ballSpeed.x; //If the ball moves to the left and hits the left wall, reflect the ball 26 | if (this.ballLocation.x > SCREEN_SIZE - BALL_SIZE && this.ballSpeed.x > 0) this.ballSpeed.x = -this.ballSpeed.x; //If the ball moves to the right and hits the right wall, reflect the ball 27 | if (this.ballLocation.y < BALL_SIZE && this.ballSpeed.y < 0) this.ballSpeed.y = -this.ballSpeed.y; //If the ball moves up and hits the top wall, reflect the ball 28 | if (this.ballLocation.y - BALL_SIZE > SCREEN_SIZE) numBalls.remove(ballNumber); //If the ball goes past the bottom of the screen, remove it 29 | 30 | //Collision of the ball with the paddle 31 | if (this.ballLocation.x + BALL_SIZE/2 > playerPaddle.paddleLocation.x //If the ball is right of the left side of the paddle 32 | && this.ballLocation.x - BALL_SIZE/2 < playerPaddle.paddleLocation.x + paddleSize.x //If the ball is on the left of the right side of the paddle 33 | && this.ballLocation.y + BALL_SIZE/2 > playerPaddle.paddleLocation.y //If the ball is past the top of the paddle 34 | && this.ballLocation.y + BALL_SIZE/2 < playerPaddle.paddleLocation.y + paddleSize.y //If the ball is above the bottom of the paddle 35 | && this.ballSpeed.y > 0) { //If the ball is moving downwards (as to stop a glitch which causes the ball to vibrate when bouncing off the paddle) 36 | if (this.ballLocation.x > playerPaddle.paddleLocation.x + paddleSize.x/2) //If the ball hits on the right side of the paddle 37 | this.ballSpeed.x = dist(playerPaddle.paddleLocation.x + paddleSize.x/2, 0, this.ballLocation.x, 0)/HORIZANTAL_SPEED_SENSITIVITY; //Angle towards the right side in proportion to the distance of the ball with the middle of the paddle 38 | else //If the ball hits on the left side of the paddle 39 | this.ballSpeed.x = -dist(playerPaddle.paddleLocation.x + paddleSize.x/2, 0, this.ballLocation.x, 0)/HORIZANTAL_SPEED_SENSITIVITY; //Angle towards the left side in proportion to the distance of the ball with the middle of the paddle 40 | this.ballSpeed.y = -this.ballSpeed.y; //Reflect the ball vertically 41 | } 42 | 43 | //Collision of the ball with a brick 44 | for (int brickNumber = 0; brickNumber < numBricks.size(); brickNumber++) { //Checks all currently rendering bricks 45 | if (this.ballLocation.x + BALL_SIZE/2 >= numBricks.get(brickNumber).brickLocation.x //If the ball's right side is past the left side of the brick 46 | && this.ballLocation.x - BALL_SIZE/2 <= numBricks.get(brickNumber).brickLocation.x + BRICK_SIZE.x //If the ball's left side is past the right side of the brick 47 | && this.ballLocation.y + BALL_SIZE/2 >= numBricks.get(brickNumber).brickLocation.y //If the ball's bottom is past the top of the brick 48 | && this.ballLocation.y - BALL_SIZE/2 <= numBricks.get(brickNumber).brickLocation.y + BRICK_SIZE.y) { //If the ball's top is above the bottom of the brick 49 | 50 | if ((this.ballLocation.x < numBricks.get(brickNumber).brickLocation.x && this.ballSpeed.x > 0) //If the ball hits the left side of the brick 51 | || (this.ballLocation.x > numBricks.get(brickNumber).brickLocation.x + BRICK_SIZE.x && this.ballSpeed.x < 0)) this.ballSpeed.x = -this.ballSpeed.x; //Or if the ball hits the right side of the brick, reflect it back 52 | if ((this.ballLocation.y < numBricks.get(brickNumber).brickLocation.y && this.ballSpeed.y > 0) //If the ball hits the top side of the brick 53 | || (this.ballLocation.y > numBricks.get(brickNumber).brickLocation.y + BRICK_SIZE.y && this.ballSpeed.y < 0)) this.ballSpeed.y = -this.ballSpeed.y; //Or the ball hits the bottom of the brick, reflect the ball vertically 54 | 55 | if (this.canNextBallBeHitTimer <= 0) { //If the timer allows another block to be destroyed 56 | 57 | //The power-up drop code of the brick 58 | if (int(random(CHANCE_OF_POWER_UP)) == 0) //If the random chance happens in which a power-up should be dropped 59 | numPowerUps.add(new PowerUp(numBricks.get(brickNumber).brickLocation.x + BRICK_SIZE.x/2, 60 | numBricks.get(brickNumber).brickLocation.y + BRICK_SIZE.y/2)); //Spawns a power-up at that brick's location 61 | 62 | this.ballColor = numBricks.get(brickNumber).brickColor; //Transfers the color of the brick to the ball 63 | numBricks.remove(brickNumber); //Removes the hit block if the ball is allowed to destroy a block 64 | this.canNextBallBeHitTimer = MINIMUM_TIME_BEFORE_NEXT_HIT; //Resets the hit timer 65 | } 66 | } 67 | } 68 | 69 | if (stickBallToPaddle) //If the ball must be stuck to the paddle 70 | this.ballLocation = new PVector(playerPaddle.paddleLocation.x + paddleSize.x/2, playerPaddle.paddleLocation.y - BALL_SIZE/2); //Move the ball just above the paddle 71 | 72 | canNextBallBeHitTimer--; //Decreases the hit timer by one 73 | 74 | //Drawing of the ball 75 | fill(this.ballColor); //Colors white 76 | ellipse(this.ballLocation.x, this.ballLocation.y, BALL_SIZE, BALL_SIZE); //Draws the ball 77 | } 78 | } 79 | 80 | -------------------------------------------------------------------------------- /breakout/Brick.pde: -------------------------------------------------------------------------------- 1 | class Brick { //Class for the bricks 2 | 3 | //Initialization of the bricks's variables 4 | PVector brickLocation; //Location of the brick 5 | color brickColor; //The color of the brick 6 | 7 | Brick(float brickSpawnLocationX, float brickSpawnLocationY, PVector currentBrickColorScheme) { //Takes neccessary inputs and creates a brick with those properties 8 | this.brickLocation = new PVector(brickSpawnLocationX, brickSpawnLocationY); //Sets the brick to the location of the inputed variables 9 | this.brickColor = color(random(currentBrickColorScheme.x - COLOR_SCHEME_RANGE, currentBrickColorScheme.x + COLOR_SCHEME_RANGE), 10 | random(currentBrickColorScheme.y - COLOR_SCHEME_RANGE, currentBrickColorScheme.y + COLOR_SCHEME_RANGE), 11 | random(currentBrickColorScheme.z - COLOR_SCHEME_RANGE, currentBrickColorScheme.z + COLOR_SCHEME_RANGE)); //Gives the brick a random color based on the current color scheme 12 | } 13 | 14 | void renderBrick() { //Renders the brick 15 | 16 | //Drawing of the brick 17 | fill(this.brickColor); //Colors the brick color 18 | rect(this.brickLocation.x, this.brickLocation.y, BRICK_SIZE.x, BRICK_SIZE.y); //Draws the brick 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /breakout/Paddle.pde: -------------------------------------------------------------------------------- 1 | class Paddle { //Class for the paddle 2 | 3 | //Initialization of the paddle's variables 4 | public PVector paddleLocation; //Location of the paddle 5 | 6 | Paddle() { //Creates a new paddle 7 | this.paddleLocation = new PVector(SCREEN_SIZE/2, SCREEN_SIZE - paddleSize.y * 2); //Moves the paddle to the middle of the x-axis, and to just above the bottom of the screen 8 | } 9 | 10 | void renderPaddle() { //Method for rendering the paddle 11 | //Movement of the paddle 12 | //if (!pauseState) //If the game is not paused 13 | //this.paddleLocation.x = mouseX - paddleSize.x / 2; //Moves the paddle to the mouse 14 | 15 | //Extended properties of the paddle 16 | if (extendedPaddleTimer > 0) //If the timer states that the paddle should be extended 17 | paddleSize.x = EXTENDED_PADDLE_WIDTH; //Extend the paddle 18 | else 19 | paddleSize.x = CONTRACTED_PADDLE_WIDTH; //Contract the paddle 20 | if (!pauseState) extendedPaddleTimer--; //Decreases the time for extending the paddle if the game is not paused 21 | 22 | //Drawing of the paddle 23 | fill(255); //Colors white 24 | rect(this.paddleLocation.x, this.paddleLocation.y, paddleSize.x, paddleSize.y); //Draws the paddle 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /breakout/PowerUp.pde: -------------------------------------------------------------------------------- 1 | class PowerUp { //Class for the power ups 2 | 3 | //Initialization of the power up's variables 4 | PVector powerUpLocation; //The location of the power ups 5 | 6 | /* PowerUp Type Values 7 | 0 = x3 Balls Power-Up 8 | 1 = Extended Paddle Power Up*/ 9 | int powerUpType; //The type of the power up 10 | 11 | PowerUp(float powerUpSpawnLocationX, float powerUpSpawnLocationY) { //Creates a power-up with the inputed proportions 12 | this.powerUpLocation = new PVector(powerUpSpawnLocationX, powerUpSpawnLocationY); //Sets the location to the inputed co-ordinates 13 | this.powerUpType = int(random(TYPES_OF_POWER_UPS)); //Sets the power up type to the inputed power up type 14 | } 15 | 16 | void renderPowerUp(int powerUpNumber) { //Renders the power up 17 | //Movement of the power up 18 | this.powerUpLocation.y += POWER_UP_SPEED; //Lowers the power up 19 | 20 | //Collision with the bottom wall 21 | if (this.powerUpLocation.y - POWER_UP_SIZE > SCREEN_SIZE) numPowerUps.remove(powerUpNumber); //If the powerup passes the bottom of the screen, remove it 22 | 23 | //Collision with the paddle 24 | if (this.powerUpLocation.x + POWER_UP_SIZE/2 > playerPaddle.paddleLocation.x //If the powerup is right of the left side of the paddle 25 | && this.powerUpLocation.x - POWER_UP_SIZE/2 < playerPaddle.paddleLocation.x + paddleSize.x //If the powerup is on the left of the right side of the paddle 26 | && this.powerUpLocation.y + POWER_UP_SIZE/2 > playerPaddle.paddleLocation.y //If the powerup is past the top of the paddle 27 | && this.powerUpLocation.y + POWER_UP_SIZE/2 < playerPaddle.paddleLocation.y + paddleSize.y) { //If the powerup is above the bottom of the paddle 28 | 29 | switch(this.powerUpType) { //Checks the power up type 30 | case 0: //If it is a x3 power up 31 | currentAmountOfBalls = numBalls.size(); //Sets the current amount of balls to the size of the arraylist as to not run out of memory in a constant loop due to newly spawned balls 32 | for (int i = 0; i < currentAmountOfBalls; i++) { //For every ball that is on the game... 33 | numBalls.add(new Ball(numBalls.get(i).ballLocation.x, numBalls.get(i).ballLocation.y, numBalls.get(i).ballSpeed.x, -numBalls.get(i).ballSpeed.y)); //Creates a ball going diagonally top-right relative to the ball's direction 34 | numBalls.add(new Ball(numBalls.get(i).ballLocation.x, numBalls.get(i).ballLocation.y, -numBalls.get(i).ballSpeed.x, numBalls.get(i).ballSpeed.y)); //Creates a ball going diagonally bottom-left relative to the ball's direction 35 | numBalls.add(new Ball(numBalls.get(i).ballLocation.x, numBalls.get(i).ballLocation.y, -numBalls.get(i).ballSpeed.x, -numBalls.get(i).ballSpeed.y)); //Creates a ball going diagonally top-left relative to the ball's direction 36 | } 37 | break; 38 | case 1: //If it is an extended paddle power up 39 | extendedPaddleTimer = PADDLE_EXTEND_TIME; //Sets sticky time to maximum sticky time 40 | break; 41 | } 42 | numPowerUps.remove(powerUpNumber); //Remove the power up 43 | } 44 | 45 | //Drawing of the power up 46 | fill(colorChangeAnimationColor); //Colors the color animation color 47 | ellipse(this.powerUpLocation.x, this.powerUpLocation.y, POWER_UP_SIZE, POWER_UP_SIZE); //Draws the power up 48 | 49 | fill(0); 50 | textFont(HUDfont, SCREEN_SIZE/50); //Sets the text font 51 | switch(this.powerUpType) { //Checks the type of the power up 52 | case 0: //If it is a x3 Power Up 53 | text("3", this.powerUpLocation.x - SCREEN_SIZE/800, this.powerUpLocation.y + SCREEN_SIZE*3/400); //Writes the number 3 on the power up for recognition from the user 54 | break; 55 | case 1: //If it is an extended paddle power up 56 | text("E", this.powerUpLocation.x - SCREEN_SIZE/800, this.powerUpLocation.y + SCREEN_SIZE*3/400); //Writes the letter E on the power up for recognition from the user 57 | break; 58 | } 59 | } 60 | } 61 | 62 | -------------------------------------------------------------------------------- /breakout/breakout.pde: -------------------------------------------------------------------------------- 1 | /*/--------------- 2 | Rainbow Breaker 3 | Made by Simon Hajjar 4 | From 06.03.12 5 | 6 | This is a simple program that remakes the famed brick-breaker, which 7 | slight variations on the color scheme. The paddle is controlled by 8 | the mouse, and when clicked, the ball is released, and the game 9 | begins. Furthermore, there are also two added power-ups - the x3 10 | Power Up which multiplies the amount of balls by three, and the 11 | Extended Paddle Power Up, which extends the paddle for a period, 12 | of time. 13 | 14 | Original source code: http://www.openprocessing.org/sketch/50736 15 | Modified for use in Digi's XBee/Arduino Compatible Coding Platform. This game 16 | uses Digi's XBee Game Controller library to handle user input by replacing the 17 | control handling through setting the variables and calling the methods 18 | originally done through mouse and keyboard input. See the buttonEvent method 19 | below, and the beginning of the draw method, for more details. 20 | ---------------/*/ 21 | 22 | // Processing XBee Java Library must be installed 23 | import com.digi.xbee.api.*; 24 | // Digi XBee Game Controller library 25 | import xbeegamecontroller.*; 26 | 27 | // Change as necessary. Specifies how to address the XBee. 28 | final String XBEE_PORT = "COM5"; 29 | final int XBEE_BAUD = 9600; 30 | 31 | Controller controller; 32 | 33 | final int PADDLE_SPEED_FACTOR = 25; // Paddle will move this many pixels per frame when joystick is all the way left or right. 34 | 35 | final int SCREEN_SIZE = 700; //Sets the variables for the width and height 36 | 37 | // Because the joystick included in the kit does not always spring back to 38 | // perfectly centered (~512), we effectively reduce the joystick sensitivity by 39 | // ignoring any values less than this far off of center. This means that, to 40 | // see the joystick as being pushed 'left', for example, the X value needs to be 41 | // less than or equal to 487 (512 - 25). 42 | final int JOYSTICK_THRESHOLD = 25; 43 | final float JOYSTICK_THRESHOLD_PERCENT = JOYSTICK_THRESHOLD / 512.0; 44 | 45 | //Variales pertaining to the paddle 46 | Paddle playerPaddle; //Creates the player's paddle 47 | PVector paddleSize = new PVector(SCREEN_SIZE/7, SCREEN_SIZE/30); //The size of the paddle 48 | final float CONTRACTED_PADDLE_WIDTH = SCREEN_SIZE/7; //Contracted width of the paddle 49 | final float EXTENDED_PADDLE_WIDTH = SCREEN_SIZE/4; //Extended width of the paddle 50 | int extendedPaddleTimer = 0, PADDLE_EXTEND_TIME = 1000; //The timer for the extended paddle, as well as the maximum time that it will remain extended 51 | 52 | //Variables pertaining to balls 53 | ArrayList numBalls; //Sets arraylist for the balls 54 | final int BALL_SIZE = SCREEN_SIZE/55; //The size of the balls 55 | final int DEFAULT_BALL_SPEED = SCREEN_SIZE/100; //The default ball speed 56 | final int HORIZANTAL_SPEED_SENSITIVITY = 8; //The sensitivity of the change of rate of speed for balls when hitting the paddle 57 | final int MINIMUM_TIME_BEFORE_NEXT_HIT = 1; //The minimum time before the next ball can be hit - this is to stop a glitch that allows the ball to hit two bricks at once 58 | boolean stickBallToPaddle = true; //If this is true, then the ball will stick to the paddle 59 | 60 | //Variables pertaining to the bricks 61 | ArrayList numBricks; //Sets the arraylist for the bricks 62 | PVector BRICK_SIZE = new PVector(SCREEN_SIZE*9/100, SCREEN_SIZE*3/100); //Size of the bricks 63 | PVector brickColorScheme; //The color scheme of the bricks of the level - changes with each new spawn 64 | final int COLOR_SCHEME_RANGE = 20; //The range of colors in the same color scheme - the larger it is, the more colorful 65 | final int MINIMUM_COLOR_SCHEME_BRIGHTNESS = 30; //The minimum brightness of the color schemes 66 | 67 | //Variables pertaining to the HUD and basic functioning of the game 68 | PFont HUDfont; //The font for the HUD 69 | int ballsLeft = 3; //The number of balls left - is equal to how many lives the player starts with 70 | int currentLevel = 1; //The current level - is equal to what level the user starts with 71 | int AVAILIBLE_LEVELS = 4; //The number of levels in the game - used to give the 'You Win!' message 72 | boolean displayedIntroduction = false; //If the introductory message has been shown to the user yet or not 73 | boolean displayWinningMessage = false; //If the winning message should be displayed 74 | boolean pauseState = false; //If the game is paused or not 75 | boolean gameOverState = false; //If the game has been lost or not 76 | final int COLOR_CHANGE_FREQUENCY = 30; //The frequency of the color change for the color changing animations 77 | int colorChangeTimer = COLOR_CHANGE_FREQUENCY; //The timer that determines when the color changing animation should change colors 78 | color colorChangeAnimationColor; //The current color of the color change animation 79 | 80 | //Variables pertaining to the powerups 81 | ArrayList numPowerUps = new ArrayList(); //Sets an arraylist for the powerups 82 | final int CHANCE_OF_POWER_UP = 8; //The reciprical of the chance of a powerup dropping when a block is destroyed -e.g., 1 is a 100% chance, where as 2 is a 50% chance 83 | final int TYPES_OF_POWER_UPS = 2; //The different types of powerups 84 | final int POWER_UP_SIZE = SCREEN_SIZE/30; //The radius of all the power ups 85 | final int POWER_UP_SPEED = SCREEN_SIZE/300; //The speed of the power up 86 | int currentAmountOfBalls; //The current amount of balls on the screen - used to check for each ball on the game whilst disregarding the newly spawned ones, as to save memory 87 | 88 | void setup() { //Runs once upon execution of the program 89 | size(SCREEN_SIZE, SCREEN_SIZE, JAVA2D); //Creates a screen 90 | HUDfont = loadFont("MicrosoftYaHei-48.vlw"); //Loads the font file from the data folde 91 | 92 | playerPaddle = new Paddle(); //Sets the player's paddle 93 | numBalls = new ArrayList(); //Sets the numBalls arraylist 94 | numBricks = new ArrayList(); //Sets the numBricks arraylist 95 | 96 | spawnLevel(currentLevel); //Spawns the first level 97 | numBalls.add(new Ball(playerPaddle.paddleLocation.x + paddleSize.x/2, playerPaddle.paddleLocation.y - BALL_SIZE/2, 0, DEFAULT_BALL_SPEED)); //Spawns the first ball 98 | 99 | // Connect to the XBee, treat it as an interface to the controller. 100 | try { 101 | controller = new Controller(this, XBEE_PORT, XBEE_BAUD); 102 | } catch (Exception e) { 103 | /* This would be unexpected. This will usually occur if the serial port 104 | * does not exist, or was already open. 105 | */ 106 | System.err.println("Failed to initialize XBee"); 107 | e.printStackTrace(); 108 | System.exit(1); 109 | } 110 | } 111 | 112 | void draw() { //Runs in a loop after the setup method 113 | background(0); //Sets a black background 114 | 115 | // Record the current paddle position. 116 | float paddleX = playerPaddle.paddleLocation.x; 117 | // Get the current joystick X position, convert it to a value from -1 to 1. 118 | float x = (controller.getX() - 512) / 512.0; 119 | 120 | // Ignore any value from when the joystick is very close to center. 121 | if (Math.abs(x) <= JOYSTICK_THRESHOLD_PERCENT) { 122 | x = 0; 123 | } else { 124 | // Adjust the percentage so that, once the joystick is outside of the 125 | // central "dead zone" (where the value is ignored), the paddle speed 126 | // starts from 0. 127 | if (x < 0) { 128 | // Negative x values will start at -JOYSTICK_THRESHOLD_PERCENT, so add 129 | // that amount to x to make the values start at 0. 130 | x = x + JOYSTICK_THRESHOLD_PERCENT; 131 | } else { 132 | // Positive x values will start at JOYSTICK_THRESHOLD_PERCENT, so 133 | // subtract that amount to x to make the values start at 0. 134 | x = x - JOYSTICK_THRESHOLD_PERCENT; 135 | } 136 | } 137 | 138 | // The 'speed factor' (maximum speed of the paddle when the joystick is all 139 | // the way left or right) needs to be scaled up, because we added or 140 | // subtracted the 'threshold percent' above. Without this scaling, the true 141 | // max speed will only be (100 - JOYSTICK_THRESHOLD)% of PADDLE_SPEED_FACTOR. 142 | float scaledSpeedFactor = PADDLE_SPEED_FACTOR / (1 - JOYSTICK_THRESHOLD_PERCENT); 143 | 144 | // Move the paddle by x * scaledSpeedFactor pixels. 145 | paddleX += x * scaledSpeedFactor; 146 | 147 | // If the paddle will end up off the left or right edges of the screen, move it back 148 | // to within screen bounds. 149 | if (paddleX < 0) 150 | paddleX = 0; 151 | if (paddleX > SCREEN_SIZE - paddleSize.x) 152 | paddleX = SCREEN_SIZE - paddleSize.x; 153 | 154 | // Set the new paddle position. 155 | playerPaddle.paddleLocation.x = paddleX; 156 | 157 | //Rendering of objects 158 | for (int i = 0; i < numBalls.size(); i++) numBalls.get(i).renderBall(i); //Renders all balls 159 | for (int i = 0; i < numBricks.size(); i++) numBricks.get(i).renderBrick(); //Renders all bricks 160 | for (int i = 0; i < numPowerUps.size(); i++) numPowerUps.get(i).renderPowerUp(i); //Renders all power ups 161 | playerPaddle.renderPaddle(); //Renders the player's paddle 162 | renderHUD(); //Renders the player's HUD 163 | 164 | //Checks and acts on the amount of balls 165 | if (numBalls.size() == 0) { //If there are no balls left 166 | if (!displayWinningMessage) ballsLeft--; //Decrease the amount of balls left by one if the user has not already won 167 | stickBallToPaddle = true; //Stick the next spawned ball to the paddle 168 | numPowerUps.clear(); //Removes all power-ups in motion 169 | extendedPaddleTimer = 0; //Contracts the paddle 170 | numBalls.add(new Ball(playerPaddle.paddleLocation.x + paddleSize.x/2, playerPaddle.paddleLocation.y - BALL_SIZE/2, 0, DEFAULT_BALL_SPEED)); //Adds a ball 171 | } 172 | if (ballsLeft <= 0) gameOverState = true; //If there are no lives left, show the game over screen 173 | 174 | //Checks and acts on the amount of bricks 175 | if (numBricks.size() == 0 && currentLevel <= AVAILIBLE_LEVELS) { //If there are no bricks left and the user has not completed all levels 176 | numPowerUps.clear(); //Removes all power-ups in motion 177 | numBalls.clear(); //Removes all balls 178 | extendedPaddleTimer = 0; //Contracts the paddle 179 | numBalls.add(new Ball(playerPaddle.paddleLocation.x + paddleSize.x/2, playerPaddle.paddleLocation.y - BALL_SIZE/2, 0, DEFAULT_BALL_SPEED)); //Adds a ball 180 | stickBallToPaddle = true; //Sticks the ball back to the paddle 181 | currentLevel++; //Increment current level by one 182 | spawnLevel(currentLevel); //Spawns the next level 183 | } 184 | } 185 | 186 | void mousePressed() { //If the mouse is pressed 187 | stickBallToPaddle = false; //Un-stick the ball from the paddle 188 | displayedIntroduction = true; //Remove the introduction message 189 | } 190 | 191 | void keyReleased() { //If a key is released 192 | if (key == 'Q' || key == 'q') exit(); //If the player presses 'q', quit the game 193 | if (key == 'P' || key == 'p') pauseState = !pauseState; //If the player presses 'p', toggle the pause 194 | } 195 | 196 | void renderHUD() { //Renders the player's HUD 197 | 198 | noCursor(); //Removes the user's cursor 199 | fill(colorChangeAnimationColor); //Colors white 200 | textAlign(LEFT); //Aligns the text to the left of co-ordinates 201 | textFont(HUDfont, SCREEN_SIZE*4/125); //Sets the text font 202 | text("Balls Left: ", SCREEN_SIZE/100, SCREEN_SIZE/25); //Writes the text "Balls Left" 203 | text("Current Level: " + currentLevel, SCREEN_SIZE/100, SCREEN_SIZE*7/80); //Writes out the current level 204 | for (int ballsToDraw = 0; ballsToDraw < ballsLeft; ballsToDraw++) ellipse(SCREEN_SIZE*2/11 + ballsToDraw * BALL_SIZE*3/2, SCREEN_SIZE/32, BALL_SIZE, BALL_SIZE); //Draws a ball for each life left 205 | 206 | textAlign(CENTER); //Aligns the text to the, center of co-ordinates 207 | textFont(HUDfont, SCREEN_SIZE/50); //Sets the text font 208 | if (!displayedIntroduction) text("Welcome to Rainbow Breaker!" + "\nTo let go of the ball, click the mouse or the left button." + "\nTo control the paddle, move the joystick." + "\nTo pause the game, press 'P'." + "\nTo quit the game, press 'Q'.", SCREEN_SIZE/2, SCREEN_SIZE*6/10); //Displays the introduction message 209 | if (displayWinningMessage) text("Congratulations!" + "\nYou won Rainbow Breaker!" + "\nPress 'Q' to quit the game.", SCREEN_SIZE/2, SCREEN_SIZE/2); //If the user has won, display the winning text 210 | 211 | if (pauseState) { //If the game is paused 212 | cursor(ARROW); //Sets the user's cursor to an arrow 213 | fill(0, 0, 0, 220); //Fills with a transparent black 214 | rect(0, 0, SCREEN_SIZE, SCREEN_SIZE); //Darkens the whole screen 215 | fill(255); //Colors white 216 | textFont(HUDfont, SCREEN_SIZE*4/125); //Sets the text font 217 | text("Game Paused", SCREEN_SIZE/2, SCREEN_SIZE/2); //Writes a pause message to the user 218 | textFont(HUDfont, SCREEN_SIZE/50); //Sets the text font 219 | text("Press 'P' or the left button to resume the game.", SCREEN_SIZE/2, SCREEN_SIZE*11/21); //Writes instructions regarding the pause to the user 220 | } 221 | else { //If the game is not paused 222 | 223 | //The color-changing animation 224 | if (colorChangeTimer >= COLOR_CHANGE_FREQUENCY) { //If it is time for the color change to occur 225 | colorChangeTimer = 0; //Resets the color change timer 226 | colorChangeAnimationColor = color(random(255), random(255), random(255)); //Randomizes the color of the imation 227 | } 228 | colorChangeTimer++; //Increments the color change timer 229 | } 230 | 231 | if (gameOverState) { //If the game has been lost 232 | background(0); //Colors the screen black, overlaying all the renderings 233 | fill(colorChangeAnimationColor); //Fills with the color change animation color 234 | textFont(HUDfont, SCREEN_SIZE*4/125); //Sets the text font 235 | text("Game Over", SCREEN_SIZE/2, SCREEN_SIZE/2); //Writes a game over message to the user 236 | textFont(HUDfont, SCREEN_SIZE/50); //Sets the text font 237 | text("Press 'Q' to exit the game.", SCREEN_SIZE/2, SCREEN_SIZE*11/21); //Writes instructions regarding the quit to the user 238 | } 239 | } 240 | 241 | void spawnLevel(int levelToSpawn) { //Spawns the level that should be spawned 242 | do { 243 | brickColorScheme = new PVector(random(255), random(255), random(255)); //Randomizes the color of the brick scheme 244 | } 245 | while (brickColorScheme.x + brickColorScheme.y + brickColorScheme.z < MINIMUM_COLOR_SCHEME_BRIGHTNESS); //If the color is less then the neccessary brightness, re-do the randomization 246 | 247 | switch(levelToSpawn) { //Checks the current level that was already incremented before this was called 248 | case 1: //If must spawn level one 249 | for (float spawnYofBrick = SCREEN_SIZE*10/45; spawnYofBrick < SCREEN_SIZE - BRICK_SIZE.y*20; spawnYofBrick += BRICK_SIZE.y) //Arranges each row one block apart 250 | for (float spawnXofBrick = BRICK_SIZE.x; spawnXofBrick < SCREEN_SIZE - BRICK_SIZE.x*2; spawnXofBrick += BRICK_SIZE.x) //Aranges each column one block apart 251 | numBricks.add(new Brick(spawnXofBrick, spawnYofBrick, brickColorScheme)); //Spawns each brick 252 | break; 253 | case 2: //If must spawn level two 254 | for (float spawnYofBrick = SCREEN_SIZE*8/45; spawnYofBrick < SCREEN_SIZE - BRICK_SIZE.y*15; spawnYofBrick += BRICK_SIZE.y) //Arranges each row one block apart 255 | for (float spawnXofBrick = BRICK_SIZE.x; spawnXofBrick < SCREEN_SIZE - BRICK_SIZE.x*2; spawnXofBrick += BRICK_SIZE.x*2) 256 | numBricks.add(new Brick(spawnXofBrick, spawnYofBrick, brickColorScheme)); //Spawns each brick 257 | break; 258 | case 3: //If must spawn level three 259 | for (float spawnYofBrick = SCREEN_SIZE*14/45; spawnYofBrick < SCREEN_SIZE - BRICK_SIZE.y*15; spawnYofBrick += BRICK_SIZE.y) //Arranges each row one block apart 260 | for (float spawnXofBrick = BRICK_SIZE.x; spawnXofBrick < SCREEN_SIZE - BRICK_SIZE.x*2; spawnXofBrick += BRICK_SIZE.x) //Aranges each column one block apart 261 | if (spawnXofBrick < SCREEN_SIZE*3/8 || spawnXofBrick > SCREEN_SIZE/2) numBricks.add(new Brick(spawnXofBrick, spawnYofBrick, brickColorScheme)); //Spawns each brick, except in the middle column 262 | break; 263 | case 4: //If must spawn level four 264 | for (float spawnYofBrick = SCREEN_SIZE*2/9; spawnYofBrick < SCREEN_SIZE - BRICK_SIZE.y*17; spawnYofBrick += BRICK_SIZE.y) //Arranges each row one block apart 265 | for (float spawnXofBrick = BRICK_SIZE.x; spawnXofBrick < SCREEN_SIZE - BRICK_SIZE.x*2; spawnXofBrick += BRICK_SIZE.x) //Aranges each column one block apart 266 | if(spawnXofBrick == BRICK_SIZE.x || spawnXofBrick >= SCREEN_SIZE - BRICK_SIZE.x*3 //If it is in one of the two columns 267 | || spawnYofBrick == SCREEN_SIZE*2/9 || spawnYofBrick >= SCREEN_SIZE - BRICK_SIZE.y*18) //If it is in on of the two rows 268 | numBricks.add(new Brick(spawnXofBrick, spawnYofBrick, brickColorScheme)); //Spawns bricks in a box shape 269 | break; 270 | case 5: //If must spawn level five (which is non-existent) 271 | displayWinningMessage = true; //Display the winning message, as there are no more levels 272 | break; 273 | } 274 | } 275 | 276 | // buttonEvent is automatically called by the XBee Game Controller library when 277 | // button states change. 278 | void buttonEvent(boolean leftButtonPushed, boolean rightButtonPushed) { 279 | if (leftButtonPushed) { 280 | // If the left button on the controller is pressed, perform the same 281 | // actions as when the mouse is clicked. 282 | mousePressed(); 283 | 284 | // Also unpause the game if it is currently paused. 285 | if (pauseState) { 286 | pauseState = false; 287 | } 288 | } 289 | } 290 | -------------------------------------------------------------------------------- /breakout/data/MicrosoftYaHei-48.vlw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/digidotcom/XBeeArduinoCodingPlatform/446208697f9cfb8c48feb1fe78a959365addb118/breakout/data/MicrosoftYaHei-48.vlw -------------------------------------------------------------------------------- /follow_the_leader/follow_the_leader.pde: -------------------------------------------------------------------------------- 1 | // XBee Java API library 2 | import com.digi.xbee.api.models.*; 3 | import com.digi.xbee.api.exceptions.*; 4 | import com.digi.xbee.api.io.*; 5 | import com.digi.xbee.api.packet.*; 6 | import com.digi.xbee.api.connection.serial.*; 7 | import com.digi.xbee.api.*; 8 | import com.digi.xbee.api.listeners.*; 9 | import com.digi.xbee.api.utils.*; 10 | import com.digi.xbee.api.packet.raw.*; 11 | import com.digi.xbee.api.packet.common.*; 12 | import com.digi.xbee.api.connection.*; 13 | 14 | import processing.serial.*; 15 | 16 | // The serial port to use to communicate to the XBee 17 | final String XBEE_PORT = "COM5"; 18 | final int XBEE_BAUD = 9600; 19 | 20 | // Should complete this sentence "Press the button". Empty 21 | // strings will be skipped, this will bias presses towards certain 22 | // buttons however 23 | String[][] buttonDescriptors = { 24 | { "Yellow", "Red", "Blue", "Green", "Black", "White" }, 25 | { "First", "Second", "Third", "Fourth", "Fifth", "Sixth" }, 26 | { "1st", "2nd", "3rd", "4th", "5th", "6th" }, 27 | }; 28 | 29 | // These are the DIO pins connected to the buttons described above 30 | // We expect that they've already been configured as Digital Inputs 31 | IOLine[] pinsOfInterest = { 32 | IOLine.DIO0_AD0, 33 | IOLine.DIO1_AD1, 34 | IOLine.DIO2_AD2, 35 | IOLine.DIO3_AD3, 36 | IOLine.DIO6, 37 | IOLine.DIO4_AD4, 38 | }; 39 | 40 | XBeeDevice xbeeDevice; // Represents the local radio 41 | float guessTime = 10000.0; // Initial time to press the correct button 42 | float scaleDown = 0.9; // Reduce guess time on each success 43 | 44 | float milliStart; // Track the start time of each round 45 | 46 | // Colors used for the words on the screen 47 | color[] colors = { 48 | color(255, 0, 0), 49 | color(0, 255, 0), 50 | color(0, 0, 255), 51 | color(255, 255, 255), 52 | color(255, 255, 0) 53 | }; 54 | 55 | boolean done = false; // Is the game over? 56 | boolean success; // Set when the user gets the button correct 57 | IOLine correctPin = null; // Selected randomly each round as the correct button 58 | String descriptor = ""; // Selected from the table above based on correctPin 59 | color descriptorColor; // The color of the word for a round 60 | 61 | void setup() { 62 | // Graphics 63 | size(displayWidth, displayHeight); // Fill the screen 64 | background(127); // Grey background 65 | textAlign(CENTER, BASELINE); 66 | textSize(height/4); // Scale the words to fit nicely based on screen size 67 | 68 | // Serial 69 | xbeeDevice = new Raw802Device(XBEE_PORT, XBEE_BAUD); 70 | try { 71 | xbeeDevice.open(); 72 | } catch (Exception e) { 73 | /* This would be unexpected. This will usually occur if the serial port 74 | * does not exist, or was already open. 75 | */ 76 | e.printStackTrace(); 77 | } 78 | 79 | // Register to receive all IO Samples 80 | xbeeDevice.addIOSampleListener(new ButtonListener()); 81 | 82 | // Pick the first button we want 83 | newChoice(); 84 | } 85 | 86 | void draw() { 87 | if (done) { 88 | // Game is over, no need to do anything 89 | return; 90 | } 91 | 92 | // Find out how much time they have left to guess 93 | float timeLeft = guessTime - (millis() - milliStart); 94 | if (timeLeft < 0) { 95 | // Time has run out, game over 96 | done = true; 97 | background(255, 0, 0); // red 98 | textAlign(CENTER, CENTER); 99 | text("Game Over!", width/2, height/2); 100 | return; 101 | } 102 | 103 | // Fade the background from gray to black based on time remaining 104 | int bg = int(timeLeft / guessTime * 200); 105 | background(bg); 106 | 107 | fill(#ffffff); // White text 108 | text("Press the", width/2, height/3 - 100); 109 | 110 | fill(descriptorColor); // Random color text 111 | text(descriptor, width/2, 2*height/3 - 100); 112 | 113 | fill(#ffffff); // White text 114 | text("button", width/2, height - 100); 115 | 116 | if (success) { 117 | newChoice(); // Reset for a new choice 118 | success = false; 119 | } 120 | } 121 | 122 | /* Cleans up the game state and selects a button to be the new 123 | * one being asked for */ 124 | void newChoice() { 125 | // Pick a button from the configured pins 126 | int pinIndex = int(random(pinsOfInterest.length)); 127 | correctPin = pinsOfInterest[pinIndex]; 128 | 129 | // Pick a word to describe this button from the various options 130 | int descriptorType; 131 | descriptor = ""; 132 | while (descriptor.equals("")) { 133 | descriptorType = int(random(buttonDescriptors.length)); 134 | descriptor = buttonDescriptors[descriptorType][pinIndex]; 135 | } 136 | // Give the word a random color to add to the mental stress 137 | descriptorColor = pickAColor(); 138 | 139 | guessTime = guessTime * scaleDown; // Get faster each time 140 | milliStart = millis(); // Record start time. 141 | } 142 | 143 | // Helper function to pick a random color from the list 144 | color pickAColor() { 145 | return colors[int(random(colors.length))]; 146 | } 147 | 148 | // Listener class which assists in processing received IO data 149 | class ButtonListener implements IIOSampleReceiveListener { 150 | @Override 151 | public void ioSampleReceived(RemoteXBeeDevice remoteDevice, 152 | IOSample ioSample) 153 | { 154 | // Loop over all the inputs we care about watching 155 | for (IOLine pin : pinsOfInterest) { 156 | IOValue value = ioSample.getDigitalValue(pin); 157 | 158 | // Pin is pulled LOW when pressed 159 | if (value == IOValue.LOW) { 160 | if (pin == correctPin) { 161 | success = true; 162 | } 163 | } 164 | } 165 | } 166 | } 167 | 168 | // This informs Processing that we want to run in full screen mode. 169 | boolean sketchFullScreen() { 170 | return true; 171 | } 172 | -------------------------------------------------------------------------------- /follow_the_leader/sketch.properties: -------------------------------------------------------------------------------- 1 | mode.id=processing.mode.java.JavaMode 2 | mode=Java 3 | -------------------------------------------------------------------------------- /mechanical_sketching_toy/mechanical_sketching_toy.pde: -------------------------------------------------------------------------------- 1 | /** 2 | * Mechanical Sketching Toy 3 | */ 4 | import java.util.*; 5 | 6 | import com.digi.xbee.api.models.*; 7 | import com.digi.xbee.api.exceptions.*; 8 | import com.digi.xbee.api.io.*; 9 | import com.digi.xbee.api.packet.*; 10 | import com.digi.xbee.api.connection.serial.*; 11 | import com.digi.xbee.api.*; 12 | import com.digi.xbee.api.listeners.*; 13 | import com.digi.xbee.api.utils.*; 14 | import com.digi.xbee.api.packet.raw.*; 15 | import com.digi.xbee.api.packet.common.*; 16 | import com.digi.xbee.api.connection.*; 17 | import processing.core.PApplet; 18 | 19 | XBeeDevice xbeeDevice; 20 | 21 | // Change as necessary. Specifies how to address the XBee. 22 | final String XBEE_PORT = "COM5"; 23 | final int XBEE_BAUD = 9600; 24 | // Change as necessary. Specifies the MY parameter values of each 'player', and the pin used for the potentiometer. 25 | final XBee16BitAddress[] addrs = { 26 | new XBee16BitAddress("1235"), /* controls movement left and right */ 27 | new XBee16BitAddress("1236") /* controls movement up and down */ 28 | }; 29 | final IOLine POT_PIN = IOLine.DIO1_AD1; 30 | 31 | // Change if necessary. Specifies the maximum value of the potentiometer reading. 32 | final int MAX_POT_VALUE = 1023; 33 | 34 | int oldX, oldY, x, y; 35 | boolean firstSample = true; 36 | 37 | // Multiply this by potentiometer value to get coordinates for screen. 38 | float X_MULT, Y_MULT; 39 | 40 | 41 | // Game displays full screen. Also needs size() call in setup() 42 | boolean sketchFullScreen() { 43 | return true; 44 | } 45 | 46 | //======================== 47 | // Utility functions 48 | 49 | void clearScreen() { 50 | background(#cccccc); 51 | } 52 | 53 | // End utility functions 54 | //======================== 55 | 56 | void setup() { 57 | // Make the game take up the whole screen 58 | size(displayWidth, displayHeight); 59 | 60 | X_MULT = displayWidth / (float)MAX_POT_VALUE; 61 | Y_MULT = displayHeight / (float)MAX_POT_VALUE; 62 | 63 | // Red background. 64 | clearScreen(); 65 | 66 | xbeeDevice = new Raw802Device(XBEE_PORT, XBEE_BAUD); 67 | try { 68 | xbeeDevice.open(); 69 | } catch (Exception e) { 70 | System.err.println("Failed to initialize XBee"); 71 | e.printStackTrace(); 72 | System.exit(1); 73 | } 74 | 75 | // InputListener is defined at the bottom of this file. 76 | xbeeDevice.addIOSampleListener(new InputListener(this)); 77 | } 78 | 79 | // The synchronized keyword here, and inside the InputListener below, ensures 80 | // that the code inside draw() and inside the InputListener do not run at the 81 | // same time. 82 | synchronized void draw() { 83 | // Keep lines from going outside display. 84 | if (x < 0) x = 0; 85 | if (x > displayWidth) x = displayWidth; 86 | if (y < 0) y = 0; 87 | if (y > displayHeight) y = displayHeight; 88 | 89 | fill(#000000); 90 | line(oldX, oldY, x, y); 91 | 92 | // Save off X and Y positions as oldX and oldY. 93 | oldX = x; 94 | oldY = y; 95 | } 96 | 97 | void mouseClicked() { 98 | clearScreen(); 99 | } 100 | 101 | class InputListener implements IIOSampleReceiveListener { 102 | private PApplet applet; 103 | 104 | public InputListener(PApplet applet) { 105 | this.applet = applet; 106 | } 107 | 108 | @Override 109 | public void ioSampleReceived(RemoteXBeeDevice remoteDevice, IOSample ioSample) { 110 | synchronized (this.applet) { 111 | XBee16BitAddress addr = remoteDevice.get16BitAddress(); 112 | 113 | if (ioSample.hasAnalogValue(POT_PIN)) { 114 | int potValue = ioSample.getAnalogValue(POT_PIN); 115 | 116 | if (addr.equals(addrs[0])) { 117 | x = (int) (potValue * X_MULT); 118 | } else if (addr.equals(addrs[1])) { 119 | // Invert Y axis, so turning it right moves up, not down. 120 | y = (int) ((MAX_POT_VALUE - potValue) * Y_MULT); 121 | } else { 122 | // Sample is from an unrecognized device - ignore it. 123 | return; 124 | } 125 | 126 | if (firstSample) { 127 | // If this is the first I/O sample received, the line will be a dot 128 | // instead. This prevents drawing an initial line from 0,0 to x,y. 129 | firstSample = false; 130 | oldX = x; 131 | oldY = y; 132 | } 133 | } 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /processing_getting_started/xbeegamecontroller.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/digidotcom/XBeeArduinoCodingPlatform/446208697f9cfb8c48feb1fe78a959365addb118/processing_getting_started/xbeegamecontroller.zip -------------------------------------------------------------------------------- /processing_getting_started/xbjlib.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/digidotcom/XBeeArduinoCodingPlatform/446208697f9cfb8c48feb1fe78a959365addb118/processing_getting_started/xbjlib.zip -------------------------------------------------------------------------------- /quizshow/QuizShow.h: -------------------------------------------------------------------------------- 1 | enum QS_State { 2 | // Reading the question, or just "paused". 3 | READING_QUESTION, 4 | // Read XBee packets in, waiting for the right signal to arrive. 5 | // Also (using state tracked elsewhere) ignores buzzes from teams who 6 | // have already buzzed in. 7 | READY_FOR_ANSWERS, 8 | // A team is buzzed in. A timer goes down... 9 | BUZZED_IN 10 | }; 11 | -------------------------------------------------------------------------------- /quizshow/quizshow.ino: -------------------------------------------------------------------------------- 1 | /* This program implements a simple quiz show buzzer. An XBee will be attached 2 | * to the Arduino on an XBee shield. This code will allow a 'host' to use 3 | * buttons connected to the Arduino to drive different game states. There are 4 | * distinct states for reading a question (which can be used as a general 5 | * 'paused' state), waiting for players to buzz in, and a player being buzzed 6 | * in. 7 | * 8 | * Players 'buzz in' by grounding a specific digital input pin on their remote 9 | * XBee nodes. This will typically be done by pressing a button. Once a player 10 | * buzzes in and answers the question, the host can record their answer as 11 | * incorrect (in which case they cannot buzz in until the next question), or as 12 | * correct (in which case the game resets and the host reads the next 13 | * question). 14 | * 15 | * This code is written assuming use of an Arduino Leonardo and access to the 16 | * hardware serial port 'Serial1'. It will need to be modified slightly if you 17 | * choose to use a software serial port or another variant of Arduino. 18 | */ 19 | 20 | // Uses the 'xbee-arduino' library. 21 | // https://code.google.com/p/xbee-arduino/ 22 | #include 23 | #include "QuizShow.h" 24 | 25 | XBee xbee = XBee(); 26 | 27 | // Change these as necessary. 28 | const uint16_t REMOTE_ADDR[] = { 0x1235, 0x1236 }; // MY parameter values of remote nodes 29 | const int LED_PINS[] = {2, 3, 4}; 30 | const int STATUS_PIN = 5; 31 | const int BUTTON_PINS[] = {8, 9, 10}; // reset, correct, incorrect. 32 | const int BUZZ_IN_PIN = 1; // DIO1 33 | 34 | // This array must be kept at least the same length as REMOTE_ADDR. 35 | boolean playerBuzzedIn[] = { false, false, false }; 36 | 37 | // Do not change these. 38 | const int PLAYER_COUNT = sizeof(REMOTE_ADDR) / sizeof(uint16_t); 39 | QS_State currentState; 40 | int currentPlayer = -1; 41 | 42 | void setup() { 43 | // The game starts in the 'reading question' state. The status LED will pulse 44 | // until the host presses the green button to move to the answering state. 45 | resetToQuestion(); 46 | 47 | // Configure the output pins on the Arduino. 48 | for (int i = 0; i < PLAYER_COUNT; i++) { 49 | pinMode(LED_PINS[i], OUTPUT); 50 | digitalWrite(LED_PINS[i], LOW); 51 | } 52 | 53 | // Status LED is off initially. 54 | pinMode(STATUS_PIN, OUTPUT); 55 | analogWrite(STATUS_PIN, 0); 56 | 57 | // Configure the input (button) pins on the Arduino. 58 | for (int i = 0; i < 3; i++) { 59 | pinMode(BUTTON_PINS[i], INPUT_PULLUP); 60 | } 61 | 62 | // Open the local serial port and tell the xbee-arduino library to use it for 63 | // XBee traffic. 64 | Serial1.begin(9600); 65 | xbee.begin(Serial1); 66 | } 67 | 68 | void loop() { 69 | // Call one of the do_ methods below, depending on which state the game is in 70 | // currently. 71 | 72 | switch (currentState) { 73 | case READING_QUESTION: 74 | do_reading_question(); 75 | break; 76 | case READY_FOR_ANSWERS: 77 | do_ready_for_answers(); 78 | break; 79 | case BUZZED_IN: 80 | do_buzzed_in(); 81 | break; 82 | default: 83 | // Should only happen if a new state is introduced in QuizShow.h or some 84 | // bug is introduced in this code. 85 | break; 86 | } 87 | } 88 | 89 | void do_reading_question() { 90 | static int pulse_value = 255; 91 | static int pulse_modifier = -5; 92 | 93 | if (answerCorrectButtonPressed()) { 94 | // Signal that we're done reading the question. 95 | currentState = READY_FOR_ANSWERS; 96 | 97 | while (answerCorrectButtonPressed()) { 98 | // Wait until the button is released. Otherwise, if a team buzzes in 99 | // quickly, we could immediately accept their answer. 100 | } 101 | } else { 102 | // While reading the question, pulse the status light. 103 | 104 | if (pulse_value == 255) { 105 | // If the LED is at its brightest, start fading down. 106 | pulse_modifier = -5; 107 | } 108 | if (pulse_value == 0) { 109 | // If the LED is off, start fading up. 110 | pulse_modifier = 5; 111 | } 112 | 113 | // Set the LED brightness. 114 | pulse_value += pulse_modifier; 115 | analogWrite(STATUS_PIN, pulse_value); 116 | 117 | // Keep reading in packets from the XBee (and ignoring them). 118 | xbee.readPacket(10); // 10 ms timeout 119 | } 120 | } 121 | 122 | void do_ready_for_answers() { 123 | // Turn on the status LED. 124 | digitalWrite(STATUS_PIN, HIGH); 125 | 126 | if (resetButtonPressed()) { 127 | // Reset the round. 128 | resetToQuestion(); 129 | 130 | // Wait until the button is released. 131 | while (resetButtonPressed()) { 132 | ; 133 | } 134 | 135 | return; 136 | } 137 | 138 | // Read a packet off the XBee, or timeout after 5ms. 139 | xbee.readPacket(5); 140 | 141 | if (xbee.getResponse().isAvailable() && xbee.getResponse().getApiId() == RX_16_IO_RESPONSE) { 142 | // It's an IO sample. 143 | Rx16IoSampleResponse response = Rx16IoSampleResponse(); 144 | xbee.getResponse().getRx16IoSampleResponse(response); 145 | 146 | // The xbee-arduino library presents the I/O data as the bytes contained in the packet. 147 | uint8_t *data = response.getData(); 148 | // The first byte is the number of samples, the next two bytes are the channel bitmask, 149 | // and the two bytes after that are the digital data. 150 | unsigned int io = (data[3] << 8) | data[4]; 151 | 152 | // First, check that the sample indicates someone buzzing in. 153 | if (io & (1 << BUZZ_IN_PIN)) { 154 | // The "buzz-in pin" is unpressed. Ignore this sample. 155 | return; 156 | } 157 | 158 | // Determine if this XBee is a known player. 159 | currentPlayer = -1; 160 | uint16_t addr = response.getRemoteAddress16(); 161 | 162 | for (int i = 0; i < PLAYER_COUNT; i++) { 163 | // If it's from a known player, and they haven't buzzed in yet... 164 | if (addr == REMOTE_ADDR[i] && !playerBuzzedIn[i]) { 165 | // Mark them down as the current answerer. 166 | currentPlayer = i; 167 | playerBuzzedIn[i] = true; 168 | 169 | signalBuzzIn(); 170 | 171 | // Move to the BUZZED_IN state. 172 | currentState = BUZZED_IN; 173 | return; 174 | } 175 | } 176 | } 177 | } 178 | 179 | void do_buzzed_in() { 180 | if (resetButtonPressed() || answerCorrectButtonPressed()) { 181 | // Reset button, or 'correct' button. Both do the same thing here. 182 | 183 | // Reset to reading the question. 184 | resetToQuestion(); 185 | resetAllLeds(); 186 | 187 | // Wait until the button is released. 188 | while (resetButtonPressed() || answerCorrectButtonPressed()) { 189 | ; 190 | } 191 | } else if (answerIncorrectButtonPressed()) { 192 | // This player/team was wrong. Reset to waiting for answers. 193 | // (Since we don't clear out `playerBuzzedIn`, this player/team will not 194 | // be able to buzz in until the next question.) 195 | currentPlayer = -1; 196 | currentState = READY_FOR_ANSWERS; 197 | resetAllLeds(); 198 | 199 | // Wait until the button is released. 200 | while (answerIncorrectButtonPressed()) { 201 | ; 202 | } 203 | } 204 | } 205 | 206 | //================================================== 207 | // Utility functions 208 | //================================================== 209 | 210 | void resetToQuestion() { 211 | // Reset round. 212 | currentState = READING_QUESTION; 213 | 214 | // Clear out playerBuzzedIn 215 | for (int i = 0; i < PLAYER_COUNT; i++) { 216 | playerBuzzedIn[i] = false; 217 | } 218 | } 219 | void resetAllLeds() { 220 | // Turn off all of the individual team LEDs. 221 | for (int i = 0; i < PLAYER_COUNT; i++) { 222 | digitalWrite(LED_PINS[i], LOW); 223 | } 224 | // Turn off the status LED. 225 | digitalWrite(STATUS_PIN, LOW); 226 | } 227 | 228 | boolean resetButtonPressed() { 229 | return !digitalRead(BUTTON_PINS[0]); 230 | } 231 | boolean answerCorrectButtonPressed() { 232 | return !digitalRead(BUTTON_PINS[1]); 233 | } 234 | boolean answerIncorrectButtonPressed() { 235 | return !digitalRead(BUTTON_PINS[2]); 236 | } 237 | 238 | void signalBuzzIn() { 239 | // Indicate that a player has buzzed in by flashing both the status LED and 240 | // their individual LED a few times. 241 | int flashCount = 5; 242 | 243 | for (int i = 0; i < flashCount; i++) { 244 | digitalWrite(LED_PINS[currentPlayer], HIGH); 245 | digitalWrite(STATUS_PIN, HIGH); 246 | delay(100); 247 | 248 | digitalWrite(LED_PINS[currentPlayer], LOW); 249 | digitalWrite(STATUS_PIN, LOW); 250 | delay(100); 251 | } 252 | 253 | // End with the team's LED lit (and the status LED off). 254 | digitalWrite(LED_PINS[currentPlayer], HIGH); 255 | } 256 | -------------------------------------------------------------------------------- /racegame/racegame.pde: -------------------------------------------------------------------------------- 1 | // XBee Java API library 2 | import com.digi.xbee.api.models.*; 3 | import com.digi.xbee.api.exceptions.*; 4 | import com.digi.xbee.api.io.*; 5 | import com.digi.xbee.api.packet.*; 6 | import com.digi.xbee.api.connection.serial.*; 7 | import com.digi.xbee.api.*; 8 | import com.digi.xbee.api.listeners.*; 9 | import com.digi.xbee.api.utils.*; 10 | import com.digi.xbee.api.packet.raw.*; 11 | import com.digi.xbee.api.packet.common.*; 12 | import com.digi.xbee.api.connection.*; 13 | 14 | // Change the following line of code to the serial port connector to your XBee. 15 | final String XBEE_PORT = "COM5"; 16 | final int XBEE_BAUD = 9600; 17 | final int CAR_COUNT = 4; // Number of racers 18 | final int XPOS_CAR_OFFSET = 80; // X Position of first car 19 | final int XPOS_CAR_SPACER = 100; // X space between cars 20 | final int YPOS_RACE_SIZE = 600; // Size of the race course in pixels 21 | final int VELOCITY_SCALER = 10000; // Scales car speed by milliseconds specified 22 | final int RACE_COURSE_UNITS = 20000; // Size of the race course in arbitrary "units" 23 | final int XPOS_CAR_SIZE = 10; // Size of the car in the x axis 24 | final int YPOS_CAR_SIZE = 30; // Size of the car in the y axis 25 | XBeeDevice xbeeDevice; 26 | final IOLine[] INPUT_PINS = {IOLine.DIO0_AD0, 27 | IOLine.DIO1_AD1, 28 | IOLine.DIO2_AD2, 29 | IOLine.DIO3_AD3}; 30 | CarTracker[] cars = new CarTracker[CAR_COUNT]; 31 | 32 | /* 33 | * The CarTracker class tracks the status of a car 34 | * in the race game. It tracks the car's button events, velocity, 35 | * distance traveled, and color. 36 | */ 37 | class CarTracker { 38 | private int[] millisPassed = {0, 0, 0}; 39 | private int millisIndex = 0; 40 | private int distance = 0; 41 | private int mycolor = 0; 42 | boolean buttonState = false; 43 | 44 | public CarTracker() { 45 | millisIndex = distance = 0; 46 | buttonState = false; 47 | } 48 | 49 | // Sets the color of the car. 50 | public void setColor(String thecolor) { 51 | switch (thecolor.charAt(0)) { 52 | case 'y': 53 | mycolor = 0xFFFFFF00; 54 | break; 55 | case 'r': 56 | mycolor = 0xFFFF0000; 57 | break; 58 | case 'b': 59 | mycolor = 0xFF0000FF; 60 | break; 61 | case 'g': 62 | mycolor = 0xFF00FF00; 63 | break; 64 | // pick a random color 65 | default: 66 | // This picks a random color by picking a random 67 | // number between 129-225 for red, green and blue. 68 | mycolor = 0xFF000000 + 69 | (128 + int(random(128)) * 0x10000) + 70 | 128 + int(random(128)) * 0x100 + 71 | 128 + int(random(128)); 72 | break; 73 | } 74 | } 75 | 76 | // Sets the pen to the color of the car. 77 | public int getColor() { 78 | return mycolor; 79 | } 80 | 81 | public int getDistance() { 82 | return distance; 83 | } 84 | 85 | public void setDistance(int distance) { 86 | this.distance = distance; 87 | } 88 | 89 | public void setButtonState(boolean buttonState) { 90 | this.buttonState = buttonState; 91 | } 92 | 93 | public boolean getButtonState() { 94 | return buttonState; 95 | } 96 | 97 | // Record a button press event (records 98 | // the time that the button was pressed). 99 | public void buttonEvent() { 100 | millisPassed[millisIndex] = millis(); 101 | // This make a round-robin index of the 102 | // millisPassed array so that millisIndex 103 | // always moves to the next postion in the array 104 | // or goes back to 0 (i.e., the sequence is 105 | // 0,1,2,0,1,2,0,1,2,0...) 106 | millisIndex = ++millisIndex % 3; 107 | } 108 | 109 | /* 110 | * Returns the current velocity of the car 111 | * based on the speed of the last 3 button 112 | * presses. 113 | */ 114 | public int getVelocity() { 115 | int current = millis(); 116 | int slowest = 0; 117 | for (int i = 0; i< 3; i++) { 118 | if (millisPassed[i] == 0) { 119 | slowest = 0x7fffffff; 120 | break; 121 | } 122 | if (slowest < current - millisPassed[i]) { 123 | slowest = current - millisPassed[i]; 124 | } 125 | } 126 | // As more than VELOCITY_SCALER milliseconds passes since the third to last 127 | // button press, the car will come to a stop. 128 | return VELOCITY_SCALER/slowest; 129 | } 130 | } 131 | 132 | void setup() { 133 | String[] colors = {"blue", "red", "green", "yellow"}; 134 | 135 | // initialize the cars 136 | for (int i = 0; i < CAR_COUNT; i++) { 137 | cars[i] = new CarTracker(); 138 | cars[i].setColor(colors[i]); 139 | } 140 | try { 141 | xbeeDevice = new Raw802Device(XBEE_PORT, XBEE_BAUD); 142 | xbeeDevice.open(); 143 | } 144 | catch (Exception e) { 145 | System.out.println("Failed to initialize XBee."); 146 | e.printStackTrace(); 147 | System.exit(1); 148 | } 149 | // Hooks the button handler to capture button press events. 150 | xbeeDevice.addIOSampleListener(new InputListener()); 151 | size(500, 700); 152 | } 153 | 154 | void drawCar(int carNum) { 155 | fill(cars[carNum].getColor()); 156 | rect(XPOS_CAR_OFFSET+XPOS_CAR_SPACER*carNum, 157 | YPOS_RACE_SIZE-(cars[carNum].getDistance()*YPOS_RACE_SIZE/RACE_COURSE_UNITS), 158 | XPOS_CAR_SIZE, 159 | YPOS_CAR_SIZE); 160 | } 161 | 162 | void checkWinner() { 163 | int winner = 0; 164 | for (int i = 0; i < CAR_COUNT; i++) { 165 | // If the car has traveled more than RACE_COURSE_UNITS it wins 166 | if (cars[i].getDistance() > RACE_COURSE_UNITS) { 167 | fill(cars[i].getColor()); 168 | background(0); 169 | winner = i + 1; 170 | textSize(32); 171 | text("Car " + winner + " wins!!!!", 50, 380); 172 | noLoop(); 173 | break; 174 | } 175 | } 176 | } 177 | 178 | void draw() { 179 | background(0); 180 | int spacer = 30; 181 | 182 | for (int i = 0; i < CAR_COUNT; i++) { 183 | cars[i].setDistance(cars[i].getDistance() + cars[i].getVelocity()); 184 | drawCar(i); 185 | } 186 | 187 | checkWinner(); 188 | } 189 | 190 | class InputListener implements IIOSampleReceiveListener { 191 | @Override 192 | public void ioSampleReceived(RemoteXBeeDevice remoteDevice, IOSample ioSample) { 193 | if (ioSample.hasDigitalValues()) { 194 | for (int i = 0; i < CAR_COUNT; i++) { 195 | IOValue ioValue = ioSample.getDigitalValue(INPUT_PINS[i]); 196 | // Require both an up and down event to register a button press event. 197 | if (ioValue == IOValue.LOW && cars[i].getButtonState() == true) { 198 | cars[i].setButtonState(false); 199 | cars[i].buttonEvent(); 200 | } 201 | else if (ioValue == IOValue.HIGH && cars[i].getButtonState() == false) { 202 | cars[i].setButtonState(true); 203 | } 204 | } 205 | } 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /racegame/sketch.properties: -------------------------------------------------------------------------------- 1 | mode.id=processing.mode.java.JavaMode 2 | mode=Java 3 | -------------------------------------------------------------------------------- /racegame_scalable/racegame_scalable.pde: -------------------------------------------------------------------------------- 1 | // XBee Java API library 2 | import com.digi.xbee.api.models.*; 3 | import com.digi.xbee.api.exceptions.*; 4 | import com.digi.xbee.api.io.*; 5 | import com.digi.xbee.api.packet.*; 6 | import com.digi.xbee.api.connection.serial.*; 7 | import com.digi.xbee.api.*; 8 | import com.digi.xbee.api.listeners.*; 9 | import com.digi.xbee.api.utils.*; 10 | import com.digi.xbee.api.packet.raw.*; 11 | import com.digi.xbee.api.packet.common.*; 12 | import com.digi.xbee.api.connection.*; 13 | 14 | /* 15 | * Game configuration section 16 | */ 17 | 18 | // Change the following line of code to the serial port connector to your XBee. 19 | final String XBEE_PORT = "COM5"; 20 | // Increase this to add additional racers (one per XBee not including the 21 | // coordinator). 22 | final int CAR_COUNT = 2; // Number of racers 23 | final int XBEE_BAUD = 9600; 24 | final int XPOS_CAR_OFFSET = 80; // X Position of first car 25 | final int XPOS_CAR_SPACER = 50; // X space between cars 26 | final int YPOS_RACE_SIZE = 600; // Size of the race course in pixels 27 | final int VELOCITY_SCALER = 10000; // Scales car speed by milliseconds specified 28 | final int RACE_COURSE_UNITS = 20000; // Size of the race course in arbitrary "units" 29 | final int XPOS_CAR_SIZE = 10; // Size of the car in the x axis 30 | final int YPOS_CAR_SIZE = 30; // Size of the car in the y axis 31 | /* 32 | * End configuration 33 | */ 34 | 35 | boolean message; 36 | XBeeDevice xbeeDevice; 37 | final IOLine INPUT_PIN = IOLine.DIO1_AD1; 38 | 39 | class CarTracker { 40 | private int[] millisPassed = {0, 0, 0}; 41 | private int millisIndex = 0; 42 | private int distance = 0; 43 | private XBee16BitAddress xbeeAddress = new XBee16BitAddress(new byte[] {0, 0}); 44 | private int mycolor = 0; 45 | boolean buttonState = false; 46 | 47 | public CarTracker() { 48 | millisIndex = distance = 0; 49 | buttonState = false; 50 | } 51 | 52 | // Sets the color of the car. 53 | public void setColor(String thecolor) { 54 | switch (thecolor.charAt(0)) { 55 | case 'y': 56 | mycolor = 0xFFFFFF00; 57 | break; 58 | case 'r': 59 | mycolor = 0xFFFF0000; 60 | break; 61 | case 'b': 62 | mycolor = 0xFF0000FF; 63 | break; 64 | case 'g': 65 | mycolor = 0xFF00FF00; 66 | break; 67 | // pick a random color 68 | default: 69 | // This picks a random color by picking a random 70 | // number between 129-225 for red, green and blue. 71 | mycolor = 0xFF000000 + 72 | (128 + int(random(128)) * 0x10000) + 73 | 128 + int(random(128)) * 0x100 + 74 | 128 + int(random(128)); 75 | break; 76 | } 77 | } 78 | 79 | // Sets the pen to the color of the car. 80 | public int getColor() { 81 | return mycolor; 82 | } 83 | 84 | public XBee16BitAddress getXBeeAddress() { 85 | return xbeeAddress; 86 | } 87 | 88 | public void setXBeeAddress(XBee16BitAddress xbeeAddress) { 89 | this.xbeeAddress = xbeeAddress; 90 | } 91 | 92 | public boolean isXBeeAddressZero() { 93 | return xbeeAddress.equals(XBee16BitAddress.COORDINATOR_ADDRESS); 94 | } 95 | 96 | public int getDistance() { 97 | return distance; 98 | } 99 | 100 | public void setDistance(int distance) { 101 | this.distance = distance; 102 | } 103 | 104 | public void setButtonState(boolean buttonState) { 105 | this.buttonState = buttonState; 106 | } 107 | 108 | public boolean getButtonState() { 109 | return buttonState; 110 | } 111 | 112 | // Record a button press event (records 113 | // the time that the button was pressed). 114 | public void buttonEvent() { 115 | millisPassed[millisIndex] = millis(); 116 | // This make a round-robin index of the 117 | // millisPassed array so that millisIndex 118 | // always moves to the next postion in the array 119 | // or goes back to 0 (i.e., the sequence is 120 | // 0,1,2,0,1,2,0,1,2,0...) 121 | millisIndex = ++millisIndex % 3; 122 | } 123 | 124 | /* 125 | * Returns the current velocity of the car 126 | * based on the speed of the last 3 button 127 | * presses. 128 | */ 129 | public int getVelocity() { 130 | int current = millis(); 131 | int slowest = 0; 132 | for (int i = 0; i< 3; i++) { 133 | if (millisPassed[i] == 0) { 134 | slowest = 0x7fffffff; 135 | break; 136 | } 137 | if (slowest < current - millisPassed[i]) { 138 | slowest = current - millisPassed[i]; 139 | } 140 | } 141 | // As more than VELOCITY_SCALER milliseconds passes since the third to last 142 | // button press, the car will come to a stop. 143 | return VELOCITY_SCALER/slowest; 144 | } 145 | } 146 | 147 | CarTracker[] cars = new CarTracker[CAR_COUNT]; 148 | 149 | int initIndex = 0; 150 | 151 | // Assigns XBees to the cars. Each time around 152 | // the draw loop prompts the next user for a button 153 | // press until all the XBees/buttons are assigned to 154 | // cars. 155 | void assignButtons() { 156 | String[] colors = {"blue", "red", "green", "yellow"}; 157 | 158 | background(0); 159 | textSize(32); 160 | if (initIndex < 4) { 161 | cars[initIndex].setColor(colors[initIndex]); 162 | } 163 | else { 164 | cars[initIndex].setColor("custom"); 165 | } 166 | fill(cars[initIndex].getColor()); 167 | int i = initIndex + 1; 168 | text("Car # " + i + " press your button.", 50, 380); 169 | } 170 | 171 | void setup() { 172 | for (int i = 0; i < CAR_COUNT; i++) { 173 | cars[i] = new CarTracker(); 174 | } 175 | 176 | try { 177 | xbeeDevice = new Raw802Device(XBEE_PORT, XBEE_BAUD); 178 | xbeeDevice.open(); 179 | 180 | // Hooks the button handler to assign buttons. 181 | xbeeDevice.addIOSampleListener(new InitInputListener()); 182 | size(500, 700); 183 | } 184 | catch (Exception e) { 185 | System.out.println("XBee failed to initialize"); 186 | e.printStackTrace(); 187 | System.exit(1); 188 | } 189 | } 190 | 191 | void drawCar(int carNum) { 192 | fill(cars[carNum].getColor()); 193 | rect(XPOS_CAR_OFFSET+XPOS_CAR_SPACER*carNum, 194 | YPOS_RACE_SIZE-(cars[carNum].getDistance()*YPOS_RACE_SIZE/RACE_COURSE_UNITS), 195 | XPOS_CAR_SIZE, 196 | YPOS_CAR_SIZE); 197 | } 198 | 199 | void checkWinner() { 200 | int winner = 0; 201 | for (int i = 0; i < CAR_COUNT; i++) { 202 | // If the car has traveled more than RACE_COURSE_UNITS it wins 203 | if (cars[i].getDistance() > RACE_COURSE_UNITS) { 204 | fill(cars[i].getColor()); 205 | background(0); 206 | winner = i + 1; 207 | textSize(32); 208 | text("Car " + winner + " wins!!!!", 50, 380); 209 | noLoop(); 210 | break; 211 | } 212 | } 213 | } 214 | 215 | 216 | void draw() { 217 | background(0); 218 | if (initIndex < CAR_COUNT) { 219 | assignButtons(); 220 | } 221 | else { 222 | int spacer = 30; 223 | 224 | for (int i = 0; i < CAR_COUNT; i++) { 225 | // Move the car. 226 | cars[i].setDistance(cars[i].getDistance() + cars[i].getVelocity()); 227 | drawCar(i); 228 | } 229 | 230 | checkWinner(); 231 | } 232 | } 233 | 234 | class InitInputListener implements IIOSampleReceiveListener { 235 | 236 | @Override 237 | public void ioSampleReceived(RemoteXBeeDevice remoteDevice, IOSample ioSample) { 238 | 239 | try { 240 | XBee16BitAddress address = remoteDevice.get16BitAddress(); 241 | for (int i = 0; i < initIndex ; i++) { 242 | if (cars[i].getXBeeAddress().equals(address)) { 243 | return; 244 | } 245 | } 246 | cars[initIndex++].setXBeeAddress(address); 247 | // Last car registered, reassign handler to start the race. 248 | if (initIndex == CAR_COUNT) { 249 | xbeeDevice.removeIOSampleListener(this); 250 | // Hooks the button handler to capture button press events. 251 | xbeeDevice.addIOSampleListener(new InputListener()); 252 | } 253 | } 254 | catch (Exception e) { 255 | println("oops"); 256 | } 257 | } 258 | 259 | } 260 | 261 | class InputListener implements IIOSampleReceiveListener { 262 | @Override 263 | public void ioSampleReceived(RemoteXBeeDevice remoteDevice, IOSample ioSample) { 264 | if (ioSample.hasDigitalValues()) { 265 | for (int i = 0; i < CAR_COUNT; i++) { 266 | if (cars[i].getXBeeAddress().equals(remoteDevice.get16BitAddress())){ 267 | IOValue ioValue = ioSample.getDigitalValue(INPUT_PIN); 268 | // Require both an up and down event to register a button press event. 269 | if (ioValue == IOValue.LOW && cars[i].getButtonState() == true) { 270 | cars[i].setButtonState(false); 271 | cars[i].buttonEvent(); 272 | } 273 | else if (ioValue == IOValue.HIGH && cars[i].getButtonState() == false) { 274 | cars[i].setButtonState(true); 275 | } 276 | } 277 | } 278 | } 279 | } 280 | } 281 | -------------------------------------------------------------------------------- /racegame_scalable/sketch.properties: -------------------------------------------------------------------------------- 1 | mode.id=processing.mode.java.JavaMode 2 | mode=Java 3 | -------------------------------------------------------------------------------- /rockpaperscissors/rockpaperscissors.ino: -------------------------------------------------------------------------------- 1 | /* This program implements a simple rock-paper-scissors game. An XBee will be 2 | * attached to the Arduino on an XBee shield. The Arduino will 'count down' 3 | * until it is ready for players to choose either rock, paper, or scissors. 4 | * Once both players have made a selection, their selections will be revealed 5 | * and the winner indicated. 6 | * 7 | * This code is written assuming use of an Arduino Leonardo and access to the 8 | * hardware serial port 'Serial1'. It will need to be modified slightly if you 9 | * choose to use a software serial port or another variant of Arduino. 10 | */ 11 | 12 | // Uses the 'xbee-arduino' library. 13 | // https://code.google.com/p/xbee-arduino/ 14 | #include 15 | 16 | // Constant values to specify player selections. 17 | #define NO_CHOICE 0 18 | #define ROCK 1 19 | #define PAPER 2 20 | #define SCISSORS 4 21 | 22 | // Digital I/O pins on the remote XBees. Change if necessary. 23 | #define ROCK_PIN 1 24 | #define PAPER_PIN 2 25 | #define SCISSORS_PIN 3 26 | 27 | // Declares which I/O pins on the Arduino correspond to the LEDs for each player. 28 | int pins[2][3] = { 29 | { 2, 3, 4 }, // Player 1: Rock, Paper, Scissors 30 | { 5, 6, 7 } // Player 2: Rock, Paper, Scissors 31 | }; 32 | 33 | // Used to determine which player an I/O packet corresponds to. 34 | const uint16_t PLAYER1_XBEE_ADDR = 0x1235; 35 | const uint16_t PLAYER2_XBEE_ADDR = 0x1236; 36 | 37 | XBee xbee = XBee(); 38 | 39 | int player1 = NO_CHOICE, 40 | player2 = NO_CHOICE; 41 | 42 | //=============================== 43 | // Utility functions 44 | 45 | void clearAll() { 46 | for (int i = 0; i < 3; i++) { 47 | digitalWrite(pins[0][i], LOW); 48 | digitalWrite(pins[1][i], LOW); 49 | } 50 | } 51 | void turnAllOn() { 52 | for (int i = 0; i < 3; i++) { 53 | digitalWrite(pins[0][i], HIGH); 54 | digitalWrite(pins[1][i], HIGH); 55 | } 56 | } 57 | int choiceToPinIndex(int choice) { 58 | switch (choice) { 59 | case ROCK: 60 | return 0; 61 | case PAPER: 62 | return 1; 63 | case SCISSORS: 64 | return 2; 65 | default: 66 | return -1; 67 | } 68 | } 69 | 70 | /** 71 | * Pre-game light show, a countdown. Goes like this: 72 | * [x] [ ] [ ] 73 | * [x] [ ] [ ] 74 | * (delay) 75 | * [ ] [x] [ ] 76 | * [ ] [x] [ ] 77 | * (delay) 78 | * [ ] [ ] [x] 79 | * [ ] [ ] [x] 80 | * (delay) 81 | * [x] [x] [x] 82 | * [x] [x] [x] 83 | * 84 | * Analogous to shouting "rock, paper, scissors" before playing. 85 | */ 86 | void pregame() { 87 | // Clear out all the pins. 88 | clearAll(); 89 | delay(300); 90 | 91 | // Initiate a "countdown." Start with the first pair of LEDs. 92 | for (int i = 0; i < 3; i++) { 93 | digitalWrite(pins[0][i], HIGH); 94 | digitalWrite(pins[1][i], HIGH); 95 | 96 | delay(250); 97 | 98 | digitalWrite(pins[0][i], LOW); 99 | digitalWrite(pins[1][i], LOW); 100 | } 101 | 102 | // Now that we're ready, turn all the LEDs on. 103 | turnAllOn(); 104 | 105 | player1 = player2 = NO_CHOICE; 106 | } 107 | 108 | int getChoiceFromResponse(Rx16IoSampleResponse response) { 109 | boolean rock, paper, scissors; 110 | 111 | rock = !response.isDigitalOn(ROCK_PIN, 0); 112 | paper = !response.isDigitalOn(PAPER_PIN, 0); 113 | scissors = !response.isDigitalOn(SCISSORS_PIN, 0); 114 | 115 | // If only one is active, then return that. 116 | if (rock && !(paper || scissors)) return ROCK; 117 | if (paper && !(rock || scissors)) return PAPER; 118 | if (scissors && !(rock || paper)) return SCISSORS; 119 | 120 | // None are active, or more than one is active. 121 | return NO_CHOICE; 122 | } 123 | 124 | /** 125 | * Make the LED for the given choice flash a few times, to indicate they won. 126 | * If `player` is -1, it is assumed that both players tied, and so the same LED 127 | * for both players will be flashed. 128 | */ 129 | void presentWinner(int player, int choice) { 130 | int pin = choiceToPinIndex(choice); 131 | boolean writeLow = true; 132 | 133 | int i = 0; 134 | do { 135 | if (player < 0) { 136 | digitalWrite(pins[0][pin], writeLow ? LOW : HIGH); 137 | digitalWrite(pins[1][pin], writeLow ? LOW : HIGH); 138 | } else { 139 | digitalWrite(pins[player][pin], writeLow ? LOW : HIGH); 140 | } 141 | 142 | writeLow = !writeLow; 143 | delay(250); 144 | } while (++i < 4); 145 | } 146 | 147 | //============================= 148 | // Required Arduino functions 149 | 150 | void setup() { 151 | // Turn all the necessary pins to OUTPUT mode 152 | for (int i = 0; i < 2; i++) { 153 | for (int j = 0; j < 3; j++) { 154 | pinMode(pins[i][j], OUTPUT); 155 | 156 | // Also turn them all off 157 | digitalWrite(pins[i][j], LOW); 158 | } 159 | } 160 | 161 | // Set up the XBee interface. 162 | Serial1.begin(9600); 163 | xbee.begin(Serial1); 164 | 165 | // Start the game. 166 | pregame(); 167 | } 168 | 169 | void loop() { 170 | if (player1 == NO_CHOICE || player2 == NO_CHOICE) { 171 | // At least one player has not made a selection yet. 172 | xbee.readPacket(100); 173 | 174 | if (xbee.getResponse().isAvailable() && xbee.getResponse().getApiId() == RX_16_IO_RESPONSE) { 175 | // And it's an IO sample response. 176 | Rx16IoSampleResponse response = Rx16IoSampleResponse(); 177 | xbee.getResponse().getRx16IoSampleResponse(response); 178 | 179 | // Determine if this data is from one of the players in this game. 180 | int *player; 181 | 182 | switch (response.getRemoteAddress16()) { 183 | case PLAYER1_XBEE_ADDR: 184 | player = &player1; 185 | break; 186 | case PLAYER2_XBEE_ADDR: 187 | player = &player2; 188 | break; 189 | default: 190 | // IO sample from the XBee on the shield, or some other XBee on this 191 | // network. 192 | return; 193 | } 194 | 195 | int choice = getChoiceFromResponse(response); 196 | if (choice == NO_CHOICE || *player != NO_CHOICE) { 197 | // No buttons are being pushed, or the player has already made a 198 | // selection. 199 | return; 200 | } 201 | 202 | // Set the player's selection. 203 | *player = choice; 204 | } 205 | } else { 206 | // Both players have made a selection. 207 | 208 | // Clear all LEDs. 209 | clearAll(); 210 | 211 | // Turn on the LEDs for each player. 212 | digitalWrite(pins[0][choiceToPinIndex(player1)], HIGH); 213 | digitalWrite(pins[1][choiceToPinIndex(player2)], HIGH); 214 | 215 | // Decide who won. 216 | int winner = -1; 217 | 218 | if (player1 == ROCK && player2 == SCISSORS || 219 | player1 == SCISSORS && player2 == PAPER || 220 | player1 == PAPER && player2 == ROCK) { 221 | winner = 0; 222 | } else if (player1 != player2) { 223 | // Both players had a different hand, and Player 1 wasn't the winner... hence player 2 wins. 224 | winner = 1; 225 | } 226 | 227 | // Indicate who won. If `winner` is -1, both player's LEDs will flash. 228 | presentWinner(winner, (winner ? player2 : player1)); 229 | 230 | // Wait a moment. 231 | delay(1500); 232 | 233 | // Start another round. 234 | pregame(); 235 | } 236 | } 237 | -------------------------------------------------------------------------------- /rssi_seek/rssi_seek.ino: -------------------------------------------------------------------------------- 1 | /* This program implements a simple hide and seek game. An XBee will 2 | * be attached to the Arduino on an XBee shield. This code will 3 | * periodically send an ATDB (RSSI) command to another XBee being 4 | * sought and display the received signal value on six LEDs attached 5 | * to digital outputs. 6 | * 7 | * For convenience, the six LEDS are assumed to be attached to digital 8 | * pins eight through thirteen. These pin indices are used directly. 9 | * Use of different pins is left as an exercise to the reader. 10 | * 11 | * This code is written assuming use of an Arduino Leonardo and access 12 | * to the hardware serial port 'Serial1'. It will need to be modified 13 | * slightly if you choose to use a software serial port or another 14 | * variant of Arduino. 15 | */ 16 | 17 | // Uses the 'xbee-arduino' library. 18 | // https://code.google.com/p/xbee-arduino/ 19 | #include 20 | 21 | // Uncomment the line below to include activity logging of this application to the 22 | // serial port of your Arduino Leonardo 23 | //#define SERIAL_LOG 1 24 | 25 | XBee xbee = XBee(); 26 | 27 | // The address of the remote XBee that we're seeking 28 | XBeeAddress64 remote = XBeeAddress64(0x0013a200, 0x40c179e1); 29 | 30 | // The command to send to the remote XBee 31 | uint8_t db_command[] = { 'D', 'B' }; 32 | 33 | // RSSI values that will light progressive LEDS based on signal strength. 34 | // Signals can take on ranges of: 35 | // XBee: 23 - 92 36 | // XBee-PRO: 36 - 100 37 | // The range here uses the outliers of both, so will work, but this 38 | //can be improved if you know the family you've selected. 39 | int led_breaks[] = { 100, 87, 74, 62, 49, 36 }; 40 | 41 | // Track the last time we requested RSSI so we can send periodically. 42 | unsigned long last_sent; 43 | 44 | void setup() { 45 | 46 | #ifdef SERIAL_LOG 47 | // Wait for serial to attach 48 | Serial.begin(9600); 49 | while (!Serial) ; 50 | #endif 51 | 52 | // Open the local serial port and tell the xbee-arduino library to 53 | // use it for XBee traffic. 54 | Serial1.begin(9600); 55 | xbee.begin(Serial1); 56 | 57 | // Configure LED pins, start them off 58 | for (int i = 8 ; i <= 13 ; i++) { 59 | pinMode(i, OUTPUT); 60 | digitalWrite(i, LOW); 61 | } 62 | // Turn 8 on as an indication that the sketch is running 63 | digitalWrite(8, HIGH); 64 | 65 | // Perform our first signal request 66 | requestRssi(); 67 | } 68 | 69 | void loop() { 70 | // Find out if a packet is available 71 | xbee.readPacket(); 72 | 73 | if (xbee.getResponse().isAvailable()) { 74 | // Process any packets received 75 | switch (xbee.getResponse().getApiId()) { 76 | case REMOTE_AT_COMMAND_RESPONSE: 77 | // Send any AT response off to be handled (we only care about DB though) 78 | processAtResponse(); 79 | break; 80 | default: 81 | #ifdef SERIAL_LOG 82 | // Our code doesn't care about any other packet so inform the 83 | // serial monitor in case someone is interested and proceed. 84 | Serial.print("Got unhandled API frame: "); 85 | Serial.println(xbee.getResponse().getApiId()); 86 | #endif 87 | 88 | break; 89 | } 90 | } 91 | 92 | if (xbee.getResponse().isError()) { 93 | #ifdef SERIAL_LOG 94 | // On error we have no sophisticated handling strategy, so inform 95 | // the serial monitor and continue. 96 | Serial.print("Error: "); 97 | Serial.println(xbee.getResponse().getErrorCode()); 98 | #endif 99 | } 100 | 101 | // Generate requests once per second. 102 | if (millis() - last_sent > 1000) { 103 | requestRssi(); 104 | } 105 | } 106 | 107 | void processAtResponse() { 108 | // Get the response details out of the packet. 109 | RemoteAtCommandResponse rsp = RemoteAtCommandResponse(); 110 | xbee.getResponse().getRemoteAtCommandResponse(rsp); 111 | 112 | // Check if this is a DB response (only thing we expect) 113 | if (memcmp(db_command, rsp.getCommand(), 2) == 0) { 114 | 115 | uint8_t status = rsp.getStatus(); 116 | #ifdef SERIAL_LOG 117 | if (status != 0) { 118 | Serial.println("Error status"); 119 | Serial.println(status); 120 | } 121 | #endif 122 | 123 | uint8_t rssi = 255; 124 | if (status == 0) { 125 | // getValue returns a pointer to array of uint8_t. We know that 126 | // on success for ATDB the RSSI will be present in the first (and 127 | // only) position. 128 | rssi = *rsp.getValue(); 129 | if (rsp.getValueLength() != 1) { 130 | /* A failed response does not contain the payload as expected, 131 | * turn off all the LEDs by indicating worst case RSSI. 132 | */ 133 | #ifdef SERIAL_LOG 134 | Serial.println("Bad value length"); 135 | #endif 136 | rssi = 255; 137 | } 138 | #ifdef SERIAL_LOG 139 | // Record signal to serial monitor 140 | Serial.println(rssi); 141 | #endif 142 | } 143 | 144 | /* Progressively light LEDs based on signal thresholds. Low DB 145 | * response values indicate better signal strength as the value is 146 | * the absolute value of negative dBm. 147 | */ 148 | for (int i = 0 ; i < 6 ; i++) { 149 | if (rssi < led_breaks[i]) { 150 | digitalWrite(i+8, HIGH); 151 | } else { 152 | digitalWrite(i+8, LOW); 153 | } 154 | } 155 | } 156 | } 157 | 158 | // Create and send an ATDB request to the remote XBee 159 | void requestRssi() { 160 | RemoteAtCommandRequest req = RemoteAtCommandRequest(remote, db_command); 161 | #ifdef SERIAL_LOG 162 | Serial.println("Making RSSI request"); 163 | #endif 164 | xbee.send(req); 165 | last_sent = millis(); 166 | } 167 | -------------------------------------------------------------------------------- /spaceinvaders/Conf.pde: -------------------------------------------------------------------------------- 1 | class Conf 2 | { 3 | boolean flag; 4 | boolean game; 5 | boolean fpY; 6 | boolean moveRight,moveLeft,fire; 7 | boolean senss; 8 | boolean jeu; 9 | boolean shiptouche; 10 | boolean shiptoucheLaser; 11 | 12 | float sense; 13 | 14 | int deltaX; 15 | int deltaY; 16 | int vie; 17 | int score; 18 | int fcount; 19 | int[] konami = new int[10]; 20 | int[] konamicode = {1,1,2,2,3,4,3,4,6,5}; 21 | 22 | PImage filtre; 23 | PFont fontA; 24 | 25 | 26 | Conf() 27 | { 28 | deltaX=width/10+35; 29 | deltaY=height/10+50; 30 | flag=true; 31 | fpY=false; 32 | game=true; 33 | moveRight=false; 34 | moveLeft=false; 35 | fire=false; 36 | senss=false; 37 | jeu=false; 38 | shiptouche=false; 39 | shiptoucheLaser=false; 40 | vie=3; 41 | sense=5; 42 | fcount=30; 43 | score=0; 44 | filtre = loadImage("filtrejeu.tga"); 45 | fontA = loadFont("CourierNew36.vlw"); 46 | } 47 | 48 | 49 | } 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /spaceinvaders/Invader.pde: -------------------------------------------------------------------------------- 1 | /** Clone de Space Invader **/ 2 | /** Programmation Tristan Brismontier **/ 3 | 4 | class Invader 5 | { 6 | int type; 7 | float spX; 8 | float spY; 9 | int taillex; 10 | int tailley; 11 | float speedx; 12 | int speedy; 13 | boolean existe; 14 | boolean fspY=false; 15 | 16 | Invader() 17 | { 18 | spX=width/2; 19 | spY=height/2; 20 | 21 | existe=true; 22 | 23 | speedy = 1; 24 | speedx = 5; 25 | 26 | taillex = 2; 27 | tailley = 2; 28 | } 29 | 30 | Invader(int X_, int Y_, int _type) 31 | { 32 | type=_type; 33 | spX=X_; 34 | spY=Y_; 35 | 36 | existe=true; 37 | 38 | speedy = 1; 39 | speedx =5; 40 | 41 | taillex = 2; 42 | tailley = 2; 43 | 44 | } 45 | 46 | void display(boolean flag) 47 | { 48 | if(existe==true) 49 | { 50 | if(type==1) 51 | { 52 | 53 | noStroke(); 54 | fill(255); 55 | rectMode(CORNER); 56 | rect(-2*taillex+spX,-4*tailley+spY,4*taillex,tailley); 57 | rect(-5*taillex+spX,-3*tailley+spY,10*taillex,tailley); 58 | rect(-6*taillex+spX,-2*tailley+spY,12*taillex,tailley); 59 | rect(-6*taillex+spX,-1*tailley+spY,3*taillex,tailley); 60 | rect(-1*taillex+spX,-1*tailley+spY,2*taillex,tailley); 61 | rect(3*taillex+spX,-1*tailley+spY,3*taillex,tailley); 62 | rect(-6*taillex+spX,spY,12*taillex,tailley); 63 | rect(1*taillex+spX,1*tailley+spY,2*taillex,tailley); 64 | rect(-3*taillex+spX,1*tailley+spY,2*taillex,tailley); 65 | rect(-1*taillex+spX,2*tailley+spY,2*taillex,tailley); 66 | 67 | if( flag==false) 68 | { 69 | rect(-4*taillex+spX,2*tailley+spY,2*taillex,tailley); 70 | rect(2*taillex+spX,2*tailley+spY,2*taillex,tailley); 71 | rect(-6*taillex+spX,3*tailley+spY,2*taillex,tailley); 72 | rect(4*taillex+spX,3*tailley+spY,2*taillex,tailley); 73 | } 74 | else 75 | { 76 | rect(-5*taillex+spX,2*tailley+spY,2*taillex,tailley); 77 | rect(3*taillex+spX,2*tailley+spY,2*taillex,tailley); 78 | rect(-4*taillex+spX,3*tailley+spY,2*taillex,tailley); 79 | rect(2*taillex+spX,3*tailley+spY,2*taillex,tailley); 80 | } 81 | 82 | } 83 | if(type==2) 84 | { 85 | noStroke(); 86 | fill(255); 87 | rectMode(CORNER); 88 | rect(-3.5*taillex+spX,-5.0*tailley+spY,1*taillex,1*tailley); 89 | rect(2.5*taillex+spX,-5.0*tailley+spY,1*taillex,1*tailley); 90 | rect(-2.5*taillex+spX,-4.0*tailley+spY,1*taillex,1*tailley); 91 | rect(1.5*taillex+spX,-4.0*tailley+spY,1*taillex,1*tailley); 92 | rect(-3.5*taillex+spX,-3.0*tailley+spY,7*taillex,1*tailley); 93 | rect(-3.5*taillex+spX,-3.0*tailley+spY,1*taillex,5*tailley); 94 | rect(2.5*taillex+spX,-3.0*tailley+spY,1*taillex,5*tailley); 95 | rect(-3.5*taillex+spX,-1.0*tailley+spY,7*taillex,2*tailley); 96 | rect(-1.5*taillex+spX,-2.0*tailley+spY,3*taillex,1*tailley); 97 | rect(-4.5*taillex+spX,-2.0*tailley+spY,1*taillex,2*tailley); 98 | rect(3.5*taillex+spX,-2.0*tailley+spY,1*taillex,2*tailley); 99 | if( flag==false) 100 | { 101 | rect(-5.5*taillex+spX,-1.0*tailley+spY,1*taillex,3*tailley); 102 | rect(4.5*taillex+spX,-1.0*tailley+spY,1*taillex,3*tailley); 103 | rect(.5*taillex+spX,2.0*tailley+spY,2*taillex,1*tailley); 104 | rect(-2.5*taillex+spX,2.0*tailley+spY,2*taillex,1*tailley); 105 | } 106 | else 107 | { 108 | rect(-5.5*taillex+spX,-4.0*tailley+spY,1*taillex,3*tailley); 109 | rect(4.5*taillex+spX,-4.0*tailley+spY,1*taillex,3*tailley); 110 | rect(3.5*taillex+spX,2.0*tailley+spY,1*taillex,1*tailley); 111 | rect(-4.5*taillex+spX,2.0*tailley+spY,1*taillex,1*tailley); 112 | } 113 | } 114 | if(type==3) 115 | { 116 | noStroke(); 117 | fill(255); 118 | rectMode(CORNER); 119 | rect(-1*taillex+spX,-3*tailley+spY,2*taillex,tailley); 120 | rect(-2*taillex+spX,-2*tailley+spY,4*taillex,tailley); 121 | rect(-3*taillex+spX,-1*tailley+spY,6*taillex,tailley); 122 | rect(-4*taillex+spX,spY,2*taillex,tailley); 123 | rect(-1*taillex+spX,spY,2*taillex,tailley); 124 | rect(2*taillex+spX,spY,2*taillex,tailley); 125 | rect(-4*taillex+spX,1*tailley+spY,8*taillex,tailley); 126 | rect(-2*taillex+spX,2*tailley+spY,taillex,tailley); 127 | rect(taillex+spX,2*tailley+spY,taillex,tailley); 128 | rect(-3*taillex+spX,3*tailley+spY,taillex,tailley); 129 | rect(2*taillex+spX,3*tailley+spY,taillex,tailley); 130 | rect(-2*taillex+spX,4*tailley+spY,taillex,tailley); 131 | rect(taillex+spX,4*tailley+spY,taillex,tailley); 132 | rect(-2*taillex+spX,4*tailley+spY,taillex,tailley); 133 | rect(taillex+spX,4*tailley+spY,taillex,tailley); 134 | 135 | if( flag==false) 136 | { 137 | rect(-4*taillex+spX,4*tailley+spY,taillex,tailley); 138 | rect(3*taillex+spX,4*tailley+spY,taillex,tailley); 139 | rect(-1*taillex+spX,3*tailley+spY,2*taillex,tailley); 140 | } 141 | 142 | } 143 | } 144 | } 145 | 146 | boolean move(float signe, boolean fpY) 147 | { 148 | 149 | if(fpY!=fspY) 150 | { 151 | spY = spY + 10; 152 | fspY=fpY; 153 | return false; 154 | } 155 | else 156 | { 157 | //float speedxt = speedx * signe; 158 | spX = spX + signe; 159 | if(existe==true) 160 | { 161 | if( spX > 14*width/15 ) 162 | { 163 | return true; 164 | } 165 | else 166 | { 167 | if( spX < width/15 ) 168 | { 169 | return true; 170 | } 171 | else 172 | { 173 | return false; 174 | } 175 | } 176 | } 177 | else 178 | { 179 | return false; 180 | } 181 | } 182 | } 183 | 184 | boolean contact(float x_, float y_) 185 | { 186 | if(existe==true) 187 | { 188 | if(x_ < 4.5*taillex+spX+taillex && x_ > -4.5*taillex+spX-taillex && y_>-5.0*tailley+spY && y_ < 2.0*tailley+spY) 189 | { 190 | existe=false; 191 | 192 | } 193 | return existe; 194 | } 195 | else 196 | { 197 | return true; 198 | } 199 | } 200 | } 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | -------------------------------------------------------------------------------- /spaceinvaders/Laser.pde: -------------------------------------------------------------------------------- 1 | /** Clone de Space Invader **/ 2 | /** Programmation Tristan Brismontier **/ 3 | 4 | class Laser 5 | { 6 | float pX; 7 | float pY; 8 | float taille; 9 | boolean tire; 10 | float speedy; 11 | int type; 12 | boolean unedeux=true; 13 | 14 | Laser(float x_, float y_) 15 | { 16 | pX=x_; 17 | pY=y_; 18 | taille = 3; 19 | tire=false; 20 | speedy=-2.5; 21 | type = 2; 22 | } 23 | 24 | Laser() 25 | { 26 | pX=width/2; 27 | pY=9*height/10; 28 | taille = 2; 29 | tire=false; 30 | speedy=4.1; 31 | type = 1; 32 | } 33 | 34 | void display() 35 | { 36 | if(tire==true) 37 | { 38 | if(type==1) 39 | { 40 | strokeWeight(taille); 41 | stroke(255); 42 | line(pX,pY,pX,pY-5*taille); 43 | } 44 | else 45 | { 46 | strokeWeight(taille-1); 47 | stroke(255); 48 | line(pX+taille,pY,pX-taille,pY-taille); 49 | line(pX-taille,pY-taille,pX+taille,pY-2*taille); 50 | line(pX+taille,pY-2*taille,pX-taille,pY-3*taille); 51 | line(pX-taille,pY-3*taille,pX+taille,pY-4*taille); 52 | line(pX+taille,pY-4*taille,pX-taille,pY-5*taille); 53 | } 54 | } 55 | } 56 | 57 | void move() 58 | { 59 | if(tire==true) 60 | { 61 | pY=pY - speedy; 62 | if( pY < 0 || pY > height+5*taille ) 63 | { 64 | pX=0; 65 | pY=0; 66 | tire=false; 67 | } 68 | } 69 | } 70 | 71 | void lancement(float x_) 72 | { 73 | if(tire==false) 74 | { 75 | tire=true; 76 | pX=x_; 77 | if(unedeux==true) 78 | { 79 | pY=9*height/10; 80 | unedeux=!unedeux; 81 | } 82 | else 83 | { 84 | pY=9*height/10-2; 85 | unedeux=!unedeux; 86 | } 87 | 88 | } 89 | } 90 | 91 | void lancement(float x_,float y_) 92 | { 93 | if(tire==false) 94 | { 95 | tire=true; 96 | pX=x_; 97 | pY=y_; 98 | 99 | 100 | } 101 | 102 | } 103 | } 104 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /spaceinvaders/MotherShip.pde: -------------------------------------------------------------------------------- 1 | 2 | class MotherShip 3 | { 4 | 5 | float spX; 6 | float spY; 7 | int taillex; 8 | int tailley; 9 | float speedx; 10 | boolean existe; 11 | boolean sens; 12 | 13 | 14 | MotherShip() 15 | { 16 | spX=width/2; 17 | spY=65; 18 | 19 | existe=false; 20 | 21 | speedx = 1; 22 | 23 | taillex = 2; 24 | tailley = 2; 25 | } 26 | 27 | 28 | 29 | void display() 30 | { 31 | if(existe==true) 32 | { 33 | 34 | noStroke(); 35 | fill(255,10,10); 36 | rectMode(CORNER); 37 | rect(-3*taillex+spX,-3*tailley+spY,6*taillex,tailley); 38 | rect(-5*taillex+spX,-2*tailley+spY,10*taillex,tailley); 39 | rect(-6*taillex+spX,-1*tailley+spY,12*taillex,tailley); 40 | rect(-7*taillex+spX,0*tailley+spY,2*taillex,tailley); 41 | rect(-4*taillex+spX,0*tailley+spY,2*taillex,tailley); 42 | rect(-1*taillex+spX,0*tailley+spY,2*taillex,tailley); 43 | rect(2*taillex+spX,0*tailley+spY,2*taillex,tailley); 44 | rect(5*taillex+spX,0*tailley+spY,2*taillex,tailley); 45 | rect(-8*taillex+spX,1*tailley+spY,16*taillex,tailley); 46 | rect(-6*taillex+spX,2*tailley+spY,3*taillex,tailley); 47 | rect(-1*taillex+spX,2*tailley+spY,2*taillex,tailley); 48 | rect(3*taillex+spX,2*tailley+spY,3*taillex,tailley); 49 | rect(-5*taillex+spX,3*tailley+spY,1*taillex,tailley); 50 | rect(4*taillex+spX,3*tailley+spY,1*taillex,tailley); 51 | 52 | } 53 | } 54 | 55 | void lancement(float k) 56 | { 57 | if( k < 1 ) 58 | { 59 | 60 | spX=-7*taillex; 61 | sens = true; 62 | } 63 | else 64 | { 65 | spX=width+7*taillex; 66 | sens=false; 67 | } 68 | speedx=random(0.8,2); 69 | existe=true; 70 | } 71 | 72 | 73 | void move() 74 | { 75 | if(spX +8*taillex > 0 && spX - 8*taillex < width) 76 | { 77 | if( sens == true ) 78 | { 79 | spX = spX + speedx; 80 | } 81 | else 82 | { 83 | 84 | spX = spX -speedx; 85 | } 86 | } 87 | else 88 | { 89 | existe=false; 90 | } 91 | } 92 | 93 | boolean contact(float x_, float y_) 94 | { 95 | if(existe==true) 96 | { 97 | if(x_ < spX +8*taillex && x_ > spX - 8*taillex && y_> -3*tailley+spY && y_ < 3*tailley+spY) 98 | { 99 | existe=false; 100 | 101 | } 102 | return existe; 103 | } 104 | else 105 | { 106 | return true; 107 | } 108 | } 109 | } 110 | 111 | 112 | -------------------------------------------------------------------------------- /spaceinvaders/Protection.pde: -------------------------------------------------------------------------------- 1 | class Protection 2 | { 3 | int x,y; 4 | int taillex,tailley; 5 | int[][] protect = { 6 | {0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0}, 7 | {0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0}, 8 | {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0}, 9 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 10 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 11 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 12 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 13 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 14 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 15 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 16 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 17 | {1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1}, 18 | {1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1}, 19 | {1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1}, 20 | {1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1} 21 | }; 22 | 23 | Protection(int x_, int y_) 24 | { 25 | x = x_; 26 | y = y_; 27 | 28 | taillex=2; 29 | tailley=2; 30 | } 31 | 32 | void display() 33 | { 34 | 35 | noStroke(); 36 | fill(0,255,0); 37 | rectMode(CENTER); 38 | for(int i =0; i<15;i++) 39 | { 40 | for(int j=0; j<20;j++) 41 | { 42 | if(protect[i][j]==1) 43 | { 44 | rect(j*taillex+x,i*tailley+y,taillex,tailley); 45 | } 46 | } 47 | } 48 | } 49 | 50 | boolean contact(float pX, float pY) 51 | { 52 | boolean flagtouch =false; 53 | for(int i =0; i<15;i++) 54 | { 55 | for(int j=0; j<20;j++) 56 | { 57 | if(pX >= j*taillex+x-taillex/2 && pX <= j*taillex+x+tailley/2 && pY >= i*tailley+y-tailley/2 && pY <= i*tailley+y+tailley/2 && protect[i][j]==1) 58 | { 59 | protect[i][j]=0; 60 | for(int t=i-2;t<=i+2;t++) 61 | { 62 | for(int r = j-2; r<=j+2;r++) 63 | { 64 | if( t>=0 && t <15 && r>=0 && r < 20) 65 | { 66 | if(random(100)>75) 67 | { 68 | protect[t][r]=0; 69 | } 70 | } 71 | } 72 | } 73 | flagtouch = true; 74 | } 75 | } 76 | } 77 | return flagtouch; 78 | } 79 | 80 | 81 | } 82 | -------------------------------------------------------------------------------- /spaceinvaders/Ship.pde: -------------------------------------------------------------------------------- 1 | /** Clone de Space Invader **/ 2 | /** Programmation Tristan Brismontier **/ 3 | 4 | class Ship 5 | { 6 | float spX; 7 | float spY; 8 | int taille; 9 | 10 | Ship(float x_, float y_) 11 | { 12 | spX=x_; 13 | spY=y_; 14 | taille=2; 15 | } 16 | Ship() 17 | { 18 | spX=width/2; 19 | spY=9*height/10; 20 | taille=2; 21 | } 22 | 23 | void display() 24 | { 25 | noStroke(); 26 | fill(0,255,0); 27 | rectMode(CENTER); 28 | rect(spX,spY,15*taille,7*taille); 29 | rect(spX,spY-5*taille,3*taille,3*taille); 30 | rect(spX,spY-7*taille,taille,taille); 31 | fill(0); 32 | rect(spX-7*taille,spY-3*taille,taille,taille); 33 | rect(spX+7*taille,spY-3*taille,taille,taille); 34 | } 35 | 36 | boolean contact(float x_, float y_) 37 | { 38 | if(x_ >spX-7*taille && x_ < spX+7*taille && y_ > spY-15*taille && y_ 14*width/15 ) 53 | { 54 | } 55 | else 56 | { 57 | if( spXt< width/15 ) 58 | { 59 | } 60 | else 61 | { 62 | spX = spX +sens; 63 | } 64 | } 65 | } 66 | 67 | } 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /spaceinvaders/data/CourierNew36.vlw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/digidotcom/XBeeArduinoCodingPlatform/446208697f9cfb8c48feb1fe78a959365addb118/spaceinvaders/data/CourierNew36.vlw -------------------------------------------------------------------------------- /spaceinvaders/data/filtrejeu.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/digidotcom/XBeeArduinoCodingPlatform/446208697f9cfb8c48feb1fe78a959365addb118/spaceinvaders/data/filtrejeu.gif -------------------------------------------------------------------------------- /spaceinvaders/data/filtrejeu.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/digidotcom/XBeeArduinoCodingPlatform/446208697f9cfb8c48feb1fe78a959365addb118/spaceinvaders/data/filtrejeu.tga -------------------------------------------------------------------------------- /spaceinvaders/spaceinvaders.pde: -------------------------------------------------------------------------------- 1 | /** Clone de Space Invader **/ 2 | /** Programmation Tristan Brismontier **/ 3 | 4 | // Modified from source code at http://www.openprocessing.org/sketch/6572 for 5 | // use in Digi's XBee/Arduino Compatible Coding Platform. This game uses Digi's 6 | // XBee Game Controller library to handle user input by replacing the control 7 | // handling through setting the variables and calling the methods originally 8 | // done through mouse and keyboard input. See the buttonEvent and draw methods 9 | // below for more details. 10 | 11 | import java.util.*; 12 | 13 | // Processing XBee Java Library must be installed 14 | import com.digi.xbee.api.*; 15 | // Digi XBee Game Controller library 16 | import xbeegamecontroller.*; 17 | 18 | Controller controller; 19 | 20 | // Change as necessary. Specifies how to address the XBee. 21 | final String XBEE_PORT = "COM5"; 22 | final int XBEE_BAUD = 9600; 23 | 24 | // Because the joystick included in the kit does not always spring back to 25 | // perfectly centered (~512), we effectively reduce the joystick sensitivity by 26 | // ignoring any values less than this far off of center. This means that, to 27 | // see the joystick as being pushed 'up', for example, the Y value needs to be 28 | // less than or equal to 412 (512 - 100). 29 | final int JOYSTICK_THRESHOLD = 100; 30 | 31 | int rows = 5; 32 | int cols = 10; 33 | Invader[][] spaceInv = new Invader[cols][rows]; 34 | Protection[] protec = new Protection[4]; 35 | Laser[] laserEn = new Laser[3]; 36 | Ship[] shipVie = new Ship[3]; 37 | MotherShip motherShip; 38 | Laser lazer; 39 | Conf conf; 40 | Ship ship; 41 | 42 | void setup() 43 | { 44 | size(501,432); 45 | background(255); 46 | frameRate(60); 47 | conf = new Conf(); 48 | ship = new Ship(); 49 | lazer = new Laser(); 50 | motherShip = new MotherShip(); 51 | 52 | for(int i=0;i= 512 + JOYSTICK_THRESHOLD; 119 | 120 | lazer.display(); 121 | ship.display(); 122 | lazer.move(); 123 | 124 | actionShip(); 125 | 126 | // Gestion du MotherShip 127 | motherShip.display(); 128 | motherShip.move(); 129 | if(motherShip.contact(lazer.pX,lazer.pY)==false) 130 | { 131 | conf.score += int(random(40,250)); 132 | lazer.tire=false; 133 | lazer.pY=height; 134 | } 135 | if(random(100) > 99.7) 136 | { 137 | 138 | if(motherShip.existe == false) 139 | { 140 | float k = random(0,2); 141 | motherShip.lancement(k); 142 | } 143 | } 144 | // fini avec le Mothership 145 | 146 | for(int i=0;ispaceInv[i][j].spX-4*spaceInv[i][j].taillex && o*protec[k].taillex+protec[k].x < spaceInv[i][j].spX+4*spaceInv[i][j].taillex && p*protec[k].tailley+protec[k].y < spaceInv[i][j].spY+4*spaceInv[i][j].tailley) 218 | { 219 | protec[k].protect[p][o]=0; 220 | } 221 | } 222 | } 223 | } 224 | } 225 | } 226 | 227 | 228 | 229 | if(spaceInv[i][j].contact(lazer.pX,lazer.pY)==false) 230 | { 231 | switch (spaceInv[i][j].type) 232 | { 233 | case 1: 234 | conf.score += 10; 235 | break; 236 | case 2: 237 | conf.score += 20; 238 | break; 239 | case 3: 240 | conf.score += 40; 241 | break; 242 | } 243 | lazer.tire=false; 244 | lazer.pY=height; 245 | } 246 | 247 | if(spaceInv[i][j].existe) 248 | { 249 | if(random(100) > 99.98) 250 | { 251 | int k = int(random(0,3)); 252 | if(laserEn[k].tire == false) 253 | { 254 | laserEn[k].lancement(spaceInv[i][j].spX,spaceInv[i][j].spY); 255 | } 256 | } 257 | if(ship.contact(spaceInv[i][j].spX,spaceInv[i][j].spY) || spaceInv[i][j].spY>=9*height/10) 258 | { 259 | conf.shiptouche=true; 260 | } 261 | conf.jeu=true; 262 | } 263 | 264 | spaceInv[i][j].display(conf.flag); 265 | 266 | } 267 | } 268 | 269 | 270 | changementDeSens(); 271 | 272 | shipTouche(); 273 | 274 | if(conf.jeu==false || conf.shiptouche) 275 | { 276 | if(conf.shiptouche)conf.vie-=1; 277 | if(conf.vie<0)conf.game=false; 278 | for(int i=0;i0) 428 | { 429 | conf.sense = conf.sense * -1 -0.3 ; 430 | } 431 | else 432 | { 433 | conf.sense = conf.sense * -1 + 0.3; 434 | } 435 | conf.sense=constrain(conf.sense,-12,12); 436 | 437 | conf.fpY=!conf.fpY; 438 | } 439 | } 440 | 441 | /*** Le Ship est Touche?? ***/ 442 | 443 | void shipTouche() 444 | { 445 | if(conf.shiptoucheLaser) 446 | { 447 | conf.vie-=1; 448 | if(conf.vie<0)conf.game=false; 449 | } 450 | } 451 | 452 | 453 | /**** Konami ***/ 454 | 455 | void konamiFonc() 456 | { 457 | int vtemp=0; 458 | if(keyCode==UP) 459 | { 460 | vtemp=1; 461 | } 462 | if(keyCode==DOWN) 463 | { 464 | vtemp=2; 465 | } 466 | if(keyCode==LEFT) 467 | { 468 | vtemp=3; 469 | } 470 | if(keyCode==RIGHT) 471 | { 472 | vtemp=4; 473 | } 474 | if(key=='a' || key=='A') 475 | { 476 | vtemp=5; 477 | } 478 | if(key=='b' || key=='B') 479 | { 480 | vtemp=6; 481 | } 482 | for(int i=0;i 29 | 30 | XBee xbee = XBee(); 31 | 32 | // Change these as necessary. 33 | uint16_t REMOTE_ADDR[] = { 0x1235, 0x1236 }; // MY parameter values of remote nodes 34 | 35 | // The pins controlling the LEDs, in the order in which they will light up. 36 | // The two examples below assumed the LEDs are wired up as shown in the diagram 37 | // in the kit documentation. 38 | int pins[] = { 2, 3, 4, 5, 6, 11, 10, 9, 8, 7 }; // Move around in a circle 39 | //{ 7, 2, 3, 8, 9, 4, 5, 10, 11, 6 }; // Wind back and forth between the two rows 40 | 41 | // Pin controlling the success LED 42 | int SUCCESS_PIN = 13; 43 | // Remote XBee DIO pin controlling the LED 44 | int REMOTE_LED_PIN = 0; // DIO0 45 | // Remote XBee DIO pin to monitor 46 | int REMOTE_BUTTON_PIN = 1; // DIO1 47 | 48 | // How long each LED is lit before moving to the next, in milliseconds. 49 | int INTERVAL = 40; 50 | 51 | // Do not change. 52 | int PIN_COUNT = sizeof(pins) / sizeof(int); 53 | 54 | // The index (in the 'pins' array above) of the currently lit-up LED. 55 | int whichLit = 0; 56 | // The last time we changed which LED was lit up. 57 | unsigned long previousMillis = 0; 58 | 59 | // Which LED player 1 landed on 60 | int player1Pin = NO_LED; 61 | // Which LED player 2 landed on 62 | int player2Pin = NO_LED; 63 | 64 | // Tracks whether each player is currently pushing their button. 65 | // (Updates with each I/O packet that is received.) 66 | boolean buttonPressed[] = { false, false }; 67 | 68 | void setup() { 69 | // Open the local serial port and tell the xbee-arduino library to 70 | // use it for XBee traffic. 71 | Serial1.begin(9600); 72 | xbee.begin(Serial1); 73 | 74 | // Configure LED pins 75 | for (int i = 0; i < PIN_COUNT; i++) { 76 | pinMode(pins[i], OUTPUT); 77 | } 78 | 79 | // Configure the success pin as output. 80 | pinMode(SUCCESS_PIN, OUTPUT); 81 | 82 | // Seed the random number generator. 83 | randomSeed(analogRead(12)); 84 | 85 | // Turn off all LEDs, shuffle the players, 86 | // and prepare for gameplay. 87 | initialize(); 88 | } 89 | 90 | // Called in setup, and when restarting play. 91 | void initialize() { 92 | // Reset all the pins 93 | for (int i = 0; i < PIN_COUNT; i++) { 94 | turnOff(i); 95 | } 96 | digitalWrite(SUCCESS_PIN, LOW); 97 | 98 | shufflePlayers(); 99 | 100 | // Signal to the first player that it's their turn. 101 | // Sometimes these commands don't work, so send them twice. 102 | for (int i = 0; i < 2; i++) { 103 | indicateTurn(REMOTE_ADDR[0], true); 104 | indicateTurn(REMOTE_ADDR[1], false); 105 | } 106 | 107 | // Check and make sure player 1 is not pressing their button. 108 | // If they are, wait until they release it. 109 | readData(); 110 | while (buttonPressed[0]) { 111 | readData(); 112 | } 113 | 114 | // Turn on the first LED. 115 | turnOn(0); 116 | 117 | // Reset other variables. 118 | player1Pin = player2Pin = NO_LED; 119 | previousMillis = millis(); 120 | whichLit = 0; 121 | } 122 | 123 | void loop() { 124 | unsigned long now = millis(); 125 | 126 | // Read in a packet from the XBee, if there is one available, 127 | // and process it. 128 | readData(); 129 | 130 | // Advance the LED if it is time to do so. 131 | if (now > previousMillis + INTERVAL) { 132 | // Switch off the current LED. 133 | turnOff(whichLit); 134 | 135 | // Change which LED is lit up. 136 | advanceLed(); 137 | 138 | // Reset the timer. 139 | previousMillis = millis(); 140 | } 141 | 142 | // Switch on the current LED. 143 | turnOn(whichLit); 144 | 145 | // If it's player 2's turn and this is the LED player 1 landed on, 146 | // light up the success LED. 147 | if (player1Pin != NO_LED && player2Pin == NO_LED) { 148 | digitalWrite(SUCCESS_PIN, whichLit == player1Pin); 149 | } 150 | // If both players have gone, light up the success LED if they 151 | // landed on the same light. 152 | if ((player1Pin != NO_LED) && (player2Pin != NO_LED) && (player1Pin == player2Pin)) { 153 | digitalWrite(SUCCESS_PIN, HIGH); 154 | } 155 | 156 | // Is it player 1's turn? 157 | if (player1Pin == NO_LED) { 158 | // Are they pushing their button? 159 | if (buttonPressed[0]) { 160 | // They are. Record their position. 161 | player1Pin = whichLit; 162 | 163 | // Flash the LED. 164 | flash(whichLit); 165 | 166 | // Wait until both buttons are released (so that if player 2 is holding their 167 | // button right now, we wait until they release it). 168 | while (buttonPressed[0]) { 169 | readData(); 170 | } 171 | while (buttonPressed[1]) { 172 | // These are two while loops, rather than one loop with an OR-ed condition, 173 | // so that once player 1 releases the button, we just wait for player 2, rather 174 | // than allowing an infinite handoff between the two. 175 | readData(); 176 | } 177 | 178 | // Signal to the second player that it's their turn. 179 | indicateTurn(REMOTE_ADDR[0], false); 180 | indicateTurn(REMOTE_ADDR[1], true); 181 | 182 | // Reset the timer. 183 | previousMillis = millis(); 184 | 185 | // Reset the pin position. 186 | whichLit = 0; 187 | } 188 | } else if (player2Pin == NO_LED) { 189 | // It's player 2's turn. 190 | // Ensure the LED player 1 landed on is lit up. 191 | turnOn(player1Pin); 192 | 193 | if (buttonPressed[1]) { 194 | // The button is pushed. Record their position. 195 | player2Pin = whichLit; 196 | 197 | // Turn off the LED on their board - it's no longer their turn. 198 | indicateTurn(REMOTE_ADDR[1], false); 199 | 200 | // Flash the LED. 201 | flash(whichLit); 202 | whichLit = NO_LED; 203 | 204 | // Reset the timer. 205 | previousMillis = millis(); 206 | } 207 | } else { 208 | // Both players have gone. 209 | 210 | // Wait until they are both pressing their button... 211 | while (!(buttonPressed[0] && buttonPressed[1])) { 212 | readData(); 213 | } 214 | 215 | // Then wait for them both to release... 216 | while (buttonPressed[0] || buttonPressed[1]) { 217 | readData(); 218 | } 219 | 220 | // Pause for a moment. 221 | delay(1000); 222 | 223 | // Start again. 224 | initialize(); 225 | } 226 | } 227 | 228 | void readData() { 229 | // Read a packet in from the XBee, if one is available. 230 | xbee.readPacket(); 231 | 232 | if (xbee.getResponse().isAvailable() && xbee.getResponse().getApiId() == RX_16_IO_RESPONSE) { 233 | // New data is available. Parse the packet. 234 | Rx16IoSampleResponse response = Rx16IoSampleResponse(); 235 | xbee.getResponse().getRx16IoSampleResponse(response); 236 | 237 | // Determine whether this button is pressed (the I/O pin is low). 238 | boolean button_down = !response.isDigitalOn(REMOTE_BUTTON_PIN, 0); 239 | 240 | // Record the button state for this player. 241 | uint16_t addr = response.getRemoteAddress16(); 242 | if (addr == REMOTE_ADDR[0]) { 243 | buttonPressed[0] = button_down; 244 | } else if (addr == REMOTE_ADDR[1]) { 245 | buttonPressed[1] = button_down; 246 | } 247 | } 248 | } 249 | 250 | // Uses a remote AT command to turn on/off the LED on the remote player's board. 251 | void indicateTurn(uint16_t address, boolean isTheirTurn) { 252 | // Convert pin number (e.g. 0) to a char. 253 | char dioNumber = char(REMOTE_LED_PIN + '0'); 254 | 255 | // Build the remote AT command. 256 | uint8_t cmd[] = {'D', dioNumber}; 257 | // If it is this player's turn, we turn their LED on (high). Otherwise, we turn it off (low). 258 | uint8_t value[] = { isTheirTurn ? 5 : 4 }; 259 | RemoteAtCommandRequest request = RemoteAtCommandRequest(address, cmd, value, 1); 260 | 261 | // Send the remote AT command. 262 | xbee.send(request); 263 | 264 | // Wait for a response, for up to 3 seconds. 265 | unsigned long start = millis(); 266 | while (1) { 267 | // Read a packet in from the XBee, if one is available. 268 | xbee.readPacket(); 269 | 270 | if (xbee.getResponse().isAvailable()) { 271 | // Check for an AT command response 272 | 273 | if (xbee.getResponse().getApiId() == RX_16_IO_RESPONSE) { 274 | // Received I/O data. Ignore. 275 | } else if (xbee.getResponse().getApiId() == REMOTE_AT_COMMAND_RESPONSE) { 276 | // It's an AT command response. 277 | RemoteAtCommandResponse response = RemoteAtCommandResponse(); 278 | xbee.getResponse().getRemoteAtCommandResponse(response); 279 | 280 | // Is it the one we're looking for, and did it work? 281 | // (Assumes that no other remote AT commands are in process currently.) 282 | if (response.getRemoteAddress16() == address && response.isOk()) { 283 | // If so, break out of this loop. 284 | break; 285 | } 286 | } 287 | } 288 | 289 | if (millis() > start + 3000) { 290 | // We've waited at least three seconds. Break out of the loop. 291 | break; 292 | } 293 | } 294 | } 295 | 296 | //===================================== 297 | // Utility functions 298 | 299 | void turnOn(int which) { 300 | if (which == NO_LED) return; 301 | digitalWrite(pins[which], HIGH); 302 | } 303 | void turnOff(int which) { 304 | if (which == NO_LED) return; 305 | digitalWrite(pins[which], LOW); 306 | } 307 | 308 | void flash(int which) { 309 | turnOff(which); 310 | delay(100); 311 | 312 | turnOn(which); 313 | delay(100); 314 | 315 | turnOff(which); 316 | delay(100); 317 | 318 | turnOn(which); 319 | delay(700); 320 | } 321 | 322 | void advanceLed() { 323 | static boolean moveRight = true; 324 | 325 | #if SWITCH_DIRECTIONS 326 | // Version 1: Left-to-right for player 1, right-to-left for player 2. 327 | if (player1Pin == NO_LED) { 328 | whichLit = (whichLit + 1) % PIN_COUNT; 329 | } else { 330 | whichLit = (whichLit ? whichLit : PIN_COUNT) - 1; 331 | } 332 | #else 333 | // Version 2: Bounce left-to-right and then right-to-left. 334 | if (moveRight) { 335 | // Move one LED to the right... 336 | if (whichLit == PIN_COUNT - 1) { 337 | // Unless we're at the far right, in which case, go left. 338 | moveRight = false; 339 | whichLit--; 340 | } else { 341 | whichLit++; 342 | } 343 | } else { 344 | // Move one LED to the left 345 | if (whichLit == 0) { 346 | // Unless we're at the far left, in which case, go right. 347 | moveRight = true; 348 | whichLit++; 349 | } else { 350 | whichLit--; 351 | } 352 | } 353 | #endif 354 | } 355 | 356 | void shufflePlayers() { 357 | if (random(1) < 0.5) { 358 | uint16_t tmp = REMOTE_ADDR[0]; 359 | REMOTE_ADDR[0] = REMOTE_ADDR[1]; 360 | REMOTE_ADDR[1] = tmp; 361 | } 362 | } 363 | -------------------------------------------------------------------------------- /xbeegamecontroller/.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .gradle 3 | build 4 | *.iml 5 | 6 | # Android Studio auto-generated file 7 | local.properties 8 | -------------------------------------------------------------------------------- /xbeegamecontroller/README.md: -------------------------------------------------------------------------------- 1 | XBee Game Controller - Processing library 2 | === 3 | 4 | This is a [Processing](http://processing.org) library which utilizes Digi's 5 | [XBee Java Library](https://github.com/digidotcom/XBeeJavaLibrary) to expose interactions with the 6 | XBee Game Controller to a Processing application. 7 | 8 | 9 | # Building the library 10 | 11 | These instructions assume that you have the RXTX library installed on your computer, or know which 12 | file to include inside this library. 13 | 14 | 1. Set the `PROCESSING_INSTALL_DIR` environment variable to point to your Processing IDE 15 | installation. The directory you specify for this value should contains directories such as 16 | core, java, launch4j, etc. 17 | 18 | - This lets the Gradle build script automatically add the Processing core libraries to the Java 19 | classpath during compilation. You may skip this step if these libraries (found under 20 | <install dir>/core/library) are already on your classpath. 21 | 22 | 2. Execute the `makeProcessingLibrary` Gradle task. For example: 23 | 24 | $ ./gradlew clean makeProcessingLibrary 25 | 26 | Or, if you are using Windows: 27 | 28 | > .\gradlew.bat clean makeProcessingLibrary 29 | 30 | 3. Copy the `xbeegamecontroller` directory from under `build/processing-lib` into your Processing 31 | libraries directory. -------------------------------------------------------------------------------- /xbeegamecontroller/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | 3 | dependencies { 4 | compile fileTree(dir: 'libs', include: '*.jar') 5 | } 6 | 7 | sourceSets { 8 | main { 9 | java { 10 | srcDir 'src' 11 | } 12 | } 13 | } 14 | 15 | sourceCompatibility = 1.6 16 | 17 | compileJava { 18 | doFirst { 19 | // Add Processing core libraries to classpath, if possible. 20 | if (System.getenv('PROCESSING_INSTALL_DIR') != null) { 21 | classpath = project.sourceSets.main.compileClasspath + files(System.getenv('PROCESSING_INSTALL_DIR') + '/core/library/core.jar') 22 | } else { 23 | logger.warn("Warning: No PROCESSING_INSTALL_DIR environment variable found. Compilation will fail unless core.jar is on your classpath!\n") 24 | } 25 | } 26 | } 27 | 28 | task makeProcessingLibrary(type: Copy, dependsOn: jar) { 29 | description "Compile the Java code for this library, and output a nearly-ready Processing library" 30 | 31 | destinationDir = new File("$project.buildDir/processing-lib/xbeegamecontroller") 32 | 33 | doFirst { 34 | destinationDir.mkdirs() 35 | } 36 | 37 | from (project.projectDir) { 38 | include 'library.properties' 39 | } 40 | into ("library") { 41 | from ("libs") { 42 | // We need xbjlib to build the xbeegamecontroller JAR file, but we 43 | // need to exclude it from the Processing library. 44 | exclude 'xbjlib*.jar' 45 | } 46 | from jar.destinationDir 47 | } 48 | into ("src") { 49 | from "src" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /xbeegamecontroller/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/digidotcom/XBeeArduinoCodingPlatform/446208697f9cfb8c48feb1fe78a959365addb118/xbeegamecontroller/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /xbeegamecontroller/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Jul 28 11:49:30 CDT 2014 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-1.12-bin.zip 7 | -------------------------------------------------------------------------------- /xbeegamecontroller/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /xbeegamecontroller/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /xbeegamecontroller/library.properties: -------------------------------------------------------------------------------- 1 | # UTF-8 supported. 2 | 3 | # The name of your library as you want it formatted. 4 | name = XBee Game Controller 5 | 6 | # List of authors. Links can be provided using the syntax [author name](url). 7 | authorList = Travis Lubbers 8 | 9 | # A web page for your library, NOT a direct link to where to download it. 10 | url = http://www.digi.com/ 11 | 12 | # The category of your library, must be one (or many) of the following: 13 | # "3D" "Animation" "Compilations" "Data" 14 | # "Fabrication" "Geometry" "GUI" "Hardware" 15 | # "I/O" "Language" "Math" "Simulation" 16 | # "Sound" "Utilities" "Typography" "Video & Vision" 17 | # 18 | # If a value other than those listed is used, your library will listed as 19 | # "Other". 20 | category = Hardware 21 | 22 | # A short sentence (or fragment) to summarize the library's function. This will 23 | # be shown from inside the PDE when the library is being installed. Avoid 24 | # repeating the name of your library here. Also, avoid saying anything redundant 25 | # like mentioning that it's a library. This should start with a capitalized 26 | # letter, and end with a period. 27 | sentence = Example library for using a simple game controller created with an XBee. 28 | 29 | # Additional information suitable for the Processing website. The value of 30 | # 'sentence' always will be prepended, so you should start by writing the 31 | # second sentence here. If your library only works on certain operating systems, 32 | # mention it here. 33 | paragraph = 34 | 35 | # Links in the 'sentence' and 'paragraph' attributes can be inserted using the 36 | # same syntax as for authors. 37 | # That is, [here is a link to Processing](http://processing.org/) 38 | 39 | # A version number that increments once with each release. This is used to 40 | # compare different versions of the same library, and check if an update is 41 | # available. You should think of it as a counter, counting the total number of 42 | # releases you've had. 43 | version = 1 44 | 45 | # The version as the user will see it. If blank, the version attribute will be 46 | # used here. 47 | prettyVersion = 0.01 # This is treated as a String 48 | 49 | # The min and max revision of Processing compatible with your library. 50 | # Note that these fields use the revision and not the version of Processing, 51 | # parsable as an int. For example, the revision number for 2.2.1 is 227. 52 | # You can find the revision numbers in the change log: 53 | # https://raw.githubusercontent.com/processing/processing/master/build/shared/revisions.txt 54 | # Only use maxRevision (or minRevision), when your library is known to 55 | # break in a later (or earlier) release. Otherwise, use the default value 0. 56 | minRevision = 0 57 | maxRevision = 0 -------------------------------------------------------------------------------- /xbeegamecontroller/libs/slf4j-api-1.7.7.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/digidotcom/XBeeArduinoCodingPlatform/446208697f9cfb8c48feb1fe78a959365addb118/xbeegamecontroller/libs/slf4j-api-1.7.7.jar -------------------------------------------------------------------------------- /xbeegamecontroller/libs/xbjlib.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/digidotcom/XBeeArduinoCodingPlatform/446208697f9cfb8c48feb1fe78a959365addb118/xbeegamecontroller/libs/xbjlib.jar -------------------------------------------------------------------------------- /xbeegamecontroller/src/xbeegamecontroller/Controller.java: -------------------------------------------------------------------------------- 1 | package xbeegamecontroller; 2 | 3 | import com.digi.xbee.api.Raw802Device; 4 | import com.digi.xbee.api.RemoteXBeeDevice; 5 | import com.digi.xbee.api.XBeeDevice; 6 | import com.digi.xbee.api.exceptions.XBeeException; 7 | import com.digi.xbee.api.io.IOLine; 8 | import com.digi.xbee.api.io.IOSample; 9 | import com.digi.xbee.api.io.IOValue; 10 | import com.digi.xbee.api.listeners.IIOSampleReceiveListener; 11 | import processing.core.PApplet; 12 | 13 | import java.lang.reflect.Method; 14 | 15 | public class Controller { 16 | private final IOLine xAxis = IOLine.DIO2_AD2; 17 | private final IOLine yAxis = IOLine.DIO1_AD1; 18 | private final IOLine rightButton = IOLine.DIO4_AD4; 19 | private final IOLine leftButton = IOLine.DIO6; 20 | 21 | private PApplet parent; 22 | private Method buttonEvent; 23 | 24 | private XBeeDevice xBeeDevice; 25 | 26 | private int x, y; 27 | private IOValue rightLast, leftLast; 28 | 29 | /* The constructor really should not take a port and baud, it should be able to specify a remote XBee 30 | the data of which we are handling. For the moment, just assume that only one XBee will report on this 31 | network and that XBee is the game controller. We could allow the user to provide an array of XBee EUI64 32 | values and use that to recognize multiple controllers. 33 | */ 34 | 35 | public Controller(PApplet p, String port, int baud) throws XBeeException { 36 | parent = p; 37 | p.registerMethod("dispose", this); 38 | try { 39 | buttonEvent = parent.getClass().getMethod("buttonEvent", boolean.class, boolean.class); 40 | } catch (Exception e) { 41 | // No event in user's sketch to call 42 | } 43 | 44 | System.out.println(buttonEvent); 45 | 46 | xBeeDevice = new Raw802Device(port, baud); 47 | xBeeDevice.open(); 48 | xBeeDevice.addIOSampleListener(new IIOSampleReceiveListener() { 49 | @Override 50 | public void ioSampleReceived(RemoteXBeeDevice remoteXBeeDevice, IOSample ioSample) { 51 | // Inverted due to orientation of joystick on board 52 | x = ioSample.getAnalogValue(xAxis); 53 | y = 1023 - ioSample.getAnalogValue(yAxis); 54 | 55 | doButtonEvents(ioSample); 56 | } 57 | }); 58 | } 59 | 60 | private void doButtonEvents(IOSample ioSample) { 61 | if (buttonEvent != null) { 62 | try { 63 | IOValue rightValue = ioSample.getDigitalValue(rightButton); 64 | IOValue leftValue = ioSample.getDigitalValue(leftButton); 65 | 66 | if (rightValue != rightLast || leftValue != leftLast) { 67 | buttonEvent.invoke(parent, leftValue == IOValue.LOW, rightValue == IOValue.LOW); 68 | } 69 | 70 | rightLast = rightValue; 71 | leftLast = leftValue; 72 | 73 | } catch (Exception e) { 74 | System.err.println("Disabled xbeegamecontroller buttonEvent due to error"); 75 | e.printStackTrace(); 76 | buttonEvent = null; 77 | } 78 | } 79 | } 80 | 81 | public void dispose() { 82 | xBeeDevice.close(); 83 | } 84 | 85 | public int getX() { 86 | return x; 87 | } 88 | 89 | public int getY() { 90 | return y; 91 | } 92 | } 93 | --------------------------------------------------------------------------------