Tutorial part 4 : Enemys - ilovethisid/Educational-Ascii-Game-engine GitHub Wiki
Last time, we implemented creating bullets, but it didn't go out. To solve that problem, we will create enemies.
First, create vector to store enemies and enemy bullets.
class Game : public GameLoop
{
private:
Object* player;
Object* boundary;
vector<Matrix> bullet_images;
vector<Object*> bullets;
vector<Object*> enemys;
vector<Object*> enemy_bullets;
...Second, we will create Enemy class, using the class Object.
// Game.h
class Game : public GameLoop
{
private:
Object* player;
Object* boundary;
vector<Matrix> bullet_images;
vector<Object*> bullets;
vector<Object*> enemys;
vector<Object*> enemy_bullets;
vector<Matrix> enemy_images;
class Enemy :public Object {
public:
char life = 1;
int fire_interval;
int type;
Enemy(int x, int y, int v_x, int v_y, int type, Matrix& image, Matrix& collider);
virtual ~Enemy() {};
void virtual shoot(Matrix& image, vector<Object*>& enemy_bullets);
void virtual event(Console& console) {};
};
...Game::Enemy::Enemy(int x, int y, int v_x, int v_y,
int type, Matrix& image, Matrix& collider) :Object(x, y) {
makeImage(image);
makeRigidbody();
rigidbody.makeMatrixCollider(collider);
rigidbody.setVelocity(v_x, v_y);
fire_interval = 0;
this->type = type;
}
void Game::Enemy::shoot(Matrix& image, vector<Object*>& enemy_bullets) {
if (fire_interval > 12) {
makeBullet(getX() + getImage().width / 2, getY() + getImage().height + 1, 0, 3, image, enemy_bullets);
fire_interval = 0;
}
else
fire_interval++;
}Also, push enemy images to enemy_images.
//enemy_images matrix
enemy_images.push_back(makeFile2Matrix("./usrlib/enemy1"));
enemy_images.push_back(makeFile2Matrix("./usrlib/enemy2"));
enemy_images.push_back(makeFile2Matrix("./usrlib/enemy3"));
}
// Game::initialize()Now that we made class Enemy, we can make enemy. We will make enemy.
// make enemy
void Game::makeEnemy()
{
int rand_num = rand();
int type = rand_num % 3;
Object* enemy = new Enemy(SCREEN_WIDTH / 8 * (rand_num % 5 + 2), 2, rand_num % 4 - 2, type + 1, type, enemy_images[type], enemy_images[type]);
enemys.push_back(enemy);
}We will make enemy continuously having a certain amount of cooldown. Goto updateLoop() and insert following :
void Game::updateLoop()
{
player->move(objects);
static int count_frames = 0;
int spawn_interval = (int)fps_;
// 1 second
if (count_frames % spawn_interval == 0) {
makeEnemy();
}
getConsole().drawTmpObject(*player);
getConsole().drawTmpObject(*boundary);
getConsole().drawTmpObjects(bullets);
getConsole().drawTmpObjects(enemys);
getConsole().drawTmpObjects(enemy_bullets);
count_frames++;
}This will create enemy every second. Remember that the bullets didn't go last time because we didn't move bullets?
Now, we have created Enemy, so we can move the bullets. We will make function collisionEvent() and check collision events and move objects.
void Game::collisionEvent()
{
for (int i = 0; i < enemys.size(); i++) {
enemys[i]->move(objects);
}
// check collision between enemy and player, boundary
// move enemy if not colliding
for (int i = 0; i < enemy_bullets.size(); i++) enemy_bullets[i]->move(objects);
// check collision between enemy bullet and player, boundary
for (int i = 0; i < bullets.size(); i++) bullets[i]->move(enemys);
// between bullets and enemies
}
// also declare in Game.hNow we have made bullets and enemies. If you run, you would see bullets firing and enemies coming down. But, you can see that bullets cannot kill enemies and enemies just passes through bullets. That's why we need events. Bullets have to kill enemies and bullets should be deleted for future memory usage. Next time, we'll implement enemy and bullet destruction.