diff --git a/core/assets/dedault_spritesheet.png b/core/assets/dedault_spritesheet.png new file mode 100644 index 00000000..e4cdc63d Binary files /dev/null and b/core/assets/dedault_spritesheet.png differ diff --git a/core/assets/default_spritesheet2.png b/core/assets/default_spritesheet2.png new file mode 100644 index 00000000..23369607 Binary files /dev/null and b/core/assets/default_spritesheet2.png differ diff --git a/core/assets/punch/punch_0000.png b/core/assets/punch/punch_0000.png new file mode 100644 index 00000000..233df2d5 Binary files /dev/null and b/core/assets/punch/punch_0000.png differ diff --git a/core/assets/punch/punch_0001.png b/core/assets/punch/punch_0001.png new file mode 100644 index 00000000..1055d395 Binary files /dev/null and b/core/assets/punch/punch_0001.png differ diff --git a/core/assets/punch/punch_0002.png b/core/assets/punch/punch_0002.png new file mode 100644 index 00000000..42e73161 Binary files /dev/null and b/core/assets/punch/punch_0002.png differ diff --git a/core/assets/punch/punch_0003.png b/core/assets/punch/punch_0003.png new file mode 100644 index 00000000..ba2882f9 Binary files /dev/null and b/core/assets/punch/punch_0003.png differ diff --git a/core/assets/punch/punch_0004.png b/core/assets/punch/punch_0004.png new file mode 100644 index 00000000..886531f1 Binary files /dev/null and b/core/assets/punch/punch_0004.png differ diff --git a/core/assets/punch/punch_0005.png b/core/assets/punch/punch_0005.png new file mode 100644 index 00000000..6f41b05e Binary files /dev/null and b/core/assets/punch/punch_0005.png differ diff --git a/core/assets/punch/punch_0006.png b/core/assets/punch/punch_0006.png new file mode 100644 index 00000000..1d49b878 Binary files /dev/null and b/core/assets/punch/punch_0006.png differ diff --git a/core/assets/punch/punch_0007.png b/core/assets/punch/punch_0007.png new file mode 100644 index 00000000..83050b3d Binary files /dev/null and b/core/assets/punch/punch_0007.png differ diff --git a/core/assets/punch/punch_0008.png b/core/assets/punch/punch_0008.png new file mode 100644 index 00000000..e7d49759 Binary files /dev/null and b/core/assets/punch/punch_0008.png differ diff --git a/core/assets/punch/punch_0009.png b/core/assets/punch/punch_0009.png new file mode 100644 index 00000000..23c38e51 Binary files /dev/null and b/core/assets/punch/punch_0009.png differ diff --git a/core/assets/punch/punch_0010.png b/core/assets/punch/punch_0010.png new file mode 100644 index 00000000..18e803d6 Binary files /dev/null and b/core/assets/punch/punch_0010.png differ diff --git a/core/assets/punch/punch_0011.png b/core/assets/punch/punch_0011.png new file mode 100644 index 00000000..85e9fcd3 Binary files /dev/null and b/core/assets/punch/punch_0011.png differ diff --git a/core/assets/punch/punch_0012.png b/core/assets/punch/punch_0012.png new file mode 100644 index 00000000..ce5d19a4 Binary files /dev/null and b/core/assets/punch/punch_0012.png differ diff --git a/core/assets/punch/punch_0013.png b/core/assets/punch/punch_0013.png new file mode 100644 index 00000000..cd5be186 Binary files /dev/null and b/core/assets/punch/punch_0013.png differ diff --git a/core/assets/punch/punch_0014.png b/core/assets/punch/punch_0014.png new file mode 100644 index 00000000..0aef6914 Binary files /dev/null and b/core/assets/punch/punch_0014.png differ diff --git a/core/assets/punch/punch_0015.png b/core/assets/punch/punch_0015.png new file mode 100644 index 00000000..bf4af316 Binary files /dev/null and b/core/assets/punch/punch_0015.png differ diff --git a/core/assets/punch/punch_0016.png b/core/assets/punch/punch_0016.png new file mode 100644 index 00000000..7e613737 Binary files /dev/null and b/core/assets/punch/punch_0016.png differ diff --git a/core/assets/punch/punch_0017.png b/core/assets/punch/punch_0017.png new file mode 100644 index 00000000..de51c6e7 Binary files /dev/null and b/core/assets/punch/punch_0017.png differ diff --git a/core/assets/punch/punch_0018.png b/core/assets/punch/punch_0018.png new file mode 100644 index 00000000..36b37085 Binary files /dev/null and b/core/assets/punch/punch_0018.png differ diff --git a/core/assets/punch/punch_0019.png b/core/assets/punch/punch_0019.png new file mode 100644 index 00000000..b1c01e7d Binary files /dev/null and b/core/assets/punch/punch_0019.png differ diff --git a/core/assets/punch/punch_0020.png b/core/assets/punch/punch_0020.png new file mode 100644 index 00000000..0f5cd5d3 Binary files /dev/null and b/core/assets/punch/punch_0020.png differ diff --git a/core/assets/punch/punch_0021.png b/core/assets/punch/punch_0021.png new file mode 100644 index 00000000..f9da836e Binary files /dev/null and b/core/assets/punch/punch_0021.png differ diff --git a/core/assets/punch/punch_0022.png b/core/assets/punch/punch_0022.png new file mode 100644 index 00000000..e0b05721 Binary files /dev/null and b/core/assets/punch/punch_0022.png differ diff --git a/core/assets/punch/punch_0023.png b/core/assets/punch/punch_0023.png new file mode 100644 index 00000000..c39e0655 Binary files /dev/null and b/core/assets/punch/punch_0023.png differ diff --git a/core/assets/punch/punch_0024.png b/core/assets/punch/punch_0024.png new file mode 100644 index 00000000..9e6690ca Binary files /dev/null and b/core/assets/punch/punch_0024.png differ diff --git a/core/assets/punch/punch_0025.png b/core/assets/punch/punch_0025.png new file mode 100644 index 00000000..547242be Binary files /dev/null and b/core/assets/punch/punch_0025.png differ diff --git a/core/assets/punch/punch_0026.png b/core/assets/punch/punch_0026.png new file mode 100644 index 00000000..f29ff0b5 Binary files /dev/null and b/core/assets/punch/punch_0026.png differ diff --git a/core/assets/walking_spritesheet.png b/core/assets/walking_spritesheet.png new file mode 100644 index 00000000..fc4e7847 Binary files /dev/null and b/core/assets/walking_spritesheet.png differ diff --git a/core/src/core/app/screen/assets/animations/AnimationState.java b/core/src/core/app/screen/assets/animations/AnimationState.java index dee60648..3bfead01 100644 --- a/core/src/core/app/screen/assets/animations/AnimationState.java +++ b/core/src/core/app/screen/assets/animations/AnimationState.java @@ -6,5 +6,6 @@ public enum AnimationState { WALKING_LEFT, JUMPING, FALLING, - ATTACKING, + PUNCH_LEFT, + PUNCH_RIGHT, } diff --git a/core/src/core/app/screen/assets/animations/GameAnimationFactory.java b/core/src/core/app/screen/assets/animations/GameAnimationFactory.java index b59f975c..55071e7d 100644 --- a/core/src/core/app/screen/assets/animations/GameAnimationFactory.java +++ b/core/src/core/app/screen/assets/animations/GameAnimationFactory.java @@ -7,7 +7,7 @@ public class GameAnimationFactory { - GameAnimation createEntityAnimation() { + GameAnimation createEntityAnimation2() { final int FRAME_COLS = 6, FRAME_ROWS = 5; Texture walkSheet = new Texture(Gdx.files.internal("sprite-animation4.png")); TextureRegion[][] tmp = @@ -45,6 +45,98 @@ GameAnimation createEntityAnimation() { .build(); } + GameAnimation createEntityAnimation() { + final int DEFAULT_FRAMES_NUM = 23; + final int DEFAULT_FRAME_COLS = 6, DEFAULT_FRAME_ROWS = 4; + final String DEFAULT_FILE_NAME = "default_spritesheet2.png"; + Texture walkSheet = new Texture(Gdx.files.internal(DEFAULT_FILE_NAME)); + TextureRegion[][] tmp = + TextureRegion.split( + walkSheet, + walkSheet.getWidth() / DEFAULT_FRAME_COLS, + walkSheet.getHeight() / DEFAULT_FRAME_ROWS); + + TextureRegion[] defaultFrames = new TextureRegion[DEFAULT_FRAMES_NUM]; + int index = 0; + for (int i = 0; i < DEFAULT_FRAME_ROWS; i++) { + for (int j = 0; j < DEFAULT_FRAME_COLS; j++) { + if (index >= DEFAULT_FRAMES_NUM) break; + defaultFrames[index++] = tmp[i][j]; + } + } + + final int WALKING_FRAMES_NUM = 26; + final int WALKING_FRAME_COLS = 6, WALKING_FRAME_ROWS = 5; + final String WALKING_FILE_NAME = "walking_spritesheet.png"; + + walkSheet = new Texture(Gdx.files.internal(WALKING_FILE_NAME)); + tmp = + TextureRegion.split( + walkSheet, + walkSheet.getWidth() / WALKING_FRAME_COLS, + walkSheet.getHeight() / WALKING_FRAME_ROWS); + + TextureRegion[] walkLeftFrames = new TextureRegion[WALKING_FRAMES_NUM]; + index = 0; + for (int i = 0; i < WALKING_FRAME_ROWS; i++) { + for (int j = 0; j < WALKING_FRAME_COLS; j++) { + // tmp[i][j].flip(true, false); + if (index >= WALKING_FRAMES_NUM) break; + + walkLeftFrames[index++] = tmp[i][j]; + } + } + + TextureRegion[] walkRightFrames = new TextureRegion[WALKING_FRAMES_NUM]; + tmp = + TextureRegion.split( + walkSheet, + walkSheet.getWidth() / WALKING_FRAME_COLS, + walkSheet.getHeight() / WALKING_FRAME_ROWS); + index = 0; + for (int i = 0; i < WALKING_FRAME_ROWS; i++) { + for (int j = 0; j < WALKING_FRAME_COLS; j++) { + if (index >= WALKING_FRAMES_NUM) break; + tmp[i][j].flip(true, false); + walkRightFrames[index++] = tmp[i][j]; + } + } + + TextureRegion[] punchFramesLeft = new TextureRegion[27]; + for (int i = 0; i < 27; i++) { + if (i < 10) + punchFramesLeft[i] = + new TextureRegion(new Texture(Gdx.files.internal("punch/punch_000" + i + ".png"))); + else + punchFramesLeft[i] = + new TextureRegion(new Texture(Gdx.files.internal("punch/punch_00" + i + ".png"))); + } + + TextureRegion[] punchFramesRight = new TextureRegion[27]; + for (int i = 0; i < 27; i++) { + if (i < 10) + punchFramesRight[i] = + new TextureRegion(new Texture(Gdx.files.internal("punch/punch_000" + i + ".png"))); + else + punchFramesRight[i] = + new TextureRegion(new Texture(Gdx.files.internal("punch/punch_00" + i + ".png"))); + + punchFramesRight[i].flip(true, false); + } + + return new GameAnimationBuilder() + .addAnimation(AnimationState.DEFAULT, new Animation(0.25f, defaultFrames)) + .addAnimation( + AnimationState.WALKING_LEFT, new Animation(0.05f, walkLeftFrames)) + .addAnimation( + AnimationState.WALKING_RIGHT, new Animation(0.05f, walkRightFrames)) + .addAnimation( + AnimationState.PUNCH_LEFT, new Animation(0.05f, punchFramesLeft)) + .addAnimation( + AnimationState.PUNCH_RIGHT, new Animation(0.05f, punchFramesRight)) + .build(); + } + GameAnimation createOrbAnimation() { TextureRegion[] orbFrames = new TextureRegion[6]; diff --git a/core/src/core/common/GameSettings.java b/core/src/core/common/GameSettings.java index f1f41bcc..195bae89 100644 --- a/core/src/core/common/GameSettings.java +++ b/core/src/core/common/GameSettings.java @@ -8,7 +8,7 @@ import java.util.Properties; public class GameSettings { - public static final boolean RENDER_DEBUG = true; + public static final boolean RENDER_DEBUG = false; public static final int AI_LIMIT = 10; @@ -17,7 +17,7 @@ public class GameSettings { public static final int WORLD_VELOCITY_ITERATIONS = 6; public static final int WORLD_POSITION_ITERATIONS = 2; public static final int CHUNK_SIZE = 5; - public static final int PIXEL_SCALE = 30; + public static final int PIXEL_SCALE = 70; public static final int PHYSICS_SCALE = 25; public static final float GRAVITY = 1f; public static final int GENERATION_THREADS = 5; diff --git a/core/src/core/entity/Entity.java b/core/src/core/entity/Entity.java index b11fa431..4b0f3967 100644 --- a/core/src/core/entity/Entity.java +++ b/core/src/core/entity/Entity.java @@ -34,8 +34,10 @@ import core.entity.controllers.EntityController; import core.entity.controllers.events.types.AbstractEntityEventType; import core.entity.controllers.events.types.EntityEventTypeFactory; +import core.entity.statemachine.EntityStateMachine; import core.networking.events.interfaces.SerializeNetworkData; import core.networking.translation.NetworkDataSerializer; +import java.util.HashMap; import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; import java.util.function.Consumer; @@ -53,6 +55,8 @@ public class Entity implements SerializeNetworkData { public Health health; protected BaseAssetManager baseAssetManager; float stateTime; + private EntityStateMachine entityStateMachine = + new EntityStateMachine(this, new HashMap<>(), new HashMap<>()); private DirectionWrapper directionWrapper = new DirectionWrapper(Direction.RIGHT); private CoordinatesWrapper coordinatesWrapper; private UUID uuid; @@ -81,6 +85,14 @@ public Entity( stateTime = (float) ThreadLocalRandom.current().nextDouble(0, 20); } + public EntityStateMachine getEntityStateMachine() { + return entityStateMachine; + } + + public void setEntityStateMachine(EntityStateMachine entityStateMachine) { + this.entityStateMachine = entityStateMachine; + } + public AnimationStateWrapper getAnimationStateWrapper() { return animationStateWrapper; } @@ -180,6 +192,7 @@ protected Pair addWorld(World world) { } public void render(AnimationManager animationManager, SpriteBatch batch) { + entityStateMachine.callAnimation(); stateTime += Gdx.graphics.getDeltaTime(); Vector2 v2 = this.getCoordinatesWrapper().getCoordinates().toRenderVector2(); diff --git a/core/src/core/entity/EntityFactory.java b/core/src/core/entity/EntityFactory.java index 14fc58dd..b93c0418 100644 --- a/core/src/core/entity/EntityFactory.java +++ b/core/src/core/entity/EntityFactory.java @@ -12,18 +12,21 @@ import core.entity.misc.Turret; import core.entity.misc.water.Water; import core.entity.misc.water.WaterPosition; +import core.entity.statemachine.EntityStateMachineFactory; public class EntityFactory { @Inject Clock clock; @Inject BaseAssetManager baseAssetManager; @Inject EntityBodyBuilder entityBodyBuilder; + @Inject EntityStateMachineFactory entityStateMachineFactory; @Inject EntityFactory() {} public Entity createEntity(Coordinates coordinates) { Entity entity = new Entity(clock, baseAssetManager, entityBodyBuilder, coordinates); + entity.setEntityStateMachine(entityStateMachineFactory.createEntityStateMachine(entity)); return entity; } diff --git a/core/src/core/entity/controllers/EntityController.java b/core/src/core/entity/controllers/EntityController.java index 1763100f..6c2143b3 100644 --- a/core/src/core/entity/controllers/EntityController.java +++ b/core/src/core/entity/controllers/EntityController.java @@ -3,6 +3,7 @@ import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.physics.box2d.Body; import core.app.game.GameController; +import core.app.screen.assets.animations.AnimationState; import core.chunk.world.exceptions.BodyNotFound; import core.common.CommonFactory; import core.common.Coordinates; @@ -61,10 +62,7 @@ public EntityController registerEntityEventConsumer(String type, EntityEventCons } public void applyAction(String type, Entity entity) throws ChunkNotFound, BodyNotFound { - entity.applyBody( - (Body body) -> { - this.actionMap.get(type).apply(body); - }); + this.actionMap.get(type).apply(entity); } public EntityAction getAction(String type) { @@ -82,12 +80,16 @@ public Set> getEntityActionEntrySet() { public void beforeWorldUpdate() throws Exception {} public void afterWorldUpdate() throws Exception { + entity.getEntityStateMachine().callAction(); Coordinates moveTo = CommonFactory.createCoordinates( this.entity.getBodyPosition().x / GameSettings.PHYSICS_SCALE, this.entity.getBodyPosition().y / GameSettings.PHYSICS_SCALE); if (!this.entity.getCoordinatesWrapper().getCoordinates().equals(moveTo)) gameController.moveEntity(this.entity.getUuid(), moveTo); + else { + entity.getEntityStateMachine().attemptTransition(AnimationState.DEFAULT); + } if (this.getAction("climbUp").isValid(entity)) { this.entity.setBodyVelocity(new Vector2(0, 0)); diff --git a/core/src/core/entity/controllers/EntityUserController.java b/core/src/core/entity/controllers/EntityUserController.java index cdb427ec..202aa292 100644 --- a/core/src/core/entity/controllers/EntityUserController.java +++ b/core/src/core/entity/controllers/EntityUserController.java @@ -15,8 +15,6 @@ import core.entity.Entity; import core.entity.attributes.inventory.Equipped; import core.entity.attributes.inventory.InventoryBag; -import core.entity.attributes.msc.AnimationStateWrapper; -import core.entity.attributes.msc.DirectionWrapper; import core.entity.block.DirtBlock; import core.entity.controllers.actions.EntityActionFactory; import core.networking.events.EventTypeFactory; @@ -77,7 +75,11 @@ public void beforeWorldUpdate() throws EntityNotFound, ChunkNotFound, BodyNotFou } } if (Gdx.input.isKeyJustPressed(Input.Keys.R)) { - gameController.useItem(this.entity); + if (entity.getDirectionWrapper().getDirection() == Direction.LEFT) + entity.getEntityStateMachine().attemptTransition(AnimationState.PUNCH_LEFT); + else if (entity.getDirectionWrapper().getDirection() == Direction.RIGHT) { + entity.getEntityStateMachine().attemptTransition(AnimationState.PUNCH_RIGHT); + } } if (Gdx.input.isKeyJustPressed(Keys.NUM_1)) { @@ -131,21 +133,11 @@ public void beforeWorldUpdate() throws EntityNotFound, ChunkNotFound, BodyNotFou if (Gdx.input.isKeyPressed(Input.Keys.A)) { if (this.getAction("left").isValid(entity)) { this.applyAction("left", entity); - this.gameController.updateEntityAttribute( - this.entity.getUuid(), new AnimationStateWrapper(AnimationState.WALKING_LEFT)); - - this.gameController.updateEntityAttribute( - this.entity.getUuid(), new DirectionWrapper(Direction.LEFT)); } } if (Gdx.input.isKeyPressed(Input.Keys.D)) { if (this.getAction("right").isValid(entity)) { this.applyAction("right", entity); - this.gameController.updateEntityAttribute( - this.entity.getUuid(), new AnimationStateWrapper(AnimationState.WALKING_RIGHT)); - - this.gameController.updateEntityAttribute( - this.entity.getUuid(), new DirectionWrapper(Direction.RIGHT)); } } } diff --git a/core/src/core/entity/controllers/actions/ClimbDownMovementAction.java b/core/src/core/entity/controllers/actions/ClimbDownMovementAction.java index 0339e665..4afd02f4 100644 --- a/core/src/core/entity/controllers/actions/ClimbDownMovementAction.java +++ b/core/src/core/entity/controllers/actions/ClimbDownMovementAction.java @@ -1,7 +1,9 @@ package core.entity.controllers.actions; import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.physics.box2d.Body; +import core.chunk.world.exceptions.BodyNotFound; +import core.common.exceptions.ChunkNotFound; +import core.entity.Entity; import core.entity.collision.ladder.EntityLadderContact; public class ClimbDownMovementAction extends ClimbUpMovementAction { @@ -10,9 +12,12 @@ public ClimbDownMovementAction(EntityLadderContact entityLadderContact) { } @Override - public void apply(Body body) { - body.setGravityScale(0); - float x = body.getLinearVelocity().x; - body.setLinearVelocity(new Vector2(x, -5)); + public void apply(Entity entity) throws ChunkNotFound, BodyNotFound { + entity.applyBody( + (body -> { + body.setGravityScale(0); + float x = body.getLinearVelocity().x; + body.setLinearVelocity(new Vector2(x, -5)); + })); } } diff --git a/core/src/core/entity/controllers/actions/ClimbUpMovementAction.java b/core/src/core/entity/controllers/actions/ClimbUpMovementAction.java index da1e7548..6cf3b3ea 100644 --- a/core/src/core/entity/controllers/actions/ClimbUpMovementAction.java +++ b/core/src/core/entity/controllers/actions/ClimbUpMovementAction.java @@ -2,9 +2,11 @@ import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.physics.box2d.Body; +import core.chunk.world.exceptions.BodyNotFound; import core.common.exceptions.ChunkNotFound; import core.entity.Entity; import core.entity.collision.ladder.EntityLadderContact; +import java.util.function.Consumer; public class ClimbUpMovementAction implements EntityAction { EntityLadderContact entityLadderContact; @@ -14,9 +16,16 @@ public ClimbUpMovementAction(EntityLadderContact entityLadderContact) { } @Override - public void apply(Body body) { - float x = body.getLinearVelocity().x; - body.setLinearVelocity(new Vector2(x, 5)); + public void apply(Entity entity) throws ChunkNotFound, BodyNotFound { + entity.applyBody(this.applyBodyConsumer()); + } + + @Override + public Consumer applyBodyConsumer() { + return (body) -> { + float x = body.getLinearVelocity().x; + body.setLinearVelocity(new Vector2(x, 5)); + }; } @Override diff --git a/core/src/core/entity/controllers/actions/EntityAction.java b/core/src/core/entity/controllers/actions/EntityAction.java index fd99f57a..792c790e 100644 --- a/core/src/core/entity/controllers/actions/EntityAction.java +++ b/core/src/core/entity/controllers/actions/EntityAction.java @@ -1,12 +1,16 @@ package core.entity.controllers.actions; import com.badlogic.gdx.physics.box2d.Body; +import core.chunk.world.exceptions.BodyNotFound; import core.common.exceptions.ChunkNotFound; import core.entity.Entity; +import java.util.function.Consumer; public interface EntityAction { - void apply(Body body); + void apply(Entity entity) throws ChunkNotFound, BodyNotFound; + + Consumer applyBodyConsumer(); Boolean isValid(Entity entity) throws ChunkNotFound; } diff --git a/core/src/core/entity/controllers/actions/HorizontalMovementAction.java b/core/src/core/entity/controllers/actions/HorizontalMovementAction.java index 3ec74c6a..677d737c 100644 --- a/core/src/core/entity/controllers/actions/HorizontalMovementAction.java +++ b/core/src/core/entity/controllers/actions/HorizontalMovementAction.java @@ -4,10 +4,13 @@ import com.badlogic.gdx.physics.box2d.Body; import com.google.inject.Inject; import core.app.game.GameController; +import core.app.screen.assets.animations.AnimationState; +import core.chunk.world.exceptions.BodyNotFound; import core.common.exceptions.ChunkNotFound; import core.entity.Entity; import core.entity.collision.left.EntityLeftContact; import core.entity.collision.right.EntityRightContact; +import java.util.function.Consumer; public class HorizontalMovementAction implements EntityAction { @@ -29,14 +32,21 @@ public class HorizontalMovementAction implements EntityAction { } @Override - public void apply(Body body) { - // if (magnitude < 0) { - // gameController.updateEntityAttribute(); - // } - // if (magnitude > 0) { - // // - // } - body.setLinearVelocity(new Vector2(this.magnitude, body.getLinearVelocity().y)); + public void apply(Entity entity) throws ChunkNotFound, BodyNotFound { + if (magnitude < 0) { + entity.getEntityStateMachine().attemptTransition(AnimationState.WALKING_LEFT); + } + if (magnitude > 0) { + entity.getEntityStateMachine().attemptTransition(AnimationState.WALKING_RIGHT); + } + entity.applyBody(this.applyBodyConsumer()); + } + + @Override + public Consumer applyBodyConsumer() { + return body -> { + body.setLinearVelocity(new Vector2(this.magnitude, body.getLinearVelocity().y)); + }; } @Override diff --git a/core/src/core/entity/controllers/actions/JumpMovementAction.java b/core/src/core/entity/controllers/actions/JumpMovementAction.java index 0ef66b8e..06fc0574 100644 --- a/core/src/core/entity/controllers/actions/JumpMovementAction.java +++ b/core/src/core/entity/controllers/actions/JumpMovementAction.java @@ -2,9 +2,12 @@ import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.physics.box2d.Body; +import core.app.screen.assets.animations.AnimationState; +import core.chunk.world.exceptions.BodyNotFound; import core.common.exceptions.ChunkNotFound; import core.entity.Entity; import core.entity.collision.ground.EntityGroundContact; +import java.util.function.Consumer; public class JumpMovementAction implements EntityAction { @@ -15,8 +18,16 @@ public class JumpMovementAction implements EntityAction { } @Override - public void apply(Body body) { - body.setLinearVelocity(new Vector2(0, 9)); + public void apply(Entity entity) throws ChunkNotFound, BodyNotFound { + entity.getEntityStateMachine().attemptTransition(AnimationState.JUMPING); + entity.applyBody(this.applyBodyConsumer()); + } + + @Override + public Consumer applyBodyConsumer() { + return (Body body) -> { + body.setLinearVelocity(new Vector2(0, 9)); + }; } @Override diff --git a/core/src/core/entity/controllers/actions/StopMovementAction.java b/core/src/core/entity/controllers/actions/StopMovementAction.java index 018f2fb3..a7c89326 100644 --- a/core/src/core/entity/controllers/actions/StopMovementAction.java +++ b/core/src/core/entity/controllers/actions/StopMovementAction.java @@ -3,7 +3,11 @@ import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.physics.box2d.Body; import com.google.inject.Inject; +import core.app.screen.assets.animations.AnimationState; +import core.chunk.world.exceptions.BodyNotFound; +import core.common.exceptions.ChunkNotFound; import core.entity.Entity; +import java.util.function.Consumer; public class StopMovementAction implements EntityAction { @@ -11,8 +15,16 @@ public class StopMovementAction implements EntityAction { StopMovementAction() {} @Override - public void apply(Body body) { - body.setLinearVelocity(new Vector2(0, body.getLinearVelocity().y)); + public void apply(Entity entity) throws ChunkNotFound, BodyNotFound { + entity.getEntityStateMachine().attemptTransition(AnimationState.DEFAULT); + entity.applyBody(this.applyBodyConsumer()); + } + + @Override + public Consumer applyBodyConsumer() { + return body -> { + body.setLinearVelocity(new Vector2(0, body.getLinearVelocity().y)); + }; } @Override diff --git a/core/src/core/entity/pathfinding/RelativeActionEdgeGenerator.java b/core/src/core/entity/pathfinding/RelativeActionEdgeGenerator.java index aee79054..34838e24 100644 --- a/core/src/core/entity/pathfinding/RelativeActionEdgeGenerator.java +++ b/core/src/core/entity/pathfinding/RelativeActionEdgeGenerator.java @@ -1,7 +1,6 @@ package core.entity.pathfinding; import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.physics.box2d.Body; import com.badlogic.gdx.physics.box2d.World; import com.google.inject.Inject; import core.chunk.Chunk; @@ -49,11 +48,7 @@ else if (actionKey.equals("stop")) entityAction = entityActionFactory.createStopMovementAction(); else return null; - worldWrapper.applyBody( - entity, - (Body body) -> { - entityAction.apply(body); - }); + worldWrapper.applyBody(entity, entityAction.applyBodyConsumer()); worldWrapper.tick(); diff --git a/core/src/core/entity/statemachine/EntityStateMachine.java b/core/src/core/entity/statemachine/EntityStateMachine.java new file mode 100644 index 00000000..2ba36b53 --- /dev/null +++ b/core/src/core/entity/statemachine/EntityStateMachine.java @@ -0,0 +1,50 @@ +package core.entity.statemachine; + +import core.app.screen.assets.animations.AnimationState; +import core.entity.Entity; +import java.util.Map; +import java.util.Set; + +public class EntityStateMachine { + private final Entity entity; + Map> transitions; + Map stateToNode; + long stateStartTime = 0; + private AnimationState currentState; + + public EntityStateMachine( + Entity entity, + Map> transitions, + Map stateToNode) { + this.transitions = transitions; + this.stateToNode = stateToNode; + this.entity = entity; + currentState = AnimationState.DEFAULT; + } + + public void attemptTransition(AnimationState transition) { + Set possibleTransitions = transitions.get(currentState); + if (possibleTransitions == null) return; + if (possibleTransitions.contains(transition)) { + this.setState(transition); + } + } + + public void setState(AnimationState transition) { + currentState = transition; + stateStartTime = System.currentTimeMillis(); + } + + public void callAnimation() { + if (currentState == null) return; + if (stateToNode.get(currentState) == null) return; + stateToNode.get(currentState).callAnimation(entity); + } + + public void callAction() { + if (currentState == null) return; + if (stateToNode.get(currentState) == null) return; + long timeInState = System.currentTimeMillis() - stateStartTime; + stateToNode.get(currentState).callAction(entity, timeInState); + } +} diff --git a/core/src/core/entity/statemachine/EntityStateMachineFactory.java b/core/src/core/entity/statemachine/EntityStateMachineFactory.java new file mode 100644 index 00000000..79bceea4 --- /dev/null +++ b/core/src/core/entity/statemachine/EntityStateMachineFactory.java @@ -0,0 +1,53 @@ +package core.entity.statemachine; + +import com.google.common.collect.Sets; +import com.google.inject.Inject; +import core.app.screen.assets.animations.AnimationState; +import core.entity.Entity; +import core.entity.statemachine.states.DefaultItemState; +import core.entity.statemachine.states.DefaultState; +import core.entity.statemachine.states.JumpState; +import core.entity.statemachine.states.LeftWalkingState; +import core.entity.statemachine.states.RightWalkingState; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public class EntityStateMachineFactory { + @Inject DefaultItemState defaultItemState; + @Inject DefaultState defaultState; + @Inject LeftWalkingState leftWalkingState; + @Inject RightWalkingState rightWalkingState; + @Inject JumpState jumpState; + + public EntityStateMachine createEntityStateMachine(Entity entity) { + + Map stateToNode = new HashMap<>(); + stateToNode.put(AnimationState.DEFAULT, defaultState); + stateToNode.put(AnimationState.PUNCH_LEFT, defaultItemState); + stateToNode.put(AnimationState.PUNCH_RIGHT, defaultItemState); + stateToNode.put(AnimationState.WALKING_LEFT, leftWalkingState); + stateToNode.put(AnimationState.WALKING_RIGHT, rightWalkingState); + stateToNode.put(AnimationState.JUMPING, jumpState); + + Map> transitions = new HashMap<>(); + + Set allStates = + Sets.newHashSet( + AnimationState.DEFAULT, + AnimationState.PUNCH_LEFT, + AnimationState.PUNCH_RIGHT, + AnimationState.WALKING_LEFT, + AnimationState.WALKING_RIGHT, + AnimationState.JUMPING); + + transitions.put(AnimationState.DEFAULT, allStates); + transitions.put(AnimationState.WALKING_LEFT, allStates); + transitions.put(AnimationState.WALKING_RIGHT, allStates); + transitions.put(AnimationState.JUMPING, allStates); + transitions.put(AnimationState.PUNCH_LEFT, Sets.newHashSet()); + transitions.put(AnimationState.PUNCH_RIGHT, Sets.newHashSet()); + + return new EntityStateMachine(entity, transitions, stateToNode); + } +} diff --git a/core/src/core/entity/statemachine/EntityStateMachineNodeInterface.java b/core/src/core/entity/statemachine/EntityStateMachineNodeInterface.java new file mode 100644 index 00000000..540a3ab1 --- /dev/null +++ b/core/src/core/entity/statemachine/EntityStateMachineNodeInterface.java @@ -0,0 +1,17 @@ +package core.entity.statemachine; + +import com.google.inject.Inject; +import core.app.game.GameController; +import core.entity.Entity; + +public abstract class EntityStateMachineNodeInterface { + + @Inject protected GameController gameController; + + public abstract void callAnimation(Entity entity); + // renders the animation + // takes the arguments needed to render the animation + + public abstract void callAction(Entity entity, long timeInState); + // calls with the +} diff --git a/core/src/core/entity/statemachine/states/DefaultItemState.java b/core/src/core/entity/statemachine/states/DefaultItemState.java new file mode 100644 index 00000000..11b2dc56 --- /dev/null +++ b/core/src/core/entity/statemachine/states/DefaultItemState.java @@ -0,0 +1,37 @@ +package core.entity.statemachine.states; + +import core.app.screen.assets.animations.AnimationState; +import core.common.Direction; +import core.common.exceptions.EntityNotFound; +import core.entity.Entity; +import core.entity.attributes.msc.AnimationStateWrapper; +import core.entity.statemachine.EntityStateMachineNodeInterface; + +public class DefaultItemState extends EntityStateMachineNodeInterface { + + @Override + public void callAnimation(Entity entity) { + AnimationState state; + if (entity.getDirectionWrapper().getDirection() == Direction.LEFT) { + state = AnimationState.PUNCH_LEFT; + } else { + state = AnimationState.PUNCH_RIGHT; + } + + if (!entity.getAnimationStateWrapper().getAnimationState().equals(state)) { + try { + gameController.updateEntityAttribute(entity.getUuid(), new AnimationStateWrapper(state)); + } catch (EntityNotFound e) { + e.printStackTrace(); + } + } + } + + @Override + public void callAction(Entity entity, long timeInState) { + if (timeInState > 150) { + gameController.useItem(entity); + entity.getEntityStateMachine().setState(AnimationState.DEFAULT); + } + } +} diff --git a/core/src/core/entity/statemachine/states/DefaultState.java b/core/src/core/entity/statemachine/states/DefaultState.java new file mode 100644 index 00000000..ffc69ad0 --- /dev/null +++ b/core/src/core/entity/statemachine/states/DefaultState.java @@ -0,0 +1,25 @@ +package core.entity.statemachine.states; + +import core.app.screen.assets.animations.AnimationState; +import core.common.exceptions.EntityNotFound; +import core.entity.Entity; +import core.entity.attributes.msc.AnimationStateWrapper; +import core.entity.statemachine.EntityStateMachineNodeInterface; + +public class DefaultState extends EntityStateMachineNodeInterface { + + @Override + public void callAnimation(Entity entity) { + if (!entity.getAnimationStateWrapper().getAnimationState().equals(AnimationState.DEFAULT)) { + try { + gameController.updateEntityAttribute( + entity.getUuid(), new AnimationStateWrapper(AnimationState.DEFAULT)); + } catch (EntityNotFound e) { + e.printStackTrace(); + } + } + } + + @Override + public void callAction(Entity entity, long timeInState) {} +} diff --git a/core/src/core/entity/statemachine/states/JumpState.java b/core/src/core/entity/statemachine/states/JumpState.java new file mode 100644 index 00000000..8c3e5a99 --- /dev/null +++ b/core/src/core/entity/statemachine/states/JumpState.java @@ -0,0 +1,25 @@ +package core.entity.statemachine.states; + +import core.app.screen.assets.animations.AnimationState; +import core.common.exceptions.EntityNotFound; +import core.entity.Entity; +import core.entity.attributes.msc.AnimationStateWrapper; +import core.entity.statemachine.EntityStateMachineNodeInterface; + +public class JumpState extends EntityStateMachineNodeInterface { + + @Override + public void callAnimation(Entity entity) { + if (!entity.getAnimationStateWrapper().getAnimationState().equals(AnimationState.DEFAULT)) { + try { + gameController.updateEntityAttribute( + entity.getUuid(), new AnimationStateWrapper(AnimationState.DEFAULT)); + } catch (EntityNotFound e) { + e.printStackTrace(); + } + } + } + + @Override + public void callAction(Entity entity, long timeInState) {} +} diff --git a/core/src/core/entity/statemachine/states/LeftWalkingState.java b/core/src/core/entity/statemachine/states/LeftWalkingState.java new file mode 100644 index 00000000..76cc1e3a --- /dev/null +++ b/core/src/core/entity/statemachine/states/LeftWalkingState.java @@ -0,0 +1,32 @@ +package core.entity.statemachine.states; + +import core.app.screen.assets.animations.AnimationState; +import core.common.Direction; +import core.common.exceptions.EntityNotFound; +import core.entity.Entity; +import core.entity.attributes.msc.AnimationStateWrapper; +import core.entity.attributes.msc.DirectionWrapper; +import core.entity.statemachine.EntityStateMachineNodeInterface; + +public class LeftWalkingState extends EntityStateMachineNodeInterface { + + @Override + public void callAnimation(Entity entity) { + if (!entity + .getAnimationStateWrapper() + .getAnimationState() + .equals(AnimationState.WALKING_LEFT)) { + try { + this.gameController.updateEntityAttribute( + entity.getUuid(), new AnimationStateWrapper(AnimationState.WALKING_LEFT)); + this.gameController.updateEntityAttribute( + entity.getUuid(), new DirectionWrapper(Direction.LEFT)); + } catch (EntityNotFound e) { + e.printStackTrace(); + } + } + } + + @Override + public void callAction(Entity entity, long timeInState) {} +} diff --git a/core/src/core/entity/statemachine/states/RightWalkingState.java b/core/src/core/entity/statemachine/states/RightWalkingState.java new file mode 100644 index 00000000..5f0f0f9a --- /dev/null +++ b/core/src/core/entity/statemachine/states/RightWalkingState.java @@ -0,0 +1,32 @@ +package core.entity.statemachine.states; + +import core.app.screen.assets.animations.AnimationState; +import core.common.Direction; +import core.common.exceptions.EntityNotFound; +import core.entity.Entity; +import core.entity.attributes.msc.AnimationStateWrapper; +import core.entity.attributes.msc.DirectionWrapper; +import core.entity.statemachine.EntityStateMachineNodeInterface; + +public class RightWalkingState extends EntityStateMachineNodeInterface { + + @Override + public void callAnimation(Entity entity) { + if (!entity + .getAnimationStateWrapper() + .getAnimationState() + .equals(AnimationState.WALKING_RIGHT)) { + try { + gameController.updateEntityAttribute( + entity.getUuid(), new AnimationStateWrapper(AnimationState.WALKING_RIGHT)); + this.gameController.updateEntityAttribute( + entity.getUuid(), new DirectionWrapper(Direction.RIGHT)); + } catch (EntityNotFound e) { + e.printStackTrace(); + } + } + } + + @Override + public void callAction(Entity entity, long timeInState) {} +} diff --git a/core/test/core/entity/attributes/testEntityUpdates.java b/core/test/core/entity/attributes/testEntityUpdates.java index 3f730d25..fd1147ec 100644 --- a/core/test/core/entity/attributes/testEntityUpdates.java +++ b/core/test/core/entity/attributes/testEntityUpdates.java @@ -83,12 +83,12 @@ public void testAnimationStateUpdate() { Entity entity = entityFactory.createEntity(CommonFactory.createCoordinates(0, 1)); AnimationStateWrapper animationStateWrapper = - new AnimationStateWrapper(AnimationState.ATTACKING); + new AnimationStateWrapper(AnimationState.PUNCH_LEFT); assert entity.getAnimationStateWrapper().getAnimationState().equals(AnimationState.DEFAULT); entity.updateAttribute(animationStateWrapper); - assert entity.getAnimationStateWrapper().getAnimationState().equals(AnimationState.ATTACKING); + assert entity.getAnimationStateWrapper().getAnimationState().equals(AnimationState.PUNCH_LEFT); } } diff --git a/core/test/core/networking/connected/testClientServerAttributes.java b/core/test/core/networking/connected/testClientServerAttributes.java index 50795a20..0c4ea29c 100644 --- a/core/test/core/networking/connected/testClientServerAttributes.java +++ b/core/test/core/networking/connected/testClientServerAttributes.java @@ -237,7 +237,7 @@ public void testAnimationStateUpdate() Entity serverEntity = serverGameController.createEntity(CommonFactory.createCoordinates(1, 1)); AnimationStateWrapper animationStateWrapper = - new AnimationStateWrapper(AnimationState.ATTACKING); + new AnimationStateWrapper(AnimationState.PUNCH_LEFT); serverGameController.updateEntityAttribute(serverEntity.getUuid(), animationStateWrapper); @@ -256,7 +256,7 @@ public void testAnimationStateUpdate() assert clientEntity .getAnimationStateWrapper() .getAnimationState() - .equals(AnimationState.ATTACKING); + .equals(AnimationState.PUNCH_LEFT); AnimationStateWrapper animationStateWrapper2 = new AnimationStateWrapper(AnimationState.FALLING); diff --git a/core/test/core/networking/translation/TranslateUpdateEntityEvent.java b/core/test/core/networking/translation/TranslateUpdateEntityEvent.java index 5b1ad600..13081486 100644 --- a/core/test/core/networking/translation/TranslateUpdateEntityEvent.java +++ b/core/test/core/networking/translation/TranslateUpdateEntityEvent.java @@ -152,7 +152,7 @@ public void testTranslateUpdateEntityAnimationStateWrapper() throws Serializatio Entity entity = entityFactory.createEntity(CommonFactory.createCoordinates(0, 0)); AnimationStateWrapper animationStateWrapper = - new AnimationStateWrapper(AnimationState.ATTACKING); + new AnimationStateWrapper(AnimationState.PUNCH_LEFT); UpdateEntityOutgoingEventType outgoing = EventTypeFactory.createUpdateEntityOutgoingEvent( diff --git a/docs/design/EntityStateMap.drawio b/docs/design/EntityStateMap.drawio new file mode 100644 index 00000000..9b67905b --- /dev/null +++ b/docs/design/EntityStateMap.drawio @@ -0,0 +1 @@ +7Vpdb+o4EP01SPc+dEU+gcdC27sfsOoulXb3aeUmhnjrxFlnUqC//o4ThxASIL1tSitVqtR4PE7sc47HMwk9axKuv0kSBzPhU94z+/66Z131TNOwbBP/KcsmtwyHg9ywlMzXTqVhzp6oNva1NWU+TSqOIAQHFleNnogi6kHFRqQUq6rbQvDqU2OypDXD3CO8bv2L+RDoVTj90v4zZcugeLLR1z0hKZy1IQmIL1Y7Juu6Z02kEJBfhesJ5Qq8Apd83M2B3u3EJI2gzYCnqUi9BG6pnN260TDxH34zLoyhnhxsihVTHwHQTSEhEEsREX5dWsdSpJFP1W372Cp9pkLEaDTQ+B8F2Gg2SQoCTQGEXPfijOXmbzX+J6do/qNvlzWu1pXWRrfqS9YoJCKVHj2yTkdLh8glhSN+o9xPYbDzAA3oNypCivNBB0k5AfZYFQnRWltu/Uo68EIz8gx29KwfCU/1k64jYAgsEKAz4gUsoj3T7ZmWUcKzQ2WyYiEnkeJsISIoWFUUEM6WEV57CCWVaHikEhjq/lJ3gOJyjI/g/pRsRKpQS4B4D0VrHAjJnvC2pKAVuyVo0nFWux5zNVKzKGmCPrcFi8aeaUbWFccpSUAbPME5iRN2v11GiISyaCwARHhKJGqFdH2UVt1rDvWe1UHLKqLRqgwBlq1twc72H7odKcGtKaFnjlXYU/xQ5OsSGzMSoxq44mYOkkXLnjmpC+Z3jNHotoQmxSBAkDEpxQOdCC5QGleRyCXEON8zFSridAEHNZTExMPJTDOfK7u0/KmBUyaBYxc8i48B87MlYZzBaZOcbMVsLFgEGbLOGP8Q/4kKIA5OfIJto2zjn3KXMBERroWwTAoUlbSiCTSK5OgGPK0crRTTbScUsyuhDBqEsscxZxl3OcfFoWb8EMEhUpUdCZrRu+wAuDBqrFt11q0Ghjm5p/xWJAyYUPeXue8e86fIraqXRQGVrEvSHbNldOiI8+GB4EAAaBjDnSRRjuiXPCx8/dz2r6wAt+X50Nm2N0Y1Tl+epZ1MBH88Hxu1zMcM510lZNtc/k3T5TeA2X1XMI9a5L06jfnMfV8597UG1dzXceqxzXAbYpth9bsKboNz7DovlY/Z+OYteEy4J/dlUU+8fT2aDb2Ukmx2HPQJW975VhlKTVzYe/XQaJfTk+4Xtn3Uf3jUHS/y+ZYC2i78BZrqH0iaFoyqV0SqnoJNTD9TpVaKf1GF1BhOukuVjAbmP0ukZ5VIz2a9oURqZL2rEskwD2x3ZIpfRiwkWX30Nd/4jwJvtptbbD29uttnfHhVpTSUUo1KGXSWbVg1qcC2gk6KF2z38uA7tDaZe/t8zHarp6NtNwBkNADkdAWQ6ZwjHTsI5elky26ZbL2vWrOYdq0K6lhwzl6uV8Tks+nNOPQZZBu3O0bEHe2VRGffgkb9e4CGxDsDHm5Tifi2Ick6R0jySRIcqRDbxqftd+2P9XHSrOfRvyCeCxYRqJdNr6vAvYrRGZ1dgPZHFqD5MQVYz+nvWEjrKXmn2nOHb6g9N0qnmzD991f6vzV5+gNmwf39RX0f6rMA1IvH4kTYT1u/4FYlKRrNm2QlJKJ2EzPvgaxp/fNQVairgAGdYwGieleSxE2JWg3PBtQPHzBmFeNBE8ZN31fc52OMzfI3OPnbpfKXTNb1dw== \ No newline at end of file diff --git a/docs/pivot/punch.piv b/docs/pivot/punch.piv new file mode 100644 index 00000000..c34cc19b Binary files /dev/null and b/docs/pivot/punch.piv differ