package com.example.helloandroid; import java.util.ArrayList; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.util.Log; public class Fleet { private int x; private int y; private double dblX; private double dblY; private double slope, xIntercept; private double direction; private Planet destination, nearPlanet; private int numShips; private int faction; private boolean isNextToAPlanet; private boolean isClockwise; private boolean done; /* Optimising: pre-calculate paths */ public Fleet(Planet source, Planet destination, int numShips, int faction) { done = false; source.setNumShips(source.getNumShips()-numShips); //Calculate initial coordinates and direction if((destination.getX() - source.getX()) != 0){ //line formula slope = getSlope(source.getX(),source.getY(),destination.getX(),destination.getY()); xIntercept = destination.getY() - (slope*destination.getX()); //direction direction = Math.atan(slope); //coordinates for all 4 coordinates if((destination.getX() - source.getX()) < 0 ) direction += Math.PI; dblX = ((Math.cos(direction)*(source.radius + 10) + source.getX())); dblY = ((Math.sin(direction)*(source.radius + 10) + source.getY())); } else { if((destination.getY() - source.getY()) > 0 ){ direction = Math.PI/2; dblX = destination.getX(); dblY = source.getY() + source.radius + 10; } else { direction = 3*Math.PI/2; dblX = destination.getX(); dblY = source.getY() - source.radius - 10; } xIntercept = destination.getX(); } x = (int)dblX; y = (int)dblY; this.numShips = numShips; this.faction = faction; this.destination = destination; this.isNextToAPlanet = false; Log.d("Galcon", "Source: ("+source.getX()+", "+source.getY()+")"); Log.d("Galcon", "Destination: ("+destination.getX()+", "+destination.getY()+")"); Log.d("Galcon", "Initial direction: "+direction); if(direction < 0) direction += Math.PI*2; } public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } public double getDirection() { return direction; } public void setDirection(double direction) { this.direction = direction; } public Planet getDestination() { return destination; } public void setDestination(Planet destination) { this.destination = destination; } public int getNumShips() { return numShips; } public void setNumShips(int numShips) { this.numShips = numShips; } public int getFaction() { return faction; } public void setFaction(int faction) { this.faction = faction; } public void draw(Canvas canvas, Paint linePaint) { Path p = new Path(); p.moveTo((float)(x+5*Math.cos(direction+Math.PI/2)), (float)(y+5*Math.sin(direction+Math.PI/2))); p.lineTo((float)(x+5*Math.cos(direction-Math.PI/2)), (float)(y+5*Math.sin(direction-Math.PI/2))); p.lineTo((float)(x+10*Math.cos(direction)), (float)(y+10*Math.sin(direction))); p.lineTo((float)(x+5*Math.cos(direction+Math.PI/2)), (float)(y+5*Math.sin(direction+Math.PI/2))); int c, prevC = linePaint.getColor(); switch(faction) { case 0: c = Color.argb(255, 100, 100, 100); break; case 1: c = Color.argb(255, 255, 0, 0); break; case 2: c = Color.argb(255, 0, 180, 0); break; case 3: c = Color.argb(255, 0, 0, 255); break; case 4: c = Color.argb(255, 150, 150, 0); break; default: c = prevC; } linePaint.setColor(c); canvas.drawPath(p, linePaint); linePaint.setColor(prevC); } public void update(ArrayList planets) { int speed = 3; //pixels per move double distance, tangentAngle, angle; //is the ship going around a planet already if(!isNextToAPlanet){ /*looks through all the planets to figure out if the ship's path is about to intersect a planet*/ for(Planet p: planets){ //if two point of intersection are found save planet distance = getDistanceBetween(dblX,dblY,p.getX(),p.getY()); if(distance <= p.radius){ nearPlanet = p; break; } } //if temp planet is not picked move along the direction by #speed if(nearPlanet == null) { dblY += (Math.sin(direction)*speed); dblX += (Math.cos(direction)*speed); x = (int)dblX; y = (int)dblY; }else { if(nearPlanet == destination){ attack(); return; } //double radAngle = Math.atan(getSlope(destination.getX(), destination.getY(), dblX, dblY)); //figure out which way to go clockwise or counter clockwise tangentAngle = (Math.atan(getSlope(nearPlanet.getX(),nearPlanet.getY(),dblX,dblY))) + (Math.PI/2); angle = Math.atan((Math.tan(tangentAngle) - Math.tan(direction))/(1 + Math.tan(tangentAngle)*Math.tan(direction))); Log.d("Galcon", "tangentAngle: "+tangentAngle); Log.d("Galcon", "direction: "+direction+", angle: "+angle); if (angle <= Math.PI/2) angle = Math.PI - angle; //double diff = direction-angle; //if(diff > 0) if(Math.abs(tangentAngle-direction) > Math.PI/2) { isClockwise = false; direction = tangentAngle-Math.PI; }else { isClockwise = true; direction = tangentAngle; } Log.d("Galcon", "isClockwise: "+isClockwise); xIntercept = dblY - (dblX*Math.tan(direction)); isNextToAPlanet = true; //figure out which way to go clockwise or counter clockwise /*tangentDirection = (Math.atan(getSlope(temp.getX(),temp.getY(),dblX,dblY))) + (Math.PI/2); angle = Math.atan((Math.tan(tangentDirection) - Math.tan(direction))/(1 + Math.tan(tangentDirection)*Math.tan(direction))); if (angle <= Math.PI/2) angle = Math.PI - angle;*/ //get next point and the direction and set it } } else { //can you reach the center of the planet by following this direction //if so set isNextToAPlanet to false and move //otherwise continue moving along the circumference double dist = Math.abs(destination.getY() - (Math.tan(direction)*destination.getX()) - xIntercept)/(double)Math.sqrt(Math.pow(direction,2)+1); //Log.d("Galcon", "dist: "+dist); if(dist < 5 && dist == 1){ dblY += (Math.sin(direction)*speed); dblX += (Math.cos(direction)*speed); x = (int)dblX; y = (int)dblY; if (getDistanceBetween(dblX,dblY,nearPlanet.getX(),nearPlanet.getY()) > nearPlanet.radius){ isNextToAPlanet = false; nearPlanet = null; } } else { angle = speed/(double)nearPlanet.radius*.1; if(!done) { Log.d("Galcon", "direction: "+direction+", angle: "+angle); Log.d("Galcon", "original: ("+dblX+", "+dblY+")"); } if(isClockwise){ dblX = Math.cos(direction - (Math.PI/2) + angle)*nearPlanet.radius + nearPlanet.getX(); dblY = Math.sin(direction - (Math.PI/2) + angle)*nearPlanet.radius + nearPlanet.getY(); direction = direction + angle; } else { dblX = Math.cos(direction + (Math.PI/2) - angle)*nearPlanet.radius + nearPlanet.getX(); dblY = Math.sin(direction + (Math.PI/2) - angle)*nearPlanet.radius + nearPlanet.getY(); direction = direction - angle; } if(!done) Log.d("Galcon", "new: ("+dblX+", "+dblY+")"); done = true; x = (int)dblX; y = (int)dblY; xIntercept = dblY - (dblX*Math.tan(direction)); } } } // attack the destination planet //after the method is called the fleet needs to removed public void attack() { if(this.faction == destination.getFaction()) destination.setNumShips(destination.getNumShips() + numShips); else if(numShips <= destination.getNumShips()){ destination.setNumShips(destination.getNumShips() - numShips); } else { destination.setNumShips(numShips - destination.getNumShips()); destination.setFaction(this.faction); } this.numShips = 0; } //helper functions private double getDistanceBetween(double x1, double y1, double x2, double y2) { return Math.sqrt(Math.pow((x2 - x1),2) + Math.pow((y2 - y1),2)); } private double getSlope(double x1, double y1, double x2, double y2) { return ((y2 - y1)/(double)(x2 - x1)); } }