diff --git a/Assignment3Project/Assignment3Project/Assignment3Project.vcxproj b/Assignment3Project/Assignment3Project/Assignment3Project.vcxproj
index cf9b104..070cef7 100644
--- a/Assignment3Project/Assignment3Project/Assignment3Project.vcxproj
+++ b/Assignment3Project/Assignment3Project/Assignment3Project.vcxproj
@@ -146,9 +146,12 @@
+
+
+
@@ -156,9 +159,12 @@
+
+
+
diff --git a/Assignment3Project/Assignment3Project/Assignment3Project.vcxproj.filters b/Assignment3Project/Assignment3Project/Assignment3Project.vcxproj.filters
index cac8692..573489a 100644
--- a/Assignment3Project/Assignment3Project/Assignment3Project.vcxproj.filters
+++ b/Assignment3Project/Assignment3Project/Assignment3Project.vcxproj.filters
@@ -63,6 +63,15 @@
Header Files\Engine
+
+ Header Files\Screens
+
+
+ Header Files\Assignment3
+
+
+ Header Files\Screens
+
@@ -89,6 +98,15 @@
Source Files\EngineImplement
+
+ Source Files\ScreensImplement
+
+
+ Source Files
+
+
+ Source Files\ScreensImplement
+
diff --git a/Assignment3Project/Assignment3Project/death.wav b/Assignment3Project/Assignment3Project/death.wav
new file mode 100644
index 0000000..a3bc1d2
Binary files /dev/null and b/Assignment3Project/Assignment3Project/death.wav differ
diff --git a/Assignment3Project/Assignment3Project/enemies.txt b/Assignment3Project/Assignment3Project/enemies.txt
index 151b182..b0a658d 100644
--- a/Assignment3Project/Assignment3Project/enemies.txt
+++ b/Assignment3Project/Assignment3Project/enemies.txt
@@ -1 +1,3 @@
-e,10,240
\ No newline at end of file
+e,10,200
+e,20,10
+e,22,50
\ No newline at end of file
diff --git a/Assignment3Project/Assignment3Project/enums.h b/Assignment3Project/Assignment3Project/enums.h
index f960635..9523b53 100644
--- a/Assignment3Project/Assignment3Project/enums.h
+++ b/Assignment3Project/Assignment3Project/enums.h
@@ -10,7 +10,8 @@
enum State {
Start,
Gameplay,
- End,
+ Win,
+ Lose,
Exit
};
@@ -30,6 +31,12 @@ enum Behavior {
Enemy
};
+enum BgLayer {
+ Front,
+ Middle,
+ Back
+};
+
struct Hitbox {
int x;
int y;
diff --git a/Assignment3Project/Assignment3Project/fire.wav b/Assignment3Project/Assignment3Project/fire.wav
new file mode 100644
index 0000000..bedb759
Binary files /dev/null and b/Assignment3Project/Assignment3Project/fire.wav differ
diff --git a/Assignment3Project/Assignment3Project/game.cpp b/Assignment3Project/Assignment3Project/game.cpp
index 930986f..587e08d 100644
--- a/Assignment3Project/Assignment3Project/game.cpp
+++ b/Assignment3Project/Assignment3Project/game.cpp
@@ -11,6 +11,7 @@ Game::Game() {
void Game::init() {
score = 0;
state = Start;
+ sprites.insert(pair("Title", al_load_bitmap("spaceforce.bmp")));
sprites.insert(pair("Ship", al_load_bitmap("placeholder.bmp")));
sprites.insert(pair("Enemy", al_load_bitmap("enemy.bmp")));
sprites.insert(pair("MusicOn", al_load_bitmap("music_on.bmp")));
@@ -18,6 +19,10 @@ void Game::init() {
al_reserve_samples(4);
samples.insert(pair("Theme", al_load_sample("cheesetheme.wav")));
+ samples.insert(pair("Fire", al_load_sample("fire.wav")));
+ samples.insert(pair("Hit", al_load_sample("hit.wav")));
+ samples.insert(pair("Die", al_load_sample("death.wav")));
+ samples.insert(pair("Win", al_load_sample("victory.wav")));
font = al_create_builtin_font();
}
@@ -31,6 +36,7 @@ void Game::run() {
//Load screens
StartScreen start_screen(sprites);
GameScreen game_screen(sprites, samples);
+ ResultScreen result_screen;
while (state != Exit) {
switch (state) {
@@ -44,7 +50,15 @@ void Game::run() {
game_screen.run(font);
state = game_screen.next_state;
break;
+ case Win:
+ case Lose:
+ result_screen.win = (state == Win) ? true : false;
+ result_screen.score = game_screen.score;
+ result_screen.run(font);
+ state = result_screen.next_state;
+ break;
}
+
}
//Garbage collection
@@ -56,4 +70,5 @@ void Game::run() {
for (it2 = samples.begin(); it2 != samples.end(); it2++) {
al_destroy_sample(it2->second);
}
+ al_destroy_font(font);
}
\ No newline at end of file
diff --git a/Assignment3Project/Assignment3Project/game.h b/Assignment3Project/Assignment3Project/game.h
index 9d91c12..748ea7b 100644
--- a/Assignment3Project/Assignment3Project/game.h
+++ b/Assignment3Project/Assignment3Project/game.h
@@ -13,6 +13,7 @@
#include "enums.h"
#include "start_screen.h"
#include "game_screen.h"
+#include "result_screen.h"
//Game state machine, contains data global to game
class Game {
diff --git a/Assignment3Project/Assignment3Project/game_element.h b/Assignment3Project/Assignment3Project/game_element.h
index d7baa01..636fa58 100644
--- a/Assignment3Project/Assignment3Project/game_element.h
+++ b/Assignment3Project/Assignment3Project/game_element.h
@@ -7,7 +7,8 @@ class GameElement {
public:
float x_pos;
float y_pos;
- float h_bound;
+ float h_t_bound;
+ float h_b_bound;
float l_bound;
float r_bound;
float speed;
diff --git a/Assignment3Project/Assignment3Project/game_screen.cpp b/Assignment3Project/Assignment3Project/game_screen.cpp
index 301e310..7008edb 100644
--- a/Assignment3Project/Assignment3Project/game_screen.cpp
+++ b/Assignment3Project/Assignment3Project/game_screen.cpp
@@ -13,6 +13,7 @@
//#include "mappy_A5.h"
#include "game_screen.h"
+#include "help_screen.h"
#define FPS 60
@@ -23,11 +24,16 @@ using std::istringstream;
using std::ifstream;
using std::map;
using std::pair;
+using std::rand;
enum KEYS {
KEYUP, KEYDOWN, KEYLEFT, KEYRIGHT, KEYSPACE, KEYCTRL, KEYH, KEYM, KEYESC
};
+enum ACTIONS {
+ FIRE, MUSIC, HELP
+};
+
GameScreen::GameScreen(std::map _sprites, std::map _samples) {
sprites = _sprites;
samples = _samples;
@@ -36,9 +42,14 @@ GameScreen::GameScreen(std::map _sprites, std::map
//Resets game to default values, and uses new given values
void GameScreen::reset() {
- objects.player = new Ship(Player);
- objects.player->set_sprite(sprites["Ship"]);
- objects.player->reset_pos(SCREEN_W / 2, SCREEN_H / 8);
+ music = true;
+ win = false;
+ score = 0;
+
+ Ship player;
+ player.set_props(sprites["Ship"], Player);
+ player.reset_pos(SCREEN_W / 2, SCREEN_H / 1.2);
+ objects.init_player(player);
max_bullets = 3;
}
@@ -75,7 +86,7 @@ void GameScreen::build_enemy_queue() {
}
enemies_file.close();
-}
+}
void GameScreen::run(ALLEGRO_FONT* font) {
ALLEGRO_EVENT_QUEUE* event_queue = NULL;
@@ -91,13 +102,22 @@ void GameScreen::run(ALLEGRO_FONT* font) {
NewEnemy next_enemy = enemy_q.back();
enemy_q.pop_back();
- map inputs;
- inputs.insert(pair("Fire", InputDelay()));
- inputs.insert(pair("Music", InputDelay()));
- inputs.insert(pair("Help", InputDelay()));
-
+ InputDelay inputs[3];
+ inputs[FIRE].input_hit = false;
+ inputs[FIRE].delay_sec = 0;
+ inputs[FIRE].max_delay = 15;
+
+ inputs[MUSIC].input_hit = false;
+ inputs[MUSIC].delay_sec = 0;
+ inputs[MUSIC].max_delay = 80;
+
+ inputs[HELP].input_hit = false;
+ inputs[HELP].delay_sec = 0;
+ inputs[HELP].max_delay = 80;
- map_y = TILE_SIZE * LEVEL_LEN;
+ int max_map = TILE_SIZE * LEVEL_LEN;
+ map_y = max_map;
+ objects.set_background();
redraw(font);
al_flip_display();
@@ -105,6 +125,18 @@ void GameScreen::run(ALLEGRO_FONT* font) {
bool keys[ALLEGRO_KEY_MAX];
for (int i = 0; i < ALLEGRO_KEY_MAX; i++) keys[i] = false;
+ map instances;
+ map::iterator it;
+ for (it = samples.begin(); it != samples.end(); it++) {
+ instances.insert(pair(it->first, al_create_sample_instance(it->second)));
+ al_attach_sample_instance_to_mixer(instances[it->first], al_get_default_mixer());
+ }
+ al_set_sample_instance_playmode(instances["Theme"], ALLEGRO_PLAYMODE_LOOP);
+ float music_vol = 0.5;
+ al_set_sample_instance_gain(instances["Theme"], music_vol);
+ play(instances["Theme"]);
+ al_set_sample_instance_gain(instances["Hit"], 2.2);
+
al_start_timer(timer);
bool exit_screen = false;
while (!exit_screen) {
@@ -112,71 +144,91 @@ void GameScreen::run(ALLEGRO_FONT* font) {
al_wait_for_event(event_queue, &ev);
if (ev.type == ALLEGRO_EVENT_TIMER) { //Check per frame
//Music toggle
- if (keys[KEYCTRL] && keys[KEYM]) {
- music = !music;
+ if (!inputs[MUSIC].input_hit) {
+ if (keys[KEYCTRL] && keys[KEYM]) {
+ if (music) {
+ al_set_sample_instance_gain(instances["Theme"], 0.0);
+ }
+ else {
+ al_set_sample_instance_gain(instances["Theme"], music_vol);
+ }
+ music = !music;
+ inputs[MUSIC].input_hit = true;
+ }
}
//Ship Movement
if (keys[KEYUP]) {
if (keys[KEYRIGHT]) {
- objects.player->move(UR);
+ objects.player.move(UR);
}
else if (keys[KEYLEFT]) {
- objects.player->move(UL);
+ objects.player.move(UL);
}
else {
- objects.player->move(U);
+ objects.player.move(U);
}
}
else if (keys[KEYDOWN]) {
if (keys[KEYRIGHT]) {
- objects.player->move(DR);
+ objects.player.move(DR);
}
else if (keys[KEYLEFT]) {
- objects.player->move(DL);
+ objects.player.move(DL);
}
else {
- objects.player->move(D);
+ objects.player.move(D);
}
}
else if (keys[KEYLEFT]) {
- objects.player->move(L);
+ objects.player.move(L);
}
else if (keys[KEYRIGHT]) {
- objects.player->move(R);
+ objects.player.move(R);
}
//Firing
- if (keys[KEYSPACE]) {
- if (objects.player_bullets.size() < max_bullets) {
- if (!objects.player->fired) {
- objects.player_bullets.push_back(&objects.player->fire());
- }
- objects.player->fired = true;
+ if (!inputs[FIRE].input_hit) {
+ if (keys[KEYSPACE] && objects.player_bullets.size() < max_bullets) {
+ objects.player_bullets.push_back(objects.player.fire());
+ inputs[FIRE].input_hit = true;
+ play(instances["Fire"]);
}
}
- if (objects.player->fired) {
- if (fired_counter >= 20) {
- objects.player->fired = false;
- fired_counter = 0;
- }
- else {
- fired_counter++;
+
+ //Help menu
+ if (!inputs[HELP].input_hit) {
+ if (keys[KEYCTRL] && keys[KEYH]) {
+ HelpScreen help_screen;
+ al_clear_to_color(al_map_rgb(0, 0, 0));
+ help_screen.run(font);
+ al_clear_to_color(al_map_rgb(0, 0, 0));
+ keys[KEYCTRL] = false;
+ keys[KEYH] = false;
}
}
+ //Move map (HAHAHA THE MAP DIDN'T WORK AND I GAVE UP this is just a glorified timer now)
if (map_y > 0) {
- map_y -= 10;
+ map_y -= 2;
}
- else {
+ else if(objects.enemies.size() == 0) {
+ win = true;
exit_screen = true;
+ al_stop_sample_instance(instances["Theme"]);
+ al_set_sample_instance_gain(instances["Win"], music_vol);
+ al_play_sample_instance(instances["Win"]);
}
- if (more_enemies && map_y >= next_enemy.when) {
- Ship* new_e = new Ship(next_enemy.e_type);
- new_e->set_sprite(sprites["Enemy"]);
- new_e->reset_pos(next_enemy.x, 0 - new_e->height + 1);
+ /* This may be used in the next assignment, this functionality is for scripting enemy appearance
+ //Check if the next enemy is due
+ if (more_enemies && (max_map - map_y) >= next_enemy.when) {
+ //If he is, generate the new ship for the enemy and set the next enemy up
+ Ship new_e;
+ new_e.set_props(sprites["Enemy"], next_enemy.e_type);
+ new_e.reset_pos(next_enemy.x + SCREEN_L_B, 0 - new_e.height + 1);
objects.enemies.push_back(new_e);
+ //Only queue up a new enemy if there is one, if there isn't then set the flag for no more enemies
if (enemy_q.size() > 0) {
next_enemy = enemy_q.back();
enemy_q.pop_back();
@@ -184,13 +236,35 @@ void GameScreen::run(ALLEGRO_FONT* font) {
else {
more_enemies = false;
}
+ }*/
+
+ //Random enemy generation
+ if (map_y > 20) { //Should only generate if not right near the end
+ int enemy_chance = rand() % 80; //1 in 20 chance to generate an enemy
+ if (enemy_chance == 4) {
+ Ship new_e;
+ new_e.set_props(sprites["Enemy"], Enemy);
+ new_e.reset_pos(rand() % ((SCREEN_R_B - (int)new_e.width) - SCREEN_L_B + 1) + SCREEN_L_B, 0 - new_e.height + 1);
+ objects.enemies.push_back(new_e);
+ }
+ }
+
+ if (keys[KEYESC]) {
+ exit_screen = true;
+ next_state = Exit;
}
//Global refresh
if (objects.chk_player_col()) {
exit_screen = true;
+ al_stop_sample_instance(instances["Theme"]);
+ play(instances["Die"]);
+ }
+ int points = objects.chk_bullet_col();
+ if (points > 0) {
+ score += points;
+ play(instances["Hit"]);
}
- //score += objects.chk_bullet_col();
objects.move_enemies();
al_clear_to_color(al_map_rgb(0, 0, 0));
redraw(font);
@@ -252,12 +326,15 @@ void GameScreen::run(ALLEGRO_FONT* font) {
break;
case ALLEGRO_KEY_SPACE:
keys[KEYSPACE] = false;
+ inputs[FIRE].input_hit = false;
break;
case ALLEGRO_KEY_M:
keys[KEYM] = false;
+ inputs[MUSIC].input_hit = false;
break;
case ALLEGRO_KEY_H:
keys[KEYH] = false;
+ inputs[HELP].input_hit = false;
break;
case ALLEGRO_KEY_ESCAPE:
keys[KEYESC] = false;
@@ -273,8 +350,8 @@ void GameScreen::run(ALLEGRO_FONT* font) {
cont();
}
+ al_clear_to_color(al_map_rgb(0, 0, 0));
//Garbage collection
- //MapFreeMem();
objects.destroy_objects();
al_destroy_event_queue(event_queue);
al_destroy_timer(timer);
@@ -286,12 +363,19 @@ void GameScreen::redraw(ALLEGRO_FONT* font) {
objects.draw_objects();
+ //Borders
+ al_draw_filled_rectangle(SCREEN_L_B - 1, 0, SCREEN_L_B, SCREEN_H, al_map_rgb(255,255,255));
+ al_draw_filled_rectangle(SCREEN_R_B, 0, SCREEN_R_B + 1, SCREEN_H, al_map_rgb(255,255,255));
+
+ //Score
ostringstream score_msg;
- score_msg << "Score: " << score;
- al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_R_B + 2, 0, ALLEGRO_ALIGN_LEFT, score_msg.str().c_str());
+ score_msg << "" << score;
+ al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_R_B + 2, 0, ALLEGRO_ALIGN_LEFT, "Score: ");
+ al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_R_B + 2, 10, ALLEGRO_ALIGN_LEFT, score_msg.str().c_str());
+ //Music
string music_img = (music) ? "MusicOn" : "MusicOff";
- al_draw_bitmap(sprites[music_img], SCREEN_R_B + 10, 90, NULL);
+ al_draw_bitmap(sprites[music_img], SCREEN_R_B + 10, 40, NULL);
}
void GameScreen::back() {
@@ -299,5 +383,5 @@ void GameScreen::back() {
}
void GameScreen::cont() {
- next_state = Start;
+ next_state = (win) ? Win : Lose;
}
\ No newline at end of file
diff --git a/Assignment3Project/Assignment3Project/game_screen.h b/Assignment3Project/Assignment3Project/game_screen.h
index efc6522..65f7d68 100644
--- a/Assignment3Project/Assignment3Project/game_screen.h
+++ b/Assignment3Project/Assignment3Project/game_screen.h
@@ -16,6 +16,7 @@ public:
int score;
int level;
bool music;
+ bool win;
int map_y;
@@ -33,5 +34,4 @@ public:
private:
void play(ALLEGRO_SAMPLE_INSTANCE* x);
void build_enemy_queue();
- void set_delays(std::map inputs);
};
\ No newline at end of file
diff --git a/Assignment3Project/Assignment3Project/help_screen.cpp b/Assignment3Project/Assignment3Project/help_screen.cpp
new file mode 100644
index 0000000..de47d84
--- /dev/null
+++ b/Assignment3Project/Assignment3Project/help_screen.cpp
@@ -0,0 +1,69 @@
+#include "help_screen.h"
+
+#include
+#include
+
+using std::vector;
+using std::string;
+
+HelpScreen::HelpScreen() {
+ vector menu_options;
+ menu_options.push_back("Continue"); //Continue game
+ menu.activate(menu_options);
+}
+
+//Run screen
+void HelpScreen::run(ALLEGRO_FONT * font) {
+ ALLEGRO_EVENT_QUEUE* event_queue = NULL;
+ event_queue = al_create_event_queue();
+ al_register_event_source(event_queue, al_get_keyboard_event_source());
+
+ redraw(font);
+ menu.draw(300.0, 400.0, 20.0, font);
+ al_flip_display();
+
+ bool ctrl = false;
+ bool exit_screen = false;
+ while (!exit_screen) {
+ ALLEGRO_EVENT ev;
+ al_wait_for_event(event_queue, &ev);
+
+ if (ev.type == ALLEGRO_EVENT_KEY_DOWN) {
+ switch (ev.keyboard.keycode) {
+ case ALLEGRO_KEY_SPACE:
+ //Select item
+ exit_screen = true;
+ break;
+ case ALLEGRO_KEY_ESCAPE:
+ //Force quit game
+ exit_screen = true;
+ break;
+ }
+ redraw(font);
+ al_flip_display();
+ }
+ }
+
+ //Garbage collection
+ al_destroy_event_queue(event_queue);
+}
+
+void HelpScreen::redraw(ALLEGRO_FONT* font) {
+ al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 12, SCREEN_H / 1.5 - 10, ALLEGRO_ALIGN_LEFT, "WASD or Arrows - Move ship");
+
+ al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 12, SCREEN_H / 1.3 - 20, ALLEGRO_ALIGN_LEFT, "Spacebar - Shoot, select menu item");
+
+ al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 12, SCREEN_H / 2 + 150, ALLEGRO_ALIGN_LEFT, "Esc - Exit Game");
+
+ al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 2 + 113, SCREEN_H / 1.5 - 10, ALLEGRO_ALIGN_LEFT, "Ctrl + H - Open help menu");
+
+ al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 2 + 113, SCREEN_H / 1.3 - 20, ALLEGRO_ALIGN_LEFT, "Ctrl + M - Toggle Music");
+
+ al_draw_text(font, al_map_rgb(255, 255, 255), 0, SCREEN_H - 10, ALLEGRO_ALIGN_LEFT, "Copyright 2019 Braydon Kains");
+}
+
+void HelpScreen::back() {
+}
+
+void HelpScreen::cont() {
+}
\ No newline at end of file
diff --git a/Assignment3Project/Assignment3Project/help_screen.h b/Assignment3Project/Assignment3Project/help_screen.h
new file mode 100644
index 0000000..d45dcfa
--- /dev/null
+++ b/Assignment3Project/Assignment3Project/help_screen.h
@@ -0,0 +1,18 @@
+#pragma once
+#include "screen.h"
+#include "cursor.h"
+#include
+
+//Screen to display results upon losing
+class HelpScreen : public Screen {
+public:
+ std::map sprites;
+ Cursor menu;
+
+ HelpScreen();
+
+ void run(ALLEGRO_FONT* font);
+ void redraw(ALLEGRO_FONT* font);
+ void back();
+ void cont();
+};
\ No newline at end of file
diff --git a/Assignment3Project/Assignment3Project/hit.wav b/Assignment3Project/Assignment3Project/hit.wav
new file mode 100644
index 0000000..f117820
Binary files /dev/null and b/Assignment3Project/Assignment3Project/hit.wav differ
diff --git a/Assignment3Project/Assignment3Project/object_manager.cpp b/Assignment3Project/Assignment3Project/object_manager.cpp
index 9322972..2c711f3 100644
--- a/Assignment3Project/Assignment3Project/object_manager.cpp
+++ b/Assignment3Project/Assignment3Project/object_manager.cpp
@@ -1,20 +1,21 @@
#include "object_manager.h"
+#include
using std::vector;
-
+using std::rand;
ObjectManager::ObjectManager() {
-
+ srand(time(NULL));
}
-void ObjectManager::initiate(Ship * _player) {
+void ObjectManager::init_player(Ship _player) {
player = _player;
}
bool ObjectManager::chk_player_col() {
if (enemies.size() > 0) {
- for (vector::iterator it = enemies.begin(); it != enemies.end(); it++) {
- if (col_eval(player->get_hitbox(), (*it)->get_hitbox())) {
+ for (vector::iterator it = enemies.begin(); it != enemies.end(); it++) {
+ if (col_eval(player.get_hitbox(), (*it).get_hitbox())) {
return true;
}
}
@@ -25,25 +26,30 @@ bool ObjectManager::chk_player_col() {
int ObjectManager::chk_bullet_col() {
int points = 0;
if (enemies.size() > 0 && player_bullets.size() > 0) {
- int i = 0;
+ int d = 0;
vector dead;
- for (vector::iterator it = enemies.begin(); it != enemies.end(); it++) {
- for (vector::iterator it_b = player_bullets.begin(); it_b != player_bullets.end(); it_b++) {
- if (col_eval((*it_b)->get_hitbox(), (*it)->get_hitbox())) {
- switch ((*it)->behavior) {
+ vector kill_bullets;
+ for (vector::iterator it = enemies.begin(); it != enemies.end(); it++) {
+ int b = 0;
+ for (vector::iterator it_b = player_bullets.begin(); it_b != player_bullets.end(); it_b++) {
+ if (col_eval((*it_b).get_hitbox(), (*it).get_hitbox())) {
+ switch ((*it).behavior) {
default:
points += 10;
}
- delete *it;
- dead.push_back(i);
+ dead.push_back(d);
+ kill_bullets.push_back(b);
}
+ b++;
}
- i++;
+ d++;
}
//Removed backwards to avoid indexing errors
- for (vector::iterator it = dead.end(); it != dead.begin(); it--) {
- delete enemies.at(*it);
- enemies.erase(enemies.begin() + *it);
+ for (unsigned int x = dead.size(); x > 0; x--) {
+ enemies.erase(enemies.begin() + dead.at(x - 1));
+ }
+ for (unsigned int x = kill_bullets.size(); x > 0; x--) {
+ player_bullets.erase(player_bullets.begin() + kill_bullets.at(x - 1));
}
}
return points;
@@ -51,14 +57,28 @@ int ObjectManager::chk_bullet_col() {
void ObjectManager::draw_objects()
{
- player->draw();
+ vector unload;
+ move_background();
+ for (unsigned int k = 0; k < background.size(); k++) {
+ if (background.at(k).oob) {
+ unload.push_back(k);
+ }
+ else {
+ background.at(k).draw();
+ }
+ }
+ for (unsigned int j = unload.size(); j > 0; j--) {
+ background.erase(background.begin() + unload.at(j - 1));
+ }
+
+ player.draw();
if (enemies.size() > 0) {
int i = 0;
vector oob_ships;
- for (vector::iterator it = enemies.begin(); it != enemies.end(); it++) {
- if (!(*it)->oob) {
- (*it)->draw();
+ for (unsigned int k = 0; k < enemies.size(); k++) {
+ if (!enemies.at(k).oob) {
+ enemies.at(k).draw();
}
else {
oob_ships.push_back(i);
@@ -66,82 +86,96 @@ void ObjectManager::draw_objects()
i++;
}
//Removed backwards to avoid indexing errors
- for (vector::iterator it = oob_ships.end(); it != oob_ships.begin(); it--) {
- enemies.erase(enemies.begin() + *it);
+ for (unsigned int x = oob_ships.size(); x > 0; x--) {
+ enemies.erase(enemies.begin() + oob_ships.at(x - 1));
}
}
- bool unload = false;
- for (unsigned int i = 0; i < player_bullets.size(); i++) {
- if (player_bullets.at(i)->oob) {
- unload = true;
+ unload.clear();
+ for (unsigned int k = 0; k < player_bullets.size(); k++) {
+ if (player_bullets.at(k).oob) {
+ unload.push_back(k);
}
else {
- player_bullets.at(i)->move(U);
- player_bullets.at(i)->draw();
+ player_bullets.at(k).move(U);
+ player_bullets.at(k).draw();
}
}
- if (unload) {
- player_bullets.pop_back();
- }
+ for (unsigned int j = unload.size(); j > 0; j--) {
+ player_bullets.erase(player_bullets.begin() + unload.at(j - 1));
+ }
}
void ObjectManager::destroy_objects() {
- delete player;
+ enemies.clear();
+ player_bullets.clear();
+ enemy_bullets.clear();
+}
+void ObjectManager::move_enemies() {
if (enemies.size() > 0) {
- for (vector::iterator it = enemies.begin(); it != enemies.end(); it++) {
- delete *it;
- }
- enemies.clear();
- }
-
- if (player_bullets.size() > 0) {
- for (vector::iterator it = player_bullets.begin(); it != player_bullets.end(); it++) {
- delete *it;
+ for (vector::iterator it = enemies.begin(); it != enemies.end(); it++) {
+ (*it).move(D);
}
- player_bullets.clear();
}
+}
- if (enemy_bullets.size() > 0) {
- for (vector::iterator it = enemy_bullets.begin(); it != enemy_bullets.end(); it++) {
- delete *it;
+void ObjectManager::set_background() {
+ for (int i = 0; i < 20; i++) {
+ Star new_star;
+ int l = rand() % 2;
+ BgLayer layer;
+ switch (l) {
+ case 0:
+ layer = Front;
+ break;
+ case 1:
+ layer = Middle;
+ break;
+ case 2:
+ layer = Back;
+ break;
}
- enemy_bullets.clear();
+ int y = rand() % SCREEN_H;
+ int x = rand() % (SCREEN_R_B - SCREEN_L_B + 1) + SCREEN_L_B;
+ new_star.reset_pos(x, y);
+ new_star.set_layer(layer);
+ background.push_back(new_star);
}
}
-void ObjectManager::move_enemies() {
- if (enemies.size() > 0) {
- for (vector::iterator it = enemies.begin(); it != enemies.end(); it++) {
- (*it)->move(D);
+void ObjectManager::move_background() {
+ for (unsigned int i = 0; i < background.size(); i++) {
+ background.at(i).move(D);
+ }
+ int generate_chance = rand() % 2;
+ if (generate_chance) {
+ Star new_star;
+ int l = rand() % 2;
+ BgLayer layer;
+ switch (l) {
+ case 0:
+ layer = Front;
+ break;
+ case 1:
+ layer = Middle;
+ break;
+ case 2:
+ layer = Back;
+ break;
}
+ int x = rand() % (SCREEN_R_B - SCREEN_L_B + 1) + SCREEN_L_B;
+ new_star.set_layer(layer);
+ new_star.reset_pos(x, new_star.h_t_bound);
+ background.push_back(new_star);
}
}
bool ObjectManager::col_eval(Hitbox h1, Hitbox h2) {
- int l1x = h1.x;
- int l1y = h1.y;
- int r1x = h1.x + h1.width;
- int r1y = h1.y + h1.height;
-
- int l2x = h2.x;
- int l2y = h2.y;
- int r2x = h2.x + h2.width;
- int r2y = h2.y + h2.height;
-
- /*if (h1.x > (h2.x + h2.width) || h2.x > (h1.x + h1.width))
- return false;
-
- if (h1.y < (h2.y + h2.height) || h2.y < (h1.y + h1.height))
- return false;*/
-
- // If one rectangle is on left side of other
- if (l1x > r2x || l2x > r1x)
+ if (h1.x > (h2.x + h2.width) || h2.x > (h1.x + h1.width))
return false;
- // If one rectangle is above other
- if (l1y < r2y || l2y < r1y)
+ if (h1.y > (h2.y + h2.height) || h2.y > (h1.y + h1.height))
return false;
return true;
diff --git a/Assignment3Project/Assignment3Project/object_manager.h b/Assignment3Project/Assignment3Project/object_manager.h
index 9018f14..3b924a9 100644
--- a/Assignment3Project/Assignment3Project/object_manager.h
+++ b/Assignment3Project/Assignment3Project/object_manager.h
@@ -4,22 +4,26 @@
#include "enums.h"
#include "bullet.h"
#include "ship.h"
+#include "star.h"
class ObjectManager {
public:
- Ship* player;
- std::vector enemies;
- std::vector player_bullets;
- std::vector enemy_bullets;
+ Ship player;
+ std::vector enemies;
+ std::vector player_bullets;
+ std::vector enemy_bullets;
+ std::vector background;
ObjectManager();
- void initiate(Ship* _player);
+ void init_player(Ship _player);
bool chk_player_col();
int chk_bullet_col();
void draw_objects();
void destroy_objects();
void move_enemies();
+ void set_background();
+ void move_background();
private:
bool col_eval(Hitbox h1, Hitbox h2);
diff --git a/Assignment3Project/Assignment3Project/result_screen.cpp b/Assignment3Project/Assignment3Project/result_screen.cpp
new file mode 100644
index 0000000..253b7e6
--- /dev/null
+++ b/Assignment3Project/Assignment3Project/result_screen.cpp
@@ -0,0 +1,91 @@
+#include
+#include
+#include "result_screen.h"
+
+using std::string;
+using std::vector;
+using std::ostringstream;
+
+ResultScreen::ResultScreen() {
+ vector menu_options;
+ menu_options.push_back("Retry"); //Restart game
+ menu_options.push_back("To Main Menu"); //Go back to main menu
+ menu_options.push_back("Exit"); //Quit game
+ menu.activate(menu_options);
+}
+
+void ResultScreen::run(ALLEGRO_FONT* font) {
+ ALLEGRO_EVENT_QUEUE* event_queue = NULL;
+ event_queue = al_create_event_queue();
+ al_register_event_source(event_queue, al_get_keyboard_event_source());
+
+ redraw(font);
+ al_flip_display();
+
+ bool exit_screen = false;
+ while (!exit_screen) {
+ ALLEGRO_EVENT ev;
+ al_wait_for_event(event_queue, &ev);
+
+ if (ev.type == ALLEGRO_EVENT_KEY_DOWN) {
+ switch (ev.keyboard.keycode) {
+ case ALLEGRO_KEY_W:
+ case ALLEGRO_KEY_UP:
+ //Move cursor up
+ menu.up();
+ break;
+ case ALLEGRO_KEY_S:
+ case ALLEGRO_KEY_DOWN:
+ //Move cursor down
+ menu.down();
+ break;
+ case ALLEGRO_KEY_SPACE:
+ //Select menu item
+ cont();
+ exit_screen = true;
+ break;
+ case ALLEGRO_KEY_ESCAPE:
+ //Force quit game
+ back();
+ exit_screen = true;
+ break;
+ }
+ redraw(font);
+ al_flip_display();
+ }
+ }
+
+ //Garbage collection
+ al_clear_to_color(al_map_rgb(0, 0, 0));
+ al_destroy_event_queue(event_queue);
+}
+
+void ResultScreen::redraw(ALLEGRO_FONT * font) {
+ //Determine whether the player receives the bad or good ending; minimum requirement for good ending is 30 catches.
+ string result_text = (win) ? "You made it literally all the way across space! Wow!" : "Oh no, you died!";
+
+ //Display score and menu
+ menu.draw(SCREEN_W / 2 - 40, SCREEN_H / 2 - 30, 20.0, font);
+ ostringstream score_msg;
+ score_msg << "Final Score: " << score;
+ al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 2, SCREEN_H / 2 - 90, ALLEGRO_ALIGN_CENTER, score_msg.str().c_str());
+
+ al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 2, SCREEN_H / 2 - 60, ALLEGRO_ALIGN_CENTER, result_text.c_str());
+}
+
+void ResultScreen::back() {
+ next_state = Exit;
+}
+
+void ResultScreen::cont() {
+ string result = menu.get_selected();
+ if (result == "Retry") {
+ next_state = Gameplay;
+ }
+ else if (result == "To Main Menu") {
+ next_state = Start;
+ }
+ else {
+ next_state = Exit;
+ }
+}
diff --git a/Assignment3Project/Assignment3Project/result_screen.h b/Assignment3Project/Assignment3Project/result_screen.h
new file mode 100644
index 0000000..3c41b8f
--- /dev/null
+++ b/Assignment3Project/Assignment3Project/result_screen.h
@@ -0,0 +1,19 @@
+#pragma once
+#include "cursor.h"
+#include "screen.h"
+
+//Screen to display results upon losing
+class ResultScreen : public Screen {
+public:
+ int score;
+ Cursor menu;
+ std::map sprites;
+ bool win;
+
+ ResultScreen();
+
+ void run(ALLEGRO_FONT* font);
+ void redraw(ALLEGRO_FONT* font);
+ void back();
+ void cont();
+};
\ No newline at end of file
diff --git a/Assignment3Project/Assignment3Project/ship.cpp b/Assignment3Project/Assignment3Project/ship.cpp
index 6345be0..397ac39 100644
--- a/Assignment3Project/Assignment3Project/ship.cpp
+++ b/Assignment3Project/Assignment3Project/ship.cpp
@@ -1,15 +1,27 @@
#include "ship.h"
-Ship::Ship(Behavior _behavior) {
- switch (_behavior) {
+Ship::Ship() {
+}
+
+void Ship::reset_pos(float x, float y) {
+ x_pos = x;
+ y_pos = y;
+}
+
+void Ship::set_props(ALLEGRO_BITMAP* _sprite, Behavior _behavior) {
+ sprite = _sprite;
+ behavior = _behavior;
+ oob = false;
+ switch (behavior) {
case Enemy:
- speed = 0.5;
+ speed = 1.1;
height = 40;
width = 40;
l_bound = SCREEN_L_B;
r_bound = SCREEN_R_B;
- h_bound = SCREEN_H;
+ h_t_bound = 0 - height;
+ h_b_bound = SCREEN_H + height;
break;
default:
speed = 1.0;
@@ -19,19 +31,10 @@ Ship::Ship(Behavior _behavior) {
l_bound = SCREEN_L_B;
r_bound = SCREEN_R_B;
r_bound -= width;
- h_bound = SCREEN_H;
- h_bound -= height;
+ h_t_bound = 0;
+ h_b_bound = SCREEN_H - height;
break;
- }
-}
-
-void Ship::reset_pos(float x, float y) {
- x_pos = x;
- y_pos = y;
-}
-
-void Ship::set_sprite(ALLEGRO_BITMAP* _sprite) {
- sprite = _sprite;
+ }
}
void Ship::draw() {
@@ -83,15 +86,15 @@ void Ship::move(Direction dir) {
}
else oob = true;
}
- if (y_pos <= 0.0) {
+ if (y_pos <= h_t_bound) {
if (behavior == Player) {
- y_pos = 0.0;
+ y_pos = h_t_bound;
}
else oob = true;
}
- else if (y_pos >= h_bound) {
+ else if (y_pos >= h_b_bound) {
if (behavior == Player) {
- y_pos = h_bound;
+ y_pos = h_b_bound;
}
else oob = true;
}
diff --git a/Assignment3Project/Assignment3Project/ship.h b/Assignment3Project/Assignment3Project/ship.h
index 17eae73..20d9ce9 100644
--- a/Assignment3Project/Assignment3Project/ship.h
+++ b/Assignment3Project/Assignment3Project/ship.h
@@ -10,7 +10,7 @@ public:
bool fired;
- Ship(Behavior _behavior);
+ Ship();
//implementing virtual methods
void reset_pos(float x, float y);
@@ -19,6 +19,6 @@ public:
Hitbox get_hitbox();
//unique to object
- void set_sprite(ALLEGRO_BITMAP* _sprite);
+ void set_props(ALLEGRO_BITMAP* _sprite, Behavior _behavior);
Bullet fire();
};
\ No newline at end of file
diff --git a/Assignment3Project/Assignment3Project/spaceforce.bmp b/Assignment3Project/Assignment3Project/spaceforce.bmp
new file mode 100644
index 0000000..8dfba4d
Binary files /dev/null and b/Assignment3Project/Assignment3Project/spaceforce.bmp differ
diff --git a/Assignment3Project/Assignment3Project/star.cpp b/Assignment3Project/Assignment3Project/star.cpp
new file mode 100644
index 0000000..d5b36ae
--- /dev/null
+++ b/Assignment3Project/Assignment3Project/star.cpp
@@ -0,0 +1,52 @@
+#include "star.h"
+
+Star::Star() {
+ oob = false;
+}
+
+void Star::reset_pos(float x, float y) {
+ x_pos = x;
+ y_pos = y;
+}
+
+void Star::set_layer(BgLayer _layer) {
+ layer = _layer;
+
+ switch (layer) {
+ case Front:
+ speed = 1.2;
+ height = 1;
+ width = 1;
+ break;
+ case Middle:
+ speed = 1.0;
+ height = 2;
+ width = 2;
+ break;
+ case Back:
+ speed = 0.4;
+ height = 4;
+ width = 4;
+ break;
+ }
+
+ h_t_bound = 0 - height;
+ h_b_bound = SCREEN_H + height;
+ l_bound = 0;
+ r_bound = SCREEN_W;
+}
+
+void Star::move(Direction dir) {
+ y_pos += 4 * speed;
+ if (y_pos > h_b_bound) oob = true;
+}
+
+void Star::draw() {
+ al_draw_filled_rectangle(x_pos, y_pos, (x_pos + width), (y_pos + height), al_map_rgb(255, 255, 255));
+}
+
+Hitbox Star::get_hitbox() {
+ return Hitbox();
+}
+
+
diff --git a/Assignment3Project/Assignment3Project/star.h b/Assignment3Project/Assignment3Project/star.h
new file mode 100644
index 0000000..57ae234
--- /dev/null
+++ b/Assignment3Project/Assignment3Project/star.h
@@ -0,0 +1,21 @@
+#pragma once
+#include "game_element.h"
+#include
+#include "enums.h"
+
+//Background elements, used to salvage parallax scrolling attempts
+class Star : public GameElement {
+public:
+ BgLayer layer;
+
+ Star();
+
+ //Implement inhereted virtuals
+ void reset_pos(float x, float y);
+ void move(Direction dir);
+ void draw();
+ Hitbox get_hitbox();
+
+ //Unique to element
+ void set_layer(BgLayer _layer);
+};
\ No newline at end of file
diff --git a/Assignment3Project/Assignment3Project/start_screen.cpp b/Assignment3Project/Assignment3Project/start_screen.cpp
index cc6506c..114bea8 100644
--- a/Assignment3Project/Assignment3Project/start_screen.cpp
+++ b/Assignment3Project/Assignment3Project/start_screen.cpp
@@ -37,10 +37,12 @@ void StartScreen::run(ALLEGRO_FONT * font) {
if (ev.type == ALLEGRO_EVENT_KEY_DOWN) {
switch (ev.keyboard.keycode) {
+ case ALLEGRO_KEY_W:
case ALLEGRO_KEY_UP:
//Move cursor up
menu.up();
break;
+ case ALLEGRO_KEY_S:
case ALLEGRO_KEY_DOWN:
//Move cursor down
menu.down();
@@ -66,36 +68,23 @@ void StartScreen::run(ALLEGRO_FONT * font) {
}
void StartScreen::redraw(ALLEGRO_FONT* font) {
- //al_draw_bitmap(sprites["Title"], SCREEN_W / 2 - 240, 20, NULL); //logo
+ //Logo
+ al_draw_bitmap(sprites["Title"], SCREEN_W / 2 - 240, 20, NULL);
-
//Instructions
- al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 2, SCREEN_H / 2, ALLEGRO_ALIGN_CENTER, "Travel across the reaches of space");
- al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 2, SCREEN_H / 2 + 10, ALLEGRO_ALIGN_CENTER, "to kill all the red ships!");
- al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 2, SCREEN_H / 2 + 20, ALLEGRO_ALIGN_CENTER, "Red is a bad colour that must be eradicated.");
- //al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 2, SCREEN_H / 2 + 40, ALLEGRO_ALIGN_CENTER, "idek.");
-
+ al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 2, SCREEN_H / 3, ALLEGRO_ALIGN_CENTER, "Journey to the end of space");
+ al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 2, SCREEN_H / 3 + 10, ALLEGRO_ALIGN_CENTER, "and kill the red ships!");
+ al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 2, SCREEN_H / 3 + 20, ALLEGRO_ALIGN_CENTER, "Red is a bad colour that must be eradicated.");
+
//Keys and their associated functions
- //al_draw_bitmap(sprites["KeyUp"], SCREEN_W / 8, SCREEN_H / 2 + 60, NULL);
- //al_draw_bitmap(sprites["KeyUp"], SCREEN_W / 8 + 34, SCREEN_H / 2 + 60, ALLEGRO_FLIP_VERTICAL);
al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 12, SCREEN_H / 1.5 - 10, ALLEGRO_ALIGN_LEFT, "WASD or Arrows - Move ship");
- //al_draw_bitmap(sprites["Spacebar"], SCREEN_W / 8 + 20, SCREEN_H / 2 + 100, NULL);
- al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 12, SCREEN_H / 1.3 - 20, ALLEGRO_ALIGN_LEFT, "Spacebar - Shoot");
- //al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 8 + 150, SCREEN_H / 1.3 - 15, ALLEGRO_ALIGN_LEFT, "Place Emplo");
- //al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 8 + 150, SCREEN_H / 1.3 - 25, ALLEGRO_ALIGN_LEFT, "Select Menu Item");
+ al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 12, SCREEN_H / 1.3 - 20, ALLEGRO_ALIGN_LEFT, "Spacebar - Shoot, select menu item");
- //al_draw_bitmap(sprites["KeyEsc"], SCREEN_W / 8 + 20, SCREEN_H / 2 + 140, NULL);
al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 12, SCREEN_H / 2 + 150, ALLEGRO_ALIGN_LEFT, "Esc - Exit Game");
- //al_draw_bitmap(sprites["KeyCtrl"], SCREEN_W / 2 + 40, SCREEN_H / 2 + 60, NULL);
- //al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 2 + 70, SCREEN_H / 1.5 - 10, ALLEGRO_ALIGN_LEFT, "+");
- //al_draw_bitmap(sprites["KeyH"], SCREEN_W / 2 + 78, SCREEN_H / 2 + 60, NULL);
- al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 2 + 113, SCREEN_H / 1.5 - 10, ALLEGRO_ALIGN_LEFT, "Ctrl + H - Help menu");
+ al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 2 + 113, SCREEN_H / 1.5 - 10, ALLEGRO_ALIGN_LEFT, "Ctrl + H - Open help menu");
- //al_draw_bitmap(sprites["KeyCtrl"], SCREEN_W / 2 + 40, SCREEN_H / 2 + 100, NULL);
- //al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 2 + 70, SCREEN_H / 2 + 110, ALLEGRO_ALIGN_LEFT, "+");
- //al_draw_bitmap(sprites["KeyM"], SCREEN_W / 2 + 78, SCREEN_H / 2 + 100, NULL);
al_draw_text(font, al_map_rgb(255, 255, 255), SCREEN_W / 2 + 113, SCREEN_H / 1.3 - 20, ALLEGRO_ALIGN_LEFT, "Ctrl + M - Toggle Music");
al_draw_text(font, al_map_rgb(255, 255, 255), 0, SCREEN_H - 10, ALLEGRO_ALIGN_LEFT, "Copyright 2019 Braydon Kains");
diff --git a/Assignment3Project/Assignment3Project/victory.wav b/Assignment3Project/Assignment3Project/victory.wav
new file mode 100644
index 0000000..2efe3a2
Binary files /dev/null and b/Assignment3Project/Assignment3Project/victory.wav differ