Ok so I am working on a tower defense game, and ive got towers that shoot at the enemies. My problem is when the tower shoots at the enemies, sometimes it will kill them, and other times it will just go right through them and the tower will get stuck trying to kill the enemy which cant be killed (since the bullets go right through it). I've been working on this for hours and I can't figure out what i'm doing wrong! thanks!
let me know if theres anything anyone needs to better understand the problem.
ps all my unit types (Infantry, Medium, Speedy, Ultra, Heavy) all inherit from an empty class called Enemy so I can easily check if an actor is an enemy
pps all my tower types (Ice, Gun, Bomb) inherit from the Tower class
ppps all my towers are the same except for different values for damage and rate of fire etc.; same with units, they are all the same except for health etc.
this is my code in class Tower.
this is my code in class Bullet( it also inherits from the smooth mover class found in the Asteroids tutorial. I also have the vector class properly placed in my program)
this is the Infantry class code:
this is the gun class code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | public Enemy target( int range){ if (field== null ){field=(Field)getWorld();} List<Enemy> enemies= getObjectsInRange(range,Enemy. class ); if (enemies.size()== 0 ){ return null ; } double dist=field.getDist( this ,enemies.get( 0 )); closest=enemies.get( 0 ); for (Enemy e:enemies){ double newdist=field.getDist( this ,e); if (newdist<dist){ dist=newdist; closest=e; } } //turnTowards(closest.getX(),closest.getY()); return closest; } public Double getTargetDist(Enemy enemy){ if (field== null ){field=(Field)getWorld();} if (enemy!= null ){ double dist=field.getDist( this ,enemy); return dist; } return null ; } public Double getClosestTargetDist( int range){ Enemy e=target(range); if (e== null ) return null ; Double dist=(Double)getTargetDist(target(range)); return dist; } public HashMap getAllEnemies(){ if (field== null ){field=(Field)getWorld();} List<Enemy> b= field.getObjects(Enemy. class ); for (Enemy x:b){ enemyMap.put(x,getTargetDist(x)); } return enemyMap; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | public int damage; public double speedDamage; public double x; public double y; public double origx; public double origy; public double dist; public int range; private Field field; public Counter counter; public Enemy e; public Bullet(){} public Bullet( double x, double y, int rotation, int range, int damage, double speedDamage){ this ( new Vector( 0 ,( double ) 0 ),rotation); setLocation(x,y); origx=x; origy=y; this .x=x; this .y=y; this .range=range; this .damage=damage; this .speedDamage=speedDamage; } public Bullet(Vector speed, int rotation){ super (speed); setRotation(rotation); addForce( new Vector(rotation, 15 )); //Greenfoot.playSound("energyGun.wav"); } /** * Act - do whatever the Bullet wants to do. This method is called whenever * the 'Act' or 'Run' button gets pressed in the environment. */ public void act() { field=(Field)getWorld(); counter=field.getCounter(); this .dist=Math.sqrt((Math.pow(( this .x-origx), 2 ))+(Math.pow(( this .y-origy), 2 ))); if ( this .dist> this .range){ getWorld().removeObject( this ); } else { move(); this .x=getExactX(); this .y=getExactY(); checkHit(); } } public void checkHit(){ e= (Enemy)getOneIntersectingObject(Enemy. class ); if (e!= null ){ if (e instanceof Infantry){ Infantry i=(Infantry)e; i.update( this .damage, this .speedDamage); counter.addMoney(i.bonus); } else if (e instanceof Speedy){ Speedy s=(Speedy)e; s.update( this .damage, this .speedDamage); counter.addMoney(s.bonus); } else if (e instanceof Medium){ Medium m=(Medium)e; m.update( this .damage, this .speedDamage); counter.addMoney(m.bonus); } else if (e instanceof Heavy){ Heavy h=(Heavy)e; h.update( this .damage, this .speedDamage); counter.addMoney(h.bonus); } else if (e instanceof Ultra){ Ultra u=(Ultra)e; u.update( this .damage, this .speedDamage); counter.addMoney(u.bonus); } getWorld().removeObject( this ); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | public class Infantry extends Enemy { public boolean isHit= false ; public double speed; public int bonus; public int health; public Infantry(){ this ( 5.0 , 5 , 10 ); } public Infantry( double speed, int bonus, int health){ this .speed=speed; this .bonus=bonus; this .health=health; } public void update( int damage, double speed){ this .speed-=speed; this .health-=damage; if ( this .health<= 0 ){ Field field=(Field)getWorld(); getWorld().removeObject( this ); field.setScore(); } else if ( this .speed<= 0 ){ this .speed= 1 ; } } /** * Act - do whatever the Infantry wants to do. This method is called whenever * the 'Act' or 'Run' button gets pressed in the environment. */ public void act() { // Add your action code here. } public double getSpeed(){ return this .speed;} public int getBonus(){ return this .bonus;} public int getHealth(){ return this .health;} } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | public class Gun extends Tower { public int level; public double rate; public int nextPrice; public int range; public int damage; public int speedDamage= 0 ; private double reloadDelayCount; private static final double [] rates={ 7.0 , 5.0 , 3.0 }; private static final int [] prices={ 10 , 15 , 30 }; private static final int [] ranges={ 50 , 70 , 90 }; private static final int [] damages={ 5 , 10 , 20 }; public Counter counter; /** * When first creating an Gun tower, this is called. * gives default values for rate, nextPrice, range, and damage amount */ public Gun(){ this ( 0 ); } /** * Gun Constructor * * @param rate The rate the tower fires at * @param nextPrice The price of purchase * @param range The range of fire * @param damage The amount the tower decreases unit health */ public Gun( int level){ update(level); this .reloadDelayCount= this .rate; } public void upgrade(){ counter=getCounter(); if (counter.canAfford( this .nextPrice)){ counter.removeMoney( this .nextPrice); if (( this .level== 1 )||( this .level== 2 )){ this .level++; update( this .level); } } } private void update( int level){ this .level=level; if ( this .level== 3 ){ this .nextPrice= 1000000000 ;} else if ( this .level== 0 ){ this .level++;} this .nextPrice=prices[Math.min( 2 , this .level)]; this .rate=rates[ this .level- 1 ]; this .range=ranges[ this .level- 1 ]; this .damage=damages[ this .level- 1 ]; this .speedDamage= 0 ; } public int getLevel(){ return this .level;} public double getRate(){ return this .rate;} public int getPrice(){ return this .nextPrice;} public int getlvlPrice( int level){ return prices[Math.max( 0 ,Math.min( 2 ,(level- 1 )))];} public int getRange(){ return this .range;} public int getDamage(){ return this .damage;} public int getSpeedDamage(){ return this .speedDamage;} public void fire(){ if (reloadDelayCount>= this .rate* 5 ){ Bullet bullet= new Bullet(( double )getX(),( double )getY(),getRotation(),getRange(),getDamage(),getSpeedDamage()); getWorld().addObject(bullet,getX(),getY()); bullet.move(); reloadDelayCount= 0 ; } } /** * Act - do whatever the Gun wants to do. This method is called whenever * the 'Act' or 'Run' button gets pressed in the environment. */ public void act() { Enemy atarget=target( this .range); if (atarget!= null ){ turnTowards(( int )atarget.getExactX(),( int )atarget.getExactY()); fire(); } reloadDelayCount++; } } |