diff --git a/Assets.java b/Assets.java new file mode 100644 index 0000000..3714b80 --- /dev/null +++ b/Assets.java @@ -0,0 +1,91 @@ +import java.awt.*; +import java.awt.image.BufferedImage; + +public class Assets { + public static final int width = 70, height = 130, offset = 26, fOffset = 22; + public static final int offsetf = 28, fOffsetf = 39, widthf = 70, offsetW = 12; + public static BufferedImage p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, bg, resized; + public static BufferedImage fp1, fp2, fp3, fp4, fp5, fp6, fp7, fp8, fp9, fp10, fp11, fp12, + t1, bullet, blood; + + public static BufferedImage resize(BufferedImage img, int height, int width) { + Image tmp = img.getScaledInstance(width, height, Image.SCALE_SMOOTH); + BufferedImage resized = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + Graphics2D g2d = resized.createGraphics(); + g2d.drawImage(tmp, 0, 0, null); + g2d.dispose(); + return resized; + } + + public static void init(){ + SpriteSheet sheet = new SpriteSheet((imageLoader.loadImage("image/bone1.png"))); + SpriteSheet fsheet = new SpriteSheet((imageLoader.loadImage("image/bonef.png"))); + SpriteSheet tower = new SpriteSheet(imageLoader.loadImage("image/tower/towers.png")); + SpriteSheet Bullet = new SpriteSheet(imageLoader.loadImage("image/bullet/bullet.png")); + SpriteSheet bloodBar = new SpriteSheet(imageLoader.loadImage("image/blood/bloodBar.png")); + + blood = bloodBar.crop(20,0,1250,90); + blood = resize(blood,6,70); + t1 = tower.crop(50,80,460,970); + bullet = Bullet.crop(0,0,65,65); + t1 = resize(t1,100,60); + bullet = resize(bullet,12,12); + + p1 = sheet.crop(fOffset,565,width,height); + p2 = sheet.crop(width + fOffset + offset,565,width,height); + p3 = sheet.crop(2*width +fOffset+2*offset,565,width,height); + p4 = sheet.crop(3*width +fOffset+ 3*offset,565,width,height); + p5 = sheet.crop(4*width+fOffset+4*offset,565,width,height); + p6 = sheet.crop(5*width+fOffset +5*offset,565,width,height); + p7 = sheet.crop(6*width+fOffset + 6*offset,565,width,height); + p8 = sheet.crop(7*width+fOffset + 7*offset,565,width,height); + p9 = sheet.crop(8*width+fOffset + 8*offset,565,width,height); + p10 = sheet.crop(9*width+fOffset + 9*offset,565,width,height); + p11 = sheet.crop(10*width+fOffset + 10*offset,565,width,height); + p12 = sheet.crop(11*width+fOffset + 11*offset,565,width,height); + p1 = resize(p1,height/3, width/3); + p2 = resize(p2,height/3, width/3); + p3 = resize(p3,height/3, width/3); + p4 = resize(p4,height/3, width/3); + p5 = resize(p5,height/3, width/3); + p6 = resize(p6,height/3, width/3); + p7 = resize(p7,height/3, width/3); + p8 = resize(p8,height/3, width/3); + p9 = resize(p9,height/3, width/3); + p10 = resize(p10,height/3, width/3); + p11 = resize(p11,height/3, width/3); + p12 = resize(p12,height/3, width/3); + + //flip + + fp1 = fsheet.crop(fOffset,565,width,height); + fp2 = fsheet.crop(widthf + fOffsetf + offsetf,565,width+offsetW,height); + fp3 = fsheet.crop(2*widthf +fOffsetf+2*offsetf,565,width+offsetW,height); + fp4 = fsheet.crop(3*widthf +fOffsetf+ 3*offsetf,565,width+offsetW,height); + fp5 = fsheet.crop(4*widthf+fOffsetf+4*offsetf,565,width+offsetW,height); + fp6 = fsheet.crop(5*widthf+fOffsetf +5*offsetf,565,width+offsetW,height); + fp7 = fsheet.crop(6*widthf+fOffsetf + 6*offsetf,565,width+offsetW,height); + fp8 = fsheet.crop(7*widthf+fOffsetf + 7*offsetf,565,width+offsetW,height); + fp9 = fsheet.crop(8*widthf+fOffsetf + 8*offsetf,565,width+offsetW,height); + fp10 = fsheet.crop(9*widthf+fOffsetf + 9*offsetf,565,width+offsetW,height); + fp11 = fsheet.crop(10*widthf+fOffsetf + 10*offsetf,565,width+offsetW,height); + fp12 = fsheet.crop(11*widthf+fOffsetf + 11*offsetf,565,width+offsetW,height); + fp1 = resize(fp1,height/3, (width+offsetW)/3); + fp2 = resize(fp2,height/3, width/3+offsetW/3); + fp3 = resize(fp3,height/3, width/3+offsetW/3); + fp4 = resize(fp4,height/3, width/3+offsetW/3); + fp5 = resize(fp5,height/3, width/3+offsetW/3); + fp6 = resize(fp6,height/3, width/3+offsetW/3); + fp7 = resize(fp7,height/3, width/3+offsetW/3); + fp8 = resize(fp8,height/3, width/3+offsetW/3); + fp9 = resize(fp9,height/3, width/3+offsetW/3); + fp10 = resize(fp10,height/3, width/3+offsetW/3); + fp11 = resize(fp11,height/3, width/3+offsetW/3); + fp12 = resize(fp12,height/3, width/3+offsetW/3); + + + bg = imageLoader.loadImage("image/back_ground/bg2.jpg"); + + } + +} diff --git a/Bullet.java b/Bullet.java new file mode 100644 index 0000000..d3b9c4f --- /dev/null +++ b/Bullet.java @@ -0,0 +1,22 @@ +import java.awt.*; + +public class Bullet { + private int x, y, dame; + + public Bullet(int x, int y, int dame) { + this.x = x; + this.y = y; + this.dame = dame; + + } + + public void tick(){ + + } + + public void rend (Graphics g){ + g.drawImage(Assets.bullet, x, y, null); + } + + +} diff --git a/Creature.java b/Creature.java new file mode 100644 index 0000000..d6a3952 --- /dev/null +++ b/Creature.java @@ -0,0 +1,19 @@ +public abstract class Creature extends Entity { + + + protected int health; + protected double speed; + + public Creature(double x, double y){ + super(x, y); + health = 100; + speed = 2; + } + + public double getSpeed() { + return speed; + } + public int getHealth() { + return health; + } +} diff --git a/Display.java b/Display.java new file mode 100644 index 0000000..8d9c8a7 --- /dev/null +++ b/Display.java @@ -0,0 +1,47 @@ +import javax.swing.*; +import java.awt.*; + +public class Display { + + private JFrame frame; + private Canvas canvas; + + private String title; + private int width; + private int height; + + public Display(String title, int width, int height){ + this.title = title; + this.width = width; + this.height = height; + + createDisplay(); + } + + public void createDisplay(){ + frame = new JFrame(title); + frame.setSize(width, height); + frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + frame.setResizable(false); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + + canvas = new Canvas(); + canvas.setPreferredSize(new Dimension(width, height)); + canvas.setMaximumSize(new Dimension(width, height)); + canvas.setMaximumSize(new Dimension(width, height)); + canvas.setMinimumSize(new Dimension(width, height)); + canvas.setFocusable(false); + + frame.add(canvas); + frame.pack(); + + } + + public Canvas getCanvas(){ + return canvas; + } + public JFrame getFrame(){ + return frame; + } +} diff --git a/Entity.java b/Entity.java new file mode 100644 index 0000000..9c2facb --- /dev/null +++ b/Entity.java @@ -0,0 +1,13 @@ +import java.awt.*; + +public abstract class Entity { + + protected double x, y; + public Entity(double x, double y){ + this.x = x; + this.y = y; + } + + public abstract void tick(); + public abstract void render(Graphics g); +} diff --git a/Game.java b/Game.java new file mode 100644 index 0000000..2c13e39 --- /dev/null +++ b/Game.java @@ -0,0 +1,141 @@ +import java.awt.*; +import java.awt.image.BufferStrategy; +import java.util.ArrayList; +import java.util.List; + +public class Game implements Runnable{ + private Display display; + private int width, height; + private String title; + + private boolean running = false; + private Thread thread; + + private BufferStrategy bs, bg; + private Graphics g,g1; + private List g2; + + //State + private State gameState; + + //Score + protected int Score; + + public Game(String title, int width, int height){ + g2 = new ArrayList<>(); + this.title = title; + this.width = width; + this.height = height; + + Score = 6; + + } + + private void init(){ + + display = new Display(title, width, height); + Assets.init(); + + gameState = new gameState(this); + + gameState.setState(gameState); + } + + private void tick(){ + + if(gameState.getState() != null) + gameState.getState().tick(); + } + + private void render(){ + bs = display.getCanvas().getBufferStrategy(); + if(bs == null){ + display.getCanvas().createBufferStrategy(3); + return; + } + + g = bs.getDrawGraphics(); + //CLear Screen + + g.clearRect(0,0,width,height); + g1 = bs.getDrawGraphics(); + + for(int i = 0; i< State.numberEnermy; ++i){ + g2.add(bs.getDrawGraphics()); + } + + //DRAW HERE + + g.drawImage(Assets.bg,0,0,null); + + for(int i=0; i=16) { + + tick(); + render(); + delta -=16; + } + } + + stop(); + + } + + + public synchronized void start(){ + if(running) + return; + running = true; + thread = new Thread(this::run); + thread.start(); + } + + public synchronized void stop(){ + if(!running) + return; + running = false; + try { + thread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + + //Score + public void setScore(int Score){ + this.Score = Score; + } + public int getScore(){ + return Score; + } +} diff --git a/Launcher.java b/Launcher.java new file mode 100644 index 0000000..92f5770 --- /dev/null +++ b/Launcher.java @@ -0,0 +1,8 @@ +public class Launcher { + + public static void main(String[] args){ + Game game = new Game("denfense tower",1280,700); + game.start(); + + } +} diff --git a/Player.java b/Player.java new file mode 100644 index 0000000..597a074 --- /dev/null +++ b/Player.java @@ -0,0 +1,183 @@ +import java.awt.*; +import java.awt.image.BufferedImage; + +public class Player extends Creature { + + private Game game; + + private int act,k=0; + private int[] maxY = {100,330,620}; + private int[] minY = {0,240,560}; + private boolean actX = true, actY = true, isFlip = false; + private BufferedImage img; + + public Player(Game game, double x, double y) { + super(x, y); + this.game = game; + } + + @Override + public void tick() { + // Move if actY enermy move cross by X + if(actY) { + + // if actX enermy go ahead + + if (actX) + x += speed; + else + x -= speed; + + // if(isFlip) enermy flip + if(isFlip) + actX = false; + else + actX = true; + + //State of enermy + act++; + if (act >= 10) + act = 0; + + // Y + double ran = Math.random() * ((1 - (-1.5)) +1)-1.5; + y += ran; + + //Make sure enermy can be go out their way + if (y >= maxY[k]) + y = maxY[k]; + if (y <= minY[k]) + y = minY[k]; + + // enermy go to the new line + if(x >= 1200){ + actY = false; + if(k == 0) + k = 1; + } + if(x<=10 && isFlip){ + actY = false; + if(k == 1) + k = 2; + } + + //if enrmy go to their end way + if(x>=1210 && y>= 560) { + if(health > 0) + game.setScore(game.getScore()-1); + this.health = 0; + } + } else { + + // enermy State + act++; + if (act >= 10) + act = 0; + + // enermy moves folow y axis + x+= 0.5; + y += 3; + if(y >= minY[k]){ + actY = true; + if(k == 1) + isFlip = true; + if(k == 2) + isFlip = false; + } + + } + + } + + @Override + public void render(Graphics g) { + g.setFont(new Font("TimesRoman", Font.PLAIN, 30)); + g.setColor(Color.red); + g.drawString("your Score " + game.getScore(),1000,50); + double h1 = health*0.7; + if (health > 0) + img = Assets.resize(Assets.blood, 8, (int) h1); + g.drawImage(img, (int) x-20, (int) y-20, null); + if(!isFlip) { + switch (act) { + case 0: + g.drawImage(Assets.p1, (int) x, (int) y, null); + break; + case 1: + g.drawImage(Assets.p2, (int) x, (int) y, null); + break; + case 2: + g.drawImage(Assets.p3, (int) x, (int) y, null); + break; + case 4: + g.drawImage(Assets.p5, (int) x, (int) y, null); + break; + case 5: + g.drawImage(Assets.p6, (int) x, (int) y, null); + break; + case 6: + g.drawImage(Assets.p7, (int) x, (int) y, null); + break; + case 7: + g.drawImage(Assets.p8, (int) x, (int) y, null); + break; + case 8: + g.drawImage(Assets.p9, (int) x, (int) y, null); + break; + case 9: + g.drawImage(Assets.p10, (int) x, (int) y, null); + break; + case 10: + g.drawImage(Assets.p11, (int) x, (int) y, null); + break; + default: + g.drawImage(Assets.p1, (int) x, (int) y, null); + break; + } + }else{ + switch (act) { + case 0: + g.drawImage(Assets.fp1, (int) x, (int) y, null); + break; + case 1: + g.drawImage(Assets.fp2, (int) x, (int) y, null); + break; + case 2: + g.drawImage(Assets.fp3, (int) x, (int) y, null); + break; + case 4: + g.drawImage(Assets.fp5, (int) x, (int) y, null); + break; + case 5: + g.drawImage(Assets.fp6, (int) x, (int) y, null); + break; + case 6: + g.drawImage(Assets.fp7, (int) x, (int) y, null); + break; + case 7: + g.drawImage(Assets.fp8, (int) x, (int) y, null); + break; + case 8: + g.drawImage(Assets.fp9, (int) x, (int) y, null); + break; + case 9: + g.drawImage(Assets.fp10, (int) x, (int) y, null); + break; + case 10: + g.drawImage(Assets.fp11, (int) x, (int) y, null); + break; + default: + g.drawImage(Assets.fp1, (int) x, (int) y, null); + break; + } + } + } + + //Function + public int getX(){ + return (int)this.x; + } + public int getY(){ + return (int)this.y; + } +} diff --git a/SpriteSheet.java b/SpriteSheet.java new file mode 100644 index 0000000..f3a6c05 --- /dev/null +++ b/SpriteSheet.java @@ -0,0 +1,13 @@ +import java.awt.image.BufferedImage; + +public class SpriteSheet { + private BufferedImage sheet; + + public SpriteSheet(BufferedImage sheet){ + this.sheet = sheet; + } + + public BufferedImage crop(int x, int y, int width, int height){ + return sheet.getSubimage(x,y,width,height); + } +} diff --git a/State.java b/State.java new file mode 100644 index 0000000..f605644 --- /dev/null +++ b/State.java @@ -0,0 +1,23 @@ +import java.awt.*; + +public abstract class State { + + private static State currentState = null; + protected static int numberEnermy; + + public static void setState(State state){ + currentState = state; + } + public static State getState(){ + return currentState; + } + + protected Game game; + + public State (Game game){ + this.game = game; + } + + public abstract void tick(); + public abstract void render(Graphics g); +} diff --git a/Tower.java b/Tower.java new file mode 100644 index 0000000..5c0576e --- /dev/null +++ b/Tower.java @@ -0,0 +1,114 @@ +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +public class Tower { + private int x, y, xB, yB, sp, scope, numberTower, dame; + private boolean pX, pY, isInside = false; + private int[] tPosX, tPosY; + + private List towerList = new ArrayList(); + + public Tower(int x, int y){ + this.x = x; + this.y = y; + this.xB = x; + this.yB = y; + sp = 5; + scope = 200; + numberTower = 4; + dame = 10; + + init(); + } + + public void init(){ + for(int i = 0; i < numberTower; ++i){ + towerEntity t1 = new towerEntity(450,150,200, 20); + } + } + + public void tick(double a, double b){ + + //enermy inside tower's scope + if(Math.abs(a-xB) <= scope && Math.abs(b-yB)<= scope) + isInside = true; + else{ + isInside = false; + } + if(isInside) { + + //check enermy in front or behind tower + // pX == true if a-xB is positive else false + + if (a > xB) + pX = true; + else + pX = false; + if (b > yB) + pY = true; + else + pY = false; + + if (pX) + xB += sp; + else + xB -= sp; + + if (pY) + yB += sp; + else + yB -= sp; + + //check if bullet collision with enermy + + if (xB >= a && pX) { + xB = (int) a; + } + if (xB <= a && !pX) + xB = (int) a; + + if (yB >= b+10 && pY) + yB = (int) b; + if (yB <= b-10 && !pY) + yB = (int) b; + + // check if bullet throw outside of their scope + + if (xB > x + scope || yB > y + scope || xB <= 30 || yB <= 30 || (xB == (int) a && yB == (int) b)) { + xB = x; + yB = y; + } + } else { + xB = x; + yB = y; + } + + } + public void render(Graphics g){ + g.drawImage(Assets.t1,x,y,null); + if(isInside) { + g.drawImage(Assets.bullet, xB, yB, null); + g.drawOval(x - 150, y - 150, 400, 400); + } + } + + public int getxB(){ + return xB; + } + public int getyB(){ + return yB; + } + public int getX(){return x;} + public int getY(){return y;} + + public void resetXb(){ + xB = x; + } + public void restYb(){ + yB = y; + } + public int getDame(){ + return dame; + } +} diff --git a/Towers.java b/Towers.java new file mode 100644 index 0000000..8cdbd07 --- /dev/null +++ b/Towers.java @@ -0,0 +1,3 @@ +public class Towers { + +} diff --git a/drawElip.java b/drawElip.java new file mode 100644 index 0000000..1fbbba6 --- /dev/null +++ b/drawElip.java @@ -0,0 +1,12 @@ +import java.awt.*; +import java.awt.geom.Ellipse2D; + +public class drawElip { + Ellipse2D e ; + private int x,y,r; + public drawElip(Graphics g, int x, int y, int r){ + Graphics2D g1 = (Graphics2D) g; + e = new Ellipse2D.Double(x,y,r,r); + g1.draw(e); + } +} diff --git a/gameState.java b/gameState.java new file mode 100644 index 0000000..d635d63 --- /dev/null +++ b/gameState.java @@ -0,0 +1,121 @@ +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +public class gameState extends State { + private List enermy; + private Player player; + private List towers; + private Tower tower; + private int towerX = 150, towerY = 150, select = 0; + + private double[] ranX; + private boolean win = false, lose = false; + + + public gameState(Game game) { + super(game); + intiEnermy(); + initiTower(); + } + + public void intiEnermy () { + numberEnermy = 8; + ranX = new double[numberEnermy]; + enermy = new ArrayList<>(); + player = new Player(game, 0 ,0); + for(int i = 0; i< numberEnermy; ++i){ + ranX[i] = Math.random()*((50-(-50))+1)-50; + Player e = new Player(game, ranX[i]-150 , -5); + enermy.add(e); + } + } + + public void initiTower () { + towers = new ArrayList<>(); + tower = new Tower(towerX, towerY); + towers.add(new Tower(towerX*6, 140)); + towers.add(new Tower(towerX,towerY*3)); + towers.add(new Tower(towerX*6, towerY*3)); + } + + + + @Override + public void tick() { + // Select random enermy in scope to hit + if(enermy.size() > 0 ) { + if (!isInside(enermy.get(select).x, enermy.get(select).y)) + select++; + + if (select >= enermy.size() - 1) + select = 0; + + tower.tick(enermy.get(select).x, enermy.get(select).y); + for (Tower t : towers) { + t.tick(enermy.get(select).x, enermy.get(select).y); + } + } else { + win = true; + } + //End select + + for(int i = 0; i < enermy.size(); ++i){ + enermy.get(i).tick(); + } + + //Collision + for(int i = 0; i < enermy.size(); ++i) { + if (isCollision(this.tower, enermy.get(i))) { + enermy.get(i).health -= tower.getDame(); + } + } + + //is die + for(int i = 0; i < numberEnermy; ++i){ + if(enermy.get(i).health <=0 ) { + tower.resetXb(); + tower.restYb(); + enermy.remove(i); + numberEnermy--; + } + } + + } + + @Override + public void render(Graphics g) { + + tower.render(g); + + for(int i = 0; i < numberEnermy; ++i){ + enermy.get(i).render(g); + } + + for (Tower t : towers) { + t.render(g); + } + //win + if(game.Score > 0 && enermy.size()<=0) { + g.setFont(new Font("TimesRoman", Font.PLAIN, 80)); + g.setColor(Color.red); + g.drawString("YOU WIN", 400, 400); + } + //lose + if(game.getScore() <=0) { + g.setFont(new Font("TimesRoman", Font.PLAIN, 80)); + g.setColor(Color.red); + g.drawString("LOSE", 400, 400); + } + } + + // function + private boolean isInside(double x, double y){ + return x - towerX <= 200 && y - towerY <=200; + } + + private boolean isCollision(Tower tower, Player enermy){ + return isInside(enermy.getX(), enermy.getY()) && Math.abs(tower.getxB() - enermy.getX())<= 10 && Math.abs(tower.getyB() - enermy.getY())<=10; + } + +} diff --git a/imageLoader.java b/imageLoader.java new file mode 100644 index 0000000..27d452a --- /dev/null +++ b/imageLoader.java @@ -0,0 +1,16 @@ +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; + +public class imageLoader { + + public static BufferedImage loadImage(String path){ + try { + return ImageIO.read(new File(path)); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/towerEntity.java b/towerEntity.java new file mode 100644 index 0000000..5ca446d --- /dev/null +++ b/towerEntity.java @@ -0,0 +1,22 @@ +import java.awt.*; + +public class towerEntity { + + private int x, y, scope, dame; + + public towerEntity(int x, int y, int scope, int dame){ + this.x = x; + this.y = y; + this.scope = 2*scope; + this.dame = dame; + } + + public void tick(){ + + } + public void render(Graphics g){ + g.drawImage(Assets.t1,x,y,null); + g.drawOval(x - 150, y - 150, scope, scope); + } + +}