Skip to content

Commit

Permalink
Merge branch 'Team-1--Mobs-Enhancement' of https://github.com/UQcsse3…
Browse files Browse the repository at this point in the history
…200/2023-studio-3 into Team-1--Mobs-Enhancement
  • Loading branch information
JSLLW committed Sep 28, 2023
2 parents 3f259d9 + 4d36a27 commit 2a7ae11
Show file tree
Hide file tree
Showing 10 changed files with 426 additions and 133 deletions.
156 changes: 137 additions & 19 deletions source/core/src/main/com/csse3200/game/areas/ForestGameArea.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.badlogic.gdx.math.Vector2;
import com.csse3200.game.areas.terrain.TerrainFactory;
import com.csse3200.game.areas.terrain.TerrainFactory.TerrainType;
import com.csse3200.game.components.ProjectileEffects;
import com.csse3200.game.entities.Entity;
import com.csse3200.game.entities.factories.*;
import com.csse3200.game.utils.math.RandomUtils;
Expand Down Expand Up @@ -257,7 +258,40 @@ public void create() {

// Set up infrastructure for end game tracking
player = spawnPlayer();
logger.info("Lol");
//player.getEvents().addListener("spawnWave", this::spawnWave);
//playMusic();

// Types of projectile
// spawnAoeProjectile(new Vector2(0, 10), player, towardsMobs, new Vector2(2f, 2f), 1);
// spawnProjectile(new Vector2(0, 10), PhysicsLayer.NPC, towardsMobs, new Vector2(2f, 2f));
// spawnMultiProjectile(new Vector2(0, 10), PhysicsLayer.NPC, towardsMobs, 20, new Vector2(2f, 2f), 7);
// spawnEffectProjectile(new Vector2(0, 10), PhysicsLayer.HUMANS, towardsMobs, new Vector2(2f, 2f), ProjectileEffects.BURN, true);
// spawnPierceFireBall(new Vector2(2, 3), PhysicsLayer.NPC, towardsMobs, new Vector2(2f, 2f));
// spawnRicochetFireball(new Vector2(2, 4), PhysicsLayer.NPC, towardsMobs, new Vector2(2f, 2f));
// spawnSplitFireWorksFireBall(new Vector2(2, 5), PhysicsLayer.NPC, towardsMobs, new Vector2(2f, 2f), 12);
// spawnEffectProjectile(new Vector2(2, 6), PhysicsLayer.NPC, towardsMobs, new Vector2(2f, 2f), ProjectileEffects.SLOW, false);
// spawnXenoGrunts();
// spawnWeaponTower();

// spawnDragonKnight();
// spawnFireWorm(19, 5); // * TEMPORARY for testing
spawnFireTowerTowerAt(3, 1);
spawnFireTowerTowerAt(3, 2);
spawnFireTowerTowerAt(3, 3);
spawnFireTowerTowerAt(3, 4);
spawnFireTowerTowerAt(3, 5);
// spawnDroidTowerAt(3, 1);
// spawnDroidTowerAt(3, 2);
// spawnDroidTowerAt(3, 3);
// spawnDroidTowerAt(3, 4);
// spawnDroidTowerAt(3, 5);
// spawnSplittingXenoGrunt(15, 5);
// spawnDeflectXenoGrunt(15, 5);
// spawnSplittingXenoGrunt(15, 4);
// spawnSplittingXenoGrunt(15, 5);
// spawnDodgingDragonKnight(15, 3);
spawnDemonBoss();
spawnPatrick();
spawnIceBaby();
player.getEvents().addListener("spawnWave", this::spawnWave);
playMusic();
Expand All @@ -269,10 +303,19 @@ public void create() {
spawnScrap();
spawnTNTTower();
spawnWeaponTower();
logger.info("Lol");
spawnGapScanners();
spawnDroidTower();
logger.info("Lol");
// spawnPatrickDeath();
// spawnFireWorm();

// startWaveTimer();
//// spawnIncome();
// spawnScrap();
spawnTNTTower();
//
// spawnGapScanners();
// spawnDroidTower();
//
}

private void displayUI() {
Expand Down Expand Up @@ -414,30 +457,20 @@ private void spawnDemonBoss() {
}

private void spawnPatrick() {
Entity patrick = MobBossFactory.createPatrickBoss(2500);
Entity patrick = MobBossFactory.createPatrickBoss();
spawnEntityAt(patrick, new GridPoint2(18, 5), true, false);
}

private void spawnPatrickDeath() {
Entity patrickDeath = MobBossFactory.patrickDead();
spawnEntityAt(patrickDeath, new GridPoint2(18, 5), true, false);
}

private void spawnIceBaby() {
Entity iceBaby = MobBossFactory.createIceBoss();
spawnEntityAt(iceBaby, new GridPoint2(19, 5), true, false);
}

private Entity spawnMobBoss1() {
int[] pickedLanes = rand.ints(0, 8)
.distinct().limit(5).toArray();
for (int i = 0; i < NUM_MOBBOSS1; i++) {
GridPoint2 randomPos = new GridPoint2(19, pickedLanes[i]);
mobBoss1 = MobBossFactory.createMobBoss1(pickedLanes[i]);
spawnEntityAt(mobBoss1,
randomPos,
true,
false);
}
return mobBoss1;
}


/**
* Spawns a projectile that only heads towards the enemies in its lane.
*
Expand Down Expand Up @@ -593,6 +626,91 @@ private void spawnWaterSlime() {
// return ghostKing;
//
// }

/**
* Creates multiple projectiles that travel simultaneous. They all have same
* the starting point but different destinations.
*
* @param position The position of the Entity that's shooting the projectile.
* @param targetLayer The enemy layer of the "shooter".
* @param direction The direction the projectile should head towards.
* @param space The space between the projectiles' destination.
* @param speed The speed of the projectiles.
* @param quantity The amount of projectiles to spawn.
*/
private void spawnMultiProjectile(Vector2 position, short targetLayer, int direction, int space, Vector2 speed, int quantity) {
int half = quantity / 2;
for (int i = 0; i < quantity; i++) {
spawnProjectile(position, targetLayer, space * half, direction, speed);
--half;
}
}

/**
* Returns projectile that can do an area of effect damage
*
* @param position The position of the Entity that's shooting the projectile.
* @param targetLayer The enemy layer of the "shooter".
* @param direction The direction the projectile should head towards.
* @param speed The speed of the projectiles.
* @param effect Type of effect.
* @param aoe Whether it is an aoe projectile.
*/
private void spawnEffectProjectile(Vector2 position, short targetLayer, int direction, Vector2 speed,
ProjectileEffects effect, boolean aoe) {
Entity Projectile = ProjectileFactory.createEffectProjectile(targetLayer, new Vector2(direction, position.y), speed, effect, aoe);
Projectile.setPosition(position);
spawnEntity(Projectile);
}

/**
* Spawns a pierce fireball.
* Pierce fireball can go through targetlayers without disappearing but damage
* will still be applied.
*
* @param position The position of the Entity that's shooting the projectile.
* @param targetLayer The enemy layer of the "shooter".
* @param direction The direction the projectile should head towards.
* @param speed The speed of the projectiles.
*/
private void spawnPierceFireBall(Vector2 position, short targetLayer, int direction, Vector2 speed) {
Entity projectile = ProjectileFactory.createPierceFireBall(targetLayer, new Vector2(direction, position.y), speed);
projectile.setPosition(position);
spawnEntity(projectile);
}

/**
* Spawns a ricochet fireball
* Ricochet fireballs bounce off targets with a specified maximum count of 3
* Possible extensions: Make the bounce count flexible with a param.
*
* @param position The position of the Entity that's shooting the projectile.
* @param targetLayer The enemy layer of the "shooter".
* @param direction The direction the projectile should head towards.
* @param speed The speed of the projectiles.
*/
private void spawnRicochetFireball(Vector2 position, short targetLayer, int direction, Vector2 speed) {
// Bounce count set to 0.
Entity projectile = ProjectileFactory.createRicochetFireball(targetLayer, new Vector2(direction, position.y), speed, 0);
projectile.setPosition(position);
spawnEntity(projectile);
}

/**
* Spawns a split firework fireball.
* Splits into mini projectiles that spreads out after collision.
*
* @param position The position of the Entity that's shooting the projectile.
* @param targetLayer The enemy layer of the "shooter".
* @param direction The direction the projectile should towards.
* @param speed The speed of the projectiles.
* @param amount The amount of projectiles appearing after collision.
*/
private void spawnSplitFireWorksFireBall(Vector2 position, short targetLayer, int direction, Vector2 speed, int amount) {
Entity projectile = ProjectileFactory.createSplitFireWorksFireball(targetLayer, new Vector2(direction, position.y), speed, amount);
projectile.setPosition(position);
spawnEntity(projectile);
}

private void spawnWeaponTower() {
GridPoint2 minPos = new GridPoint2(0, 2);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public class DodgingComponent extends Component {
// top and bottom detection is also taken care of, ensuring the entity will
// dodge.
private static final float Y_OFFSET_MOB_DETECTION = 0.35f;
public static final String DODGE_EVENT = "dodgeIncomingEntity";

/**
* Initialises a component that dodges an incoming entity based on its target
Expand Down Expand Up @@ -78,7 +79,7 @@ public DodgingComponent(short targetLayer, float rangeDetection, float dodgeSpee
@Override
public void create() {
physics = ServiceLocator.getPhysicsService().getPhysics();
entity.getEvents().addListener("dodgeIncomingEntity", this::changeTraverseDirection);
entity.getEvents().addListener(DODGE_EVENT, this::changeTraverseDirection);
originalSpeed = entity.getComponent(PhysicsMovementComponent.class).getSpeed().y;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public class DemonBossTask extends DefaultTask implements PriorityTask {
private static final int Y_BOT_BOUNDARY = 1;
private static final int BREATH_ANIM_TIME = 2;
private static final int SMASH_RADIUS = 3;
private static final float MOVE_FORWARD_DELAY = 30;
private static final int MOVE_FORWARD_DELAY = 15;
private static final float BREATH_DURATION = 4.2f;
private static final int SMASH_DAMAGE = 30;
private static final int CLEAVE_DAMAGE = 50;
Expand All @@ -56,7 +56,7 @@ public class DemonBossTask extends DefaultTask implements PriorityTask {
private DemonState prevState;
private AnimationRenderComponent animation;
private Entity demon;
private int numBalls = 6;
private int numBalls = 3;
private static int xRightBoundary = 17;
private static int xLeftBoundary = 12;
private ProjectileEffects effect = ProjectileEffects.BURN;
Expand All @@ -72,9 +72,7 @@ public class DemonBossTask extends DefaultTask implements PriorityTask {
* The different demon states.
*/
private enum DemonState {
TRANSFORM, IDLE, CAST, CLEAVE, DEATH, BREATH, SMASH, TAKE_HIT,
WALK, TRANSFORM_REVERSE, SLIME_IDLE, SLIME_MOVE, PROJECTILE_EXPLOSION,
PROJECTILE_IDLE, SLIME_TAKE_HIT
TRANSFORM, IDLE, CAST, CLEAVE, DEATH, BREATH, SMASH, TAKE_HIT, WALK
}

/**
Expand Down Expand Up @@ -217,12 +215,6 @@ private void animate() {
case CLEAVE -> demon.getEvents().trigger("demon_cleave");
case TAKE_HIT -> demon.getEvents().trigger("demon_take_hit");
case TRANSFORM -> demon.getEvents().trigger("transform");
case TRANSFORM_REVERSE -> demon.getEvents().trigger("transform_reverse");
case SLIME_IDLE -> demon.getEvents().trigger("idle");
case SLIME_MOVE -> demon.getEvents().trigger("move");
case SLIME_TAKE_HIT -> demon.getEvents().trigger("take_hit");
case PROJECTILE_IDLE -> demon.getEvents().trigger("projectile_explosion");
case PROJECTILE_EXPLOSION -> demon.getEvents().trigger("projectile_idle");
default -> logger.debug("Demon animation {state} not found");
}
prevState = state;
Expand Down Expand Up @@ -285,7 +277,7 @@ private void jump(Vector2 finalPos) {

/**
* Returns a random position 3 units away for the demon to jump to.
*
*
* @return a position 3 units away from the demon to jump to
*/
private Vector2 getJumpPos() {
Expand All @@ -295,6 +287,12 @@ private Vector2 getJumpPos() {
return jumpPos;
}

// jump backwards if right next to tower
if (currentPos.dst(ServiceLocator.getEntityService().getClosestEntityOfLayer(
demon, PhysicsLayer.HUMANS).getPosition()) < 2f) {
jumpPos = new Vector2(currentPos.x + JUMP_DISTANCE, currentPos.y);
}

float randomAngle = MathUtils.random(0, 2 * MathUtils.PI);
float x = JUMP_DISTANCE * MathUtils.cos(randomAngle);
float y = JUMP_DISTANCE * MathUtils.sin(randomAngle);
Expand All @@ -316,7 +314,7 @@ private Vector2 getJumpPos() {

/**
* Returns a boolean to confirm whether the demon has completed a jump or not.
*
*
* @return if demon has completed jump or not
*/
private boolean jumpComplete() {
Expand Down Expand Up @@ -394,30 +392,7 @@ private void applyAoeDamage(Array<Entity> targets, int damage) {
}

/**
* Returns the closest human entity from a given array.
*
* @param targets array of human entities
* @return closest human entity
*/
private Entity getClosestHuman(Array<Entity> targets) {
Entity closestEntity = null;
float closestDistance = SMASH_RADIUS;

for (int i = 0; i < targets.size; i++) {
Entity targetEntity = targets.get(i);
Vector2 targetPosition = targetEntity.getPosition();
float distance = currentPos.dst(targetPosition);

if (distance < closestDistance) {
closestEntity = targetEntity;
closestDistance = distance;
}
}
return closestEntity;
}

/**
* Change state to cleave and deals damage to target.
* Change state to cleave and deals damage to target
*/
private void cleave() {
changeState(DemonState.CLEAVE);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.csse3200.game.components.tasks.bosstask;

import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Timer;
import com.csse3200.game.ai.tasks.DefaultTask;
import com.csse3200.game.ai.tasks.PriorityTask;
import com.csse3200.game.entities.Entity;
import com.csse3200.game.entities.factories.MobBossFactory;
import com.csse3200.game.rendering.AnimationRenderComponent;
import com.csse3200.game.services.ServiceLocator;

public class PatrickDeathTask extends DefaultTask implements PriorityTask {

private boolean startFlag = false;
private static final int PRIORITY = 3;

/**
* What is run when patrick's death task is assigned
*/
@Override
public void start() {
super.start();
startFlag = true;
owner.getEntity().getEvents().trigger("patrick_death");
}

/**
* What is run every frame
*/
@Override
public void update() {
if (startFlag && owner.getEntity().getComponent(AnimationRenderComponent.class).
isFinished()) {
owner.getEntity().setFlagForDelete(true);
}
}

/**
* @return priority of task
*/
@Override
public int getPriority() {
return PRIORITY;
}
}
Loading

0 comments on commit 2a7ae11

Please sign in to comment.