single player mbedKart

Dependencies:   Motor

(notes)

Committer:
DerekW2015
Date:
Tue Dec 11 01:21:49 2018 +0000
Revision:
16:40f697a68445
Parent:
15:350b9128a602
Child:
18:6c93ec600402
Changed send/receive code to 802.15.4 API. Rearranged code to make more sense.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
DerekW2015 0:a9a4c0fd5f8a 1 #include "mbed.h"
DerekW2015 0:a9a4c0fd5f8a 2 #include "Motor.h"
DerekW2015 0:a9a4c0fd5f8a 3 #include "rgbled.h"
DerekW2015 0:a9a4c0fd5f8a 4 #include "rgbSensor.h"
DerekW2015 16:40f697a68445 5 #include "xbee_functions.h"
DerekW2015 11:8d4b7702ac06 6 // Define threads and mutexes
DerekW2015 11:8d4b7702ac06 7 Thread thread1;
DerekW2015 11:8d4b7702ac06 8 Thread thread2;
DerekW2015 11:8d4b7702ac06 9
DerekW2015 0:a9a4c0fd5f8a 10 // Define devices
DerekW2015 0:a9a4c0fd5f8a 11 Motor left(p22, p16, p15); // pwm, fwd, rev
DerekW2015 0:a9a4c0fd5f8a 12 Motor right(p23, p19, p20); // pwm, fwd, rev
DerekW2015 0:a9a4c0fd5f8a 13 BusOut myled(LED1,LED2,LED3,LED4);
DerekW2015 0:a9a4c0fd5f8a 14 RGBLed myRGBled(p26, p25, p24); // red, green, blue
DerekW2015 0:a9a4c0fd5f8a 15 rgbSensor rgbsensor(p28, p27);
DerekW2015 0:a9a4c0fd5f8a 16 Serial blue(p13, p14); // serial tx, serial rx
DerekW2015 11:8d4b7702ac06 17 enum speed_state { accelerating, braking, coasting };
sli425 13:583181de031e 18 XBeeZB xbee = XBeeZB(RADIO_TX, RADIO_RX, RADIO_RESET, NC, NC, 9600); //Change these to pins used
DerekW2015 0:a9a4c0fd5f8a 19
sli425 3:6c749bff51aa 20 //Game state variables
sli425 3:6c749bff51aa 21 int progress = 0;
sli425 13:583181de031e 22 int position = 1;
DerekW2015 11:8d4b7702ac06 23 int current_item = 0;
sli425 12:4fec6ed886ab 24 bool holding_item = false;
sli425 12:4fec6ed886ab 25 bool itembox = false;
sli425 13:583181de031e 26 bool is_hit = false;
DerekW2015 11:8d4b7702ac06 27 float speed_cmd = 0.0;
DerekW2015 11:8d4b7702ac06 28 float max_speed = 1.0;
DerekW2015 11:8d4b7702ac06 29 float acceleration_rate = 0.04;
DerekW2015 11:8d4b7702ac06 30 float brake_rate = 0.1;
DerekW2015 11:8d4b7702ac06 31 float coast_rate = 0.02;
sli425 3:6c749bff51aa 32 int cstate;
DerekW2015 11:8d4b7702ac06 33 speed_state sstate = coasting;
DerekW2015 6:57a0323bb6b7 34 bool collide = false;
sli425 3:6c749bff51aa 35
DerekW2015 0:a9a4c0fd5f8a 36 // Global game actions
DerekW2015 8:92bf0cc337b5 37 bool paused = false;
DerekW2015 8:92bf0cc337b5 38 void check_unpause() {
DerekW2015 8:92bf0cc337b5 39 char bnum=0;
DerekW2015 8:92bf0cc337b5 40 char bhit=0;
DerekW2015 8:92bf0cc337b5 41 while (true) {
DerekW2015 8:92bf0cc337b5 42 if (blue.getc()=='B') { //button data packet
DerekW2015 8:92bf0cc337b5 43 bnum = blue.getc(); //button number
DerekW2015 8:92bf0cc337b5 44 bhit = blue.getc(); //1=hit, 0=release
DerekW2015 8:92bf0cc337b5 45 if (blue.getc()==char(~('!' + 'B' + bnum + bhit))) { //checksum OK?
DerekW2015 8:92bf0cc337b5 46 if (bnum == '1') { //number button 1, pause
DerekW2015 8:92bf0cc337b5 47 if (bhit=='1') paused = false;
DerekW2015 8:92bf0cc337b5 48 }
DerekW2015 8:92bf0cc337b5 49 }
DerekW2015 8:92bf0cc337b5 50 }
DerekW2015 8:92bf0cc337b5 51 }
DerekW2015 8:92bf0cc337b5 52 }
sli425 12:4fec6ed886ab 53
DerekW2015 8:92bf0cc337b5 54 void game_paused() {
DerekW2015 8:92bf0cc337b5 55 // Cycle through LEDs
DerekW2015 8:92bf0cc337b5 56 Thread pause_thread;
DerekW2015 8:92bf0cc337b5 57 pause_thread.start(check_unpause);
DerekW2015 8:92bf0cc337b5 58 while (paused) {
DerekW2015 8:92bf0cc337b5 59 int num = 1;
DerekW2015 8:92bf0cc337b5 60 for (int i = 0; i < 3; i++) {
DerekW2015 8:92bf0cc337b5 61 num *= 2;
DerekW2015 8:92bf0cc337b5 62 myled = num;
DerekW2015 8:92bf0cc337b5 63 ThisThread::sleep_for(100);
DerekW2015 8:92bf0cc337b5 64 }
DerekW2015 8:92bf0cc337b5 65 ThisThread::sleep_for(500);
DerekW2015 8:92bf0cc337b5 66 for (int i = 3; i > 0; i--) {
DerekW2015 8:92bf0cc337b5 67 num /= 2;
DerekW2015 8:92bf0cc337b5 68 myled = num;
DerekW2015 8:92bf0cc337b5 69 ThisThread::sleep_for(100);
DerekW2015 8:92bf0cc337b5 70 }
DerekW2015 8:92bf0cc337b5 71 ThisThread::sleep_for(500);
DerekW2015 8:92bf0cc337b5 72 }
DerekW2015 11:8d4b7702ac06 73 }
DerekW2015 11:8d4b7702ac06 74
DerekW2015 11:8d4b7702ac06 75 // Thread to control speed
DerekW2015 11:8d4b7702ac06 76 void speed_control() {
DerekW2015 11:8d4b7702ac06 77 // The kart has to be in one of three states at all times
DerekW2015 11:8d4b7702ac06 78 while(1) {
DerekW2015 11:8d4b7702ac06 79 while(sstate == coasting) {
DerekW2015 15:350b9128a602 80 if (speed_cmd > 0.0) speed_cmd -= coast_rate;
DerekW2015 15:350b9128a602 81 else speed_cmd = 0.0;
DerekW2015 15:350b9128a602 82 left.speed(speed_cmd);
DerekW2015 15:350b9128a602 83 right.speed(speed_cmd);
DerekW2015 11:8d4b7702ac06 84 ThisThread::sleep_for(200);
DerekW2015 11:8d4b7702ac06 85 }
DerekW2015 11:8d4b7702ac06 86 while(sstate == accelerating) {
DerekW2015 15:350b9128a602 87 if (speed_cmd < max_speed) speed_cmd += acceleration_rate;
DerekW2015 15:350b9128a602 88 else speed_cmd = max_speed;
DerekW2015 15:350b9128a602 89 left.speed(speed_cmd);
DerekW2015 15:350b9128a602 90 right.speed(speed_cmd);
DerekW2015 11:8d4b7702ac06 91 ThisThread::sleep_for(200);
DerekW2015 11:8d4b7702ac06 92 }
DerekW2015 11:8d4b7702ac06 93 while(sstate == braking) {
DerekW2015 15:350b9128a602 94 if (speed_cmd > 0.0) speed_cmd -= brake_rate;
DerekW2015 15:350b9128a602 95 else speed_cmd = 0.0;
DerekW2015 15:350b9128a602 96 left.speed(speed_cmd);
DerekW2015 15:350b9128a602 97 right.speed(speed_cmd);
DerekW2015 11:8d4b7702ac06 98 ThisThread::sleep_for(200);
DerekW2015 11:8d4b7702ac06 99 }
DerekW2015 11:8d4b7702ac06 100 }
DerekW2015 11:8d4b7702ac06 101 }
DerekW2015 11:8d4b7702ac06 102
sli425 3:6c749bff51aa 103 // Thread for checking rgb sensor values and updating game variables
sli425 3:6c749bff51aa 104 // Change later depending on behavior of RGB sensor and colors used
sli425 3:6c749bff51aa 105 int thresh = 150; //change this depending on RGB values
sli425 3:6c749bff51aa 106 void check_RGB() {
sli425 12:4fec6ed886ab 107 while(true){
sli425 12:4fec6ed886ab 108 rgbsensor.update();
sli425 12:4fec6ed886ab 109 int C_value = rgbsensor.get_C();
sli425 12:4fec6ed886ab 110 int R_value = rgbsensor.get_R();
sli425 12:4fec6ed886ab 111 int G_value = rgbsensor.get_G();
sli425 12:4fec6ed886ab 112 int B_value = rgbsensor.get_B();
sli425 12:4fec6ed886ab 113 if(C_value > thresh && R_value > thresh && G_value > thresh && B_value > thresh && current_item == 0) { //Check for if cart runs over an item box
sli425 12:4fec6ed886ab 114 itembox = true;
sli425 12:4fec6ed886ab 115 cstate = 0;
sli425 12:4fec6ed886ab 116 }
sli425 12:4fec6ed886ab 117 else if(C_value > thresh && R_value > thresh && G_value > thresh && B_value > thresh) { //Check for if cart runs over a speed boost panel
sli425 12:4fec6ed886ab 118 max_speed = 1; //change this depending on speed up panel algs
sli425 12:4fec6ed886ab 119 cstate = 0;
sli425 12:4fec6ed886ab 120 }
sli425 12:4fec6ed886ab 121 else if(C_value > thresh && R_value > thresh && G_value > thresh && B_value > thresh) { //Check if cart collides with wall
sli425 12:4fec6ed886ab 122 collide = true;
sli425 12:4fec6ed886ab 123 }
sli425 12:4fec6ed886ab 124 else if(C_value > thresh && R_value > thresh && G_value > thresh && B_value > thresh) { //Check if cart reaches next checkpoint. cstate is set to 1 upon seeing first color of checkpoint
sli425 12:4fec6ed886ab 125 cstate = 1;
sli425 12:4fec6ed886ab 126 }
sli425 12:4fec6ed886ab 127 else if(C_value > thresh && R_value > thresh && G_value > thresh && B_value > thresh && cstate == 1) {
sli425 12:4fec6ed886ab 128 //Second part of checking if cart reaches next checkpoint. If the previous color was passed through previously, updates checkpoint progress
sli425 12:4fec6ed886ab 129 cstate = 0;
sli425 12:4fec6ed886ab 130 progress++;
sli425 12:4fec6ed886ab 131 }
sli425 12:4fec6ed886ab 132 else {
sli425 12:4fec6ed886ab 133 cstate = 0;
sli425 12:4fec6ed886ab 134 }
sli425 12:4fec6ed886ab 135 ThisThread::sleep_for(500);
sli425 3:6c749bff51aa 136 }
sli425 3:6c749bff51aa 137 }
sli425 3:6c749bff51aa 138
sli425 12:4fec6ed886ab 139 void set_item() {
sli425 12:4fec6ed886ab 140 while(true){
sli425 12:4fec6ed886ab 141 if(itembox && current_item == 0) {
sli425 12:4fec6ed886ab 142 //playsound
sli425 12:4fec6ed886ab 143 for(int n = 0, n < 10, n++){ //flash the led to simulate slot machine effect
sli425 12:4fec6ed886ab 144 myRGBled(1.0,0.0,0.0);
sli425 12:4fec6ed886ab 145 ThisThread::sleep_for(50);
sli425 12:4fec6ed886ab 146 myRGBled(0.0,1.0,0.0);
sli425 12:4fec6ed886ab 147 ThisThread::sleep_for(50);
sli425 12:4fec6ed886ab 148 myRGBled(0.0,0.0,1.0);
sli425 12:4fec6ed886ab 149 ThisThread::sleep_for(50);
sli425 12:4fec6ed886ab 150 myRGBled(1.0,1.0,0.0);
sli425 12:4fec6ed886ab 151 ThisThread::sleep_for(50);
sli425 12:4fec6ed886ab 152 }
sli425 12:4fec6ed886ab 153 current_item = rand() % 4 + 1; //change this depending on items implemented and random item alg
sli425 12:4fec6ed886ab 154 if(current_item == 1){ //mushroom
sli425 12:4fec6ed886ab 155 myRGBled(1.0,0.0,0.0);
sli425 12:4fec6ed886ab 156 }
sli425 12:4fec6ed886ab 157 if(current_item == 2){ //green shell
sli425 12:4fec6ed886ab 158 myRGBled(0.0,1.0,0.0);
sli425 12:4fec6ed886ab 159 }
sli425 12:4fec6ed886ab 160 if(current_item == 3){ //blue shell
sli425 12:4fec6ed886ab 161 myRGBled(0.0,0.0,1.0);
sli425 12:4fec6ed886ab 162 }
sli425 12:4fec6ed886ab 163 if(current_item == 4){ //banana
sli425 12:4fec6ed886ab 164 myRGBled(1.0,1.0,0.0);
sli425 12:4fec6ed886ab 165 }
sli425 12:4fec6ed886ab 166 itembox = false;
sli425 12:4fec6ed886ab 167 }
sli425 12:4fec6ed886ab 168 ThisThread::sleep_for(500);
sli425 12:4fec6ed886ab 169 }
sli425 12:4fec6ed886ab 170 }
sli425 12:4fec6ed886ab 171
sli425 12:4fec6ed886ab 172 void hold_item() {
sli425 12:4fec6ed886ab 173 if(current_item == 0){
sli425 12:4fec6ed886ab 174 return;
sli425 12:4fec6ed886ab 175 }
sli425 12:4fec6ed886ab 176 if(current_item == 1){
sli425 12:4fec6ed886ab 177 max_speed = 1;
sli425 12:4fec6ed886ab 178 current_item = 0;
sli425 12:4fec6ed886ab 179 }
sli425 12:4fec6ed886ab 180 else{
sli425 12:4fec6ed886ab 181 holding_item = true;
sli425 12:4fec6ed886ab 182 }
sli425 12:4fec6ed886ab 183 return;
sli425 12:4fec6ed886ab 184 }
sli425 12:4fec6ed886ab 185
sli425 12:4fec6ed886ab 186 void release_item(){
sli425 12:4fec6ed886ab 187 holding_item = false;
sli425 12:4fec6ed886ab 188 if(current_item == 2){
sli425 12:4fec6ed886ab 189 //hit player in front
sli425 12:4fec6ed886ab 190 return;
sli425 12:4fec6ed886ab 191 }
sli425 12:4fec6ed886ab 192 if(current_item == 3){
sli425 12:4fec6ed886ab 193 //hit player in first
sli425 12:4fec6ed886ab 194 return;
sli425 12:4fec6ed886ab 195 }
sli425 12:4fec6ed886ab 196 if(current_item == 4){
sli425 12:4fec6ed886ab 197 //hit player behind
sli425 12:4fec6ed886ab 198 return;
sli425 12:4fec6ed886ab 199 }
sli425 12:4fec6ed886ab 200 }
sli425 12:4fec6ed886ab 201
DerekW2015 0:a9a4c0fd5f8a 202 int main() {
DerekW2015 0:a9a4c0fd5f8a 203 // Start threads
DerekW2015 9:6649141315be 204 thread1.start(check_RGB);
DerekW2015 11:8d4b7702ac06 205 thread2.start(speed_control); // Since we're stopped, this won't do anything
DerekW2015 16:40f697a68445 206
DerekW2015 16:40f697a68445 207 // Initialize Xbee and remote modules
sli425 13:583181de031e 208 xbee.register_receive_cb(&receive_cb);
DerekW2015 16:40f697a68445 209 RadioStatus const radioStatus = xbee.init();
DerekW2015 16:40f697a68445 210 const RemoteXBeeZB remoteDevice = RemoteXBeeZB(REMOTE_NODE_ADDR64);
DerekW2015 0:a9a4c0fd5f8a 211
DerekW2015 0:a9a4c0fd5f8a 212 // Bluetooth controller code
DerekW2015 0:a9a4c0fd5f8a 213 char bnum=0;
DerekW2015 0:a9a4c0fd5f8a 214 char bhit=0;
DerekW2015 0:a9a4c0fd5f8a 215 while(1) {
DerekW2015 0:a9a4c0fd5f8a 216 if (blue.getc()=='!') {
DerekW2015 0:a9a4c0fd5f8a 217 if (blue.getc()=='B') { //button data packet
DerekW2015 0:a9a4c0fd5f8a 218 bnum = blue.getc(); //button number
DerekW2015 0:a9a4c0fd5f8a 219 bhit = blue.getc(); //1=hit, 0=release
DerekW2015 0:a9a4c0fd5f8a 220 if (blue.getc()==char(~('!' + 'B' + bnum + bhit))) { //checksum OK?
DerekW2015 0:a9a4c0fd5f8a 221 switch (bnum) {
DerekW2015 0:a9a4c0fd5f8a 222 case '1': //number button 1, pause
DerekW2015 0:a9a4c0fd5f8a 223 if (bhit=='1') {
DerekW2015 0:a9a4c0fd5f8a 224 //myled = bnum - '0'; //current button number will appear on LEDs
DerekW2015 8:92bf0cc337b5 225 paused = true;
DerekW2015 8:92bf0cc337b5 226 game_paused();
DerekW2015 0:a9a4c0fd5f8a 227 }
DerekW2015 0:a9a4c0fd5f8a 228 break;
DerekW2015 0:a9a4c0fd5f8a 229 case '2': //number button 2, accelerate
DerekW2015 0:a9a4c0fd5f8a 230 if (bhit=='1') {
DerekW2015 11:8d4b7702ac06 231 sstate = accelerating;
DerekW2015 0:a9a4c0fd5f8a 232 } else {
DerekW2015 11:8d4b7702ac06 233 sstate = coasting;
DerekW2015 0:a9a4c0fd5f8a 234 }
DerekW2015 0:a9a4c0fd5f8a 235 break;
DerekW2015 0:a9a4c0fd5f8a 236 case '3': //number button 3
DerekW2015 0:a9a4c0fd5f8a 237 if (bhit=='1') {
sli425 12:4fec6ed886ab 238 hold_item(); //holds item to protect player from incoming hazards
DerekW2015 0:a9a4c0fd5f8a 239 } else {
sli425 12:4fec6ed886ab 240 release_item(); //release item to attack
DerekW2015 0:a9a4c0fd5f8a 241 }
DerekW2015 0:a9a4c0fd5f8a 242 break;
DerekW2015 0:a9a4c0fd5f8a 243 case '4': //number button 4, brakes
DerekW2015 0:a9a4c0fd5f8a 244 if (bhit=='1') {
DerekW2015 0:a9a4c0fd5f8a 245 //myled = bnum - '0'; //current button number will appear on LEDs
DerekW2015 11:8d4b7702ac06 246 sstate = braking;
DerekW2015 0:a9a4c0fd5f8a 247 } else {
DerekW2015 11:8d4b7702ac06 248 sstate = coasting;
DerekW2015 0:a9a4c0fd5f8a 249 }
DerekW2015 0:a9a4c0fd5f8a 250 break;
DerekW2015 0:a9a4c0fd5f8a 251 case '5': //button 5 up arrow
DerekW2015 0:a9a4c0fd5f8a 252 if (bhit=='1') {
DerekW2015 0:a9a4c0fd5f8a 253 //myled = bnum - '0'; //current button number will appear on LEDs
DerekW2015 0:a9a4c0fd5f8a 254 //throw_item();
DerekW2015 0:a9a4c0fd5f8a 255 //item_box();
DerekW2015 0:a9a4c0fd5f8a 256 } else {
DerekW2015 0:a9a4c0fd5f8a 257
DerekW2015 0:a9a4c0fd5f8a 258 }
DerekW2015 0:a9a4c0fd5f8a 259 break;
DerekW2015 0:a9a4c0fd5f8a 260 case '6': //button 6 down arrow
DerekW2015 0:a9a4c0fd5f8a 261 if (bhit=='1') {
DerekW2015 11:8d4b7702ac06 262 //myled = bnum - '0'; //current button number will appear on LEDs
DerekW2015 0:a9a4c0fd5f8a 263 left.speed(-1.0);
DerekW2015 0:a9a4c0fd5f8a 264 right.speed(-1.0);
DerekW2015 0:a9a4c0fd5f8a 265 } else {
DerekW2015 0:a9a4c0fd5f8a 266 left.speed(0.0);
DerekW2015 0:a9a4c0fd5f8a 267 right.speed(0.0);
DerekW2015 0:a9a4c0fd5f8a 268 }
DerekW2015 0:a9a4c0fd5f8a 269 break;
DerekW2015 0:a9a4c0fd5f8a 270 case '7': //button 7 left arrow
DerekW2015 0:a9a4c0fd5f8a 271 if (bhit=='1') {
DerekW2015 0:a9a4c0fd5f8a 272 //myled = bnum - '0'; //current button number will appear on LEDs
DerekW2015 0:a9a4c0fd5f8a 273 left.speed(0.3);
DerekW2015 0:a9a4c0fd5f8a 274 right.speed(1.0);
DerekW2015 0:a9a4c0fd5f8a 275 } else {
DerekW2015 0:a9a4c0fd5f8a 276 left.speed(0.0);
DerekW2015 0:a9a4c0fd5f8a 277 right.speed(0.0);
DerekW2015 0:a9a4c0fd5f8a 278 }
DerekW2015 0:a9a4c0fd5f8a 279 break;
DerekW2015 0:a9a4c0fd5f8a 280 case '8': //button 8 right arrow
DerekW2015 0:a9a4c0fd5f8a 281 if (bhit=='1') {
DerekW2015 0:a9a4c0fd5f8a 282 //myled = bnum - '0'; //current button number will appear on LEDs
DerekW2015 0:a9a4c0fd5f8a 283 left.speed(1.0);
DerekW2015 0:a9a4c0fd5f8a 284 right.speed(0.3);
DerekW2015 0:a9a4c0fd5f8a 285 } else {
DerekW2015 0:a9a4c0fd5f8a 286 left.speed(0.0);
DerekW2015 0:a9a4c0fd5f8a 287 right.speed(0.0);
DerekW2015 0:a9a4c0fd5f8a 288 }
DerekW2015 0:a9a4c0fd5f8a 289 break;
DerekW2015 0:a9a4c0fd5f8a 290 default:
DerekW2015 0:a9a4c0fd5f8a 291 break;
DerekW2015 0:a9a4c0fd5f8a 292 }
DerekW2015 0:a9a4c0fd5f8a 293 }
DerekW2015 0:a9a4c0fd5f8a 294 }
DerekW2015 0:a9a4c0fd5f8a 295 }
DerekW2015 16:40f697a68445 296 // Finish up loop
DerekW2015 16:40f697a68445 297 xbee.process_rx_frames();
DerekW2015 0:a9a4c0fd5f8a 298 }
DerekW2015 0:a9a4c0fd5f8a 299 }