Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Team 4 general mobs #136

Merged
merged 52 commits into from
Sep 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
1e18d77
Made changes to xenoAnimationController and ForestGameArea to support…
BlairCannon97 Sep 4, 2023
1408d26
Merge remote-tracking branch 'origin/Team4-GeneralMobs-Megan' into te…
BlairCannon97 Sep 6, 2023
a97c059
Merge branch 'main' into feature/Team4/integrate-enemies
samsully Sep 7, 2023
8a50404
Merge branch 'Team-3-maps-main' into Team4-GeneralMobs-Megan
meganroxburgh Sep 8, 2023
ab853e0
Removed the rescaling of projectiles in MobAttackTask
meganroxburgh Sep 8, 2023
9780bc8
Modifies spawning functionality of mobs to correspond with the lanes …
bojyyy Sep 8, 2023
60a0e6b
Merge branch 'Team-4---General-Mobs' into team-4---General-Mobs---Ani…
BlairCannon97 Sep 8, 2023
6888d38
Refactored xeno files into mobs folder
BlairCannon97 Sep 8, 2023
0e68b7b
Updated references to xeno atlas
BlairCannon97 Sep 8, 2023
cdc8b59
Cleaned up CreateXeno function in NPC factory. Added animation trigge…
BlairCannon97 Sep 9, 2023
b581bc9
Updated and removed redundant code in MobAttackTask
meganroxburgh Sep 9, 2023
cd4895e
Added comments for testing
meganroxburgh Sep 9, 2023
0954648
Added in print statements for testing
meganroxburgh Sep 9, 2023
92d3c99
Merge branch 'main' into Team4-GeneralMobs-Megan
meganroxburgh Sep 9, 2023
a9aedbc
got mobs to stop when firing
samsully Sep 9, 2023
0aa993a
Removed extra print statements for testing and moved position of mobball
meganroxburgh Sep 9, 2023
fba189a
Merge branch 'feature/Team4/integrate-enemies' into Team4-GeneralMobs…
meganroxburgh Sep 9, 2023
111f022
Fixed build errors of missing commas
meganroxburgh Sep 9, 2023
bde19c5
created raycast function to find fixture
samsully Sep 9, 2023
8808670
Commented out some spawning of entities for testing purposes
meganroxburgh Sep 9, 2023
64d0d13
Merge branch 'feature/Team4/integrate-enemies' into Team4-GeneralMobs…
meganroxburgh Sep 9, 2023
da3b804
Fixed issues with mob not stopping when moving
meganroxburgh Sep 9, 2023
62141ea
Committing changes to merge feature branch.
BlairCannon97 Sep 9, 2023
f277fd4
Fixed merge conflicts
BlairCannon97 Sep 9, 2023
4d3ab82
Animation checks added to XenoAnimation controller to assist with ani…
BlairCannon97 Sep 10, 2023
bb66ce4
Added death animation and currency dropping to the WanderTask.java. M…
Sep 10, 2023
c2c873c
Added comments to abandoned MobDeathTask.java
Sep 10, 2023
72c1ca4
Changed the hitbox properties of the NPC entities to suit the Xeno
BlairCannon97 Sep 10, 2023
0ff348f
Merged recent changes to main onto feature branch
BlairCannon97 Sep 10, 2023
f8102bf
for each attack task start, choose between melee and projectiles
samsully Sep 10, 2023
9372179
clean up
samsully Sep 10, 2023
f832a84
will only activate shoot task if target is attackable
samsully Sep 10, 2023
d1a2a98
Merge branch 'Team-4---General-Mobs' into feature/Team4/integrate-ene…
samsully Sep 10, 2023
b4ebcc1
mobs stopping when shooting again and fixed spawning coordinates
samsully Sep 10, 2023
bdbb628
clean up
samsully Sep 10, 2023
7b27e04
Merge branch 'Team-4---General-Mobs' into Team-4--General-Mobs-Max
Sep 10, 2023
4003dcd
Merge branch 'Team-4---General-Mobs' into feature/Team4/integrate-ene…
samsully Sep 10, 2023
01c32e7
Fixed local conflicts
BlairCannon97 Sep 10, 2023
e303bd5
Removed MobDeathTask.java use from NPCFactory.java as it is not longe…
Sep 10, 2023
c1ca012
Some basic tests added for NPCFactory regarding Xeno creation.
BlairCannon97 Sep 11, 2023
783bd7e
More tests added for NPCFactory regarding Xeno creation.
BlairCannon97 Sep 11, 2023
28de058
Adds unit testing for SpawnWaveTask
bojyyy Sep 11, 2023
7d5637e
mobs will attack with melee if within range
samsully Sep 11, 2023
1c6dac0
Merge branch 'Team-4---General-Mobs' into Team-4--General-Mobs-Max
Sep 11, 2023
4beb796
Removed several unused statements which were added for mob death from…
Sep 11, 2023
12395d0
Fixed recent merge conflicts
BlairCannon97 Sep 11, 2023
64512c2
Merge remote-tracking branch 'origin/Team-4---General-Mobs' into Team…
Sep 11, 2023
ac20c2a
Merge branch 'Team-4---General-Mobs' of github.com:UQcsse3200/2023-st…
BlairCannon97 Sep 11, 2023
eaa840d
Fixing merge conflicts
bojyyy Sep 11, 2023
e075616
Modifies mob spawning to correspond to new allowable game area
bojyyy Sep 11, 2023
24a9daf
Fixed merge conflicts after merging main.
BlairCannon97 Sep 11, 2023
4a23ae5
Removed scale down of mob balls in MobAttackTask
meganroxburgh Sep 11, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions source/core/src/main/com/csse3200/game/areas/ForestGameArea.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,7 @@ public class ForestGameArea extends GameArea {
private int bossSpawnInterval = 10000; // 1 minute in milliseconds

private static final int NUM_WEAPON_TOWERS = 3;

private static final GridPoint2 PLAYER_SPAWN = new GridPoint2(1, 4);

private static final GridPoint2 PLAYER_SPAWN = new GridPoint2(0, 0);
// Temporary spawn point for testing
private static final float WALL_WIDTH = 0.1f;

Expand Down Expand Up @@ -124,18 +122,16 @@ public class ForestGameArea extends GameArea {
"images/ghostKing.atlas",
"images/towers/turret.atlas",
"images/towers/turret01.atlas",
"images/mobs/xenoGrunt.atlas",
"images/towers/fire_tower_atlas.atlas",
"images/towers/stun_tower.atlas",
"images/mobs/xenoGruntRunning.atlas",
"images/mobs/robot.atlas",
"images/mobs/rangeBossRight.atlas",
"images/towers/DroidTower.atlas",
"images/xenoGrunt.atlas",
"images/mobs/robot.atlas",
"images/mobs/rangeBossRight.atlas",
"images/towers/TNTTower.atlas",
"images/projectiles/basic_projectile.atlas",

"images/projectiles/mobProjectile.atlas",
"images/projectiles/engineer_projectile.atlas",
"images/projectiles/mobKing_projectile.atlas",
Expand Down Expand Up @@ -379,14 +375,14 @@ private void spawnProjectile(Vector2 position, short targetLayer, int space, in


private void spawnXenoGrunts() {
GridPoint2 minPos = terrain.getMapBounds(0).sub(1, 5);
GridPoint2 maxPos = terrain.getMapBounds(0).sub(1, 25);
int[] pickedLanes = new Random().ints(1, 7)
.distinct().limit(5).toArray();
for (int i = 0; i < NUM_GRUNTS; i++) {
GridPoint2 randomPos = RandomUtils.random(maxPos, minPos);
GridPoint2 randomPos = new GridPoint2(19, pickedLanes[i]);
System.out.println(randomPos);
Entity xenoGrunt = NPCFactory.createXenoGrunt(player);
xenoGrunt.setScale(1.5f, 1.5f);
spawnEntityAt(xenoGrunt, randomPos, true, true);
spawnEntityAt(xenoGrunt, randomPos, true, false);
}
}

Expand Down Expand Up @@ -620,6 +616,12 @@ private void spawnGapScanners() {
Entity scanner = GapScannerFactory.createScanner();
spawnEntityAt(scanner, new GridPoint2(0, i), true, true);
}
// GridPoint2 minPos = new GridPoint2(0, 0);
// GridPoint2 maxPos = new GridPoint2(5, terrain.getMapBounds(0).sub(2, 2).y);
// GridPoint2 randomPos = RandomUtils.random(minPos, maxPos);
//
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this commented out code added here?

// Entity engineer = EngineerFactory.createEngineer();
// spawnEntityAt(engineer, randomPos, true, true);
}

// private void gameTrackerStart() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.Fixture;
import com.csse3200.game.entities.Entity;
import com.csse3200.game.entities.Weapon;
import com.csse3200.game.physics.BodyUserData;
import com.csse3200.game.physics.PhysicsLayer;
import com.csse3200.game.physics.components.HitboxComponent;
Expand Down Expand Up @@ -64,7 +65,7 @@ public void create() {
hitboxComponent = entity.getComponent(HitboxComponent.class);
}

private void onCollisionStart(Fixture me, Fixture other) {
public void onCollisionStart(Fixture me, Fixture other) {
if (hitboxComponent.getFixture() != me) {
// Not triggered by hitbox, ignore
return;
Expand Down Expand Up @@ -105,9 +106,22 @@ public void setDisposeOnHit(boolean disposeOnHit) {
this.disposeOnHit = disposeOnHit;
}


public void setKnockBack(float knockback) {
this.knockbackForce = knockback;
}
public Weapon chooseWeapon(Fixture other) {
Entity target = ((BodyUserData) other.getBody().getUserData()).entity;
Weapon weapon = null;
if (target.getComponent(CombatStatsComponent.class) != null) {
weapon = combatStats.getWeapon(target);
}
return weapon;
}

private void onCollisionEnd(Fixture me, Fixture other) {
// Nothing to do on collision end
}
// private void onCollisionEnd(Fixture me, Fixture other) {
// // Nothing to do on collision end
// }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package com.csse3200.game.components.npc;

import com.badlogic.gdx.graphics.g2d.Animation;
import com.csse3200.game.components.Component;
import com.csse3200.game.rendering.AnimationRenderComponent;

import java.util.Objects;

/**
* This class listens to events relevant to a ghost entity's state and plays the animation when one
* of the events is triggered.
Expand All @@ -14,34 +17,48 @@ public class XenoAnimationController extends Component {
public void create() {
super.create();
animator = this.entity.getComponent(AnimationRenderComponent.class);
entity.getEvents().addListener("wanderStart", this::animateWander);
entity.getEvents().addListener("chaseStart", this::animateChase);
entity.getEvents().addListener("wanderStart", this::animateRun);
entity.getEvents().addListener("runHurt", this::animateHurt);
entity.getEvents().addListener("meleeStart", this::animateMelee1);
entity.getEvents().addListener("meleeStart", this::animateMelee2);
entity.getEvents().addListener("shootStart", this::animateShoot);
entity.getEvents().addListener("dieStart", this::animateDie);
entity.getEvents().addListener("stop", this::stopAnimation);
}

void animateWander() {
animator.startAnimation("xeno_run");
void animateRun() {
if (!Objects.equals(animator.getCurrentAnimation(), "xeno_shoot")) {
animator.stopAnimation();
animator.startAnimation("xeno_run");
}
}

void animateChase() {
animator.startAnimation("xeno_run");
void animateHurt() {
animator.stopAnimation();
animator.startAnimation("xeno_hurt");
}

void animateShoot() {
animator.stopAnimation();
animator.startAnimation("xeno_shoot");
}

void animateMelee1() {
animator.stopAnimation();
animator.startAnimation("xeno_melee_1");
}

void animateMelee2() {
animator.stopAnimation();
animator.startAnimation("xeno_melee_2");
}

void animateDie() {
animator.stopAnimation();
animator.startAnimation("xeno_die");
}

void stopAnimation() {
animator.stopAnimation();
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
package com.csse3200.game.components.tasks;

import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Fixture;
import com.csse3200.game.ai.tasks.DefaultTask;
import com.csse3200.game.ai.tasks.PriorityTask;
import com.csse3200.game.components.CombatStatsComponent;
import com.csse3200.game.components.TouchAttackComponent;
import com.csse3200.game.entities.Entity;
import com.badlogic.gdx.math.Vector2;
import com.csse3200.game.entities.Melee;
import com.csse3200.game.entities.Weapon;
import com.csse3200.game.entities.factories.ProjectileFactory;
import com.csse3200.game.physics.PhysicsEngine;
import com.csse3200.game.physics.PhysicsLayer;
import com.csse3200.game.physics.components.HitboxComponent;
import com.csse3200.game.physics.components.PhysicsMovementComponent;
import com.csse3200.game.physics.raycast.RaycastHit;
import com.csse3200.game.services.ServiceLocator;
import com.csse3200.game.rendering.AnimationRenderComponent;
import com.csse3200.game.services.GameTime;
import com.csse3200.game.entities.factories.ProjectileFactory;
import com.csse3200.game.services.ServiceLocator;


/**
Expand All @@ -22,11 +27,13 @@ public class MobAttackTask extends DefaultTask implements PriorityTask {
private static final short TARGET = PhysicsLayer.HUMANS; // mobs detecting for towers
// ^ fix this

private static final String STOW = "stowStart";
private static final String STOW = "wanderStart";
private static final String DEPLOY = "deployStart";
private static final String FIRING = "firingStart";
private static final String FIRING = "shootStart";
private static final String IDLE = "idleStart";

private Fixture target;

private final int priority;
private final float maxRange;
private Vector2 mobPosition = new Vector2(10f,10f);
Expand Down Expand Up @@ -67,7 +74,7 @@ public void start() {
startTime = timeSource.getTime();
this.mobPosition = owner.getEntity().getCenterPosition();
this.maxRangePosition.set(0, mobPosition.y);
owner.getEntity().getEvents().trigger(IDLE);
//owner.getEntity().getEvents().trigger(IDLE);
endTime = timeSource.getTime() + (INTERVAL * 500);
owner.getEntity().getEvents().trigger("shootStart");
}
Expand All @@ -90,14 +97,6 @@ public void update() {
* triggers the appropriate events corresponding to the STATE enum.
*/
public void updateMobState() {
// TouchAttackComponent attackComp = owner.getEntity().getComponent(TouchAttackComponent.class);
CombatStatsComponent statsComp = owner.getEntity().getComponent(CombatStatsComponent.class);
// if (statsComp != null) {
// System.out.println("is the target visible " + isTargetVisible());
// }
if (!isTargetVisible()) {
System.out.println("target is not visible for " + owner.getEntity().getId());
}
switch (mobState) {

case IDLE -> {
Expand All @@ -110,7 +109,8 @@ public void updateMobState() {

case DEPLOY -> {
// currently deploying,
if (isTargetVisible()) {
if (isTargetVisible() || this.meleeOrProjectile() != null) {
owner.getEntity().getComponent(PhysicsMovementComponent.class).setEnabled(false);
owner.getEntity().getEvents().trigger(FIRING);
mobState = STATE.FIRING;
} else {
Expand All @@ -120,19 +120,29 @@ public void updateMobState() {
}

case FIRING -> {
// targets gone - stop firing
if (!isTargetVisible()) {
// targets gone or cannot be attacked - stop firing
if (!isTargetVisible() || this.meleeOrProjectile() == null) {
owner.getEntity().getEvents().trigger(STOW);
mobState = STATE.STOW;
} else {
owner.getEntity().getEvents().trigger(FIRING);
Entity newProjectile = ProjectileFactory.createMobBall(PhysicsLayer.HUMANS, new Vector2(0, owner.getEntity().getPosition().y), new Vector2(2f,2f));
newProjectile.setPosition((float) (owner.getEntity().getPosition().x), (float) (owner.getEntity().getPosition().y + 0.1));
newProjectile.setScale(-0.7f, 0.7f);
ServiceLocator.getEntityService().register(newProjectile);
mobState = STATE.STOW;
owner.getEntity().getEvents().trigger("shootStart");
if (this.meleeOrProjectile() instanceof Melee) {
System.out.println("Melee attack");
TouchAttackComponent attackComp = owner.getEntity().getComponent(TouchAttackComponent.class);
HitboxComponent hitboxComp = owner.getEntity().getComponent(HitboxComponent.class);
attackComp.onCollisionStart(hitboxComp.getFixture(), target);
} else {
Entity newProjectile = ProjectileFactory.createMobBall(PhysicsLayer.HUMANS, new Vector2(0, owner.getEntity().getPosition().y), new Vector2(2f,2f));
newProjectile.setPosition((float) (owner.getEntity().getPosition().x), (float) (owner.getEntity().getPosition().y));
// newProjectile.setScale(-1f, 0.5f);
ServiceLocator.getEntityService().register(newProjectile);

// System.out.printf("ANIMATION: " + owner.getEntity().getComponent(AnimationRenderComponent.class).getCurrentAnimation() + "\n");
owner.getEntity().getEvents().trigger(FIRING);
mobState = STATE.STOW;
}
}
owner.getEntity().getComponent(PhysicsMovementComponent.class).setEnabled(true);

}

case STOW -> {
Expand All @@ -153,8 +163,12 @@ public void updateMobState() {
*/
@Override
public void stop() {
super.stop();
owner.getEntity().getEvents().trigger(STOW);
if (mobState == STATE.FIRING || mobState == STATE.DEPLOY) {
this.updateMobState();
} else {
super.stop();
owner.getEntity().getEvents().trigger(STOW);
}
}

/**
Expand All @@ -163,26 +177,20 @@ public void stop() {
*/
@Override
public int getPriority() {
// return -1;
if (status == Status.ACTIVE) {
return getActivePriority();
}
return getInactivePriority();
// return isTargetVisible() ? getActivePriority() : getInactivePriority();
}

/**
* Fetches the active priority of the Task if a target is visible.
* @return (int) active priority if a target is visible, -1 otherwise
*/
private int getActivePriority() {
if ((startTime + delay) < timeSource.getTime()) {
// if (isTargetVisible() && (startTime + delay) > timeSource.getTime()) {
// System.out.println("ready to fire while active");
if ((startTime + delay) < timeSource.getTime() && isTargetVisible() && this.meleeOrProjectile() != null) {
return priority;
}
// System.out.println("not ready to fire while active");
// return !isTargetVisible() ? -1 : priority;
return -1;
}

Expand All @@ -191,22 +199,46 @@ private int getActivePriority() {
* @return (int) -1 if a target is not visible, active priority otherwise
*/
private int getInactivePriority() {
// return isTargetVisible() ? priority : 0;
if ((startTime + delay) < timeSource.getTime()) {
// if (isTargetVisible() && (startTime + delay) > timeSource.getTime()) {
// System.out.println("ready to fire while inactive");
if ((startTime + delay) < timeSource.getTime() && isTargetVisible() && this.meleeOrProjectile() != null) {
return priority;
}
return -1;
// System.out.println("not ready to fire while inactive");
// return isTargetVisible() ? priority : -1;
}

/**
* Uses a raycast to determine whether there are any targets in detection range
* @return true if a target is visible, false otherwise
*/
private boolean isTargetVisible() {
return physics.raycast(mobPosition, maxRangePosition, TARGET, hit);
Vector2 newVector = new Vector2(owner.getEntity().getPosition().x - 10f, owner.getEntity().getPosition().y - 2f);
return physics.raycast(owner.getEntity().getPosition(), newVector, TARGET, hit);
}

/**
* Uses a custom raycast method to find the closest target to the mob. Based on the distance to the
* target, the mob will choose a weapon to attack with.
*
* If the object does not have a CombatStatsComponent (which handles dealing damage etc), then
* the function will return null. If it returns null when the mob is in state FIRING or DEPLOY, it will not fire
* and will STOW.
*
* returns the Weapon (Melee or Projectile) the mob will use to attack the target. null if immune target or no target
* */
private Weapon meleeOrProjectile() {
// Vector2 newVector = new Vector2(owner.getEntity().getPosition().x - 10f, owner.getEntity().getPosition().y - 2f);
// Fixture hitraycast = physics.raycastGetHit(owner.getEntity().getPosition(), newVector, TARGET);
setTarget();
TouchAttackComponent comp = owner.getEntity().getComponent(TouchAttackComponent.class);
Weapon chosenWeapon = null;
if (comp != null) {
chosenWeapon = comp.chooseWeapon(target);
}

return chosenWeapon;
}

private void setTarget() {
Vector2 newVector = new Vector2(owner.getEntity().getPosition().x - 10f, owner.getEntity().getPosition().y - 2f);
target = physics.raycastGetHit(owner.getEntity().getPosition(), newVector, TARGET);
}
}
Loading