BEETLEBOT
Ant invasion, Boss fight, Power-ups
Overview
Project Duration
6 Weeks at PlaygroundSquad
Game Engine
TenGine 5
Platforms
PS5 & PC
Responsibilities
Modular Gun Controller
Sniper, Melee & Bomb
Boss Fight
An Arena with a boss in the middle
Throws eggs that hatch into ants
Dualsense controller support
This is a showcase of what I made during the project
This six-week game project, developed with a team of 12 members (4 programmers, 3 designers, and 5 artists), was my first major game development experience.
It was also my first project using C++, working with a framework that had no documentation, making problem-solving both challenging and enjoyable.
Given the time constraints and the steep learning curve, I primarily focused on developing the gun controller and boss manager.
The modular gun controller I created was versatile enough to support various attacks, such as molotovs and grenades, and was also adapted for melee combat.
In the final two weeks, I concentrated on enhancing the boss fight to ensure it integrated seamlessly with the game.
This project was also my introduction to memory-dependent coding, which was crucial due to the performance demands of our hack 'n' slash game.
I hope you enjoy exploring my first game project with PlaygroundSquad!
Gun Controller
It instantiates an entity which is the bullet, moving in the direction of where you aim.
Sniper(tg::cModel* _model, tg::cVector3f _camera)
if (m_gun_timer <= 0.0f && m_gun_unlocked )
{
auto* bullet = new cProjectile();
bullet->m_model = m_sniper_model;
bullet->setType(cEntity::kSniper);
m_offset = _model->transform.local.at() * 0.5f;
m_offset += _model->transform.local.up() * 0.6f;
tg::cVector3f particle_offset{0.7f, 0.5f, 0.6f};
if (m_shooting_left)
{
m_offset += _model->transform.local.left() * 0.7f;
m_shooting_left = false;
}
else
{
m_offset += _model->transform.local.left() * -0.7f;
particle_offset.x *= -1;
m_shooting_left = true;
}
bullet->m_lifetime = 1.2f;
m_gun_timer = m_gun_cooldown;
m_hud_ui->setGunLock( true );
bullet->getPosition() = _model->transform.local.pos() + m_offset;
bullet->setVelocity(_camera * m_speed);
bullet->alterPushDistance(sniperSize);
bullet->setSize(m_size);
auto* ents = cEntityManager::getInstance().getEntities();
ents->push_back((cEntity*)bullet);
cParticleManager::getInstance().emplaceParticle( std::to_string( _model->transform.local.pos().z ),
new cParticle( "data/particles/PS_gunSmoke_v2.tfp", &cEntityManager::getInstance().getPlayer()->getPosition(),
0.4f, true, true, particle_offset, true ) );
cSoundPlayer::getInstance().play( "sfx_player_sniper_3_HIGHPASS_ALT", eAudioChannel::kPlayer );
cEntityManager::getInstance().getPlayer()->getCamera()->shake( m_sniperShakeMagnitude, m_sniperShakeTime,
m_sniperShakeSpeed, 1 );
}
Boss Manager
The boss' attack include throwing an egg towards the player, with the player's velocity in mind.
ShootEgg()
{
m_cooldown = m_timer;
auto* eggs = cEntityManager::getInstance().getEntities();
eggs->push_back( new cProjectile() );
eggs->back()->setType( cEntity::kEgg );
eggs->back()->m_model = m_egg_model;
m_offset = m_boss_model->transform.local.at() * 1.1f;
m_offset += m_boss_model->transform.local.up() * 3.0f;
m_offset += m_boss_model->transform.local.left() * 0.0;
eggs->back()->getPosition() = m_boss_model->transform.local.pos() + m_offset;
m_length = ( cEntityManager::getInstance().getPlayer()->getPosition()
- m_boss_model->transform.local.pos() );
if( cEntityManager::getInstance().getPlayer()->m_dashing_timer <= 0.0f
&& !cEntityManager::getInstance().getPlayer()->m_colliding_wall )
{
m_calculated_egg_direction = m_boss_model->transform.local.at() +
cEntityManager::getInstance().getPlayer()->getVelocity() + m_length;
}
else if( cEntityManager::getInstance().getPlayer()->m_dashing_timer >= 0.0f
|| cEntityManager::getInstance().getPlayer()->m_colliding_wall )
{
m_calculated_egg_direction = m_boss_model->transform.local.at() + m_length;
}
cSoundPlayer::getInstance().play("sfx_boss_throw", eAudioChannel::kDefault);
eggs->back()->setVelocity( m_calculated_egg_direction );
eggs->back()->setSize( 2 );
eggs->back()->setUseGravity( true );
}