DEADSOFTWARE

Add tooltips
[cavedroid.git] / core / src / ru / deadsoftware / cavedroid / game / mobs / player / Player.java
1 package ru.deadsoftware.cavedroid.game.mobs.player;
3 import com.badlogic.gdx.graphics.g2d.Sprite;
4 import com.badlogic.gdx.graphics.g2d.SpriteBatch;
5 import com.badlogic.gdx.math.MathUtils;
6 import com.badlogic.gdx.math.Vector2;
7 import ru.deadsoftware.cavedroid.game.GameItemsHolder;
8 import ru.deadsoftware.cavedroid.game.mobs.Mob;
9 import ru.deadsoftware.cavedroid.game.model.block.Block;
10 import ru.deadsoftware.cavedroid.game.model.item.InventoryItem;
11 import ru.deadsoftware.cavedroid.game.model.item.Item;
12 import ru.deadsoftware.cavedroid.game.objects.Drop;
13 import ru.deadsoftware.cavedroid.game.ui.TooltipManager;
14 import ru.deadsoftware.cavedroid.game.world.GameWorld;
15 import ru.deadsoftware.cavedroid.misc.Assets;
16 import ru.deadsoftware.cavedroid.misc.utils.SpriteOrigin;
17 import ru.deadsoftware.cavedroid.misc.utils.SpriteUtilsKt;
19 import javax.annotation.CheckForNull;
21 public class Player extends Mob {
23 private static final float SPEED = 69.072f;
24 private static final float JUMP_VELOCITY = -133.332f;
26 public static final int MAX_HEALTH = 20;
27 public static final int INVENTORY_SIZE = 36;
28 public static final int HOTBAR_SIZE = 9;
30 private boolean hitting = false, hittingWithDamage = false;
31 private float hitAnim = 0f;
32 private float hitAnimDelta = ANIMATION_SPEED;
34 public final Inventory inventory;
36 public int gameMode;
37 public boolean swim;
38 public float headRotation = 0f;
40 public float blockDamage = 0f;
41 public int cursorX = 0;
42 public int cursorY = 0;
44 @CheckForNull
45 private Vector2 spawnPoint = null;
47 public ControlMode controlMode = ControlMode.WALK;
49 public enum ControlMode {
50 WALK,
51 CURSOR
52 }
54 public Player(GameItemsHolder gameItemsHolder, TooltipManager tooltipManager) {
55 super(0, 0, 4, 30, randomDir(), Type.MOB, MAX_HEALTH);
56 inventory = new Inventory(INVENTORY_SIZE, HOTBAR_SIZE, gameItemsHolder, tooltipManager);
57 swim = false;
58 }
60 public void initInventory(GameItemsHolder gameItemsHolder, TooltipManager tooltipManager) {
61 inventory.initItems(gameItemsHolder, tooltipManager);
62 }
64 public void respawn(GameWorld gameWorld, GameItemsHolder itemsHolder) {
65 Vector2 pos = getSpawnPoint(gameWorld, itemsHolder);
66 this.x = pos.x;
67 this.y = pos.y;
68 mVelocity.setZero();
69 mDead = false;
70 heal(MAX_HEALTH);
71 }
73 public void decreaseCurrentItemCount(GameItemsHolder gameItemsHolder) {
74 if (gameMode == 1) {
75 return;
76 }
78 final InventoryItem item = inventory.getActiveItem();
79 item.subtract();
80 if (item.getAmount() <= 0) {
81 setCurrentInventorySlotItem(gameItemsHolder.getFallbackItem());
82 }
83 }
85 private Vector2 getSpawnPoint(GameWorld gameWorld, GameItemsHolder itemsHolder) {
86 if (spawnPoint != null) {
87 return spawnPoint;
88 }
90 int y, x = gameWorld.getWidth() / 2;
91 for (y = 0; y <= gameWorld.getWorldConfig().getSeaLevel(); y++) {
92 if (y == gameWorld.getWorldConfig().getSeaLevel()) {
93 for (x = 0; x < gameWorld.getWidth(); x++) {
94 if (gameWorld.getForeMap(x, y).getParams().getHasCollision()) {
95 break;
96 }
97 if (x == gameWorld.getWidth() - 1) {
98 gameWorld.setForeMap(x, y, itemsHolder.getBlock("grass"));
99 break;
102 break;
104 if (gameWorld.hasForeAt(x, y) && gameWorld.getForeMap(x, y).hasCollision()) {
105 break;
108 spawnPoint = new Vector2(x * 16 + 8 - getWidth() / 2, (float) y * 16 - getHeight());
109 return spawnPoint;
112 public void setDir(Direction dir) {
113 if (dir != getDirection()) {
114 switchDir();
118 public void setCurrentInventorySlotItem(Item item) {
119 inventory.getItems().set(inventory.getActiveSlot(), item.toInventoryItem());
122 @Override
123 public float getSpeed() {
124 return SPEED;
127 @Override
128 public void jump() {
129 mVelocity.y = JUMP_VELOCITY;
132 private boolean checkBlockCanBeHit(Block block) {
133 return !block.isNone() && block.getParams().getHitPoints() >= 0;
136 private void hitBlock(GameWorld gameWorld, GameItemsHolder gameItemsHolder) {
137 if (!hitting || !hittingWithDamage) {
138 return;
141 final Block foregroundBlock = gameWorld.getForeMap(cursorX, cursorY);
142 final Block backgroundBlock = gameWorld.getBackMap(cursorX, cursorY);
145 if ((checkBlockCanBeHit(foregroundBlock)) ||
146 (foregroundBlock.isNone() && checkBlockCanBeHit(backgroundBlock))) {
147 if (gameMode == 0) {
148 if (!foregroundBlock.isNone()) {
149 if (blockDamage >= foregroundBlock.getParams().getHitPoints()) {
150 gameWorld.destroyForeMap(cursorX, cursorY);
151 blockDamage = 0;
153 } else if (!backgroundBlock.isNone()) {
154 if (blockDamage >= backgroundBlock.getParams().getHitPoints()) {
155 gameWorld.destroyBackMap(cursorX, cursorY);
156 blockDamage = 0;
159 } else {
160 if (!foregroundBlock.isNone()) {
161 gameWorld.placeToForeground(cursorX, cursorY, gameItemsHolder.getFallbackBlock());
162 } else if (!backgroundBlock.isNone()) {
163 gameWorld.placeToBackground(cursorX, cursorY, gameItemsHolder.getFallbackBlock());
165 stopHitting();
167 } else {
168 stopHitting();
172 @Override
173 public void ai(GameWorld gameWorld, GameItemsHolder gameItemsHolder, float delta) {
174 updateAnimation(delta);
175 hitBlock(gameWorld, gameItemsHolder);
177 if (gameMode == 1) {
178 return;
181 final Block foregroundBlock = gameWorld.getForeMap(cursorX, cursorY);
182 final Block backgroundBlock = gameWorld.getBackMap(cursorX, cursorY);
183 @CheckForNull final Block target;
185 if (checkBlockCanBeHit(foregroundBlock)) {
186 target = foregroundBlock;
187 } else if (checkBlockCanBeHit(backgroundBlock)) {
188 target = backgroundBlock;
189 } else {
190 target = null;
193 final boolean canHitBlock = target != null;
195 float multiplier = 1f;
196 final Item currentItem = inventory.getActiveItem().getItem();
197 if (currentItem instanceof Item.Tool && canHitBlock) {
198 if (target.getParams().getToolType() == currentItem.getClass()
199 && ((Item.Tool)currentItem).getLevel() >= target.getParams().getToolLevel()) {
200 multiplier = 2f * ((Item.Tool)currentItem).getLevel();
202 multiplier *= ((Item.Tool)currentItem).getBlockDamageMultiplier();
205 if (hitting && hittingWithDamage && canHitBlock) {
206 blockDamage += 60f * delta * multiplier;
207 } else {
208 blockDamage = 0f;
212 @Override
213 public void changeDir() {
216 @Override
217 public void damage(int damage) {
218 if (gameMode == 1) {
219 return;
222 if (damage > 0) {
223 getVelocity().y += JUMP_VELOCITY / 3f;
226 super.damage(damage);
229 @Override
230 public void heal(int heal) {
231 if (gameMode == 1) {
232 return;
234 super.heal(heal);
237 private void drawItem(SpriteBatch spriteBatch, float x, float y, float anim) {
238 final Item item = inventory.getActiveItem().getItem();
240 if (item == null || item.isNone()) {
241 return;
244 final Sprite sprite = item.getSprite();
245 final boolean smallSprite = !item.isTool() || item.isShears();
247 final float originalWidth = sprite.getWidth();
248 final float originalHeight = sprite.getHeight();
250 if (smallSprite) {
251 sprite.setSize(Drop.DROP_SIZE, Drop.DROP_SIZE);
254 final float handLength = Assets.playerSprite[0][2].getHeight();
256 final SpriteOrigin spriteOrigin = item.getParams().getInHandSpriteOrigin();
257 final int handMultiplier = -getDirection().getBasis();
258 final float xOffset = (-1 + getDirection().getIndex()) * sprite.getWidth() + 4 + handMultiplier * (sprite.getWidth() * spriteOrigin.getX());
259 final float yOffset = !smallSprite ? -sprite.getHeight() / 2 : 0;
261 float rotate = anim + 30;
263 if (item.isTool()) {
264 sprite.rotate90(looksLeft());
267 final float itemX = x + handLength * MathUtils.sin(handMultiplier * anim * MathUtils.degRad) + xOffset;
268 final float itemY = y + handLength * MathUtils.cos(handMultiplier * anim * MathUtils.degRad) + yOffset;
270 if (looksLeft()) {
271 sprite.setFlip(!item.isTool(), sprite.isFlipY());
272 SpriteUtilsKt.applyOrigin(sprite, spriteOrigin.getFlipped(true, false));
273 } else {
274 sprite.setFlip(item.isTool(), sprite.isFlipY());
275 SpriteUtilsKt.applyOrigin(sprite, spriteOrigin);
278 sprite.setRotation(-handMultiplier * rotate);
279 sprite.setPosition(itemX, itemY);
280 sprite.draw(spriteBatch);
282 // dont forget to reset
283 sprite.setFlip(false, sprite.isFlipY());
284 sprite.setRotation(0);
285 sprite.setOriginCenter();
286 sprite.setSize(originalWidth, originalHeight);
287 if (item.isTool()) {
288 sprite.rotate90(looksRight());
292 public void startHitting(boolean withDamage) {
293 if (hitting) {
294 return;
297 hitting = true;
298 hittingWithDamage = withDamage;
299 hitAnim = 90f;
300 hitAnimDelta = ANIMATION_SPEED;
303 public void startHitting() {
304 startHitting(true);
307 public void stopHitting() {
308 blockDamage = 0f;
309 hitting = false;
312 private float getRightHandAnim(float delta) {
313 hitAnim -= hitAnimDelta * delta;
315 if (hitAnim < 30f || hitAnim > 90f) {
316 if (hitting) {
317 hitAnim = MathUtils.clamp(hitAnim, 30f, 90f);
318 hitAnimDelta = -hitAnimDelta;
319 } else {
320 hitAnimDelta = ANIMATION_SPEED;
324 if (!hitting) {
325 if (hitAnim < hitAnimDelta * delta) {
326 hitAnim = 0;
327 hitAnimDelta = 0;
328 return -mAnim;
332 return hitAnim;
335 @Override
336 public void draw(SpriteBatch spriteBatch, float x, float y, float delta) {
337 final Sprite backHand = Assets.playerSprite[1][2];
338 final Sprite backLeg = Assets.playerSprite[1][3];
339 final Sprite frontLeg = Assets.playerSprite[0][3];
340 final Sprite head = Assets.playerSprite[getDirection().getIndex()][0];
341 final Sprite body = Assets.playerSprite[getDirection().getIndex()][1];
342 final Sprite frontHand = Assets.playerSprite[0][2];
344 float backHandAnim, frontHandAnim;
346 final float rightHandAnim = getRightHandAnim(delta);
348 if (looksLeft()) {
349 backHandAnim = rightHandAnim;
350 frontHandAnim = mAnim;
351 } else {
352 backHandAnim = -mAnim;
353 frontHandAnim = -rightHandAnim;
356 SpriteUtilsKt.drawSprite(spriteBatch, backHand, x + 2, y + 8, backHandAnim);
358 if (looksLeft()) {
359 drawItem(spriteBatch, x, y, -backHandAnim);
362 SpriteUtilsKt.drawSprite(spriteBatch, backLeg, x + 2, y + 20, mAnim);
363 SpriteUtilsKt.drawSprite(spriteBatch, frontLeg, x + 2, y + 20, -mAnim);
364 SpriteUtilsKt.drawSprite(spriteBatch, head, x, y, headRotation);
365 SpriteUtilsKt.drawSprite(spriteBatch, body, x + 2, y + 8);
367 if (looksRight()) {
368 drawItem(spriteBatch, x, y, frontHandAnim);
371 SpriteUtilsKt.drawSprite(spriteBatch, frontHand, x + 2, y + 8, frontHandAnim);