package ru.vagrant_ai.questionmarkgame.obj;
import java.util.Random;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.Input;
import org.newdawn.slick.geom.Point;
import org.newdawn.slick.geom.Rectangle;
import ru.vagrant_ai.questionmarkgame.main.Game;
import ru.vagrant_ai.questionmarkgame.main.GameplayState;
import ru.vagrant_ai.questionmarkgame.util.Particle;
import ru.vagrant_ai.questionmarkgame.util.Util;
import ru.vagrant_ai.questionmarkgame.util.list.ITEM;
import ru.vagrant_ai.questionmarkgame.util.list.PS;
import ru.vagrant_ai.questionmarkgame.util.list.PT;
public class Player {
private Image pl_idle;
private Image pl_jump;
private Image pl_walk;
private Image pl_fall;
private Image pl_hand_pocket;
private Image pl_hand_full;
public PS state;
public Rectangle hitbox = new Rectangle(0,0,0,0);
public Point pl_center = new Point(0,0);
public Gun gun;
public byte width = 25;
public byte height = 45;
public Player()
{
pl_idle = Util.loadImage("player/player_idle.png");
pl_jump = Util.loadImage("player/player_jump.png");
pl_walk = Util.loadImage("player/player_walk.png");
pl_fall = Util.loadImage("player/player_fall.png");
pl_hand_pocket = Util.loadImage("player/hand_pocket.png");
pl_hand_full = Util.loadImage("player/hand_full.png");
state = PS.IDLE;
money = 0;
bunker_opened = false;
ramp_opened = false;
}
public void render(Graphics g)
{
if (!util_facing) gun.render(g);
hitbox.setBounds(pl_x, pl_y, width, height);
switch(state)
{
case IDLE:
if (util_facing == false)
{
pl_idle.getFlippedCopy(true, false).draw((int)pl_x, (int)pl_y);
pl_hand_pocket.draw((int)pl_x+12, (int)pl_y+11);
}
else pl_idle.draw((int)pl_x, (int)pl_y);
break;
case JUMPING:
if (util_facing == false)
{
pl_jump.getFlippedCopy(true, false).draw((int)pl_x, (int)pl_y);
pl_hand_pocket.draw((int)pl_x+12, (int)pl_y+11);
}
else pl_jump.draw((int)pl_x, (int)pl_y);
break;
case FALLING:
if (util_facing == false)
{
pl_fall.getFlippedCopy(true, false).draw((int)pl_x, (int)pl_y);
pl_hand_full.getFlippedCopy(true, false).draw((int)pl_x+11, (int)pl_y+11);
}
else
pl_fall.draw((int)pl_x, (int)pl_y);
break;
case WALKING:
if (util_walking_state)
{
if (util_facing == false)
{
pl_walk.getFlippedCopy(true, false).draw((int)pl_x, (int)pl_y);
pl_hand_pocket.draw((int)pl_x+12, (int)pl_y+11);
}
else pl_walk.draw((int)pl_x, (int)pl_y);
}
else
{
if (util_facing == false)
{
pl_idle.getFlippedCopy(true, false).draw((int)pl_x, (int)pl_y);
pl_hand_pocket.draw((int)pl_x+12, (int)pl_y+11);
}
else pl_idle.draw((int)pl_x, (int)pl_y);
}
default:
break;
}
if (util_facing) gun.render(g);
}
public void update(GameContainer gc)
{
update_player_movements(); //left, right, jump, etc
update_player_force(); //gravity force
update_player_state(); //for render needs
update_player_facing(); // -//-
update_player_bonus(); //check for different bonus interactions
gun.update(gc);
}
private float util_iter_fall = 0;
boolean util_x_movement_lock = false;
private short util_impulse_length = 0; //impulse time
private float util_impulse_sub = 0f; //impulse subtraction per iter
private float util_impulse_current = 0f; //impulse height per iter
private short util_opt_invisible = 0;
private byte util_jump_quantity = 1;
private short util_jump_quantity_cooldown = 0;
public boolean util_facing = true; //true for right, false for left
private short money;
public boolean bunker_opened;
public boolean ramp_opened;
public boolean util_thorny = false;
public boolean util_poison_cloud = false;
public short pl_ground_level = GameplayState.ground_level;
float pl_x = 446;
float pl_y = pl_ground_level;
private float pl_speed = 3;
private short pl_jump_impulse = 120;
private short pl_jump_length = 20;
public byte pl_jump_quantity = 1;
private byte pl_jump_quantity_cooldown = 15;
/* MOVEMENTS */
private void update_player_movements()
{
util_x = pl_x;
Input input = Game.app.getInput();
update_player_movement_moveleft(input);
update_player_movement_moveright(input);
update_player_movement_jump(input);
update_player_movement_fall(input);
}
private void update_player_movement_moveleft(Input input)
{
if ((input.isKeyDown(Input.KEY_A) || input.isKeyDown(Input.KEY_LEFT)) && !util_x_movement_lock)
pl_x -= pl_speed;
}
private void update_player_movement_moveright(Input input)
{
if ((input.isKeyDown(Input.KEY_D) || input.isKeyDown(Input.KEY_RIGHT)) && !util_x_movement_lock)
pl_x += pl_speed;
}
private void update_player_movement_jump(Input input)
{
if (input.isKeyDown(Input.KEY_W) || input.isKeyDown(Input.KEY_UP) || input.isKeyDown(Input.KEY_SPACE)) //if jump key is down
if (
(input.isKeyPressed(Input.KEY_W) || input.isKeyPressed(Input.KEY_UP)) //if key was just pressed (to avoid insta-doublejump)
&& (util_jump_quantity > 0 && util_jump_quantity_cooldown == 0) //if player got doublejump
&& pl_ground_level != GameplayState.room_level //if player not in room
)
{
addYImpulse(pl_jump_impulse+Elements.extractLevel(ITEM.P_UPG_FREE_JUMP_LOW)*13, pl_jump_length);
util_jump_quantity--;
util_jump_quantity_cooldown = pl_jump_quantity_cooldown;
}
else if (pl_ground_level == GameplayState.room_level && pl_x >= 175 && pl_x <= 200) //if jumping away from room
{
addYImpulse(pl_jump_impulse*2, 20);
pl_ground_level = GameplayState.ground_level;
util_x_movement_lock = true;
}
}
private void update_player_movement_fall(Input input)
{
if (input.isKeyDown(Input.KEY_S) || input.isKeyDown(Input.KEY_DOWN))
{
if (pl_x >= 175 && pl_x <= 200 && pl_y == GameplayState.ground_level
&& bunker_opened)
{
pl_ground_level = GameplayState.room_level;
util_x_movement_lock = true; //lock player movements, while falling
}
else if (pl_y == GameplayState.ramp_level)
{
pl_y++;
pl_ground_level = GameplayState.ground_level;
}
}
}
boolean util_pressed = false;
/* FORCE */
private void update_player_force()
{
update_player_force_fall();
update_player_force_collision();
update_player_force_state();
}
private void update_player_force_fall() //JUMPING FORMULA HERE
{
if (util_impulse_length > 0 && util_impulse_current > 0) //if jumping
{
util_iter_fall = 0;
pl_y -= util_impulse_current;
util_impulse_current -= util_impulse_sub;
util_impulse_length--;
util_jump_quantity_cooldown--;
if (util_jump_quantity_cooldown < 1) util_jump_quantity_cooldown = 0;
if (util_impulse_length == 1)
{
util_iter_fall++;
util_impulse_length = 0;
util_impulse_current = 0;
}
}
else //if falling
{
util_iter_fall++;
pl_y += util_iter_fall/pl_speed;
if (pl_x > 217 && pl_x < 352 && pl_y < GameplayState.ramp_level && ramp_opened)
{
pl_ground_level = GameplayState.ramp_level;
}
if (pl_y >= pl_ground_level) //checking, if player reached ground level
{
pl_y = pl_ground_level;
util_iter_fall = 0;
util_jump_quantity = pl_jump_quantity;
util_jump_quantity_cooldown = 0;
}
if (util_x_movement_lock && (
(pl_y <= pl_ground_level && pl_ground_level == GameplayState.ground_level) //when jumping out of
||
(pl_y >= pl_ground_level && pl_ground_level == GameplayState.room_level) //when falling in
)) //the room and if player satisfies that ground level, then player could now move left and right
{
util_x_movement_lock = false;
}
if (util_impulse_current > 0) util_iter_fall = 0;
}
}
private void update_player_force_collision()
{
if (pl_y < 8) pl_y = 8; //if player wants to jump to the sky (+hpbar height)
if (pl_x < 0 && pl_ground_level == GameplayState.ground_level) pl_x = 0;
if (pl_x > Game.getAppX()-width && pl_ground_level == GameplayState.ground_level) pl_x = Game.getAppX()-width;
if (pl_x < 123 && pl_ground_level == GameplayState.room_level) pl_x = 123;
if (pl_x > 259 && pl_ground_level == GameplayState.room_level) pl_x = 259;
if ((pl_x < 217 || pl_x > 352) && pl_ground_level == GameplayState.ramp_level) pl_ground_level = GameplayState.ground_level; //check if player falling off the ramp
}
private void update_player_force_state()
{
if (util_opt_invisible > 0) util_opt_invisible--;
}
/* PLAYER STATE */
float util_x = pl_x;
byte util_movement_iter = 0;
boolean util_walking_state = false;
private void update_player_state()
{
if (util_x != pl_x)
{
if (util_movement_iter == 0) util_movement_iter = 11;
else util_movement_iter++;
}
else if (util_x == pl_x)
{
util_movement_iter = 0;
util_walking_state = false;
}
state = PS.IDLE;
if (util_impulse_length != 0) state = PS.JUMPING;
if (util_iter_fall != 0 && util_impulse_length == 0) state = PS.FALLING;
else if (util_movement_iter > 1 && util_impulse_length == 0)
{
state = PS.WALKING;
if (util_movement_iter > 10)
{
util_movement_iter = 1;
util_walking_state ^= true; //invert
}
}
}
/* PLAYER FACING */
private void update_player_facing()
{
pl_center.setLocation(pl_x + (float)width/2, pl_y + (float)height/2);
Input input = Game.app.getInput();
if (input.isKeyDown(Input.KEY_D) || input.isKeyDown(Input.KEY_RIGHT))
util_facing = true;
else if (input.isKeyDown(Input.KEY_A) || input.isKeyDown(Input.KEY_LEFT))
util_facing = false;
}
/* PLAYER BONUS */
private int util_bonus_delay = 0;
private int util_thorns[] = {0,0}; //thorn particle duration
private int util_ramp = 400;
private void performHurtBonus()
{
if (util_thorny)
{
util_thorns[0] = 5;
util_thorns[1] = 1;
}
if (util_poison_cloud)
Particle.addNew(PT.POISON_CLOUD, (int) pl_center.getX(), (int) pl_center.getY());
util_bonus_delay = 60;
addInvisible(30);
Elements.addKnockback(pl_center.getX(), pl_center.getY(), 2, 3, (int)pl_center.getX(), (byte) 80);
}
private void update_player_bonus()
{
if (util_bonus_delay > 0) util_bonus_delay--; //Thorny bonus
if (util_thorns[0] > 0)
{
util_thorns[1]--;
if (util_thorns[1] < 0)
{
util_thorns[0]--;
util_thorns[1] = 1;
for (int i = 0; i < new Random().nextInt(8)+12; i++)
Particle.addNew(PT.THORN, (int)pl_center.getX(), (int)pl_center.getY());
}
}
if (pl_ground_level == GameplayState.ramp_level) //Ramp standing delay
{
util_ramp--;
if (util_ramp < 60+Elements.extractLevel(ITEM.P_UPG_RAMP)*10)
GameplayState.background.shakeRamp();
if (util_ramp < 1)
pl_ground_level = GameplayState.ground_level;
}
else if (ramp_opened)
{
util_ramp++;
if (util_ramp > 400+Elements.extractLevel(ITEM.P_UPG_RAMP)*50)
util_ramp = 400+Elements.extractLevel(ITEM.P_UPG_RAMP)*50;
}
}
/* UTIL */
private void addYImpulse(float impulse, int power)
{
util_impulse_length = (short) power;
util_impulse_sub = (2 * impulse / power - 2) / (power - 1);
util_impulse_current = util_impulse_sub * (power - 1);
}
private void addInvisible(int frames)
{
util_opt_invisible = (short) frames;
}
public void addDamage(short damage)
{
if (util_opt_invisible > 0) return;
GameplayState.hp.util_regen = 30;
short hp = GameplayState.hp.hp;
if (hp > 0 && damage > 0)
{
GameplayState.hp.setHP((short) (hp-damage));
Particle.addNew(PT.HPDOWN, damage);
addInvisible(8);
if ((util_thorny || util_poison_cloud) && util_bonus_delay == 0)
performHurtBonus();
}
}
public void heal(short heal_amt) {
short hp = GameplayState.hp.getHP();
short hp_max = GameplayState.hp.getHPMax();
if (hp >= hp_max)
{
if (hp > hp_max) GameplayState.hp.hp = GameplayState.hp.hp_max;
return;
}
if (hp+heal_amt >= hp_max) {
heal_amt = (short) (hp_max-hp);
if (heal_amt < 1) return;
}
GameplayState.hp.setHP((short) (hp+heal_amt));
Particle.addNew(PT.HPUP, heal_amt);
}
public float getX()
{
return pl_x;
}
public float getY()
{
return pl_y;
}
public float getWidth()
{
return width;
}
public float getHeight()
{
return height;
}
public void addMoney(int arg)
{
money += arg;
if (money < 0)
money = 0;
}
public int getMoney()
{
return money;
}
}