Ranged Weapon Implementation - UQdeco2800/2022-studio-2 GitHub Wiki

Summary

This wiki page will explain the implementation of ranged weapons like bows to deal damage to enemies without needing to be in close proximity with the enemy. This implementation is heavily based on Projectile Skill by team 02. Therefore, this documentation will talk about the changes made with respect to their code, and not the code from scratch.

PlayerTouchAttackComponent

Located in: source/core/src/main/com/deco2800/game/components/player/PlayerTouchAttackComponent.java

In the attack function, if the weapon equipped is a ranged weapon, then the spawnWeaponProjectile() method is called in the current gameArea, be it ForestGameArea or UndergroundGameArea.

else if (weaponEquipped != null && weaponEquipped.checkEntityType(EntityTypes.RANGED)) {
        if (ServiceLocator.getGameArea() instanceof ForestGameArea) {
                ((ForestGameArea) ServiceLocator.getGameArea()).spawnWeaponProjectile();
        }
        else if (ServiceLocator.getGameArea() instanceof UndergroundGameArea){
            ((UndergroundGameArea) ServiceLocator.getGameArea()).spawnWeaponProjectile();
        }
}

GameArea

Located in: source/core/src/main/com/deco2800/game/areas/___GameArea.java

In the gameAreas at source/core/src/main/com/deco2800/game/areas/terrain, the spawnWeaponProjectile() method initialises a new projectile entity with createWeaponProjectile() from ProjectileFactory at the players position,

    public void spawnWeaponProjectile() { //TEAM 04
        Entity newProjectile = ProjectileFactory.createWeaponProjectile(player, 0);
        spawnEntityAt(newProjectile,
                new GridPoint2((int) player.getCenterPosition().x, (int) player.getCenterPosition().y),
                true, true);
    }

ProjectileFactory

Located in: source/core/src/main/com/deco2800/game/entities/factories/ProjectileFactory.java

In the ProjectileFactory, the createWeaponProjectile() initialises an projectile entity with a CombatStatsComponent tied to it. The damage value being inserted into the component is the damage value of the equipped ranged weapon with the following code

double dmg = player.getComponent(InventoryComponent.class).getEquipable(0).getComponent(PhysicalWeaponStatsComponent.class).getDamage();

The other difference with respect to createBasePlayerProjectile() created by team02 is that the animation atlases' path is changed to the plungerBowProjectile's path. Also, the frameDuration parameter in addAnimation is adjusted to refine the animations displayed.

 AnimationRenderComponent projectileAnimator = new AnimationRenderComponent(
                ServiceLocator.getResourceService().getAsset("images/CombatItems/animations/PlungerBow/plungerBowProjectile.atlas",
                        TextureAtlas.class));
        projectileAnimator.addAnimation("upright",0.05f,  Animation.PlayMode.LOOP);
        projectileAnimator.addAnimation("right",0.05f, Animation.PlayMode.LOOP);
        projectileAnimator.addAnimation("downright",0.05f, Animation.PlayMode.LOOP);
        projectileAnimator.addAnimation("down",0.05f, Animation.PlayMode.LOOP);
        projectileAnimator.addAnimation("downleft",0.05f, Animation.PlayMode.LOOP);
        projectileAnimator.addAnimation("left",0.05f, Animation.PlayMode.LOOP);
        projectileAnimator.addAnimation("upleft",0.05f, Animation.PlayMode.LOOP);
        projectileAnimator.addAnimation("up",0.05f, Animation.PlayMode.LOOP);

Compared to the projectile entity in createBasePlayerProjectile, instead of adding a PlayerSkillProjectileComponent to the entity, a WeaponArrowProjectileComponent is added to the entity.

WeaponArrowProjectileComponent

Located in: source/core/src/main/com/deco2800/game/components/CombatItemsComponents/WeaponArrowProjectileComponent.java

This component is basically a copy of PlayerSkillProjectileComponent, with changes differences stated below. The velocity of the projectile is changed to 6 instead of the 15 in PlayerSkillProjectileComponent.

    private final Vector2 projectileVelocity = new Vector2(6, 6);

Next, in the create() method, an extra listener is added

entity.getEvents().addListener("collisionStart", this::onCollisionStart);

The onCollisionStart method is called when there is a collision between the arrow with another entity. If the entity that collides with the arrow is an ememy (checked with their fixtures), then the given attack sounds will play.

 private void onCollisionStart(Fixture me, Fixture other) {
        Entity enemy = ((BodyUserData) other.getBody().getUserData()).entity;
        if (enemy.checkEntityType(EntityTypes.ENEMY)) {
            Sound attackSound = ServiceLocator.getResourceService().getAsset("sounds/plungerArrowSound.mp3", Sound.class);
            attackSound.play();
        }
    }

Back to Combat Items Contents Page

Author

  • Eugene Chong
  • GitHub: @eugene2341
  • Discord: gene#0005
  • Slack: Eugene Chong