ECE2035 Project 2

Dependencies:   mbed mbed-rtos SDFileSystem

main.cpp

Committer:
kwengryn3
Date:
2021-04-20
Revision:
10:1994adcfc86f
Parent:
9:f1d34ef049c5

File content as of revision 10:1994adcfc86f:

//=================================================================
// The main program file.
//
// Copyright 2020 Georgia Tech.  All rights reserved.
// The materials provided by the instructor in this course are for
// the use of the students currently enrolled in the course.
// Copyrighted course materials may not be further disseminated.
// This file must not be made publicly available anywhere.
//==================================================================

// External libs
#include <stdlib.h>

// Project includes
#include "globals.h"
#include "hardware.h"
#include "compost_pile_public.h"
#include "fruit_public.h"
#include "player_public.h"
#include "mbed.h"
#include "doubly_linked_list.h"
#include "rtos.h"
#include "Speaker.h"

//For sound components
//AnalogOut DACout(p18);
//PwmOut pwmout(p26);
//PwmOut speaker(p25);
Speaker speak(p25);

//wave_player waver(&DACout);
//SDFileSystem sd(p5, p6, p7, p8, "sd"); // mosi, miso, sck, cs

DigitalOut myled1(LED1);
DigitalOut myled2(LED2);
DigitalOut myled3(LED3);
DigitalOut myled4(LED4);
bool exitFlag = false;
int score = 0;
int lives = 3;
Thread thread;
int sound = 0;

// ===User implementations start===
int fruit_contact(void); // iterate through fruits and see if any collided
int compost_pile_update(void);

void playSound(void);
void playNotes(void);
void set_random_seed(Timer);
int pause_menu();
bool compare_bounding_boxes(boundingBox box1, boundingBox box2);



int main()
{
    GameInputs inputs; 
    // First things first: initialize hardware
    ASSERT_P(hardware_init() == ERROR_NONE, "Hardware init failed!");
    pc.printf("Program Starting\n");
    pc.printf("-------------------------\n");

    
    // ===User implementations start===
    // Game state variables
    
    // Timer to measure game update speed (secondarily used to generate random seed)
    Timer t;
    int dt; // delta time
    set_random_seed(t);
    wait(0.3);
    //mkdir("/sd/wavfiles", 0777);
    //pwmout.period(1.0/4000.0);
    //playSound();//test the sound convert to thread
    //wait(0.1);
    //playNotes();
    
    //initialize functions

    fruit_init();
    player_init();
    compost_pile_init();        
    pc.printf("Initialization complete\n");
    //uLCD.printf("Score: %d", score);
    
    while(1)
    {
        t.start();
       
        // Draw fruits first
        uLCD.text_string("",0, 0, FONT_7X8, BLACK);
        uLCD.color(WHITE);
        uLCD.printf("X:%d|strk:%d pts:%d\n",lives, get_player_strikes(), score);
        
       
        fruit_generator();
        //Put score on screen
        // NOTE: Text is 8 pixels tall
      
        player_move(inputs.ax);
        
        if (get_player_strikes() == 0) {
            uLCD.cls();
            uLCD.printf("Game Ended:\n");
            uLCD.printf("Too Many Strikes\n\n");
            break;
        
        }
        
        inputs = read_inputs();
        if (!inputs.b1) {
            int action = pause_menu();
            if (action == 0) {
                break;
            }
        }
        
        
        if (!inputs.b3) {
            //speak.PlayNote(400.0, 0.1, 0.1);
            sound = 1;
            thread.start(playSound);
            player_throw();
        }
        
    
        //handling collisions in the compost pile
        int compost_contact = compost_pile_update();
        
        if (compost_contact == 1) {
            lives--;
            if (lives == 0) {
                uLCD.cls();
                uLCD.printf("Game Ended:\n");
                uLCD.printf("Too Much Compost\n\n");
                break;  
            } else {
                remove_tallest_pile();    
            }
            
        }
        
       
        //checking for knife contact
        int knife_contact = fruit_contact();
        
        if (knife_contact == -1) {
            lives--;
            if (lives == 0) {
                uLCD.cls();
                uLCD.printf("Game Ended:\nBomb Destroyed\n\n");
                break;
            }
           
        }
        
        if (score == 10) {
            uLCD.cls();
            uLCD.printf("Victory!\n\n");
            break;
        }
        
        
        // TODO: Check if game won

        // Compute update time
        t.stop();
        dt = t.read_ms();
        
        if (dt < 100) wait_ms(100 - dt);
    
    }
    uLCD.color(0xFF0000);
    uLCD.printf("Final Score: %d\n", score);
    destroyList(get_fruit_list());
    //thread.stop();
    
    return 0;
    // ===User implementations end===
}

// ===User implementations start===

/* This function iterate through the fruit list, checking if anyone one of them is contacting 
*  with the player's knife. Don't forget to check if the "fruit" is the bomb, since we 
*  generated bombs using the fruit_generator. 
*/ 
int fruit_contact(void) {
    PLAYER player = player_get_info();
    if (player.player_has_knife) {
        return 0;
    }
    DLinkedList* fruits = get_fruit_list();
    LLNode* curr = fruits->head;
    while (curr) {
        FRUIT* fruitData = (FRUIT*)curr->data;
        boundingBox box1 = player.knife_boundingBox;
        boundingBox box2 = fruitData->box;
        if (compare_bounding_boxes(box1, box2)) {
            fruitData->status = FRUIT_SLICED;
            if (fruitData->type == 0) {
                player_knife_return();
                return -1;
            }
            //player_knife_return();
            score++;
            //pc.printf("score: %d\n", score);
            sound = 2;
            thread.start(playSound);
            return 1;
        }
        curr = curr->next;
    }
    return 0;
     
}

/** Call compost_pile_update() repeatedly in your game-loop. ex: main()
    This function iterate through the fruit list. Add fruits that reach the bottom of the screen
    to the compost pile.
    @return  Number of remaining cities. You might end the game when all cities are demolished.
*/
int compost_pile_update(void){
    DLinkedList* fruits = get_fruit_list();
    int numPiles = get_num_piles();
    for (int i = 0; i < numPiles; i++) {
        LLNode* curr = fruits->head;
        while (curr) {
            FRUIT* fruitData = (FRUIT*)curr->data;
            boundingBox box1 = compost_get_info(i).box;
            boundingBox box2 = fruitData->box;
            if (compare_bounding_boxes(box1, box2)) {
                //pc.printf("Collision between fruit and compost\n");
                fruitData->status = FRUIT_SLICED;
                compost_add(i);
                if (check_overflow()) {
                    return 1;
                }
                return 0;
            }
            curr = curr->next;
        }
    }
    draw_compost();
    return 0;
        
}

bool compare_bounding_boxes(boundingBox box1, boundingBox box2) {
    return ((box1.topLeft.x < box2.bottomRight.x) && (box1.bottomRight.x > box2.topLeft.x) &&
            (box1.topLeft.y < box2.bottomRight.y) && (box1.bottomRight.y > box2.topLeft.y));
}

//fcn to play a wav
void playSound()
{
    //open wav file
    FILE *wave_file;
    char* wav;
    
    switch (sound) {
        case 1:
            wav = "/sd/wavfiles/FIRE.wav";
            break;
        case 2:
            wav = "/sd/wavfiles/SCORE.wav";
            break;
        default:
            break;
        
    }

    wave_file=fopen(wav,"r");
    //waver.set_verbosity(1);
    
    if(wave_file != NULL) 
    {
        pc.printf("File opened successfully\n");

        //play wav file
        pc.printf("Sound playing...\n");
        waver.play(wave_file);
    
        //close wav file
        pc.printf("Sound stopped...\n");
        fclose(wave_file);
        return;
    }
    
    pc.printf("Could not open file for reading - %s\n", wav);
        return;
}

/* Wanna hear some annoying sounds?*/
void playNotes(void)
{
    int i;
// generate a 500Hz tone using PWM hardware output
    speaker.period(1.0/500.0); // 500hz period
    speaker =0.5; //50% duty cycle - max volume
    wait(3);
    speaker=0.0; // turn off audio
    wait(2);
// generate a short 150Hz tone using PWM hardware output
// something like this can be used for a button click effect for feedback
    for (i=0; i<10; i++) {
        speaker.period(1.0/150.0); // 500hz period
        speaker =0.25; //25% duty cycle - mid range volume
        wait(.02);
        speaker=0.0; // turn off audio
        wait(0.5);
    }

// sweep up in frequency by changing the PWM period
    for (i=0; i<8000; i=i+100) {
        speaker.period(1.0/float(i));
        speaker=0.25;
        wait(.1);
    }
    wait(2);

// two tone police siren effect -  two periods or two frequencies
// increase volume - by changing the PWM duty cycle
    for (i=0; i<26; i=i+2) {
        speaker.period(1.0/969.0);
        speaker = float(i)/50.0;
        wait(.5);
        speaker.period(1.0/800.0);
        wait(.5);
    }
    // decrease volume
    for (i=25; i>=0; i=i-2) {
        speaker.period(1.0/969.0);
        speaker = float(i)/50.0;
        wait(.5);
        speaker.period(1.0/800.0);
        wait(.5);
    }
    speaker =0.0;
    wait(2);
}

void set_random_seed(Timer t) {
    //thread.start(playSound);
    GameInputs inputs; 
    t.start();
    uLCD.printf("Push any button to start.\n");
    while(1){
      inputs = read_inputs();
      if (!inputs.b1 || !inputs.b2 || !inputs.b3) {
          break;
        }
    }
    uLCD.cls();
    t.stop();
    int seed = t.read_ms();    
    srand(seed);
    }
    
int pause_menu() {
uLCD.cls();
uLCD.printf("   Game Paused\n\n\n");
uLCD.printf("  End Game | Play");
GameInputs inputs;
while(1) {
    inputs = read_inputs();
    if (!inputs.b1) {
        uLCD.cls();
        return 0;
    }
    if (!inputs.b3) {
        uLCD.cls();
        return 1;    
    }
    
}
    
    
    
    
}
// ===User implementations end===