tao lao

Dependencies:   mbed wave_player 4DGL-uLCD-SE MMA8452

main.cpp

Committer:
hnguyen403
Date:
2020-11-24
Revision:
3:33bf11645fe1
Parent:
2:4947d6a82971

File content as of revision 3:33bf11645fe1:

//=================================================================
// 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.
//==================================================================

// Project includes
#include "globals.h"
#include "hardware.h"
#include "map.h"
#include "graphics.h"
#include "snake.h"
#include "mbed.h"
//#include "wave_player.h"
#include "SDFileSystem.h"
#include <math.h>
#include<stdio.h>

#define CITY_HIT_MARGIN 1
#define CITY_UPPER_BOUND (SIZE_Y-(LANDSCAPE_HEIGHT+MAX_BUILDING_HEIGHT))
int go_right(int x, int y);
int go_left(int x, int y);
int go_up(int x, int y);
int go_down(int x, int y);
// Helper function declarations
void playSound(char* wav);

/**
 * The main game state. Must include snake locations and previous locations for
 * drawing to work properly. Other items can be added as needed.
 */

/**
 * Given the game inputs, determine what kind of update needs to happen.
 * Possbile return values are defined below.
 */
Snake snake;

// Function prototypes

/**
 * Given the game inputs, determine what kind of update needs to happen.
 * Possible return values are defined below.
 */
#define NO_RESULT 0
#define NO_ACTION 0
#define ACTION_BUTTON 1
#define MENU_BUTTON 2
#define GO_LEFT 3
#define GO_RIGHT 4
#define GO_UP 5
#define GO_DOWN 6
#define GAME_OVER 7
#define FULL_DRAW 8
#define WON 9
#define FOODN 10
#define FOODS 11
#define FOODW 12
#define FOODE 13

// Get Actions from User (push buttons & accelerometer)
// Based on push button and accelerometer inputs, determine which action
// needs to be performed (may be no action).
int get_action(GameInputs inputs)
{
    MapItem* N=get_north(snake.head_x,snake.head_y);
    MapItem* S=get_south(snake.head_x,snake.head_y);
    MapItem* W=get_east(snake.head_x, snake.head_y);
    MapItem* E=get_west(snake.head_x, snake.head_y);

    if (E->type==WALL || N->type==WALL || S->type==WALL ||W->type==WALL)   return GAME_OVER;
    if (inputs.ay >= 0.20) return GO_UP;
    if (inputs.ay < -0.20) return GO_DOWN;
    if (inputs.ax < -0.20) return GO_LEFT;
    if (inputs.ax >= 0.20) return GO_RIGHT;
    else return NO_ACTION;
}
/**
 * Update the game state based on the user action. For example, if the user
 * requests GO_UP, then this function should determine if that is possible by
 * consulting the map, and update the snake position accordingly.
 *
 * Return values are defined below. FULL_DRAW indicates that for this frame,
 * draw_game should not optimize drawing and should draw every tile, even if
 * the snake has not moved.
 */
int update_game(int action)
{
     
   snake.head_px = snake.head_x;
   snake.head_py = snake.head_y;   
    
    switch(action) {
        case GO_UP:
                 snake.head_y -= 1;               
                 
               for (int i = 1; i < snake.length-1; i++){   
                   int oldx = snake.head_px;
                 int oldy = snake.head_py;          
                int temx = snake.locations[i].x;
                int temy = snake.locations[i].y;
                 snake.locations[i].x = oldx;
               snake.locations[i].y = oldy;
                 oldx = temx;
                 oldy = temy;}
           if (get_north(snake.head_x,snake.head_y)->type == GOODIE)
                {map_erase(snake.head_x,snake.head_y-1);
                 return FULL_DRAW;}
            break;
        case GO_LEFT:
                snake.head_x -= 1;                                
               for (int i = 1; i < snake.length-1; i++){   
                   int oldx = snake.head_px;
                 int oldy = snake.head_py;          
                int temx = snake.locations[i].x;
                int temy = snake.locations[i].y;
                 snake.locations[i].x = oldx;
               snake.locations[i].y = oldy;
                 oldx = temx;
                 oldy = temy;}
           if (get_west(snake.head_x-1,snake.head_y)->type == GOODIE)
                {map_erase(snake.head_x,snake.head_y);
                 return FULL_DRAW;}
            break;
                
 
        case GO_DOWN:
                snake.head_y += 1;
                                
               for (int i = 1; i < snake.length-1; i++){   
                   int oldx = snake.head_px;
                 int oldy = snake.head_py;          
                int temx = snake.locations[i].x;
                int temy = snake.locations[i].y;
                 snake.locations[i].x = oldx;
               snake.locations[i].y = oldy;
                 oldx = temx;
                 oldy = temy;}
           if (get_south(snake.head_x,snake.head_y+1)->type == GOODIE)
                {map_erase(snake.head_x,snake.head_y);
                 return FULL_DRAW;}
            break;
        case GO_RIGHT:
                snake.head_x += 1;
                                 
               for (int i = 1; i < snake.length-1; i++){   
                   int oldx = snake.head_px;
                 int oldy = snake.head_py;          
                int temx = snake.locations[i].x;
                int temy = snake.locations[i].y;
                 snake.locations[i].x = oldx;
               snake.locations[i].y = oldy;
                 oldx = temx;
                 oldy = temy;}
           if (get_here(snake.head_x,snake.head_y)->type == GOODIE)
                {add_nothing(snake.head_x,snake.head_y);
                 draw_snake_head(snake.head_x,snake.head_y);
                snake.score= snake.score + 1;}
            
            break;
           
        case GAME_OVER:
         
            {uLCD.color(RED);
            uLCD.cls();
            uLCD.text_width(3);
            uLCD.text_height(3);
            uLCD.printf("GAME\nOVER");
            uLCD.color(GREEN);
            uLCD.text_width(1);
            uLCD.text_height(1);
            uLCD.printf("\n\n\n\n\nScore %d", snake.score);
            uLCD.color(GREEN);}
            while(1 == 1);
            
            }
    return NO_RESULT;
    
}

/**
 * Draw the upper status bar.
 */
void draw_upper_status()
{
    uLCD.line(0, 9, 127, 9, GREEN);

}

/**
 * Draw the lower status bar.
 */
void draw_lower_status()
{
    uLCD.line(0, 118, 127, 118, GREEN);
}

/**
 * Draw the border for the map.
 */
void draw_border()
{
    uLCD.filled_rectangle(0,     9, 127,  14, WHITE); // Top
    uLCD.filled_rectangle(0,    13,   2, 114, WHITE); // Left
    uLCD.filled_rectangle(0,   114, 127, 117, WHITE); // Bottom
    uLCD.filled_rectangle(124,  14, 127, 117, WHITE); // Right
}

/**
 * Entry point for frame drawing. This should be called once per iteration of
 * the game loop. This draws all tiles on the screen, followed by the status
 * bars. Unless init is nonzero, this function will optimize drawing by only
 * drawing tiles that have changed from the previous frame.
 */
void draw_game(int draw_option)
{
    // Draw game border first
    if(draw_option == FULL_DRAW) 
    {
        draw_border();
        int u = 58;
        int v = 59;
        draw_snake_head(u, v);
        draw_snake_body(u-11, v);
        draw_snake_tail(u-22, v);
        return;
    }
    // Iterate over all visible map tiles
    for (int i = -5; i <= 5; i++) { // Iterate over columns of tiles
        for (int j = -4; j <= 4; j++) { // Iterate over one column of tiles
            // Here, we have a given (i,j)

            // Compute the current map (x,y) of this tile
            int x = i + snake.head_x;
            int y = j + snake.head_y;

            // Compute the previous map (px, py) of this tile
            int px = i + snake.head_px;
            int py = j + snake.head_py;

            // Compute u,v coordinates for drawing
            int u = (i+5)*11 + 3;
            int v = (j+4)*11 + 15;

            // Figure out what to draw
            DrawFunc draw = NULL;
            if (x >= 0 && y >= 0 && x < map_width() && y < map_height()) { // Current (i,j) in the map
                MapItem* curr_item = get_here(x, y);
                MapItem* prev_item = get_here(px, py);
                if (draw_option || curr_item != prev_item) { // Only draw if they're different
                    if (curr_item) { // There's something here! Draw it
                        draw = curr_item->draw;
                    } else { // There used to be something, but now there isn't
                        draw = draw_nothing;
                    }
                } else if (curr_item && curr_item->type == CLEAR) {
                    // This is a special case for erasing things like doors.
                    draw = curr_item->draw; // i.e. draw_nothing
                }
            } else if (draw_option) { // If doing a full draw, but we're out of bounds, draw the walls.
                draw = draw_wall;
            }

            // Actually draw the tile
            if (draw) draw(u, v);
        }
    }

    // Draw status bars
    draw_upper_status();
    draw_lower_status();
}

/**
 * Initialize the main world map. Add walls around the edges, interior chambers,
 * and plants in the background so you can see motion.
 */
void init_main_map()
{
    uLCD.text_width(1);
    uLCD.text_height(1);
    uLCD.printf("Score %d", snake.score);
    uLCD.color(GREEN);
    // "Random" plants
    Map* map = set_active_map(0);
    for(int i = map_width() + 3; i < map_area(); i += 39) {
        add_goodie(i % map_width(), i / map_width());
    }
    pc.printf("plants\r\n");

    pc.printf("Adding walls!\r\n");
    add_wall(0,              0,              HORIZONTAL, map_width());
    add_wall(0,              map_height()-1, HORIZONTAL, map_width());
    add_wall(0,              0,              VERTICAL,   map_height());
    add_wall(map_width()-1,  0,              VERTICAL,   map_height());
    pc.printf("Walls done!\r\n");
    
    add_snake_head(snake.locations[0].x, snake.locations[0].y);
    add_snake_body(snake.locations[1].x, snake.locations[1].y);
    add_snake_tail(snake.locations[2].x, snake.locations[2].y);
    
    pc.printf("Add extra chamber\r\n");
    add_wall(30, 0, VERTICAL, 10);
    add_wall(30, 10, HORIZONTAL, 10);
    add_wall(39, 0, VERTICAL, 10);
    pc.printf("Added!\r\n");

    
    // Add stairs to chamber (map 1)
    //add_stairs(15, 5, 1, 5, 5);

//    profile_hashtable();
    print_map();
}

/**
 * Program entry point! This is where it all begins.
 * This function or all the parts of the game. Most of your
 * implementation should be elsewhere - this holds the game loop, and should
 * read like a road map for the rest of the code.
 */
int main()
{
    // First things first: initialize hardware
    ASSERT_P(hardware_init() == ERROR_NONE, "Hardware init failed!");

    snake_init(&snake);
    // 0. Initialize the maps -- implement this function:
    maps_init();
    init_main_map();
     playSound("/sd/wavfiles/track.wav");

    // Initialize game state
    set_active_map(0);
    snake.head_x = snake.head_y = 5 ;
    // Initial drawing
    draw_game(FULL_DRAW);
    // Main game loop
    while(1) {
        // Timer to measure game update speed
        Timer t;
        t.start();

        // 1. Read inputs -- implement this function:
        GameInputs inputs = read_inputs();
        
        // 2. Determine action (move, act, menu, etc.) -- implement this function:
        int action = get_action(inputs);
        
        // 3. Update game -- implement this function:
        int result = update_game(action);
        
        // 3b. Check for game over based on result
        // and if so, handle game over -- implement this.
                
        // 4. Draw screen -- provided:
        draw_game(result);
        
        // Compute update time
        t.stop();
        int dt = t.read_ms();

        // Display and wait
        // NOTE: Text is 8 pixels tall
        if (dt < 100) wait_ms(100 - dt);
    }
}

// Plays a wavfile
void playSound(char* wav)
{
   
}