import javax.swing.*;
import java.awt.*;
class Hero extends Item{
public static final int NONE = 0, BORDER = 1, BUMPER = 2, FIGHT = 3;
public double dy,dx;
private double SPEED = 3;
private GWar world;
int jumps=0;
private int sparkindex=0;
private int sparkcounter=0;
private int tiedcount=0;
public double mass=1;
private boolean lacceleration;
private boolean racceleration;
private boolean onbumper = false;
private final static boolean DEBUG=false;
private double[] xspark = new double[5];
private double[] yspark = new double[5];
private int xflash;
private int yflash;
private boolean flashleft;
private int flashcount = 0;
private int lastPositionValue=-500, actionType, actionValue=-1;
public Hero(double x, double y, int r,GWar tp, java.awt.Color c,double mass){
super(x,y,r,c);
dy=0;
dx=0;
world=tp;
this.mass =mass;
SPEED=(3/mass);
actionType = NONE;
actionValue = -1;
}
private void addsparkle(){
for (int k = xspark.length-1;k>0;k--){
xspark[k]=xspark[k-1];
yspark[k]=yspark[k-1];
}
xspark[0]=x;
yspark[0]=y;
}
public void reset(){
actionType = NONE;
actionValue = -1;
lastPositionValue = -500;
}
public void update(){
flashcount--;
onbumper=onBumper();
if (tiedcount>0)
tiedcount --;
sparkcounter++;
if (sparkcounter>=3){
sparkcounter=0;
addsparkle();
}
if (onbumper){
//System.out.println("onbumper");
if (racceleration==lacceleration){
if(tiedcount==0)
dx=dx*.975;//friction?
}
else{
}
if(dy>=0)
jumps = 0;
if (Math.abs(dx) < .05)
dx=0;
}
if(tiedcount==0){
if(lacceleration&&dx>-SPEED)
dx -= 1;
if(racceleration&&dx<SPEED)
dx += 1;
}
if (checkVBumper()){
dy = Math.abs(dy);
}
else if (checkHBumper()){
dx = -dx;
}
lX = x;
lY = y;
y += dy;
x += dx;
onbumper=onBumper();
}
public double nearestBorder(Hero h){
double wL = h.x,wR = GWar.WIDTH-h.x;
double hT = h.y,hB = GWar.HEIGHT-h.y;
double min=wL;
if(wR < min)
{
min = wR;
}
if(hT < min)
{
min = hT;
}
if(hB < min)
{
min = hB;
}
return min;
}
public int getBorderValue(Hero h){
double minDist = nearestBorder(h);
if(minDist<40)
{
return -6;
}
else if(minDist<80)
{
return -3;
}
else if(minDist < 120)
{
return 3;
}
else
{
return 6;
}
}
public int getBumperValue(Hero h){
if(h.onBumper())
{
return 6;
}
else if(h.overBumper())
{
return 3;
}
else
{
return -6;
}
}
public int getPositionValue(Hero h){
int val = 0;
val+=getBorderValue(h);
val+=getBumperValue(h);
return val;
}
public int getProblem(Hero h){
int bord = getBorderValue(h);
int bump = getBumperValue(h);
if(bump<0)
{
return BUMPER;
}
if(bord<0)
{
return BORDER;
}
return NONE;
}
public void fixBorder(){
actionType = BORDER;
actionValue = -1;
}
public void fixBumper(){
actionType = BUMPER;
actionValue = -1;
}
public void setTarget(){
actionType = FIGHT;
actionValue = findNickTarget(this);
}
public void fixBumperProblem(){
if(actionValue == -1)
{
actionValue = nearestTargetBumper(0,0,this,false);
}
else
{
try
{
Bumper tar = world.bump[actionValue];
goToTarget(tar);
Bumper on = onWhatBumper();
if(on!=null && on.x == tar.x && on.y == tar.y)
{
stop();
actionType = NONE;
}
}
catch(ArrayIndexOutOfBoundsException e)
{
}
}
}
public void fixBorderProblem(){
if(actionValue == -1)
{
actionValue = nearestTargetBumper(GWar.WIDTH/2,GWar.HEIGHT/2,this,true);
}
else
{
try
{
Bumper tar = world.bump[actionValue];
goToTarget(tar);
Bumper on = onWhatBumper();
if(on!=null && on.x == tar.x && on.y == tar.y)
{
stop();
actionType = NONE;
}
}
catch(ArrayIndexOutOfBoundsException e)
{
System.out.println("Wrong index!");
}
}
}
public void goToTarget(Bumper b)
{
double cX = b.x + b.width/2, dif = cX-x;
if(dif > 3)
{
racceleration = true;
lacceleration = false;
}
else if(dif < -3)
{
lacceleration = true;
racceleration = false;
}
if(b.y < y && dy >= 0)
{
jump();
}
}
public void checkVelocityProblem()
{
if(dx>9)
{
if(onWhatBumper() instanceof SpeedBumper)
{
jump();
}
attackLeft();
}
else if(dx>6&&GWar.WIDTH-x<50)
{
attackLeft();
}
if(dx<-9)
{
if(onWhatBumper() instanceof SpeedBumper)
{
jump();
}
attackRight();
}
else if(dx<-6&&x<50)
{
attackRight();
}
if(dy<-8&&overBumper()&&y<50)
{
fastFall();
}
}
public void nickAI(){
int position = getPositionValue(this);
int problem = NONE;
checkVelocityProblem();
if(actionType == NONE)
{
problem = getProblem(this);
}
else if(actionType == BORDER)
{
fixBorderProblem();
}
else if(actionType == BUMPER)
{
fixBumperProblem();
}
if(problem == BORDER)
{
fixBorder();
}
else if(problem == BUMPER)
{
fixBumper();
}
else if(problem == NONE)
{
// setTarget();
}
/*if(position < lastPositionValue)
{
reverseLastAction();
}*/
lastPositionValue = position;
}
public int findNickTarget(Hero h){
int mVal = 9999,value,distValue=0, lifeValue, totValue;
int min=-1;
Hero t;
for(int k =0; k < world.p.length;k++)
{
t = world.p[k];
distValue = (int)(distance(h,t.x,t.y)/50);
value = getPositionValue(t);
lifeValue = world.TOTALLIVES-world.lives[k];
totValue = distValue+value+lifeValue;
/* System.out.println("---- " + k+" ----");
System.out.println("Dif: "+(b.y-h.y));
System.out.println(dist1);
System.out.println(dist2);
System.out.println(distTot);*/
if(totValue<mVal)
{
mVal = totValue;
min = k;
}
}
return min;
}
public double getMaxXDist(double tx, double ty, Hero h){
int lJumps = 2-jumps;
if(lJumps==2)
{
return 170;
}
else if(lJumps==1)
{
return 90;
}
else if(lJumps==0)
{
return 50;
}
return 0;
}
public int nearestTargetBumper(double tx,double ty, Hero h, boolean both){
double mDist = 999999999,dist1,dist2=0,distTot;
int min=-1;
Bumper b;
for(int k =0; k < world.bump.length;k++)
{
b = world.bump[k];
dist1 = distance(h,b.x+b.width/2,b.y);
if(b.y - h.y < -(2-jumps)*55)
{
dist1*=5;
}
if(Math.abs(b.x+b.width/2-h.x)>getMaxXDist(b.x,b.y,h))
{
dist1*=5;
}
if(both)
{
dist2 = distance(tx,ty,b.x+b.width/2,b.y)*1.5;
}
distTot = dist1+dist2;
/* System.out.println("---- " + k+" ----");
System.out.println("Dif: "+(b.y-h.y));
System.out.println(dist1);
System.out.println(dist2);
System.out.println(distTot);*/
if(distTot<mDist)
{
mDist = distTot;
min = k;
}
}
return min;
}
public void ai(){
if(!overBumper()&&!onBumper()){
if(dy>=0)
jump();
Bumper goal = world.bump[0];
double tdistance=distance(this, goal.getX(),goal.getY());
for (int k = 0; k <world.bump.length;k++){
if(distance(this, world.bump[k].getX(),world.bump[k].getY())<tdistance){
goal=world.bump[k];
tdistance=distance(this, world.bump[k].getX(),world.bump[k].getY());
}
if(distance(this, world.bump[k].getX() + world.bump[k].getWidth(),world.bump[k].getY())<tdistance){
goal=world.bump[k];
tdistance=distance(this, world.bump[k].getX()+world.bump[k].getWidth(),world.bump[k].getY());
}
}
if(goal.getX()>x){
racceleration=true;
lacceleration=false;
if(goal.getY()>y)
attackRight();
}
else{
racceleration=false;
lacceleration=true;
if(goal.getY()>y)
attackLeft();
}
}
else{
Hero target = findTarget();
if (target ==null)
return;
if((Math.abs(target.x-x)<r)&&(y<target.y)){
fastFall();
}
if (target.x<x){
lacceleration=true;
racceleration=false;
}
else{
lacceleration=false;
racceleration=true;
}
if(target.y<y&&dy>=0)
jump();
if(Math.abs(target.y-y)<5)
if (target.x<x)
attackLeft();
else
attackRight();
}
}
public void stop(){
dx=0;
racceleration = false;
lacceleration = false;
}
private Hero findTarget(){
Hero target = null;
double distance = -1;
for (int k = 0; k< world.p.length; k++){
if (target==null){
target=world.p[k];
if(target==null)
continue;
distance = distance(this,target);
if (target==this)
target=null;
}
Hero ptarget = world.p[k];
if(ptarget!=null){
double pdist = distance(this,ptarget);
if(ptarget!=this&&pdist<distance){
distance=pdist;
target=ptarget;
}
}
}
return target;
}
public void moveLeft(){
lacceleration=true;
}
public void attackLeft(){
if(tiedcount==0){
dx-=2*SPEED;
tiedcount = 15;
xflash=(int)x;
yflash=(int)y;
flashcount=5;
flashleft=true;
}
}
public void unMoveRight(){
racceleration=false;
}
public void unMoveLeft(){
lacceleration=false;
}
public void moveRight(){
racceleration=true;
}
public void attackRight(){
if(tiedcount==0){
dx+=2*SPEED;
tiedcount = 15;
flashleft=false;
xflash=(int)x;
yflash=(int)y;
flashcount=5;
}
}
public void jump(){
if(tiedcount==0)
if (jumps < 2){
dy = -2.5*SPEED;
jumps++;
if(!onbumper)
dx=0;
}
}
public void fastFall(){
if(tiedcount==0){
if (onBumper()){
if (onWhatBumper().passthrough){
y++;
dy=10;
}
}
else if ((dy <10)&&(jumps<2)){
dy=10;
jumps++;
dx=0;
}
}
}
public void gravity(){
if(!onBumper())
dy+=.5;
}
public boolean overBumper(){
boolean temp = false;
for(int k = 0;k<world.bump.length;k++){
if(world.bump[k].overBumper(this)){
temp = true;
break;
}
}
return temp;
}
public boolean checkHBumper()
{
if (onBumper())
return false;
else
return checkBumper(dx,0)!=-1;
}
public boolean checkVBumper()
{
int k = checkBumper(0,dy);
if (k!=-1){
if (y<world.bump[k].y){
y = world.bump[k].y-r;
dy = 0;
return false;
}
return true;
}
return false;
}
public boolean onBumper(){
for(int k=0;k<world.bump.length;k++)
if (world.bump[k].onBumper(this)){
return true;
}
return false;
}
public Bumper onWhatBumper(){
for(int k=0;k<world.bump.length;k++)
if (world.bump[k].onBumper(this)){
return world.bump[k];
}
return null;
}
public int checkBumper(double pdx, double pdy){
for(int k=0;k<world.bump.length;k++)
if (checkBumper(world.bump[k],pdx,pdy))
return k;
return -1;
}
public boolean checkBumper(Bumper b,double pdx, double pdy){
if ((b.overBumper(x+pdx,y,r)||b.onBumper(this))&&(y+r+pdy>b.y)){
y= b.y-r;
dy=0;
return false;
}
else if (b.check(x,y,pdx,pdy,r)){
return true;
}
return false;
}
public boolean onScreen(int width, int height)
{
if(x-r>0&&x+r<width&&y-r>0&&y+r<height)
return true;
return false;
}
public void checkPlayer(Hero p){
if (intersects(p)){
/*if(y<p.y){
dy = Math.min(dy-3,-3);
}
else if(p.y<y){
dy = Math.max(dy+3,3);
}
if (p.x<x){
dx +=5;
dy -=1;
}
else if (x<p.x){
dx -=5;
dy -=1;
}
*/
double angle = Math.atan2(p.y-y,p.x-x)+Math.PI;
//dx+=((1/mass)*8*(p.mass)/distance(this,p))*Math.cos(angle);
//dy+=((1/mass)*8*(p.mass)/distance(this,p))*Math.sin(angle);
//double dxAdd
double phi = angle;
//double term = Math.PI/180;
double v1i = Math.sqrt(Math.pow(dx,2)+Math.pow(dy,2));
double v2i = Math.sqrt(Math.pow(p.dx,2)+Math.pow(p.dy,2));
double ang1 =Math.atan2(dy,dx);
double ang2 = Math.atan2(p.dy,p.dx);
double v1xr = v1i*Math.cos((ang1-phi));
double v1yr = v1i*Math.sin((ang1-phi));
double v2xr = v2i*Math.cos((ang2-phi));
double v2yr = v2i*Math.sin((ang2-phi));
double v1fxr = ((mass-p.mass)*v1xr+(2*p.mass)*v2xr)/(mass+p.mass);
double v2fxr = ((2*mass)*v1xr+(p.mass-mass)*v2xr)/(mass+p.mass);
double v1fyr = v1yr;
double v2fyr = v2yr;
double v1fx = Math.cos(phi)*v1fxr+Math.cos(phi+Math.PI/2)*v1fyr;
double v1fy = Math.sin(phi)*v1fxr+Math.sin(phi+Math.PI/2)*v1fyr;
double v2fx = Math.cos(phi)*v2fxr+Math.cos(phi+Math.PI/2)*v2fyr;
double v2fy = Math.sin(phi)*v2fxr+Math.sin(phi+Math.PI/2)*v2fyr;
dx = v1fx;
dy = v1fy;
p.dx = v2fx;
p.dy = v2fy;
//System.out.println("DX: "+dx);
//System.out.println("DY: "+dy);
//System.out.println("P DX: "+p.dx);
//System.out.println("P DY: "+p.dy);
double newx = (p.x+x)/2+Math.cos(angle)*(r+1);
double newy = (p.y+y)/2+Math.sin(angle)*(r+1);
p.x = (p.x+x)/2+Math.cos(angle+Math.PI)*(p.r+1);
p.y = (p.y+y)/2+Math.sin(angle+Math.PI)*(p.r+1);
x=newx;
y=newy;
tiedcount+=2;
}
}
public static void main(String[] aahrghs){
GWar.main(aahrghs);
}
/*public void goOnScreen(int n)
{
if (x-r<=0)
{
x+=SPEED;
}
if (y-r<=0)
{
y+=SPEED;
}
if (y+r>=n)
{
dy = -.75*Math.abs(dy);
}
if (x+r>=n)
{
x-=SPEED;
}
}*/
public static double distance(Item i1, Item i2){
return Math.sqrt(Math.pow(i1.x-i2.x,2)+Math.pow(i1.y-i2.y,2));
}
public static double distance(Item i1, double x2, double y2){
return Math.sqrt(Math.pow(i1.x-x2,2)+Math.pow(i1.y-y2,2));
}
public static double distance(double x1, double y1, double x2, double y2){
return Math.sqrt(Math.pow(x1-x2,2)+Math.pow(y1-y2,2));
}
public void draw(java.awt.Graphics g){
super.draw(g,world.xScale,world.yScale);
if (flashcount>0){
if(world.sparkles){
Color[] colors = {Color.white,Color.blue,Color.yellow};
int ranColor,ranX,ranY;
for(int a=0;a<10;a++){
ranColor = (int)(Math.random()*colors.length);
ranX = (int)(Math.random()*(this.r*2+10))-5;
ranY = (int)(Math.random()*(this.r*2+10))-5;
g.setColor(colors[ranColor]);
g.fillOval((int)((this.lX-this.r+ranX-1)*world.xScale),(int)((this.lY-this.r+ranY-1)*world.yScale),(int)(2*world.xScale),(int)(2*world.yScale));
}
}
else{
g.setColor(new java.awt.Color(255,75,75));
if(!flashleft)
g.fillPolygon(new int[]{(int)(xflash*world.xScale),(int)((xflash-r)*world.xScale),(int)((xflash-(r/2))*world.xScale),(int)((xflash-r)*world.xScale)},new int[]{(int)(yflash*world.yScale),(int)((yflash+r)*world.yScale),(int)(yflash*world.yScale),(int)((yflash-r)*world.yScale)},4);
else
g.fillPolygon(new int[]{(int)(xflash*world.xScale),(int)((xflash+r)*world.xScale),(int)((xflash+(r/2))*world.xScale),(int)((xflash+r)*world.xScale)},new int[]{(int)(yflash*world.yScale),(int)((yflash+r)*world.yScale),(int)(yflash*world.yScale),(int)((yflash-r)*world.yScale)},4);
}
}
if(DEBUG==true){
g.setColor(new java.awt.Color(255,255,0));
g.drawLine((int)(x*world.xScale),(int)(y*world.yScale),(int)((x+(dx*3))*world.xScale),(int)((y+(dy*3))*world.yScale));
}
}
/*public void draw(java.awt.Graphics g){
super.draw(g);
g.setColor(java.awt.Color.WHITE);
for (int k = 0; k < xspark.length;k++)
g.fillRect((int)xspark[k]-3,(int)yspark[k]-3,6,6);
}*/
}