ECE 2035 Homework

Dependencies:   mbed wave_player 4DGL-uLCD-SE MMA8452

main.cpp

Committer:
zkang0729
Date:
2019-11-14
Revision:
4:e3fbc74a3783
Parent:
3:e4690ad5a4d2

File content as of revision 4:e3fbc74a3783:

// Project includes
#include "globals.h"
#include "hardware.h"
#include "map.h"
#include "graphics.h"
#include "speech.h"

// Functions in this file
int get_action(GameInputs inputs);
int update_game(int action);
void draw_game(int init);
void init_main_map();
int main();

/**
 * The main game state. Must include Player locations and previous locations for
 * drawing to work properly. Other items can be added as needed.
 */
struct
{
  int x, y;   // Current locations
  int px, py; // Previous locations
  int has_key;
  // You can add other properties for the player here
} Player;

/**
 * Given the game inputs, determine what kind of update needs to happen.
 * Possbile return values are defined below.
 */
#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
int get_action(GameInputs inputs)
{
  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 Player 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 player has not moved.
 */
#define NO_RESULT 0
#define GAME_OVER 1
#define FULL_DRAW 2
int update_game(int action)
{
  // Save player previous location before updating
  Player.px = Player.x;
  Player.py = Player.y;

  // Do different things based on the each action.
  // You can define functions like "go_up()" that get called for each case.
  switch (action)
  {
  case GO_UP:
    Player.y != 0 && Player.y - 1;
    break;
  case GO_LEFT:
    Player.x != 0 && Player.x - 1;
    break;
  case GO_DOWN:
    Player.y != map_height() && Player.y + 1;
    break;
  case GO_RIGHT:
    Player.x != map_width() && Player.x + 1;
    break;
  case ACTION_BUTTON:
    break;
  case MENU_BUTTON:
    break;
  default:
    break;
  }
  return NO_RESULT;
}

/**
 * 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 init)
{
  // Draw game border first
  if (init)
    draw_border();

  // 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 + Player.x;
      int y = j + Player.y;

      // Compute the previous map (px, py) of this tile
      int px = i + Player.px;
      int py = j + Player.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 (init && i == 0 && j == 0) // Only draw the player on init
      {
        draw_player(u, v, Player.has_key);
        continue;
      }
      else 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 (init || 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 (init) // 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. Note: using the similar
 * procedure you can init the secondary map(s).
 */
void init_main_map()
{
  // "Random" plants
  Map *map = set_active_map(0);
  for (int i = map_width() + 3; i < map_area(); i += 39)
  {
    add_plant(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");

  print_map();
}

/**
 * Program entry point! This is where it all begins.
 * This function orchestrates 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()
{
  //Game Over Indication
  unsigned int GameOver = 0;
  
  // First things first: initialize hardware
  ASSERT_P(hardware_init() == ERROR_NONE, "Hardware init failed!");

  // Initialize the maps
  maps_init();
  init_main_map();

  // Initialize game state
  set_active_map(0);
  Player.x = Player.y = 5;

  // Initial drawing
  draw_game(true);

  // Main game loop
  while (!GameOver)
  {
    // Timer to measure game update speed
    Timer t;
    t.start();

    // Actuall do the game update:
    // 1. Read inputs
    //inputs = read_inputs();
    
    // 2. Determine action (get_action)
    //action = get_action(input);
    
    // 3. Update game (update_game)
    //next_state = update_game(action);
    
    // 3b. Check for game over
    
    
    // 4. Draw frame (draw_game)

    // 5. Frame delay
    t.stop();
    int dt = t.read_ms();
    if (dt < 100)
      wait_ms(100 - dt);
  }
}