P2-2 Harris Barton
Dependencies: mbed wave_player 4DGL-uLCD-SE MMA8452
Revision 3:e2fb359d6545, committed 2020-11-25
- Comitter:
- hbarton7
- Date:
- Wed Nov 25 01:17:39 2020 +0000
- Parent:
- 2:4947d6a82971
- Commit message:
- P2-2 Harris Barton;
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Speaker.h Wed Nov 25 01:17:39 2020 +0000 @@ -0,0 +1,19 @@ +#include "mbed.h" +// new class to play a note on Speaker based on PwmOut class +class Speaker +{ +public: + Speaker(PinName pin) : _pin(pin) { +// _pin(pin) means pass pin to the Speaker Constructor + } +// class method to play a note based on PwmOut class + void PlayNote(float frequency, float duration, float volume) { + _pin.period(1.0/frequency); + _pin = volume/2.0; + wait(duration); + _pin = 0.0; + } + +private: + PwmOut _pin; +}; \ No newline at end of file
--- a/graphics.cpp Fri Oct 23 16:30:18 2020 -0400 +++ b/graphics.cpp Wed Nov 25 01:17:39 2020 +0000 @@ -8,6 +8,150 @@ #include "globals.h" +#define YELLOW 0xFFFF00 +#define BROWN 0xD2691E +#define DIRT BROWN + +const char head[121] = { + 'G','G','G','G','G','G','G','G','G','G','G', + 'G','G','G','G','G','G','G','G','G','G','G', + 'G','R','R','R','G','G','R','R','R','G','G', + 'G','R','R','R','G','G','R','R','R','G','G', + 'G','R','R','R','G','G','R','R','R','G','G', + 'G','G','G','G','G','G','G','G','G','G','G', + 'G','R','R','R','G','G','R','R','R','G','G', + 'G','R','R','R','G','G','R','R','R','G','G', + 'G','R','R','R','G','G','R','R','R','G','G', + 'G','G','G','G','G','G','G','G','G','G','G', + 'G','G','G','G','G','G','G','G','G','G','G', + }; + +const char tail[121] = { + 'G','G','G','G','G','G','G','G','G','G','G', + 'G','G','G','G','G','G','G','G','G','G','G', + 'G','Y','Y','Y','G','G','G','Y','Y','Y','G', + 'G','Y','Y','Y','G','G','G','Y','Y','Y','G', + 'G','Y','Y','Y','G','G','G','Y','Y','Y','G', + 'G','G','G','G','G','G','G','G','G','G','G', + 'G','G','G','G','G','G','G','G','G','G','G', + 'G','Y','Y','Y','G','G','Y','Y','Y','G','G', + 'G','Y','Y','Y','G','G','Y','Y','Y','G','G', + 'G','Y','Y','Y','G','G','Y','Y','Y','G','G', + 'G','G','G','G','G','G','G','G','G','G','G', + }; + +const char poison[121] = { + 'Y','3','3','3','3','3','3','3','3','3','Y', + '3','Y','3','3','3','3','3','3','3','Y','3', + '3','3','Y','3','3','3','3','3','Y','3','3', + '3','3','3','Y','3','3','3','Y','3','3','3', + '3','3','3','3','Y','3','Y','3','3','3','3', + '3','3','3','3','3','Y','3','3','3','3','3', + '3','3','3','3','Y','3','Y','3','3','3','3', + '3','3','3','Y','3','3','3','Y','3','3','3', + '3','3','Y','3','3','3','3','3','Y','3','3', + '3','Y','3','3','3','3','3','3','3','Y','3', + 'Y','3','3','3','3','3','3','3','3','3','Y', + }; + +const char speedup[121] = { + '3','3','3','3','3','G','3','3','3','3','3', + '3','3','3','3','G','3','G','3','3','3','3', + '3','3','3','G','3','3','3','G','3','3','3', + '3','3','G','3','3','3','3','3','G','3','3', + '3','G','3','3','3','3','3','3','3','G','3', + 'G','3','3','3','3','3','3','3','3','3','G', + '3','3','3','3','3','G','3','3','3','3','3', + '3','3','3','3','G','3','G','3','3','3','3', + '3','3','3','G','3','3','3','G','3','3','3', + '3','3','G','3','3','3','3','3','G','3','3', + '3','G','3','3','3','3','3','3','3','G','3', + }; + +const char slowdown[121] = { + 'G','3','3','3','3','3','3','3','3','3','G', + '3','G','3','3','3','3','3','3','3','G','3', + '3','3','G','3','3','3','3','3','G','3','3', + '3','3','3','G','3','3','3','G','3','3','3', + '3','3','3','3','G','3','G','3','3','3','3', + '3','3','3','3','3','G','3','3','3','3','3', + 'G','3','3','3','3','3','3','3','3','3','G', + '3','G','3','3','3','3','3','3','3','G','3', + '3','3','G','3','3','3','3','3','G','3','3', + '3','3','3','G','3','3','3','G','3','3','3', + '3','3','3','3','G','3','G','3','3','3','3', + }; + +const char decrease_length[121] = { + '3','3','3','3','3','3','3','3','3','3','3', + '3','3','3','3','Y','Y','3','3','3','3','3', + '3','3','3','Y','3','3','Y','Y','Y','3','3', + '3','3','3','Y','3','3','Y','3','3','3','3', + '3','3','3','3','Y','Y','3','3','3','3','3', + '3','3','3','3','3','3','3','3','3','3','3', + '3','3','3','3','3','3','3','3','3','3','3', + '3','3','3','3','3','3','3','3','3','3','3', + '3','3','3','3','3','3','3','3','3','3','3', + '3','3','3','3','3','3','3','3','3','3','3', + '3','3','3','3','3','3','3','3','3','3','3', + }; + +const char random[121] = { + '5','5','5','5','5','G','5','5','5','5','5', + '5','5','5','5','G','5','G','5','5','5','5', + '5','5','5','G','5','5','5','G','5','5','5', + '5','5','5','5','5','5','5','G','5','5','5', + '5','5','5','5','5','5','5','G','5','5','5', + '5','5','5','5','5','5','G','5','5','5','5', + '5','5','5','5','5','G','5','5','5','5','5', + '5','5','5','5','5','G','5','5','5','5','5', + '5','5','5','5','5','G','5','5','5','5','5', + '5','5','5','5','5','5','5','5','5','5','5', + '5','5','5','5','5','G','5','5','5','5','5', + }; + +const char moving[121] = { + '5','5','5','5','5','D','5','5','5','5','5', + '5','5','5','5','D','5','D','5','5','5','5', + '5','5','5','D','5','5','5','D','5','5','5', + '5','5','5','5','5','5','5','D','5','5','5', + '5','5','5','5','5','5','5','D','5','5','5', + '5','5','5','5','5','5','D','5','5','5','5', + '5','5','5','5','5','D','5','5','5','5','5', + '5','5','5','5','5','D','5','5','5','5','5', + '5','5','5','5','5','D','5','5','5','5','5', + '5','5','5','5','5','5','5','5','5','5','5', + '5','5','5','5','5','D','5','5','5','5','5', + }; + +const char invinc[121] = { + '3','3','3','3','3','R','3','3','3','3','3', + '3','3','3','3','3','R','3','3','3','3','3', + '3','3','3','3','3','R','3','3','3','3','3', + '3','3','3','3','3','R','3','3','3','3','3', + '3','3','3','3','3','R','3','3','3','3','3', + 'R','R','R','R','R','R','R','R','R','R','R', + '3','3','3','3','3','R','3','3','3','3','3', + '3','3','3','3','3','R','3','3','3','3','3', + '3','3','3','3','3','R','3','3','3','3','3', + '3','3','3','3','3','R','3','3','3','3','3', + '3','3','3','3','3','R','3','3','3','3','3', + }; + +const char megaGoodie[121] = { + 'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y', + 'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y', + 'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y', + 'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y', + 'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y', + 'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y', + 'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y', + 'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y', + 'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y', + 'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y', + 'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y', + }; + void draw_nothing(int u, int v) { uLCD.filled_rectangle(u, v, u+10, v+10, BLACK); @@ -32,7 +176,7 @@ void draw_wall(int u, int v) { - uLCD.filled_rectangle(u, v, u+10, v+10, BLACK); + uLCD.filled_rectangle(u, v, u+10, v+10, LGREY); } void draw_plant(int u, int v) @@ -42,7 +186,7 @@ void draw_goodie(int u, int v) { - uLCD.filled_rectangle(u, v, u+10, v+10, GREEN); + uLCD.filled_rectangle(u, v, u+10, v+10, 0xD2691E); //DIRT } void draw_snake_body(int u, int v) @@ -54,15 +198,66 @@ { //May need to design a snake head sprite //Tile still need to be designed on paper - + uLCD.filled_rectangle(u, v, u+10, v+10, GREEN); + draw_img(u,v, head); +// uLCD.filled_rectangle(u+1, v+1, u+3, v+3, RED); +// uLCD.filled_rectangle(u+7, v+1, u+9, v+3, RED); +// uLCD.filled_rectangle(u+1, v+7, u+3, v+9, RED); +// uLCD.filled_rectangle(u+7, v+7, u+9, v+9, RED); + } void draw_snake_tail(int u, int v) { //May need to design a snake tail sprite //Tile still need to be designed on paper + uLCD.filled_rectangle(u, v, u+10, v+10, GREEN); + draw_img(u,v, tail); +// uLCD.filled_rectangle(u+1, v+1, u+3, v+3, 0xFFFF00); //YELLOW +// uLCD.filled_rectangle(u+7, v+1, u+9, v+3, 0xFFFF00); +// uLCD.filled_rectangle(u+1, v+7, u+3, v+9, 0xFFFF00); +// uLCD.filled_rectangle(u+7, v+7, u+9, v+9, 0xFFFF00); +} + +void draw_poison(int u, int v) { + uLCD.filled_rectangle(u, v, u+10, v+10, BLACK); + draw_img(u, v, poison); +} + +void draw_speedup(int u, int v) { + uLCD.filled_rectangle(u, v, u+10, v+10, BLACK); + draw_img(u, v, speedup); +} + +void draw_slowdown(int u, int v) { + uLCD.filled_rectangle(u, v, u+10, v+10, BLACK); + draw_img(u, v, slowdown); +} + +void draw_decrease_length(int u, int v) { + uLCD.filled_rectangle(u, v, u+10, v+10, BLACK); + draw_img(u, v, decrease_length); +} + +void draw_random(int u, int v) { + uLCD.filled_rectangle(u, v, u+10, v+10, BLACK); + draw_img(u, v, random); +} + +void draw_moving(int u, int v) { + uLCD.filled_rectangle(u, v, u+10, v+10, BLACK); + draw_img(u, v, moving); +} + +void draw_invinc(int u, int v) { + uLCD.filled_rectangle(u, v, u+10, v+10, BLACK); + draw_img(u, v, invinc); +} +void draw_megaGoodie(int u, int v) { + uLCD.filled_rectangle(u, v, u+10, v+10, BLACK); + draw_img(u, v, megaGoodie); }
--- a/graphics.h Fri Oct 23 16:30:18 2020 -0400 +++ b/graphics.h Wed Nov 25 01:17:39 2020 +0000 @@ -34,6 +34,15 @@ void draw_snake_body(int u, int v); void draw_snake_head(int u, int v); void draw_snake_tail(int u, int v); +//new buffs/debuffs/extra stuff below +void draw_poison(int u, int v); +void draw_speedup(int u, int v); +void draw_slowdown(int u, int v); +void draw_decrease_length(int u, int v); +void draw_random(int u, int v); +void draw_moving(int u, int v); +void draw_invinc(int u, int v); +void draw_megaGoodie(int u, int v); #endif // GRAPHICS_H \ No newline at end of file
--- a/hardware.cpp Fri Oct 23 16:30:18 2020 -0400 +++ b/hardware.cpp Wed Nov 25 01:17:39 2020 +0000 @@ -29,6 +29,7 @@ // Some hardware also needs to have functions called before it will set up // properly. Do that here. + int hardware_init() { // Crank up the speed @@ -49,5 +50,19 @@ GameInputs read_inputs() { GameInputs in; + + // Read the values and store them in in + //tilting board left = -x + //tilting board down towards table = +y + + in.b1 = button3; //top button on breadboard is connected to p23 + in.b2 = button2; //middle button on breadboard is connected to p22 + in.b3 = button1; //bottom button ob breadboard is connected to p21 + + acc.readXGravity(&in.ax); + acc.readYGravity(&in.ay); + acc.readZGravity(&in.az); + + //pc.printf("xAccel: %f yAccel: %f zAccel: %f\n",in.ax,in.ay,in.az); return in; }
--- a/hash_table.cpp Fri Oct 23 16:30:18 2020 -0400 +++ b/hash_table.cpp Wed Nov 25 01:17:39 2020 +0000 @@ -1,55 +1,3 @@ -// 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. -/* - Student Name: - Date: - -======================= -ECE 2035 Project 2-1: -======================= -This file provides definition for the structs and functions declared in the -header file. It also contains helper functions that are not accessible from -outside of the file. - -FOR FULL CREDIT, BE SURE TO TRY MULTIPLE TEST CASES and DOCUMENT YOUR CODE. - -=================================== -Naming conventions in this file: -=================================== -1. All struct names use camel case where the first letter is capitalized. - e.g. "HashTable", or "HashTableEntry" - -2. Variable names with a preceding underscore "_" will not be called directly. - e.g. "_HashTable", "_HashTableEntry" - - Recall that in C, we have to type "struct" together with the name of the struct - in order to initialize a new variable. To avoid this, in hash_table.h - we use typedef to provide new "nicknames" for "struct _HashTable" and - "struct _HashTableEntry". As a result, we can create new struct variables - by just using: - - "HashTable myNewTable;" - or - - "HashTableEntry myNewHashTableEntry;" - - The preceding underscore "_" simply provides a distinction between the names - of the actual struct defition and the "nicknames" that we use to initialize - new structs. - [See Hidden Definitions section for more information.] - -3. Functions, their local variables and arguments are named with camel case, where - the first letter is lower-case. - e.g. "createHashTable" is a function. One of its arguments is "numBuckets". - It also has a local variable called "newTable". - -4. The name of a struct member is divided by using underscores "_". This serves - as a distinction between function local variables and struct members. - e.g. "num_buckets" is a member of "HashTable". - -*/ - /**************************************************************************** * Include the Public Interface * @@ -59,8 +7,8 @@ * correctness, but it is better than nothing! ***************************************************************************/ #include "hash_table.h" - - + + /**************************************************************************** * Include other private dependencies * @@ -69,8 +17,8 @@ ***************************************************************************/ #include <stdlib.h> // For malloc and free #include <stdio.h> // For printf - - + + /**************************************************************************** * Hidden Definitions * @@ -80,39 +28,37 @@ ***************************************************************************/ /** * This structure represents an a hash table. - * Use "HashTable" instead when you are creating a new variable. [See top comments] */ struct _HashTable { /** The array of pointers to the head of a singly linked list, whose nodes are HashTableEntry objects */ HashTableEntry** buckets; - + /** The hash function pointer */ HashFunction hash; - + /** The number of buckets in the hash table */ unsigned int num_buckets; }; - + /** * This structure represents a hash table entry. - * Use "HashTableEntry" instead when you are creating a new variable. [See top comments] */ struct _HashTableEntry { /** The key for the hash table entry */ unsigned int key; - + /** The value associated with this hash table entry */ void* value; - + /** * A pointer pointing to the next hash table entry * NULL means there is no next entry (i.e. this is the tail) */ HashTableEntry* next; }; - - + + /**************************************************************************** * Private Functions * @@ -131,23 +77,39 @@ * @return The pointer to the hash table entry */ static HashTableEntry* createHashTableEntry(unsigned int key, void* value) { - + // Create an initialize a new hash table entry. + HashTableEntry* newEntry = (HashTableEntry*)malloc(sizeof(HashTableEntry)); + newEntry->key = key; + newEntry->value = value; + newEntry->next = NULL; + + return newEntry; } - + /** * findItem * * Helper function that checks whether there exists the hash table entry that * contains a specific key. * -* @param hashTable The pointer to the hash table. +* @param myHashTable The pointer to the hash table. * @param key The key corresponds to the hash table entry * @return The pointer to the hash table entry, or NULL if key does not exist */ -static HashTableEntry* findItem(HashTable* hashTable, unsigned int key) { - +static HashTableEntry* findItem(HashTable* myHashTable, unsigned int key) { + unsigned int bucketNum = myHashTable->hash(key); // Get the bucket number. + HashTableEntry* temp = myHashTable->buckets[bucketNum]; // Get the head entry. + + if (temp == NULL) return NULL; // If there's nothing in the bucket, return NULL. + + while (temp!=NULL) { + if (temp->key==key) return temp; // Return the hash table entry if the key is found. + temp = temp->next; // Otherwise, move to next node. + } + + return NULL; // Return NULL if key is not present. } - + /**************************************************************************** * Public Interface Functions * @@ -155,48 +117,117 @@ * file, and make use of the private functions and hidden definitions in the * above sections. ****************************************************************************/ -// The createHashTable is provided for you as a starting point. -HashTable* createHashTable(HashFunction hashFunction, unsigned int numBuckets) { +HashTable* createHashTable(HashFunction myHashFunc, unsigned int numBuckets) { // The hash table has to contain at least one bucket. Exit gracefully if // this condition is not met. if (numBuckets==0) { printf("Hash table has to contain at least 1 bucket...\n"); exit(1); } - + // Allocate memory for the new HashTable struct on heap. HashTable* newTable = (HashTable*)malloc(sizeof(HashTable)); - + // Initialize the components of the new HashTable struct. - newTable->hash = hashFunction; + newTable->hash = myHashFunc; newTable->num_buckets = numBuckets; newTable->buckets = (HashTableEntry**)malloc(numBuckets*sizeof(HashTableEntry*)); - - // As the new buckets are empty, init each bucket as NULL. + + // As the new buckets contain indeterminant values, init each bucket as NULL. unsigned int i; for (i=0; i<numBuckets; ++i) { newTable->buckets[i] = NULL; } - - // Return the new HashTable struct. + + // Return the newly created hash table. return newTable; } - -void destroyHashTable(HashTable* hashTable) { - + +void destroyHashTable(HashTable* myHashTable) { + unsigned int i; + HashTableEntry* temp; + HashTableEntry* next; + + // Loop through each bucket of the hash table to remove all items. + for (i=0; i<myHashTable->num_buckets; ++i) { + temp = myHashTable->buckets[i]; // set temp to be the first entry of the ith bucket + + // delete all entries + while (temp != NULL) { + next = temp->next; + free(temp->value); + free(temp); + temp = next; + } + } + + // free buckets + free(myHashTable->buckets); + + // free hash table + free(myHashTable); } - -void* insertItem(HashTable* hashTable, unsigned int key, void* value) { + +void* insertItem(HashTable* myHashTable, unsigned int key, void* value) { + // First, we want to check if the key is present in the hash table. + HashTableEntry* temp = findItem(myHashTable, key); + + if (temp) { + // The key is present in the hash table. + void* oldValue = temp->value; + temp->value = value; + return oldValue; + } else { + // The key is not present in the hash table. + temp = createHashTableEntry(key, value); + temp->next = myHashTable->buckets[myHashTable->hash(key)]; + myHashTable->buckets[myHashTable->hash(key)] = temp; + return NULL; // Return NULL as nothing is overwritten. + } } - -void* getItem(HashTable* hashTable, unsigned int key) { - + +void* getItem(HashTable* myHashTable, unsigned int key) { + // First, we want to check if the key is present in the hash table. + HashTableEntry* temp = findItem(myHashTable, key); + + if (temp) // if the key exists + return temp->value; + else // return NULL if the key does not exist + return NULL; } - -void* removeItem(HashTable* hashTable, unsigned int key) { - + +void* removeItem(HashTable* myHashTable, unsigned int key) { + // Reference: https://www.geeksforgeeks.org/linked-list-set-3-deleting-node/ + unsigned int bucketNum = myHashTable->hash(key); // get the bucket number + HashTableEntry* temp = myHashTable->buckets[bucketNum]; // get the head entry + HashTableEntry* prev; + + // If head holds the key + if (temp != NULL && temp->key == key) { + myHashTable->buckets[bucketNum] = temp->next; // Change head + void* oldValue = temp->value; // hold the old value + free(temp); + return oldValue; + } + + // Search for the key to be removed + while (temp != NULL && temp->key != key) { + prev = temp; + temp = temp->next; + } + + // If the key is not present in the list + if (temp == NULL) return NULL; + + // Unlink the node from list + prev->next = temp->next; + void* oldValue = temp->value; // hold the old value + free(temp); + + return oldValue; } - -void deleteItem(HashTable* hashTable, unsigned int key) { - + +void deleteItem(HashTable* myHashTable, unsigned int key) { + // remove the entry and free the returned data + free(removeItem(myHashTable, key)); } \ No newline at end of file
--- a/hash_table.h Fri Oct 23 16:30:18 2020 -0400 +++ b/hash_table.h Wed Nov 25 01:17:39 2020 +0000 @@ -1,8 +1,10 @@ +//================================================================= // 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. +//================================================================= /**************************************************************************** * Include guards @@ -130,4 +132,4 @@ */ void deleteItem(HashTable* myHashTable, unsigned int key); -#endif \ No newline at end of file +#endif
--- a/main.cpp Fri Oct 23 16:30:18 2020 -0400 +++ b/main.cpp Wed Nov 25 01:17:39 2020 +0000 @@ -7,36 +7,46 @@ // 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 "Speaker.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); - + + +Speaker mySpeaker(p26); /** * 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. @@ -51,13 +61,114 @@ #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) { - return 0; + 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(button3 == 0){ + while(button3 == 0) + {} + } + + if (button2 == 0) { + if (snake.invincTimer == 0) + snake.invincible = !snake.invincible; + else + snake.invincible = 1; + } + if ((E->type==WALL || N->type==WALL || S->type==WALL ||W->type==WALL) && !snake.invincible) return GAME_OVER; + if (inputs.ay >= 0.20) return GO_DOWN; + if (inputs.ay < -0.20) return GO_UP; + if (inputs.ax < -0.20) return GO_RIGHT; + if (inputs.ax >= 0.20) return GO_LEFT; + else return NO_ACTION; } + +void checkCollisions() { + //Check Objects here + if (get_here(snake.head_x,snake.head_y)->type == RANDOM) { + void* d = get_here(snake.head_x,snake.head_y)->data; + if (((int)d % 4) + 13 == 13) + snake.pointLockTime = 10000; + if (((int)d % 4) + 13 == 14) + snake.speedupTime = 10000; + if (((int)d % 4) + 13 == 15) + snake.slowdownTime = 10000; + if (((int)d % 4) + 13 == 16) { + if (snake.length > 1) { + map_erase(snake.locations[snake.length - 2].x, snake.locations[snake.length - 2].y); + map_erase(snake.locations[snake.length - 1].x, snake.locations[snake.length - 1].y); + snake.length -= 2; + } + } + else + snake.pointLockTime = 10000; + return; + } + + if (get_here(snake.head_x,snake.head_y)->type == INVINC) { + snake.invincTimer = 10000; + snake.invincible = 1; + } + + //Check Goodie + + if (get_here(snake.head_x,snake.head_y)->type == GOODIE) { + snake.length++; + mySpeaker.PlayNote(440.0,2,0.3); + if (snake.pointLockTime == 0) //If snake hasn't hit poison in last 10 sec + snake.score++; + } + + + if (get_here(snake.head_x,snake.head_y)->type == MEGAGOODIE) { + snake.length += 3; + mySpeaker.PlayNote(440.0,2,0.3); + if (snake.pointLockTime == 0) //If snake hasn't hit poison in last 10 sec + snake.score += 3; + } + + if (get_here(snake.head_x,snake.head_y)->type == MOVING) { + snake.score += 10; + } + + if (get_here(snake.head_x,snake.head_y)->type == POISON) { + mySpeaker.PlayNote(65.0,2,0.3); + snake.pointLockTime += 10000; //10 sec + } + + if (get_here(snake.head_x,snake.head_y)->type == SPEEDUP) { + mySpeaker.PlayNote(65.0,0.2,0.3); + snake.speedupTime += 10000; //10 sec + } + + if (get_here(snake.head_x,snake.head_y)->type == SLOWDOWN) { + snake.slowdownTime += 10000; //10 sec + } + + if (get_here(snake.head_x,snake.head_y)->type == DECLENGTH) { + if (snake.length > 1) { + map_erase(snake.locations[snake.length - 2].x, snake.locations[snake.length - 2].y); + map_erase(snake.locations[snake.length - 1].x, snake.locations[snake.length - 1].y); + snake.length -= 2; + } + + } +} + /** * 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 @@ -69,17 +180,204 @@ */ int update_game(int action) { - return 0; + + snake.head_px = snake.head_x; + snake.head_py = snake.head_y; + + int oldx = snake.head_px; + int oldy = snake.head_py; + + map_erase(oldx, oldy); + + switch(action) { + case GO_UP: + snake.head_y -= 1; + + checkCollisions(); + //Check un-walkable object + if (get_here(snake.head_x, snake.head_y)->type != SNAKE_HEAD && + get_here(snake.head_x, snake.head_y)->walkable == 0 + && !snake.invincible) { + action = GAME_OVER; + break; + } + //Add snake head now + add_snake_head(snake.head_x, snake.head_y); + //Check max length + if (snake.length == SNAKE_MAX_LENGTH && !snake.invincible) { + action = GAME_OVER; + break; + } + for (int i = 0; i < snake.length; i++) { + map_erase(oldx, oldy); + int tempy = snake.locations[i].y; + snake.locations[i].y = oldy; + + int tempx = snake.locations[i].x; + snake.locations[i].x = oldx; + + oldy = tempy; + oldx = tempx; + map_erase(oldx, oldy); + + if (i < snake.length - 1) + add_snake_body(snake.locations[i].x, snake.locations[i].y); + else + add_snake_tail(snake.locations[i].x, snake.locations[i].y); + } + return ACTION_BUTTON; + case GO_LEFT: + snake.head_x -= 1; + + checkCollisions(); + + //Check un-walkable object + if (get_here(snake.head_x, snake.head_y)->type != SNAKE_HEAD && + get_here(snake.head_x, snake.head_y)->walkable == 0 + && !snake.invincible) { + action = GAME_OVER; + break; + } + + add_snake_head(snake.head_x, snake.head_y); + //Check max length + if (snake.length == SNAKE_MAX_LENGTH && !snake.invincible) { + action = GAME_OVER; + break; + } + for (int i = 0; i < snake.length; i++) { + map_erase(oldx, oldy); + int tempy = snake.locations[i].y; + snake.locations[i].y = oldy; + + int tempx = snake.locations[i].x; + snake.locations[i].x = oldx; + + oldy = tempy; + oldx = tempx; + map_erase(oldx, oldy); + + if (i < snake.length - 1) + add_snake_body(snake.locations[i].x, snake.locations[i].y); + else + add_snake_tail(snake.locations[i].x, snake.locations[i].y); + } + return ACTION_BUTTON; + case GO_DOWN: + snake.head_y += 1; + + checkCollisions(); + + //Check un-walkable object + if (get_here(snake.head_x, snake.head_y)->type != SNAKE_HEAD && + get_here(snake.head_x, snake.head_y)->walkable == 0 + && !snake.invincible) { + action = GAME_OVER; + break; + } + + add_snake_head(snake.head_x, snake.head_y); + //Check max length + if (snake.length == SNAKE_MAX_LENGTH && !snake.invincible) { + action = GAME_OVER; + break; + } + for (int i = 0; i < snake.length; i++) { + int tempy = snake.locations[i].y; + snake.locations[i].y = oldy; + + int tempx = snake.locations[i].x; + snake.locations[i].x = oldx; + + oldy = tempy; + oldx = tempx; + map_erase(oldx, oldy); + + if (i < snake.length - 1) + add_snake_body(snake.locations[i].x, snake.locations[i].y); + else + add_snake_tail(snake.locations[i].x, snake.locations[i].y); + } + return ACTION_BUTTON; + + case GO_RIGHT: + snake.head_x += 1; + + checkCollisions(); + + //Check un-walkable object + if (get_here(snake.head_x, snake.head_y)->type != SNAKE_HEAD && + get_here(snake.head_x, snake.head_y)->walkable == 0 + && !snake.invincible) { + action = GAME_OVER; + break; + } + + add_snake_head(snake.head_x, snake.head_y); + //Check max length + if (snake.length == SNAKE_MAX_LENGTH && !snake.invincible) { + action = GAME_OVER; + break; + } + for (int i = 0; i < snake.length; i++) { + int tempy = snake.locations[i].y; + snake.locations[i].y = oldy; + + int tempx = snake.locations[i].x; + snake.locations[i].x = oldx; + + oldy = tempy; + oldx = tempx; + map_erase(oldx, oldy); + + if (i < snake.length - 1) + add_snake_body(snake.locations[i].x, snake.locations[i].y); + else + add_snake_tail(snake.locations[i].x, snake.locations[i].y); + } + return ACTION_BUTTON; + + 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); + } + + if (action == 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. */ @@ -87,7 +385,7 @@ { uLCD.line(0, 118, 127, 118, GREEN); } - + /** * Draw the border for the map. */ @@ -98,7 +396,7 @@ 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 @@ -107,34 +405,56 @@ */ void draw_game(int draw_option) { + uLCD.locate(0, 0); + uLCD.text_width(1); + uLCD.text_height(1); + uLCD.printf("Score %d", snake.score); + uLCD.color(GREEN); + + uLCD.locate(8, 0); + uLCD.text_width(1); + uLCD.text_height(1); + uLCD.printf("Loc: %d,%d ", snake.head_x, snake.head_y); + uLCD.color(GREEN); + // Draw game border first - if(draw_option == FULL_DRAW) - { + if(draw_option == FULL_DRAW) { draw_border(); int u = 58; - int v = 56; + int v = 59; draw_snake_head(u, v); draw_snake_body(u-11, v); draw_snake_tail(u-22, v); - return; + int i = 1; + for (; i < snake.length; i++) { + int x = u - (11 * (snake.head_x - snake.locations[i].x)); + int y = v - (11 * (snake.head_y - snake.locations[i].y)); + if (i < snake.length - 1) { + add_snake_body(snake.locations[i].x, snake.locations[i].y); + draw_snake_body(x, y); + } + else { + add_snake_tail(snake.locations[i].x, snake.locations[i].y); + draw_snake_tail(x, y); + } + } } + // 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 @@ -153,30 +473,37 @@ } 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() { + Timer t; + t.start(); + 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()); @@ -193,15 +520,41 @@ add_wall(30, 10, HORIZONTAL, 10); add_wall(39, 0, VERTICAL, 10); pc.printf("Added!\r\n"); - - + + //ADD POISON, ANY OTHER BUFFS/DEBUFFS HERE!!******************************************************* + //Buffs: Decrement length, Slow (slows time) + //Debuffs: Poison (prevents gaining points for certain time), Speedup thing (literally just 1.5x time or something), + //Extra: Random, Strength (prevent death once or something), Pause button (just pause time), Moving object, multiple lives + //Also: Button or sprite to invert controls + for(int i = map_width() + 8; i < map_area(); i += 31) { + add_poison(i % map_width() + 4, i / map_width()); + } + + + for(int i = map_width() + 8; i < map_area(); i += 32) { + add_megaGoodie(i % map_width() + 4, i / map_width()); + } + + + for(int i = map_width() + 8; i < map_area(); i += 44) { + add_speedup(i % map_width() + 4, i / map_width()); + } + + for(int i = map_width() + 8; i < map_area(); i += 52) { + add_slowdown(i % map_width() + 4, i / map_width()); + } + + for(int i = map_width() + 8; i < map_area(); i += 64) { + add_decrease_length(i % map_width() + 4, i / map_width()); + } + // 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 @@ -212,15 +565,17 @@ { // 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; + //snake.head_x = snake.head_y = 5 ; + // Initial drawing draw_game(FULL_DRAW); // Main game loop @@ -228,7 +583,7 @@ // Timer to measure game update speed Timer t; t.start(); - + // 1. Read inputs -- implement this function: GameInputs inputs = read_inputs(); @@ -247,15 +602,61 @@ // Compute update time t.stop(); int dt = t.read_ms(); - + + //Add boolean on snake, check boolean, make dt 75 instead of 100. Boom, speedup debuff. + //Do same thing for slow buff essentially. + if (dt % 8 == 0 || dt % 8 == 1) { + map_erase(5, 5); + add_moving(45, 45); + } + else if (dt % 8 == 2 || dt % 8 == 3) { + map_erase(45, 45); + add_moving(5, 45); + } + else if (dt % 8 == 4 || dt % 8 == 5) { + map_erase(5, 45); + add_moving(45, 5); + } + else { + map_erase(45, 5); + add_moving(5, 5); + } + + if (snake.invincTimer > 0) { + snake.invincTimer -= 100; + if (snake.invincTimer == 0) + snake.invincible = 0; + } + // Display and wait // NOTE: Text is 8 pixels tall - if (dt < 100) wait_ms(100 - dt); + if (snake.speedupTime > 0 && snake.slowdownTime > 0) { + if (dt < 100) wait_ms(100 - dt); + snake.speedupTime -= 100; + snake.slowdownTime -= 100; + } + else if (snake.speedupTime > 0) { + if (dt < 80) wait_ms(80 - dt); + snake.speedupTime -= 100; + } + else if (snake.slowdownTime > 0) { + if (dt < 125) wait_ms(125 - dt); + snake.slowdownTime -= 100; + } + else + if (dt < 100) wait_ms(100 - dt); + + //Subtract from point lock time, if it's on + if (snake.pointLockTime > 0) + snake.pointLockTime -= 100; + } } - + // Plays a wavfile void playSound(char* wav) { - -} \ No newline at end of file + +} + + \ No newline at end of file
--- a/map.cpp Fri Oct 23 16:30:18 2020 -0400 +++ b/map.cpp Wed Nov 25 01:17:39 2020 +0000 @@ -19,6 +19,8 @@ }; #define NUM_MAPS 1 +#define MAP_WIDTH 50 +#define MAP_HEIGHT 50 static Map maps[NUM_MAPS]; static int active_map; @@ -33,7 +35,9 @@ * This function should uniquely map (x,y) onto the space of unsigned integers. */ static unsigned XY_KEY(int X, int Y) { - // TODO: Fix me! + + return X*maps[0].h + Y; + } /** @@ -43,14 +47,14 @@ */ unsigned map_hash(unsigned key) { - // TODO: Fix me! + return key%(NUM_MAPS); } void maps_init() { - // TODO: Implement! - // Initialize hash table - // Set width & height + maps[0].items = createHashTable(map_hash, NUM_MAPS); + maps[0].w = MAP_WIDTH; + maps[0].h = MAP_HEIGHT; } Map* get_active_map() @@ -82,51 +86,51 @@ int map_width() { - + return get_active_map()->w; } int map_height() { - + return get_active_map()->h; } int map_area() { - + return map_width() * map_height(); } -MapItem* get_current(int x, int y) -{ - -} + MapItem* get_north(int x, int y) { - + return get_here(x, y-1); } + MapItem* get_south(int x, int y) { - + return get_here(x, y+1); } MapItem* get_east(int x, int y) { - + return get_here(x+1, y); } MapItem* get_west(int x, int y) { - + return get_here(x-1, y); } MapItem* get_here(int x, int y) { - + return (MapItem*) getItem(get_active_map()->items, XY_KEY(x, y)); } void map_erase(int x, int y) { - + MapItem* item = get_here(x, y); + if (item && item->data) + free(item->data); + deleteItem(get_active_map()->items, XY_KEY(x, y)); } - void add_wall(int x, int y, int dir, int len) { for(int i = 0; i < len; i++) @@ -189,7 +193,7 @@ void add_snake_head(int x, int y) { MapItem* w1 = (MapItem*) malloc(sizeof(MapItem)); - w1->type = SNAKE_BODY; + w1->type = SNAKE_HEAD; w1->draw = draw_snake_head; w1->walkable = false; w1->data = NULL; @@ -207,3 +211,103 @@ void* val = insertItem(get_active_map()->items, XY_KEY(x, y), w1); if (val) free(val); // If something is already there, free it } + +void add_poison(int x, int y) +{ + MapItem* w1 = (MapItem*) malloc(sizeof(MapItem)); + w1->type = POISON; + w1->draw = draw_poison; + w1->walkable = true; + w1->data = NULL; + void* val = insertItem(get_active_map()->items, XY_KEY(x, y), w1); + if (val) free(val); // If something is already there, free it +} + +void add_speedup(int x, int y) +{ + MapItem* w1 = (MapItem*) malloc(sizeof(MapItem)); + w1->type = SPEEDUP; + w1->draw = draw_speedup; + w1->walkable = true; + w1->data = NULL; + void* val = insertItem(get_active_map()->items, XY_KEY(x, y), w1); + if (val) free(val); // If something is already there, free it + +} + +void add_slowdown(int x, int y) +{ + MapItem* w1 = (MapItem*) malloc(sizeof(MapItem)); + w1->type = SLOWDOWN; + w1->draw = draw_slowdown; + w1->walkable = true; + w1->data = NULL; + void* val = insertItem(get_active_map()->items, XY_KEY(x, y), w1); + if (val) free(val); // If something is already there, free it + +} + +void add_decrease_length(int x, int y) +{ + MapItem* w1 = (MapItem*) malloc(sizeof(MapItem)); + w1->type = DECLENGTH; + w1->draw = draw_decrease_length; + w1->walkable = true; + w1->data = NULL; + void* val = insertItem(get_active_map()->items, XY_KEY(x, y), w1); + if (val) free(val); // If something is already there, free it + +} + +void add_random(int x, int y, int d) +{ + MapItem* w1 = (MapItem*) malloc(sizeof(MapItem)); + w1->type = RANDOM; + w1->draw = draw_random; + w1->walkable = true; + d = d % 4; + w1->data = (int*)(d + 13); + void* val = insertItem(get_active_map()->items, XY_KEY(x, y), w1); + if (val) free(val); // If something is already there, free it +} + +void add_moving(int x, int y) { + MapItem* w1 = (MapItem*) malloc(sizeof(MapItem)); + w1->type = MOVING; + w1->draw = draw_moving; + w1->walkable = true; + w1->data = NULL; + void* val = insertItem(get_active_map()->items, XY_KEY(x, y), w1); + if (val) free(val); // If something is already there, free it +} + +void add_invinc(int x, int y) { + MapItem* w1 = (MapItem*) malloc(sizeof(MapItem)); + w1->type = INVINC; + w1->draw = draw_invinc; + w1->walkable = true; + w1->data = NULL; + void* val = insertItem(get_active_map()->items, XY_KEY(x, y), w1); + if (val) free(val); // If something is already there, free it +} + +void add_megaGoodie(int x, int y) +{ + MapItem* w1 = (MapItem*) malloc(sizeof(MapItem)); + w1->type = GOODIE; + w1->draw = draw_megaGoodie; + w1->walkable = true; + w1->data = NULL; + void* val = insertItem(get_active_map()->items, XY_KEY(x, y), w1); + if (val) free(val); // If something is already there, free it +} +void add_nothing(int x, int y) +{ + MapItem* w1 = (MapItem*) malloc(sizeof(MapItem)); + w1->type = CLEAR; + w1->draw = draw_nothing; + w1->walkable = true; + w1->data = NULL; + void* val = insertItem(get_active_map()->items, XY_KEY(x, y), w1); + if (val) free(val); // If something is already there, free it +} \ No newline at end of file
--- a/map.h Fri Oct 23 16:30:18 2020 -0400 +++ b/map.h Wed Nov 25 01:17:39 2020 +0000 @@ -71,6 +71,15 @@ #define SONAR 9 #define PUZZLE 10 #define NPC 11 +#define SNAKE_HEAD 12 +#define POISON 13 +#define SPEEDUP 14 +#define SLOWDOWN 15 +#define DECLENGTH 16 +#define RANDOM 17 +#define MOVING 18 +#define INVINC 19 +#define MEGAGOODIE 20 /** @@ -178,6 +187,16 @@ void add_snake_body(int x, int y); void add_snake_head(int x, int y); void add_snake_tail(int x, int y); +void add_nothing(int x, int y); +//Added buffs/debuffs/extra stuff below +void add_poison(int x, int y); +void add_speedup(int x, int y); +void add_slowdown(int x, int y); +void add_decrease_length(int x, int y); +void add_random(int x, int y, int d); +void add_moving(int x, int y); +void add_invinc(int x, int y); +void add_megaGoodie(int x, int y); #endif //MAP_H \ No newline at end of file
--- a/snake.cpp Fri Oct 23 16:30:18 2020 -0400 +++ b/snake.cpp Wed Nov 25 01:17:39 2020 +0000 @@ -8,5 +8,21 @@ void snake_init (Snake * s) { - -} + s->head_x = 5; + s->head_px =0; + s->head_y = 5; + s->head_py =0; + s->length = 3; + + for (int i = 0; i < SNAKE_MAX_LENGTH; i++) { + s->locations[i].x = s->head_x - i; + s->locations[i].y = s->head_y; + } + + s->pointLockTime = 0; //Time that snake can't gain points + s->speedupTime = 0; + s->slowdownTime = 0; + s->score = 0; //Current score of the snake + s->invincible = false; + s->invincTimer = 0; +} \ No newline at end of file
--- a/snake.h Fri Oct 23 16:30:18 2020 -0400 +++ b/snake.h Wed Nov 25 01:17:39 2020 +0000 @@ -18,6 +18,12 @@ int length; // length of the snake Coordinate locations[SNAKE_MAX_LENGTH]; // Snake body locations int score; //Current score of the snake + int pointLockTime; + int speedupTime; + int slowdownTime; + bool invincible; + int invincTimer; + int lives; } Snake; // Initialize a snake structure