//------------------梁子轩-雷电战机------------------------
#include<iostream>
#include<ctime>
#include<cstdlib>
#include<windows.h>
#include<conio.h>
#include<chrono>
#include<stdlib.h>
#include<string>
#define KEY_UP 38
#define KEY_DOWN 40
#define KEY_LEFT 37
#define KEY_RIGHT 39
#define bullet_color '|'
#define player_color '+'
#define enemy_color '@'
#define Explode_color '.'
#define player_bullet_color '●'
#define Boss_color 'V'
using ElemType = char;
class Window {
int width, height;
char bg_color = ' ';
char* frame_buffer = nullptr;
int* explode_time = nullptr;
const int extend = 30;
public:
Window(int w, int h, char bgColor) {
width = w, height = h, bg_color = bgColor,
frame_buffer = new char[(w + extend) * h], explode_time = new int[(w + extend) * h];
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
frame_buffer[i * (width + extend) + j] = bg_color;
explode_time[i * (width + extend) + j] = 0;
}
for (int t = width; t < extend + width; t++) {
frame_buffer[i * (width + extend) + t] = '|';
explode_time[i * (width + extend) + t] = 0;
}
}
}
~Window() {
delete[] frame_buffer;
}
void set_pixel(int x, int y, char color, int time) {
if (y * (width + extend) + x < height * (width + extend)) {
int i = y * (width + extend) + x;
frame_buffer[i] = color;
explode_time[i] = time;
}
}
void printAnswer() {
int x = width / 2;
int y = height / 2;
int t = 0;
std::string str = " You Lose!";
for (int i = 0; i < height / 3 * 2; i++) {
for (int j = 0; j < width; j++)
std::cout << " ";
std::cout << '\n';
}
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++)
if (i * width + j <= y * width + x - str.size() / 2 || i * width + j >= y * width + x + str.size() / 2 + 1)
std::cout << " ";
else {
std::cout << str[t];
t++;
}
std::cout << '\n';
}
}
char get_pixel(int x, int y) {
int i = y * (width + extend) + x;
return frame_buffer[i];
}
void clear() {
for (int i = 0; i < height; i++) {
for (int j = 0; j < (width + extend); j++) {
if (explode_time[i * (width + extend) + j] == 0) {
frame_buffer[i * (width + extend) + j] = bg_color;
}
else {
explode_time[i * (width + extend) + j]--;
}
}
}
}
void show() {
for (int i = 0; i < height; i++) {
for (int j = 0; j < (width + extend); j++)
std::cout << frame_buffer[i * (width + extend) + j];
std::cout << '\n';
}
}
int get_width() {
return width;
}
int get_height() {
return height;
}
int get_extend() {
return extend;
}
char get_bg_color() {
return bg_color;
}
};
class Position {
int x = 0, y = 0;
public:
Position(int i = 0, int j = 0) {
x = i;
y = j;
}
void set_x(int i) {
this->x = i;
}
void set_y(int j) {
this->y = j;
}
int get_x() {
return x;
}
int get_y() {
return y;
}
int operator[](const int num)const {
if (num == 0)
return x;
if (num == 1)
return y;
else throw "下标非法";
}
int& operator[](const int num) {
if (num == 0)
return x;
if (num == 1)
return y;
else throw "下标非法";
}
};
class BackGround {
char top_boundary_color = ' ', bottom_boundary_color = '_';
char left_right_boundary_color = '|';
std::string str = " You Lose!";
std::string score = "Your Score:";
std::string live = "Your lives:";
int tmp = 0;
public:
void draw(Window& window) {
int right = window.get_width() - 1;
int bottom = window.get_height() - 1;
for (int x = 0; x < window.get_width() + window.get_extend(); x++) {
window.set_pixel(x, 0, top_boundary_color, 0);
window.set_pixel(x, bottom, bottom_boundary_color, 0);
}
for (int y = 0; y < window.get_height(); y++) {
window.set_pixel(0, y, left_right_boundary_color, 0);
window.set_pixel(right, y, left_right_boundary_color, 0);
window.set_pixel(right + window.get_extend(), y, left_right_boundary_color, 0);
}
tmp = 0;
for (int x = right + window.get_extend() / 3, y = window.get_height() / 2 + 7;
x < score.size() + right + window.get_extend() / 3; x++) {
window.set_pixel(x, y, score[tmp], 0);
tmp++;
}
tmp = 0;
for (int x = right + window.get_extend() / 3, y = window.get_height() / 2 - 10;
x < live.size() + right + window.get_extend() / 3; x++) {
window.set_pixel(x, y, live[tmp], 0);
tmp++;
}
}
};
class Rect {
public:
Position pos, size;
Rect(Position p, Position s) {
pos = p, size = s;
}
Rect(const int x, const int y, const int w, const int h) {
pos = Position(x, y), size = Position(w, h);
}
bool collide(const Rect& other) {
return(
(pos[0] < other.pos[0] + other.size[0]) &&
(pos[0] + size[0] > other.pos[0]) &&
(pos[1] < other.pos[1] + other.size[1]) &&
(pos[1] + size[1] > other.pos[1])
);
}
};
class Sprite {
protected:
Window* window{ nullptr };
Position pos, vel, size_;
char color;
int lives{ 1 };
Rect rect;
public:
Sprite(Window* window, const char c, const Position p,
const Position v = Position{ 0, 0 }, const Position s = Position{ 1, 1 },
const int lives = 1)
:window{ window }, pos{ p }, vel{ v }, size_{ s },
color{ c }, lives{ lives }, rect{ Position(pos[0] - s[0] / 2, pos[1] - s[1] / 2), s }
{
}
virtual void update() {
pos[0] += vel[0];
pos[1] += vel[1];
rect.pos[0] = (pos[0] - rect.size[0] / 2);
rect.pos[1] = (pos[1] - rect.size[1] / 2);
}
virtual void draw() {}
virtual bool is_dead() {
return lives <= 0;
}
virtual Rect get_rect() {
return rect;
}
virtual bool collide(const Rect & other)
{
return rect.collide(other);
}
virtual int get_pos_y() {
return pos[1];
}
virtual int get_pos_x() {
return pos[0];
}
int get_lives() {
return lives;
}
};
class Score :public Sprite {
protected:
int score = 0;
int lives = 0;
int tmp = 0;
std::string str1, str2;
public:
std::string to_String(int n)
{
int m = n;
int tmp = n;
int cap = 1;
while (tmp / 10) {
tmp /= 10;
cap++;
}
char s[100];
char ss[100];
int i = 0, j = 0;
if (n < 0)// 处理负数
{
m = 0 - m;
j = 1;
ss[0] = '-';
}
while (m > 0)
{
s[i++] = m % 10 + '0';
m /= 10;
}
s[i] = '\0';
i = i - 1;
while (i >= 0)
{
ss[j++] = s[i--];
}
ss[j] = '\0';
return ss;
}
Score(Window* window, const char c, const Position p, const Position v = Position(0, 0),
const Position s = Position{ 1, 1 },
const int lives = 1) :
Sprite(window, c, p, v, s, lives) {}
int get_score() {
return score;
}
void score_plus() {
score++;
}
void score_reduce() {
score--;
}
virtual void draw() {
str1 = to_String(score);
str2 = to_String(lives);
tmp = 0;
int x = window->get_width() + window->get_extend() / 3 + 3;
int y = window->get_height() / 2 + 10;
for (; x < str1.size() + window->get_width() + window->get_extend() / 3 + 3; x++) {
window->set_pixel(x, y, str1[tmp], 0);
tmp++;
}
tmp = 0;
x = window->get_width() + window->get_extend() / 3 + 3;
y = window->get_height() / 2 - 8;
for (; x < str2.size() + window->get_width() + window->get_extend() / 3 + 3; x++) {
window->set_pixel(x, y, str2[tmp], 0);
tmp++;
}
}
void set_lives(int n) {
lives = n;
}
};
class Bullet :public Sprite {
public:
Bullet(Window* window, const char c, const Position p,
const Position v = Position(0, 0)) :Sprite(window, c, p, v) {
}
virtual void draw() {
auto x = pos[0], y = pos[1];
window->set_pixel(x, y, color, 0);
}
virtual bool hitted() {
lives--;
return true;
}
};
class Flighter :public Sprite {
protected:
Bullet* bullet{ nullptr };
int Explode = 0;
public:
Flighter(Window* window, const char c, const Position p, const Position v = Position(0, 0),
const Position s = Position{ 1, 1 },
const int lives = 1) :
Sprite(window, c, p, v, s, lives) {}
virtual Bullet* shot(const Position& vel) {
auto x = pos[0];
auto y = pos[1] - rect.size[1] / 2;
bullet = new Bullet(window, bullet_color, Position(x, y), vel);
return bullet;
}
virtual void move(Position vel) {
auto x = pos[0] + vel[0];
auto y = pos[1] + vel[1];
if (x >= rect.size[0] / 2 && x < window->get_width() - rect.size[0] / 2 - 1) {
pos[0] = x;
}
if (y >= rect.size[1] / 2 && y < window->get_height() - rect.size[1] / 2 - 1) {
pos[1] = y;
}
}
void set_explode(int x) {
Explode = x;
}
int get_explode() {
return Explode;
}
};
class Vector {
Sprite** data{ nullptr };
int capacity{ 0 }, n{ 0 };
public:
Vector(const int cap = 10) :capacity{ cap }, data{ new Sprite * [cap] }{}
bool insert(const int i, Sprite*& e) {
if (i < 0 || i >= n)return false;
if (n == capacity && !add_capacity())
return false;
for (auto j = n; j > i; j--)
data[j] = data[j - 1];
data[i] = e;
return true;
}
bool erase(const int i) {
if (i < 0 || i >= n)return false;
for (auto j = i; j < n - 1; j++)
data[j] = data[j + 1];
n--;
return true;
}
bool push_back(Sprite * e) {
if (n == capacity && !add_capacity())
return false;
data[n++] = e;
return true;
}
bool pop_back() {
if (n == 0)return false;
n--;
return true;
}
Sprite* get(const int i) {
if (i >= 0 && i < n)
return data[i];
throw "下标非法!\n";
}
Sprite* get(const int i, Sprite * &e) {
if (i >= 0 && i < n)
return data[i] = e;
}
Sprite*& operator[](int i) {
if (i >= 0 && i < n)return data[i];
}
Sprite* operator[](const int i) const {
if (i >= 0 && i < n)return data[i];
}
bool add_capacity() {
Sprite** temp = new Sprite * [2 * capacity];
if (!temp)return false;
for (auto i = 0; i < n; i++) {
temp[i] = data[i];
}
delete[] data;
data = temp;
capacity *= 2;
return true;
}
int size() const { return n; }
int set_size(int x) {
n = x;
return true;
}
};
class Player :public Flighter {
public:
Player(Window* window, const char c, const Position p, const Position v = Position(0, 0),
const Position s = Position{ 1, 1 },
const int lives = 3) :Flighter(window, c, p, v, s, lives) {}
virtual void move(Position vel) {
auto x = pos[0] + vel[0];
auto y = pos[1] + vel[1];
if (x >= rect.size[0] / 2 && x < window->get_width() - rect.size[0] / 2 - 1) {
pos[0] = x;
}
if (y >= rect.size[1] / 2 && y < window->get_height() - rect.size[1] / 2 - 1) {
pos[1] = y;
}
}
virtual Bullet* shot(const Position& vel) {
auto x = pos[0];
auto y = pos[1] - rect.size[1] / 2;
bullet = new Bullet(window, '\6', Position(x, y), vel);
return bullet;
}
virtual void draw() {
auto x = pos[0], y = pos[1];
if (Explode != 0) {
window->set_pixel(x, y - 1, Explode_color, 5);
window->set_pixel(x - 1, y, Explode_color, 5);
window->set_pixel(x - 1, y + 1, Explode_color, 5);
window->set_pixel(x, y, Explode_color, 5);
window->set_pixel(x - 1, y + 1, Explode_color, 5);
window->set_pixel(x + 1, y, Explode_color, 5);
window->set_pixel(x + 1, y + 1, Explode_color, 5);
}
else {
window->set_pixel(x, y - 1, player_color, 0);
window->set_pixel(x - 1, y, player_color, 0);
window->set_pixel(x - 1, y + 1, player_color, 0);
window->set_pixel(x, y, player_color, 0);
window->set_pixel(x - 1, y + 1, player_color, 0);
window->set_pixel(x + 1, y, player_color, 0);
window->set_pixel(x + 1, y + 1, player_color, 0);
}
}
virtual bool hitted() {
lives--;
return true;
}
};
class SpecialBullet :public Flighter {
public:
SpecialBullet(Window* window, const char c, const Position p, const Position v = Position(0, 0),
const Position s = Position{ 3, 3 },
const int lives = 1) :Flighter(window, c, p, v, s, lives) {}
virtual void move(Position vel) {
auto x = pos[0] + vel[0];
auto y = pos[1] + vel[1];
if (x >= rect.size[0] / 2 && x < window->get_width() - rect.size[0] / 2 - 1) {
pos[0] = x;
}
if (y >= rect.size[1] / 2 && y < window->get_height() - rect.size[1] / 2 - 1) {
pos[1] = y;
}
}
virtual Bullet* shot(const Position& vel) {
auto x = pos[0];
auto y = pos[1] - rect.size[1] / 2;
bullet = new Bullet(window, '*', Position(x, y), vel);
return bullet;
}
virtual void draw() {
auto x = pos[0], y = pos[1];
if (Explode != 0) {
//window->set_pixel(x, y, Explode_color, 5);
}
else {
//window->set_pixel(x, y, '*', 0);
window->set_pixel(x + 1, y, '*', 0);
window->set_pixel(x - 1, y, '*', 0);
window->set_pixel(x, y + 1, '*', 0);
window->set_pixel(x, y - 1, '*', 0);
}
}
virtual bool hitted() {
lives--;
return true;
}
Bullet* get_bullet() {
Bullet* p = bullet;
bullet = 0;
return p;
}
};
class Enemy :public Flighter {
public:
Enemy(Window* window, const char c, const Position p, const Position v = Position(0, 0),
const Position s = Position{ 1, 1 },
const int lives = 1) :Flighter(window, c, p, v, s, lives) {
}
virtual void draw() {
auto x = pos[0], y = pos[1];
if (Explode != 0) {
window->set_pixel(x - 1, y, Explode_color, 5);
window->set_pixel(x - 1, y - 1, Explode_color, 5);
window->set_pixel(x - 1, y + 1, Explode_color, 5);
window->set_pixel(x, y - 1, Explode_color, 5);
window->set_pixel(x, y, Explode_color, 5);
window->set_pixel(x, y + 1, Explode_color, 5);
window->set_pixel(x + 1, y - 1, Explode_color, 5);
window->set_pixel(x + 1, y, Explode_color, 5);
window->set_pixel(x + 1, y + 1, Explode_color, 5);
window->set_pixel(x - 2, y, Explode_color, 5);
window->set_pixel(x + 2, y, Explode_color, 5);
window->set_pixel(x, y - 2, Explode_color, 5);
window->set_pixel(x, y + 2, Explode_color, 5);
Explode--;
}
else {
window->set_pixel(x, y, enemy_color, 0);
window->set_pixel(x - 1, y, enemy_color, 0);
window->set_pixel(x - 1, y - 1, enemy_color, 0);
window->set_pixel(x, y + 1, enemy_color, 0);
window->set_pixel(x, y - 1, enemy_color, 0);
window->set_pixel(x + 1, y, enemy_color, 0);
window->set_pixel(x + 1, y - 1, enemy_color, 0);
}
}
virtual bool hitted() {
lives--;
return true;
}
int random_int(int x, int y) {
static bool is_seeded1 = false;
if (!is_seeded1) {
srand((unsigned)time(0));
is_seeded1 = true;
}
return rand() % (y - x) + x;
}
virtual void update() {
static int bullet_num = 5;
static auto shot_start = std::chrono::high_resolution_clock::now();
auto shot_last = shot_start;
auto now = std::chrono::high_resolution_clock::now();
auto dur = now - shot_start;
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(dur).count();
if (ms > 2000) {
bullet_num = 5;
shot_start = now;
}
if (bullet_num > 0) {
auto dur2 = now - shot_last;
auto ms2 = std::chrono::duration_cast<std::chrono::milliseconds>(dur2).count();
if (ms2 > 100) {
shot_last = now;
shot(Position(0, 1));
bullet_num--;
}
}
static auto move_start = std::chrono::high_resolution_clock::now();
auto dur_move = now - move_start;
auto ms_move = std::chrono::duration_cast<std::chrono::milliseconds>(dur_move).count();
if (ms_move > 300) {
auto a = random_int(0, 5);
if (a > 0) {
if (a == 1) {
move(Position(-1, 0));
if (window->get_pixel(pos[0] - 3, pos[1]) != ' ')
move(Position(1, 0));
}
else if (a == 2) {
move(Position(1, 0));
if (window->get_pixel(pos[0] + 3, pos[1]) != ' ')
move(Position(-1, 0));
}
else if (a == 3) {
move(Position(0, 1));
if (window->get_pixel(pos[0], pos[1] + 3) != ' ')
move(Position(0, -1));
}
else if (a == 4) {
move(Position(0, -1));
if (window->get_pixel(pos[0], pos[1] - 3) != ' ')
move(Position(0, 1));
}
}
}
Flighter::update();
}
Bullet* get_bullet() {
Bullet* p = bullet;
bullet = 0;
return p;
}
};
class Boss :public Flighter {
SpecialBullet* special_bullet = nullptr;
public:
Boss(Window* window, const char c, const Position p, const Position v = Position(0, 0),
const Position s = Position{ 1, 1 },
const int lives = 5) :Flighter(window, c, p, v, s, lives) {
}
virtual void draw() {
auto x = pos[0], y = pos[1];
if (Explode != 0) {
window->set_pixel(x, y, Explode_color, 5);
window->set_pixel(x - 1, y, Explode_color, 5);
window->set_pixel(x + 1, y, Explode_color, 5);
window->set_pixel(x - 2, y - 1, Explode_color, 5);
window->set_pixel(x - 1, y - 1, Explode_color, 5);
window->set_pixel(x, y - 1, Explode_color, 5);
window->set_pixel(x + 1, y - 1, Explode_color, 5);
window->set_pixel(x + 2, y - 1, Explode_color, 5);
window->set_pixel(x, y + 1, Explode_color, 5);
Explode--;
}
else {
window->set_pixel(x, y + 1, Boss_color, 0);
window->set_pixel(x, y, Boss_color, 0);
window->set_pixel(x - 1, y, Boss_color, 0);
window->set_pixel(x + 1, y, Boss_color, 0);
window->set_pixel(x - 2, y - 1, Boss_color, 0);
window->set_pixel(x - 1, y - 1, Boss_color, 0);
window->set_pixel(x, y - 1, Boss_color, 0);
window->set_pixel(x + 1, y - 1, Boss_color, 0);
window->set_pixel(x + 2, y - 1, Boss_color, 0);
window->set_pixel(x - 3, y - 2, Boss_color, 0);
window->set_pixel(x - 2, y - 2, Boss_color, 0);
window->set_pixel(x - 1, y - 2, Boss_color, 0);
window->set_pixel(x, y - 2, Boss_color, 0);
window->set_pixel(x + 1, y - 2, Boss_color, 0);
window->set_pixel(x + 2, y - 2, Boss_color, 0);
window->set_pixel(x + 3, y - 2, Boss_color, 0);
}
}
SpecialBullet* SpecialShot(const Position& vel) {
auto x = pos[0];
auto y = pos[1] - rect.size[1] / 2;
special_bullet = new SpecialBullet(window, '*', Position(x, y+3), vel);
return special_bullet;
}
virtual bool hitted() {
lives--;
return true;
}
int random_int(int x, int y) {
static bool is_seeded1 = false;
if (!is_seeded1) {
srand((unsigned)time(0));
is_seeded1 = true;
}
return rand() % (y - x) + x;
}
virtual void update() {
static int boss_bullet_num = 6;
static int special_bullet_num = 1;
static auto boss_shot_start = std::chrono::high_resolution_clock::now();
auto shot_last = boss_shot_start;
auto now = std::chrono::high_resolution_clock::now();
auto dur = now - boss_shot_start;
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(dur).count();
if (ms > 8000) {
boss_bullet_num = 5;
special_bullet_num = 1;
boss_shot_start = now;
}
if (boss_bullet_num > 0) {
auto dur2 = now - shot_last;
auto ms2 = std::chrono::duration_cast<std::chrono::milliseconds>(dur2).count();
if (ms2 > 100) {
shot_last = now;
shot(Position(0, 1));
boss_bullet_num--;
}
}
if (special_bullet_num > 0) {
SpecialShot(Position(0, 1));
special_bullet_num--;
}
static auto move_start = std::chrono::high_resolution_clock::now();
auto dur_move = now - move_start;
auto ms_move = std::chrono::duration_cast<std::chrono::milliseconds>(dur_move).count();
if (ms_move > 300) {
//auto a = ms_move % 6;
auto a = random_int(0, 5);
if (a > 0) {
if (a == 1) {
move(Position(-1, 0));
if (window->get_pixel(pos[0] - 5, pos[1]) != ' ')
move(Position(1, 0));
}
else if (a == 2) {
move(Position(1, 0));
if (window->get_pixel(pos[0] + 5, pos[1]) != ' ')
move(Position(-1, 0));
}
else if (a == 3 && pos[1] < window->get_height() / 3) {
move(Position(0, 1));
if (window->get_pixel(pos[0], pos[1] + 5) != ' ')
move(Position(0, -1));
}
else if (a == 4) {
move(Position(0, -1));
if (window->get_pixel(pos[0], pos[1] - 5) != ' ')
move(Position(0, 1));
}
}
}
Flighter::update();
}
SpecialBullet* get_Special_bullet() {
SpecialBullet* p = special_bullet;
special_bullet = 0;
return p;
}
Bullet* get_bullet() {
Bullet* p = bullet;
bullet = 0;
return p;
}
};
class GameEngine {
protected:
Window* window;
Vector sprites;
BackGround* bg{ new BackGround() };
bool running = true;
public:
GameEngine(int w = 80, int h = 40) {
window = new Window(w, h, ' ');
window->clear();
hideCursor();
}
~GameEngine() {
delete window;
}
void gotoxy(int x, int y) {
COORD coord = { x, y };
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
void hideCursor() {
CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}
virtual void collosion() {
}
virtual void render() {
gotoxy(0, 0); //将画面固定在左上角
hideCursor(); //隐藏光标
window->clear(); //重置画面
draw_scene(); //每个精灵绘制自己(执行精灵自身draw()函数)
window->show(); //显示画面
if (!running)return;
}
virtual void draw_scene() {
bg->draw(*window);
for (auto j = 0; j < sprites.size(); j++)
sprites[j]->draw();
}
int random_int(int x, int y) {
static bool is_seeded1 = false;
if (!is_seeded1) {
srand((unsigned)time(0));
is_seeded1 = true;
}
return rand() % (y - x) + x;
}
virtual void processEvent() {
char key;
if (_kbhit()) {
key = _getch();
if (key == 27)
running = false;
}
}
virtual void update() {
for (auto j = 0; j < sprites.size(); j++)
sprites[j]->update();
}
virtual void run() {
while (running) {
processEvent(); //键盘控制
update(); //游戏内容更新(每个精灵都运行一遍其update()函数)
collosion(); //检测碰撞
render(); //重新绘制游戏
Sleep(10);
}
window->printAnswer(); //显示游戏结束画面
system("pause");
}
};
class SpaceInvander :public GameEngine {
protected:
Player* player;
Vector enemies;
Score* score;
Vector bullets, enemy_bullets;
Vector BOSS, special;
public:
SpaceInvander(int w = 80, int h = 40) :GameEngine(w, h) {
auto player_w{ 3 }, player_h{ 3 };
player = new Player(window, player_color,
Position(window->get_width() / 2, window->get_height() - player_h - 1),
Position(0, 0), Position(player_w, player_h));
sprites.push_back(player);
score = new Score(window, enemy_color, Position(0, 0), Position(0, 0), Position(player_w, player_h));
score->set_lives(player->get_lives());
sprites.push_back(score);
}
void add_enemies() {
if (enemies.size() <= 3 && BOSS.size() == 0) {
int x_off = 10, y_off = 5;
auto x_min{ x_off }, x_max{ window->get_width() - x_off },
y_min{ 1 }, y_max{ y_off };
auto x = random_int(x_min, x_max);
auto y = random_int(y_min, y_max);
Enemy* enemy = new Enemy(window, enemy_color, Position(x, y), Position(0, 0), Position(3, 3));
sprites.push_back(enemy);
enemies.push_back(enemy);
}
if (score->get_score() == 10) {
if (BOSS.size() == 0) {
for (auto i = 0; i < enemies.size(); i++) {
static_cast<Enemy*>(enemies[i])->hitted();
score->score_reduce();
}
int x_off = 10, y_off = 5;
auto x_min{ x_off }, x_max{ window->get_width() - x_off },
y_min{ 1 }, y_max{ y_off };
auto x = random_int(x_min, x_max);
auto y = random_int(y_min, y_max);
Boss* boss = new Boss(window, Boss_color, Position(x, y), Position(0, 0), Position(4, 4));
sprites.push_back(boss);
BOSS.push_back(boss);
}
}
}
void update() {
add_enemies();
for (auto i = 0; i < enemies.size(); i++) {
auto enemy = enemies[i];
Bullet* bullet = static_cast<Enemy*>(enemy)->get_bullet();
if (bullet) {
enemy_bullets.push_back(bullet);
sprites.push_back(bullet);
}
}
for (auto i = 0; i < BOSS.size(); i++) {
static auto Boss_shot_start = std::chrono::high_resolution_clock::now();
auto shot_last = Boss_shot_start;
auto now = std::chrono::high_resolution_clock::now();
auto dur = now - Boss_shot_start;
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(dur).count();
if (ms > 2000) {
auto boss = BOSS[i];
//static_cast<Boss*>(boss)->SpecialShot(Position(0, 1));
SpecialBullet* SpecialBullet = static_cast<Boss*>(boss)->get_Special_bullet();
if (SpecialBullet) {
enemies.push_back(SpecialBullet);
special.push_back(SpecialBullet);
sprites.push_back(SpecialBullet);
}
static_cast<Boss*>(boss)->shot(Position(0, 1));
Bullet* bullet = static_cast<Boss*>(boss)->get_bullet();
if (bullet) {
enemy_bullets.push_back(bullet);
sprites.push_back(bullet);
}
static_cast<Boss*>(boss)->move(Position(-4, 0));
static_cast<Boss*>(boss)->shot(Position(0, 1));
bullet = static_cast<Boss*>(boss)->get_bullet();
if (bullet) {
enemy_bullets.push_back(bullet);
sprites.push_back(bullet);
}
static_cast<Boss*>(boss)->move(Position(8, 0));
static_cast<Boss*>(boss)->shot(Position(0, 1));
bullet = static_cast<Boss*>(boss)->get_bullet();
if (bullet) {
enemy_bullets.push_back(bullet);
sprites.push_back(bullet);
}
static_cast<Boss*>(boss)->move(Position(-4, 0));
Boss_shot_start = now;
}
}
GameEngine::update();
}
void collosion() {
for (auto i = 0; i < enemies.size(); i++) {
auto enemy = enemies[i];
if (player && player->collide(enemy->get_rect())) {
player->hitted();
score->set_lives(player->get_lives());
static_cast<Enemy*>(enemy)->hitted();
}
for (auto j = 0; j < bullets.size(); j++) {
auto bullet = bullets[j];
if (enemy->collide(bullet->get_rect())) {
static_cast<Enemy*>(enemy)->hitted();
static_cast<Enemy*>(enemy)->set_explode(1);
static_cast<Enemy*>(enemy)->draw();
static_cast<Bullet*>(bullet)->hitted();
j = bullets.size();
}
}
}
if (BOSS.size() != 0 || BOSS[0]->get_lives() > 0) {
for (auto i = 0; i < BOSS.size(); i++) {
auto boss = BOSS[i];
if (boss->get_lives() == 0)break;
if (player && player->collide(boss->get_rect())) {
player->hitted();
score->set_lives(player->get_lives());
static_cast<Boss*>(boss)->hitted();
}
for (auto j = 0; j < bullets.size(); j++) {
auto bullet = bullets[j];
if (boss->collide(bullet->get_rect())) {
static_cast<Boss*>(boss)->hitted();
if (boss->is_dead()) {
BOSS.erase(0);
score->score_plus();
}
static_cast<Bullet*>(bullet)->hitted();
j = bullets.size();
}
}
}
}
if (player) {
for (auto j = 0; j < enemy_bullets.size(); j++) {
auto bullet = enemy_bullets[j];
if (player && player->collide(bullet->get_rect())) {
player->hitted();
score->set_lives(player->get_lives());
if (player->is_dead())
{
//window->printAnswer();
running = false;
}
static_cast<Bullet*>(bullet)->hitted();
}
}
}
Vector deads;
for (auto i = 0; i < sprites.size();) {
if (sprites[i]->is_dead()) {
delete sprites[i];
deads.push_back(sprites[i]);
sprites.erase(i);
}
else i++;
}
for (auto i = 0; i < sprites.size();) {
if (sprites[i]->get_pos_y() < 0 || sprites[i]->get_pos_y() > window->get_height()
|| sprites[i]->get_pos_x() > window->get_width() || sprites[i]->get_pos_x() < 0) {
delete sprites[i];
deads.push_back(sprites[i]);
sprites.erase(i);
}
else i++;
}
for (auto i = 0; i < special.size(); i++) {
auto y = random_int(window->get_height() / 3 * 2 + 7, window->get_height());
if (special[i]->get_lives() <= 0)break;
if (special[i]->get_pos_y() > y) {
static_cast<SpecialBullet*>(special[i])->hitted();
static_cast<SpecialBullet*>(special[i])->shot(Position(1, 0));
Bullet* bullet = static_cast<SpecialBullet*>(special[i])->get_bullet();
if (bullet) {
enemy_bullets.push_back(bullet);
sprites.push_back(bullet);
};
static_cast<SpecialBullet*>(special[i])->shot(Position(-1, 0));
bullet = static_cast<SpecialBullet*>(special[i])->get_bullet();
if (bullet) {
enemy_bullets.push_back(bullet);
sprites.push_back(bullet);
};
static_cast<SpecialBullet*>(special[i])->shot(Position(0, 1));
bullet = static_cast<SpecialBullet*>(special[i])->get_bullet();
if (bullet) {
enemy_bullets.push_back(bullet);
sprites.push_back(bullet);
};
}
}
for (auto i = 0; i < deads.size(); i++) {
Sprite* p = deads[i];
auto deleted = false;
for (auto i = 0; i < enemies.size(); i++) {
if (enemies[i] == p) {
enemies.erase(i);
score->score_plus();
//deleted = true;
break;
}
}
for (auto i = 0; i < enemy_bullets.size(); i++) {
if (enemy_bullets[i] == p) {
enemy_bullets.erase(i);
deleted = true;
break;
}
}
if (deleted)continue;
for (auto i = 0; i < bullets.size(); i++) {
if (bullets[i] == p) {
bullets.erase(i);
deleted = true;
break;
}
}
if (deleted)continue;
for (auto i = 0; i < special.size(); i++) {
if (special[i] == p) {
special.erase(i);
}
}
//special.set_size(0);
for (auto i = 0; i < BOSS.size(); i++) {
if (bullets[i] == p) {
BOSS.erase(i);
score->score_plus();
static_cast<Boss*>(BOSS[i])->set_explode(1);
static_cast<Boss*>(BOSS[i])->draw();
break;
}
}
}
deads.set_size(0);
}
void processEvent() {
char key;
if (_kbhit()) {
key = _getch();
if (key == 27)
running = false;
if (key == ' ' || key == 'j') {
Bullet* bullet = static_cast<Player*>(player)->shot(Position(0, -1));
bullets.push_back(bullet);
sprites.push_back(bullet);
}
else if (key == 'a' || key == 'A' || key == KEY_LEFT) {
player->move(Position(-1, 0));
}
else if (key == 'd' || key == 'D' || key == KEY_RIGHT) {
player->move(Position(1, 0));
}
else if (key == 'w' || key == 'W' || key == KEY_UP) {
player->move(Position(0, -1));
}
else if (key == 's' || key == 'S' || key == KEY_DOWN) {
player->move(Position(0, 1));
}
fflush(stdin);
}
}
};
int main() {
SpaceInvander game;
game.run();
}