for (Iterator<Mob> it = mMobsController.getMobs().iterator(); it.hasNext(); ) {
Mob mob = it.next();
- mob.ai(mGameWorld, mGameItemsHolder, delta);
+ mob.ai(mGameWorld, mGameItemsHolder, mMobsController, delta);
mobPhy(mob, delta);
if (mob.isDead()) {
it.remove();
}
playerPhy(player, delta);
- player.ai(mGameWorld, mGameItemsHolder, delta);
+ player.ai(mGameWorld, mGameItemsHolder, mMobsController, delta);
if (player.isDead()) {
player.respawn(mGameWorld, mGameItemsHolder);
}
package ru.deadsoftware.cavedroid.game.actions.useitem
+import ru.deadsoftware.cavedroid.game.GameItemsHolder
import ru.deadsoftware.cavedroid.game.GameScope
import ru.deadsoftware.cavedroid.game.mobs.MobsController
import ru.deadsoftware.cavedroid.game.mobs.Pig
@GameScope
class UsePigSpawnEggAction @Inject constructor(
private val mobsController: MobsController,
+ private val gameItemsHolder: GameItemsHolder,
) : IUseItemAction {
override fun perform(item: Item.Usable, x: Int, y: Int) {
attachToController(mobsController)
}
- mobsController.player.inventory.decreaseCurrentItemAmount()
+ mobsController.player.decreaseCurrentItemCount(gameItemsHolder)
}
companion object {
}
@Override
- public void ai(GameWorld gameWorld, GameItemsHolder gameItemsHolder, float delta) {
+ public void ai(GameWorld gameWorld, GameItemsHolder gameItemsHolder, MobsController mobsController, float delta) {
if (mVelocity.isZero()) {
gameWorld.setForeMap(getMapX(), getUpperMapY(), gameItemsHolder.getBlock("gravel"));
kill();
public void changeDir() {
}
+ @Override
+ public void damage(int damage) {
+ // no-op
+ }
+
@Override
public void draw(SpriteBatch spriteBatch, float x, float y, float delta) {
@CheckForNull final Texture texture = Assets.blockTextures.get("gravel");
}
@Override
- public void ai(GameWorld gameWorld, GameItemsHolder gameItemsHolder, float delta) {
+ public void ai(GameWorld gameWorld, GameItemsHolder gameItemsHolder, MobsController mobsController, float delta) {
if (mVelocity.isZero()) {
gameWorld.setForeMap(getMapX(), getUpperMapY(), gameItemsHolder.getBlock("sand"));
kill();
public void changeDir() {
}
+ @Override
+ public void damage(int damage) {
+ // no-op
+ }
+
@Override
public void draw(SpriteBatch spriteBatch, float x, float y, float delta) {
@CheckForNull final Texture texture = Assets.blockTextures.get("sand");
package ru.deadsoftware.cavedroid.game.mobs;
import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
+import com.badlogic.gdx.utils.Timer;
import ru.deadsoftware.cavedroid.game.GameItemsHolder;
import ru.deadsoftware.cavedroid.game.world.GameWorld;
+import javax.annotation.CheckForNull;
import java.io.Serializable;
/**
*/
public abstract class Mob extends Rectangle implements Serializable {
+ private static final float DAMAGE_TINT_TIMEOUT_S = 0.5f;
+ private static final Color DAMAGE_TINT_COLOR = new Color(0xff8080ff);
+
+ private static final float HIT_RANGE = 8f;
+
protected static int ANIMATION_SPEED = 360;
public enum Type {
}
}
+ private class ResetTakeDamageTask extends Timer.Task {
+
+ @Override
+ public void run() {
+ mTakingDamage = false;
+ }
+ }
+
protected Vector2 mVelocity;
protected Type mType;
protected int mAnimDelta = ANIMATION_SPEED;
private final int mMaxHealth;
private int mHealth;
+ private transient boolean mTakingDamage = false;
+ @CheckForNull private transient ResetTakeDamageTask mResetTakeDamageTask = null;
+
/**
* @param x in pixels
* @param y in pixels
mHealth -= damage;
checkHealth();
+
+ setTakingDamage(true);
}
public void heal(int heal) {
checkHealth();
}
+ public Rectangle getHitBox() {
+ return new Rectangle(x - HIT_RANGE, y - HIT_RANGE, width + HIT_RANGE, height + HIT_RANGE);
+ }
+
+ public boolean isTakingDamage() {
+ return mTakingDamage;
+ }
+
+ public void setTakingDamage(boolean takingDamage) {
+ mTakingDamage = takingDamage;
+
+ if (takingDamage) {
+ if (mResetTakeDamageTask != null && mResetTakeDamageTask.isScheduled()) {
+ mResetTakeDamageTask.cancel();
+ } else if (mResetTakeDamageTask == null) {
+ mResetTakeDamageTask = new ResetTakeDamageTask();
+ }
+
+ Timer.schedule(mResetTakeDamageTask, DAMAGE_TINT_TIMEOUT_S);
+ }
+ }
+
+ protected Color getTintColor() {
+ return isTakingDamage() ? DAMAGE_TINT_COLOR : Color.WHITE;
+ }
+
public abstract void draw(SpriteBatch spriteBatch, float x, float y, float delta);
- public abstract void ai(GameWorld gameWorld, GameItemsHolder gameItemsHolder, float delta);
+ public abstract void ai(GameWorld gameWorld, GameItemsHolder gameItemsHolder, MobsController mobsController, float delta);
public abstract void changeDir();
override fun jump() {
velocity.y = JUMP_VELOCITY
}
-
- override fun ai(world: GameWorld, gameItemsHolder: GameItemsHolder, delta: Float) {
+
+ override fun damage(damage: Int) {
+ super.damage(damage)
+
+ if (damage > 0) {
+ if (canJump()) {
+ jump()
+ }
+ }
+ }
+
+ override fun ai(world: GameWorld, gameItemsHolder: GameItemsHolder, mobsController: MobsController, delta: Float) {
if (MathUtils.randomBoolean(delta)) {
if (velocity.x != 0f) {
velocity.x = 0f
val rightLegX = x + getRightLegRelativeX(direction)
val legY = y + getLegsRelativeY()
- spriteBatch.drawSprite(getBackgroundLeg(), leftLegX, legY, -anim)
- spriteBatch.drawSprite(getBackgroundLeg(), rightLegX, legY, -anim)
- spriteBatch.drawSprite(getBody(direction), x, y)
- spriteBatch.drawSprite(getForegroundLeg(), leftLegX, legY, anim)
- spriteBatch.drawSprite(getForegroundLeg(), rightLegX, legY, anim)
+ spriteBatch.drawSprite(getBackgroundLeg(), leftLegX, legY, -anim, tint = tintColor)
+ spriteBatch.drawSprite(getBackgroundLeg(), rightLegX, legY, -anim, tint = tintColor)
+ spriteBatch.drawSprite(getBody(direction), x, y, tint = tintColor)
+ spriteBatch.drawSprite(getForegroundLeg(), leftLegX, legY, anim, tint = tintColor)
+ spriteBatch.drawSprite(getForegroundLeg(), rightLegX, legY, anim, tint = tintColor)
}
private companion object {
private const val WIDTH = 25f
private const val HEIGHT = 18f
- private const val SPEED = 69.072f
+ private const val SPEED = 48f
private const val JUMP_VELOCITY = -133.332f
- private const val MAX_HEALTH = 10;
+ private const val MAX_HEALTH = 10
}
}
\ No newline at end of file
import com.badlogic.gdx.math.Vector2;
import ru.deadsoftware.cavedroid.game.GameItemsHolder;
import ru.deadsoftware.cavedroid.game.mobs.Mob;
+import ru.deadsoftware.cavedroid.game.mobs.MobsController;
import ru.deadsoftware.cavedroid.game.model.block.Block;
import ru.deadsoftware.cavedroid.game.model.item.InventoryItem;
import ru.deadsoftware.cavedroid.game.model.item.Item;
return !block.isNone() && block.getParams().getHitPoints() >= 0;
}
+ /**
+ * @return true if any mob fas hit
+ */
+ private boolean hitMobs(GameItemsHolder gameItemsHolder, MobsController mobsController) {
+ if (!hitting || !hittingWithDamage) {
+ return false;
+ }
+
+ boolean result = false;
+ for (Mob mob : mobsController.getMobs()) {
+ if (overlaps(mob.getHitBox())) {
+ final Item activeItem = inventory.getActiveItem().getItem();
+ final Item.Tool tool = activeItem.isTool() ? (Item.Tool) activeItem : null;
+ if (tool != null) {
+ decreaseCurrentItemCount(gameItemsHolder);
+ }
+ result = true;
+ mob.damage(MathUtils.floor(tool != null ? tool.getMobDamageMultiplier() : 1));
+ }
+ }
+ return result;
+ }
+
private void hitBlock(GameWorld gameWorld, GameItemsHolder gameItemsHolder) {
if (!hitting || !hittingWithDamage) {
return;
}
@Override
- public void ai(GameWorld gameWorld, GameItemsHolder gameItemsHolder, float delta) {
+ public void ai(GameWorld gameWorld, GameItemsHolder gameItemsHolder, MobsController mobsController, float delta) {
updateAnimation(delta);
- hitBlock(gameWorld, gameItemsHolder);
+
+ if (!hitMobs(gameItemsHolder, mobsController)) {
+ hitBlock(gameWorld, gameItemsHolder);
+ } else {
+ stopHitting();
+ }
if (gameMode == 1) {
return;
frontHandAnim = -rightHandAnim;
}
+ backHand.setColor(getTintColor());
+ backLeg.setColor(getTintColor());
+ frontLeg.setColor(getTintColor());
+ head.setColor(getTintColor());
+ body.setColor(getTintColor());
+ frontHand.setColor(getTintColor());
+
SpriteUtilsKt.drawSprite(spriteBatch, backHand, x + 2, y + 8, backHandAnim);
if (looksLeft()) {
package ru.deadsoftware.cavedroid.game.world;
+import com.badlogic.gdx.math.MathUtils;
import kotlin.Pair;
import ru.deadsoftware.cavedroid.game.GameItemsHolder;
import ru.deadsoftware.cavedroid.game.GameScope;
import ru.deadsoftware.cavedroid.game.mobs.MobsController;
+import ru.deadsoftware.cavedroid.game.mobs.Pig;
import ru.deadsoftware.cavedroid.game.model.block.Block;
import ru.deadsoftware.cavedroid.game.model.item.InventoryItem;
import ru.deadsoftware.cavedroid.game.model.item.Item;
Pair<Block[][], Block[][]> maps = new GameWorldGenerator(mWorldConfig, mGameItemsHolder).generate();
mForeMap = maps.getFirst();
mBackMap = maps.getSecond();
+ spawnInitialMobs();
mMobsController.getPlayer().respawn(this, mGameItemsHolder);
} else {
mForeMap = foreMap;
return toolLevel >= block.getParams().getToolLevel();
}
+ private void spawnInitialMobs() {
+ for (int x = 0; x < getWidth(); x++) {
+ int y = 0;
+ while (y < getWorldConfig().getSeaLevel()) {
+ if (getForeMap(x, y) == mGameItemsHolder.getBlock("grass")) {
+ if (MathUtils.randomBoolean(.125f)) {
+ mMobsController.addMob(new Pig(MeasureUnitsUtilsKt.getPx(x), MeasureUnitsUtilsKt.getPx(y)));
+ }
+ break;
+ }
+ y++;
+ }
+ }
+ }
+
public void destroyForeMap(int x, int y) {
Block block = getForeMap(x, y);
if (block.isContainer()) {
- mContainerController.destroyContainer(x, y, FOREGROUND_Z);
+ mContainerController.destroyContainer(x, y, FOREGROUND_Z, true);
}
if (block.hasDrop() && shouldDrop(block)) {
for (int i = 0; i < block.getParams().getDropInfo().getCount(); i++) {
public void destroyBackMap(int x, int y) {
Block block = getBackMap(x, y);
+ if (block.isContainer()) {
+ mContainerController.destroyContainer(x, y, BACKGROUND_Z, true);
+ }
if (block.hasDrop() && shouldDrop(block)) {
for (int i = 0; i < block.getParams().getDropInfo().getCount(); i++) {
mDropController.addDrop(transformX(x) * 16 + 4, y * 16 + 4, mGameItemsHolder.getItem(block.getDrop()));
val foregroundBlock = gameWorld.getForeMap(x, y)
val backgroundBlock = gameWorld.getBackMap(x, y)
- mob.damage(max(foregroundBlock.params.damage, backgroundBlock.params.damage))
+ val damage = max(foregroundBlock.params.damage, backgroundBlock.params.damage)
+ if (damage > 0) {
+ mob.damage(damage)
+ }
}
}
package ru.deadsoftware.cavedroid.misc.utils
+import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.g2d.Sprite
import com.badlogic.gdx.graphics.g2d.SpriteBatch
rotation: Float = 0f,
width: Float = sprite.regionWidth.toFloat(),
height: Float = sprite.regionHeight.toFloat(),
+ tint: Color? = null,
) {
+ val oldColor = sprite.color
+
sprite.setPosition(x, y)
sprite.setSize(width, height)
sprite.rotation = rotation
+ tint?.let(sprite::setColor)
+
sprite.draw(this)
sprite.setSize(sprite.regionWidth.toFloat(), sprite.regionHeight.toFloat())
sprite.rotation = 0f
+ sprite.color = oldColor
}
fun Sprite.applyOrigin(origin: SpriteOrigin) {