1.项目结构截图
2.源代码
2.1 backgroud
package com.sxt; import javax.swing.*; import java.awt.*; public class Background extends GameObject { public Background(GameFrame gameFrame) { super(gameFrame); // TODO Auto-generated constructor stub } Image bg = Toolkit.getDefaultToolkit().getImage("img/Map.jpg"); public void paintSelf(Graphics g){ g.drawImage(bg,0,0,null); } @Override public Rectangle getRec() { // TODO Auto-generated method stub return null; } }
2.2 bullet
package com.sxt; import java.awt.Color; import java.awt.Graphics; import java.awt.Rectangle; public class Bullet extends GameObject { //发射子弹的游戏元素 GameObject attacker; //目标 GameObject target; //攻击力 int ad; public Bullet(GameFrame gameFrame, GameObject attacker, GameObject target, int ad, int spd) { super(attacker.getX(), attacker.getY(), gameFrame); this.attacker = attacker; this.target = target; setAd(ad); setSpd(spd); // TODO Auto-generated constructor stub } public Bullet(GameFrame gameFrame, GameObject attacker, GameObject target, int ad, int spd, String img) { super(attacker.getX(), attacker.getY(), gameFrame); this.attacker = attacker; this.target = target; setImg(img); setAd(ad); setSpd(spd); // TODO Auto-generated constructor stub } public Bullet() { super(); // TODO Auto-generated constructor stub } public void move() { //子弹与目标碰撞,子弹消失,目标减血 if(recIntersectsRec(getRec(), target.getRec())) { target.setCurrentHp(target.getCurrentHp() - getAd()); gameFrame.removeList.add(this); } double dis = getDis(getX(), getY(), target.getX(), target.getY()); int xSpeed = (int)(getSpd() * (target.getX() - getX()) / dis); int ySpeed = (int)(getSpd() * (target.getY() - getY()) / dis); setX(getX() + xSpeed); setY(getY() + ySpeed); } @Override public void paintSelf(Graphics g) { // TODO Auto-generated method stub g.drawImage(getImg(), getX()-16, getY()-16, null); g.setColor(Color.BLACK); g.fillOval(getX()-5, getY()-5, 10, 10); g.drawRect(getX()-5, getY()-5, 10, 10); move(); } @Override public Rectangle getRec() { // TODO Auto-generated method stub return new Rectangle(getX()-5, getY()-5, 10, 10); } /** * @return the ad */ public int getAd() { return ad; } /** * @param ad the ad to set */ public void setAd(int ad) { this.ad = ad; } }
2.3 champoin
package com.sxt; import java.awt.Color; import java.awt.Graphics; import java.awt.Image; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import javax.swing.JButton; public abstract class Champion extends GameObject { // 移动 public boolean up, down, left, right; // 移动图集 static String[] imgs = new String[8]; // 第几张图片 int moveCount = 1; //技能图片 Image abilityOne; Image abilityTwo; Image abilityThree; //技能冷却时间 int coolDownTimeOne; int coolDownTimeTwo; int coolDownTimeThree; //三个技能是否处于冷却状态 boolean coolDownOne = true; boolean coolDownTwo = true; boolean coolDownThree = true; static { for (int i = 1; i < 8; i++) { imgs[i] = "img/move/" + i + ".png"; } } public Champion(GameFrame gameFrame) { // TODO Auto-generated constructor stub super(gameFrame); setImg("img/stand.png"); setX(700); setY(3800); setSpd(85); setHp(24000); setDis(250); setAttackCoolDownTime(1000); setCurrentHp(getHp()); } public void keyPressed(KeyEvent e) { int key = e.getKeyCode(); if (key == KeyEvent.VK_D) { right = true; } if (key == KeyEvent.VK_A) { left = true; } if (key == KeyEvent.VK_W) { up = true; } if (key == KeyEvent.VK_S) { down = true; } } public void keyReleased(KeyEvent e) { int key = e.getKeyCode(); if (key == KeyEvent.VK_D) { right = false; } if (key == KeyEvent.VK_A) { left = false; } if (key == KeyEvent.VK_W) { up = false; } if (key == KeyEvent.VK_S) { down = false; } } public void move() { if (up) { setY(getY() - getSpd()); } if (down) { setY(getY() + getSpd()); } if (left) { setX(getX() - getSpd()); } if (right) { setX(getX() + getSpd()); } if (up || down || left || right) { setImg(imgs[moveCount]); moveCount++; if (moveCount == 8) { moveCount = 1; } } else { setImg("img/stand.png"); } } /** * 添加三个技能按钮 * */ public void addButton() { JButton button1 = new JButton(); button1.setSize(100, 100); button1.setLocation(1056, 513); button1.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { abilityOne(); } }); JButton button2 = new JButton(); button2.setSize(100, 100); button2.setLocation(1090, 370); button2.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { abilityTwo(); } }); JButton button3 = new JButton(); button3.setSize(100, 100); button3.setLocation(1220, 300); button3.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { abilityThree(); } }); gameFrame.add(button1); gameFrame.add(button2); gameFrame.add(button3); } public abstract void abilityOne(); public abstract void abilityTwo(); public abstract void abilityThree(); public abstract void abilityEffect(Graphics g); @Override public void paintSelf(Graphics g) { // TODO Auto-generated method stub // 生命值为0 if (getCurrentHp() <= 0) { setAlive(false); gameFrame.removeList.add(this); } else { // 添加生命值 addHp(g, 30, 80, 80, 20, Color.GREEN); //绘制技能图片 g.drawImage(abilityOne, getX() + 360, getY() + 180, null); g.drawImage(abilityTwo, getX() + 400, getY() + 40, null); g.drawImage(abilityThree, getX() + 520, getY() - 30, null); // 绘制图片 g.drawImage(this.getImg(), getX() - 33, getY() - 50, null); // 改变画笔颜色 g.setColor(Color.GREEN); // 绘制中心圆点 g.fillOval(getX(), getY(), 10, 10); // 绘制矩形边框 g.drawRect(getX() - 23, getY() - 50, 60, 120); move(); abilityEffect(g); } } @Override public Rectangle getRec() { // TODO Auto-generated method stub return new Rectangle(getX() - 30, getY() - 60, 60, 120); } }
2.4 champoinDaji
package com.sxt; import java.awt.Color; import java.awt.Graphics; import java.awt.Polygon; import java.awt.Toolkit; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.Random; public class ChampionDaji extends Champion { // 技能是否处于释放状态 boolean ifAbilityOne = false; boolean ifAbilityTwo = false; // 鼠标监视器 MouseMonitor m; // 一技能多边形 Polygon p; // 一技能三角函数 double sin; double cos; // 一技能已经攻击过的目标 ArrayList<GameObject> attacked; // 一技能移动次数 int step = 0; // 技能二目标 GameObject abilityTwoTarget; // 技能二子弹 Bullet abilityTwoBullet; // 三技能子弹列表 Bullet[] bulletList = { new Bullet(), new Bullet(), new Bullet(), new Bullet(), new Bullet() }; public ChampionDaji(GameFrame gameFrame) { super(gameFrame); abilityOne = Toolkit.getDefaultToolkit().getImage("img/Daji/abilityOne.jpg"); abilityTwo = Toolkit.getDefaultToolkit().getImage("img/Daji/abilityTwo.jpg"); abilityThree = Toolkit.getDefaultToolkit().getImage("img/Daji/abilityThree.jpg"); // 三个技能冷却时间 coolDownTimeOne = 600; coolDownTimeTwo = 800; coolDownTimeThree = 8000; } public void exit() { this.gameFrame.removeMouseListener(m); } public void abilityOneMove() { p.translate((int) (50 * cos), -(int) (50 * sin)); for (GameObject redObj : gameFrame.redList) { // 是红色方小兵 && 发生碰撞 && 没在attacked列表里 if (redObj instanceof MinionRed && p.intersects(redObj.getRec()) && attacked.indexOf(redObj) == -1) { // 小兵扣血,添加到attacked里 redObj.setCurrentHp(redObj.getCurrentHp() - 400); attacked.add(redObj); } } } @Override public void abilityOne() { // TODO Auto-generated method stub if (coolDownOne) { m = new MouseMonitor(); p = new Polygon(); gameFrame.addMouseListener(m); attacked = new ArrayList<GameObject>(); } } @Override public void abilityTwo() { // TODO Auto-generated method stub if (coolDownTwo) { boolean find = false; for (GameObject redObj : gameFrame.objList) { // 是红色小兵 && 距离小于250 && 存活 if (redObj instanceof MinionRed && recIntersectsCir(redObj.getRec(), getX(), getY(), 250) && redObj.isAlive()) { // 添加子弹 abilityTwoBullet = new Bullet(gameFrame, this, redObj, 250, 60, "img/Daji/abilityTwoBullet.png"); gameFrame.objList.add(abilityTwoBullet); // 给目标赋值 abilityTwoTarget = redObj; // 释放二技能 ifAbilityTwo = true; find = true; break; } } if (find) { new AbilityTwoCD().start(); find = false; } } } /** * 点击技能三释放技能 先将技能范围内目标储存到targetList里 提前定义五个子弹 技能释放时初始化五个子弹 子弹目标从targetList里随机选择 * 如果期间目标死亡,制作一个目标替身,生命值设置为true 子弹与目标或替身碰撞后消失 */ @Override public void abilityThree() { // TODO Auto-generated method stub // 三技能没在冷却状态 if (coolDownThree) { // 创建列表来储存目标 ArrayList<GameObject> targetList = new ArrayList<GameObject>(); // 遍历redList for (int i = 0; i < gameFrame.redList.size(); i++) { GameObject target = gameFrame.redList.get(i); // 是红色小兵 && 在技能范围里 && 存活 if (target instanceof MinionRed && recIntersectsCir(target.getRec(), getX(), getY(), 250) && target.isAlive()) { targetList.add(target); } } //找到目标 if(targetList.size() != 0) { //初始化五个子弹,随机攻击列表里的目标 Random random = new Random(); int count = 0; while(count < 5) { int r = random.nextInt(targetList.size()); if(!targetList.get(r).isAlive()) { //目标死亡,制作替身 GameObject substitute = targetList.get(r); substitute.setAlive(true); bulletList[count] = new Bullet(gameFrame, this, substitute, 250, 60, "img/Daji/abilityTwoBullet.png"); }else { bulletList[count] = new Bullet(gameFrame, this, targetList.get(r), 250, 60, "img/Daji/abilityTwoBullet.png"); } count++; } new AbilityThreeBulletCD().start(); new AbilityThreeCD().start(); } } } @Override public void abilityEffect(Graphics g) { // TODO Auto-generated method stub if (ifAbilityOne) { g.setColor(Color.RED); g.fillPolygon(p); abilityOneMove(); step++; if (step == 10) { step = 0; ifAbilityOne = false; } } if (ifAbilityTwo) { System.out.println(abilityTwoTarget.beControlled); if (abilityTwoBullet.getRec().intersects(abilityTwoTarget.getRec())) { new AbilityControllCD().start(); ifAbilityTwo = false; } } } // 技能一冷却时间 class AbilityOneCD extends Thread { public void run() { // 将技能一设置为冷却状态 coolDownOne = false; // 线程休眠 try { // one来表示一技能冷却时间 int one = coolDownTimeOne; while (one > 0) { Thread.sleep(1000); System.out.println("一技能冷却时间: " + one / 1000); one -= 1000; } } catch (Exception e) { e.printStackTrace(); } // 将技能一设置为攻击状态 coolDownOne = true; // 线程终止 this.stop(); } } // 技能二冷却时间 class AbilityTwoCD extends Thread { public void run() { // 将技能二设置为冷却状态 coolDownTwo = false; // 线程休眠 try { // one来表示二技能冷却时间 int two = coolDownTimeTwo; while (two > 0) { Thread.sleep(1000); System.out.println("二技能冷却时间: " + two / 1000); two -= 1000; } } catch (Exception e) { e.printStackTrace(); } // 将技能二设置为攻击状态 coolDownTwo = true; // 线程终止 this.stop(); } } // 技能二控制时间 class AbilityControllCD extends Thread { public void run() { abilityTwoTarget.beControlled = true; // 线程休眠 try { Thread.sleep(20000); } catch (Exception e) { e.printStackTrace(); } abilityTwoTarget.beControlled = false; this.stop(); } } // 技能三冷却时间 class AbilityThreeCD extends Thread { public void run() { // 将技能三设置为冷却状态 coolDownThree = false; // 线程休眠 try { // three来表示三技能冷却时间 int three = coolDownTimeThree; while (three > 0) { Thread.sleep(1000); System.out.println("三技能冷却时间: " + three / 1000); three -= 1000; } } catch (Exception e) { e.printStackTrace(); } // 将技能三设置为攻击状态 coolDownThree = true; // 线程终止 this.stop(); } } //技能三子弹时间间隔 class AbilityThreeBulletCD extends Thread{ public void run() { try { gameFrame.objList.add(bulletList[0]); Thread.sleep(200); gameFrame.objList.add(bulletList[1]); Thread.sleep(200); gameFrame.objList.add(bulletList[2]); Thread.sleep(200); gameFrame.objList.add(bulletList[3]); Thread.sleep(200); gameFrame.objList.add(bulletList[4]); }catch(Exception e) { e.printStackTrace(); } this.stop(); } } // 鼠标监视器 private class MouseMonitor extends MouseAdapter { @Override public void mousePressed(MouseEvent e) {// 当鼠标点击时 int mouseX = e.getX(), mouseY = e.getY(), playerX = 700, playerY = 350; double dis = getDis(mouseX, mouseY, playerX, playerY); // 三角函数 cos = (mouseX - playerX) / dis; sin = -(mouseY - playerY) / dis; // 坐标差 int difX = (int) (60 * sin); int difY = (int) (60 * cos); p.addPoint(getX() - difX, getY() - difY); p.addPoint(getX() + difX, getY() + difY); p.addPoint(getX() + difX + (int) (20 * cos), getY() + difY - (int) (20 * sin)); p.addPoint(getX() - difX + (int) (20 * cos), getY() - difY - (int) (20 * sin)); exit(); new AbilityOneCD().start(); ifAbilityOne = true; } } }
2.5 champoinHouyi
package com.sxt; import java.awt.Color; import java.awt.Graphics; import java.awt.Image; import java.awt.Polygon; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; import javax.swing.JButton; public class ChampionHouyi extends Champion { // 技能是否处于释放状态 boolean ifAbilityTwo = false; boolean ifAbilityThree = false; // 鼠标监视器 MouseMonitorTwo m2; MouseMonitor m; // 一技能多边形 Polygon p; // 一技能三角函数 double sin; double cos; // 二技能坐标 int abilityTwoX; int abilityTwoY; // 技能三目标 GameObject abilityThreeTarget; // 技能三是否出界 boolean ifXOutside = false; boolean ifYOutside = false; public ChampionHouyi(GameFrame gameFrame) { super(gameFrame); abilityOne = Toolkit.getDefaultToolkit().createImage("img/Houyi/abilityOne.jpg"); abilityTwo = Toolkit.getDefaultToolkit().createImage("img/Houyi/abilityTwo.jpg"); abilityThree = Toolkit.getDefaultToolkit().createImage("img/Houyi/abilityThree.jpg"); // 三个技能冷却时间 coolDownTimeOne = 600; coolDownTimeTwo = 800; coolDownTimeThree = 8000; // TODO Auto-generated constructor stub } public void exit(MouseAdapter ma) { this.gameFrame.removeMouseListener(ma); } public void abilityOneAttack() { // 目标列表,最多三个目标 ArrayList<GameObject> targets = new ArrayList<GameObject>(); // 遍历敌方列表寻找目标 for (GameObject redObj : gameFrame.redList) { // 是红色小兵 && 在攻击范围内 if (redObj instanceof MinionRed && recIntersectsCir(redObj.getRec(), getX() - 250, getY() - 250, 500)) { targets.add(redObj); if (targets.size() == 3) { break; } } } for (int i = 0; i < targets.size(); i++) { Bullet bullet; if (i == 0) { bullet = new Bullet(gameFrame, this, targets.get(i), 400, 50); } else { bullet = new Bullet(gameFrame, this, targets.get(i), 200, 50); } gameFrame.objList.add(bullet); } } public void abilityTwoAttack() { for (GameObject redObj : gameFrame.redList) { // 红色小兵 && 与大圆相交 if (redObj instanceof MinionRed && recIntersectsCir(redObj.getRec(), abilityTwoX, abilityTwoY, 60)) { redObj.setCurrentHp(redObj.getCurrentHp() - 400); // 红色小兵 && 与小圆相交 if (redObj instanceof MinionRed && recIntersectsCir(redObj.getRec(), abilityTwoX, abilityTwoY, 30)) { redObj.setCurrentHp(redObj.getCurrentHp() - 200); } } } } public void abilityThreeMove() { p.translate((int) (50 * cos), -(int) (50 * sin)); for (GameObject redObj : gameFrame.redList) { // 是红色方小兵 && 发生碰撞 if (redObj instanceof MinionRed && p.intersects(redObj.getRec())) { redObj.setCurrentHp(redObj.getCurrentHp() - 400); abilityThreeTarget = redObj; new AbilityControlCD().start(); ifAbilityThree = false; } } if (!ifXOutside) { for (int x : p.xpoints) { if (x < 0 || x >= 5165) { ifXOutside = true; break; } } } if (!ifYOutside) { for (int y : p.ypoints) { if (y < 0 || y >= 4085) { ifYOutside = true; break; } } } } /** * 制作游戏界面攻击按钮的替身 替换攻击按钮 新的攻击按钮事件: 1. 定义目标列表 2. 添加目标,最多添加三个 3. * 目标列表第一个造成400伤害,其余200伤害 4. 持续5秒,结束后替换攻击按钮️ */ @Override public void abilityOne() { // TODO Auto-generated method stub new AbilityOneDuration().start(); new AbilityOneCD().start(); } /** * 技能二 点击按钮释放二技能 点击技能范围内任意位置 生成一个直径120大圆和一个直径60小圆 大圆造成400伤害 小圆造成200伤害 */ @Override public void abilityTwo() { // TODO Auto-generated method stub m2 = new MouseMonitorTwo(); gameFrame.addMouseListener(m2); abilityTwoX = 0; abilityTwoY = 0; } @Override public void abilityThree() { // TODO Auto-generated method stub if (coolDownThree) { m = new MouseMonitor(); p = new Polygon(); gameFrame.addMouseListener(m); ifAbilityThree = true; new AbilityThreeCD().start(); } } @Override public void abilityEffect(Graphics g) { // TODO Auto-generated method stub if (ifAbilityTwo) { g.setColor(Color.RED); g.fillOval(abilityTwoX - 60, abilityTwoY - 60, 120, 120); g.setColor(Color.BLACK); g.fillOval(abilityTwoX - 30, abilityTwoY - 30, 60, 60); abilityTwoAttack(); // 释放结束 abilityTwoX = 0; abilityTwoY = 0; ifAbilityTwo = false; new AbilityTwoCD().start(); } if (ifAbilityThree) { g.setColor(Color.RED); g.fillPolygon(p); abilityThreeMove(); if (ifXOutside || ifYOutside) { ifAbilityThree = false; p = new Polygon(); } } } // 技能一冷却时间 class AbilityOneCD extends Thread { public void run() { // 将技能一设置为冷却状态 coolDownOne = false; // 线程休眠 try { // one来表示一技能冷却时间 int one = coolDownTimeOne; while (one > 0) { Thread.sleep(1000); System.out.println("一技能冷却时间: " + one / 1000); one -= 1000; } } catch (Exception e) { e.printStackTrace(); } // 将技能一设置为攻击状态 coolDownOne = true; // 线程终止 this.stop(); } } // 技能一攻击时间间隔 class AttackCD extends Thread { public void run() { // 将攻击功能设置为冷却状态 setAttackCoolDown(false); // 线程休眠 try { Thread.sleep(getAttackCoolDownTime()); } catch (Exception e) { e.printStackTrace(); } // 将攻击功能设置为攻击状态 setAttackCoolDown(true); // 线程终止 this.stop(); } } // 技能一效果持续时间 class AbilityOneDuration extends Thread { public void run() { JButton substitute = gameFrame.attackButton; gameFrame.remove(gameFrame.attackButton); JButton abilityOneButton = new JButton(); abilityOneButton.setSize(130, 132); abilityOneButton.setLocation(1150, 430); abilityOneButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { abilityOneAttack(); } }); gameFrame.add(abilityOneButton); // 休眠五秒 try { Thread.sleep(5000); } catch (Exception e) { e.printStackTrace(); } gameFrame.remove(abilityOneButton); gameFrame.add(substitute); this.stop(); } } // 技能二冷却时间 class AbilityTwoCD extends Thread { public void run() { // 将技能二设置为冷却状态 coolDownTwo = false; // 线程休眠 try { // two来表示二技能冷却时间 int two = coolDownTimeTwo; while (two > 0) { Thread.sleep(1000); System.out.println("二技能冷却时间: " + two / 1000); two -= 1000; } } catch (Exception e) { e.printStackTrace(); } // 将技能二设置为攻击状态 coolDownTwo = true; // 线程终止 this.stop(); } } class AbilityThreeCD extends Thread { public void run() { // 将攻击功能设置为冷却状态 coolDownThree = false; // 休眠 try { int three = coolDownTimeThree; while (coolDownTimeThree > 0) { Thread.sleep(1000); System.out.println("技能三冷却时间: " + coolDownTimeThree / 1000); coolDownTimeThree -= 1000; } coolDownTimeThree = three; } catch (Exception e) { e.printStackTrace(); } // 将攻击功能解除冷却状态 coolDownThree = true; // 线程终止 this.stop(); } } // 技能三控制时间 class AbilityControlCD extends Thread { public void run() { abilityThreeTarget.beControlled = true; // 线程休眠 try { Thread.sleep(20000); } catch (Exception e) { e.printStackTrace(); } abilityThreeTarget.beControlled = false; this.stop(); } } // 二技能鼠标监视器 private class MouseMonitorTwo extends MouseAdapter { @Override public void mousePressed(MouseEvent e) {// 当鼠标点击时 int mouseX = e.getX(), mouseY = e.getY(), playerX = 700, playerY = 350; double dis = getDis(mouseX, mouseY, playerX, playerY); // 点击位置在技能范围里 if (dis < 250) { abilityTwoX = mouseX - playerX + getX(); abilityTwoY = mouseY - playerY + getY(); } ifAbilityTwo = true; exit(this); } } // 鼠标监视器 private class MouseMonitor extends MouseAdapter { @Override public void mousePressed(MouseEvent e) {// 当鼠标点击时 int mouseX = e.getX(), mouseY = e.getY(), playerX = 700, playerY = 350; double dis = getDis(mouseX, mouseY, playerX, playerY); // 三角函数 cos = (mouseX - playerX) / dis; sin = -(mouseY - playerY) / dis; // 坐标差 int difX = (int) (60 * sin); int difY = (int) (60 * cos); p.addPoint(getX() - difX, getY() - difY); p.addPoint(getX() + difX, getY() + difY); p.addPoint(getX() + difX + (int) (20 * cos), getY() + difY - (int) (20 * sin)); p.addPoint(getX() - difX + (int) (20 * cos), getY() - difY - (int) (20 * sin)); exit(this); new AbilityOneCD().start(); ifAbilityThree = true; } } }
2.6 GameFrame
package com.sxt; import java.awt.Graphics; import java.awt.Image; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.util.ArrayList; import javax.swing.JButton; import javax.swing.JFrame; public class GameFrame extends JFrame { // 窗口尺寸 private int windowWidth = 1400; private int windowHeight = 700; // 双缓冲图片 private Image offScreenImage = null; // 攻击图片 private Image attack = Toolkit.getDefaultToolkit().getImage("img/attack.jpg"); // 游戏背景 Background background = new Background(this); // 游戏玩家 Champion player = new ChampionHouyi(this); // 双方小兵 MinionBlue mb = new MinionBlue(this); MinionRed mr = new MinionRed(this); // 防御塔 Turret turret = new Turret(this); // 攻击按钮 JButton attackButton; // 游戏元素列表 ArrayList<GameObject> objList = new ArrayList<GameObject>(); ArrayList<GameObject> redList = new ArrayList<GameObject>();// 红色方 ArrayList<GameObject> blueList = new ArrayList<GameObject>();// 蓝色方 ArrayList<GameObject> removeList = new ArrayList<GameObject>();// 存放将要删除的元素 public void launch() { // 设置尺寸 setSize(windowWidth, windowHeight); // 窗口居中 setLocationRelativeTo(null); // 关闭事件 setDefaultCloseOperation(3); // 用户不能调整窗口大小 setResizable(false); // 标题 setTitle("尚学堂王者荣耀"); // 窗口可见 setVisible(true); // 添加键盘监视器 this.addKeyListener(new GameFrame.KeyMonitor()); // 添加游戏元素 objList.add(background); objList.add(player); objList.addAll(turret.turretList); blueList.add(turret.turretList.get(0)); redList.add(turret.turretList.get(4)); /** * 攻击按钮 */ attackButton = new JButton(); attackButton.setSize(130, 132); attackButton.setLocation(1150, 430); attackButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // 按钮事件 player.attack(redList); } }); this.add(attackButton); player.addButton(); while (true) { mb.createMinion(this, blueList); mr.createMinion(this, redList); turret.addTurret(this); repaint(); try { Thread.sleep(25); } catch (Exception e) { e.printStackTrace(); } } } public void paint(Graphics g) { // System.out.println(player.getX()+" "+player.getY()); if (offScreenImage == null) { offScreenImage = this.createImage(5984, 4452); } Graphics gImage = offScreenImage.getGraphics(); for (int i = 0; i < objList.size(); i++) { objList.get(i).paintSelf(gImage); } // 绘制攻击图片 gImage.drawImage(attack, player.getX() + 500, player.getY() + 100, null); objList.removeAll(removeList); g.drawImage(offScreenImage, -player.getX() + 700, -player.getY() + 350, null); /** * 添加按钮后不能调用键盘事件 因为程序的焦点变成了按钮 this.requestFocus() 把焦点重新改变到游戏界面上 */ this.requestFocus(); } // main方法 public static void main(String[] args) { GameFrame gameFrame = new GameFrame(); gameFrame.launch(); } // 键盘事件 private class KeyMonitor extends KeyAdapter { @Override public void keyPressed(KeyEvent e) { int key = e.getKeyCode(); player.keyPressed(e); } @Override public void keyReleased(KeyEvent e) { int key = e.getKeyCode(); player.keyReleased(e); } } }
2.7 GameObject
package com.sxt; import java.awt.Color; import java.awt.Graphics; import java.awt.Image; import java.awt.Rectangle; import java.awt.Toolkit; import java.util.ArrayList; public abstract class GameObject { // 坐标 private int x; private int y; // 图片 private Image img; // 游戏界面 GameFrame gameFrame; // 速度 private int spd; // 初始生命值 private int hp; // 当前生命值 private int currentHp; // 攻击目标 private GameObject target; // 是否有目标 private boolean hasTarget = false; // 攻击距离 private int dis; // 攻击时间间隔 private int attackCoolDownTime; // 攻击是否冷却 private boolean attackCoolDown = true; // 是否存活 private boolean alive = true; //是否被控制 boolean beControlled = false; public GameObject(GameFrame gameFrame) { this.gameFrame = gameFrame; } public GameObject(int x, int y, GameFrame gameFrame) { this.x = x; this.y = y; this.gameFrame = gameFrame; } public GameObject() { // TODO Auto-generated constructor stub } public void addHp(Graphics g, int difX, int difY, int width, int height, Color color) { // 绘制外部轮廓 g.setColor(Color.black); g.drawRect(getX() - difX, getY() - difY, width, height); // 填充矩形 g.setColor(color); g.fillRect(getX() - difX, getY() - difY, (int) (width * getCurrentHp() / getHp()), height); } public double getDis(int x1, int y1, int x2, int y2) { return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2)); } // 矩形矩形碰撞检测 public boolean recIntersectsRec(Rectangle r1, Rectangle r2) { return r1.intersects(r2); } public boolean recIntersectsCir(Rectangle rec, int x, int y, int r) { /** 矩形于圆相交: 圆心到至少一个矩形定点的距离小于r */ if ((getDis(x, y, rec.x, rec.y) < r) || (getDis(x, y, rec.x, rec.y + rec.height) < r) || (getDis(x, y, rec.x + rec.width, rec.y) < r) || (getDis(x, y, rec.x + rec.width, rec.y + rec.height) < r)) { return true; } return false; } // 攻击方法 public void attack(ArrayList<GameObject> gameObjList) { if (hasTarget) { // 目标离开范围后寻找新的目标 if (!recIntersectsCir(target.getRec(), getX(), getY(), getDis())) { setHasTarget(false); } // 目标死亡,寻找新目标 else if (!target.isAlive()) { setHasTarget(false); } else if (isAttackCoolDown() && isAlive()) { Bullet bullet = null; // 防御塔攻击 if (Turret.class.isAssignableFrom(getClass())) { bullet = new Bullet(gameFrame, this, getTarget(), 500, 50); } // 小兵攻击 else if (Minion.class.isAssignableFrom(getClass())) { bullet = new Bullet(gameFrame, this, getTarget(), 50, 30); } // 玩家攻击 else if (this instanceof Champion) { bullet = new Bullet(gameFrame, this, getTarget(), 50000, 50); } gameFrame.objList.add(bullet); // 线程开始 new AttackCD().start(); } } else { // 遍历列表 for (GameObject obj : gameObjList) { // 判断攻击范围(圆形)与敌方(矩形)是否相交 if (recIntersectsCir(obj.getRec(), getX(), getY(), getDis())) { // 找到目标 setTarget(obj); setHasTarget(true); // 跳出循环 break; } } // 玩家是否在攻击范围内 if (!hasTarget && gameObjList == gameFrame.blueList) { if (recIntersectsCir(gameFrame.player.getRec(), getX(), getY(), getDis())) { // 找到目标 setTarget(gameFrame.player); setHasTarget(true); } } } } class AttackCD extends Thread { public void run() { // 将攻击功能设置为冷却状态 setAttackCoolDown(false); // 线程休眠 try { Thread.sleep(attackCoolDownTime); } catch (Exception e) { e.printStackTrace(); } // 将攻击功能设置为攻击状态 setAttackCoolDown(true); // 线程终止 this.stop(); } } // 绘制元素 public abstract void paintSelf(Graphics g); // 返回矩形 public abstract Rectangle getRec(); /** * @return the x */ public int getX() { return x; } /** * @param x the x to set */ public void setX(int x) { this.x = x; } /** * @return the y */ public int getY() { return y; } /** * @param y the y to set */ public void setY(int y) { this.y = y; } /** * @return the img */ public Image getImg() { return img; } /** * @param img the img to set */ public void setImg(String img) { this.img = Toolkit.getDefaultToolkit().getImage(img); } /** * @return the spd */ public int getSpd() { return spd; } /** * @param spd the spd to set */ public void setSpd(int spd) { this.spd = spd; } /** * @return the hp */ public int getHp() { return hp; } /** * @param hp the hp to set */ public void setHp(int hp) { this.hp = hp; } /** * @return the currentHp */ public int getCurrentHp() { return currentHp; } /** * @param currentHp the currentHp to set */ public void setCurrentHp(int currentHp) { this.currentHp = currentHp; } /** * @return the target */ public GameObject getTarget() { return target; } /** * @param target the target to set */ public void setTarget(GameObject target) { this.target = target; } /** * @return the hasTarget */ public boolean isHasTarget() { return hasTarget; } /** * @param hasTarget the hasTarget to set */ public void setHasTarget(boolean hasTarget) { this.hasTarget = hasTarget; } /** * @return the dis */ public int getDis() { return dis; } /** * @param dis the dis to set */ public void setDis(int dis) { this.dis = dis; } /** * @return the attackCoolDownTime */ public int getAttackCoolDownTime() { return attackCoolDownTime; } /** * @param attackCoolDownTime the attackCoolDownTime to set */ public void setAttackCoolDownTime(int attackCoolDownTime) { this.attackCoolDownTime = attackCoolDownTime; } /** * @return the attackCoolDown */ public boolean isAttackCoolDown() { return attackCoolDown; } /** * @param attackCoolDown the attackCoolDown to set */ public void setAttackCoolDown(boolean attackCoolDown) { this.attackCoolDown = attackCoolDown; } /** * @return the alive */ public boolean isAlive() { return alive; } /** * @param alive the alive to set */ public void setAlive(boolean alive) { this.alive = alive; } }
2.8 Minion
package com.sxt; import java.awt.Color; import java.awt.Graphics; import java.awt.Rectangle; import java.util.ArrayList; public abstract class Minion extends GameObject { // 是否生成下一个小兵 private boolean nextMinion = true; // 是否生成下一波小兵 private boolean nextLine = true; // 生成小兵数量 private int minionCount = 0; // 是否检测到目标 private boolean ifFindTarget = false; public Minion(GameFrame gameFrame) { super(gameFrame); setHp(800); setCurrentHp(getHp()); setDis(100); setAttackCoolDownTime(2000); // TODO Auto-generated constructor stub } /** * (1325, 3750) (4425, 3750) (5050, 3125) (5050, 1125) */ public abstract void move(ArrayList<GameObject> objList); public void findTarget(ArrayList<GameObject> objList) { for (GameObject obj : objList) { if (recIntersectsCir(obj.getRec(), getX(), getY(), 200)) { setTarget(obj); setIfFindTarget(true); } } if (objList == gameFrame.blueList) { if (recIntersectsCir(gameFrame.player.getRec(), getX(), getY(), 200)) { setTarget(gameFrame.player); setIfFindTarget(true); } } } public void moveToTarget() { int dis = (int) getDis(getX(), getY(), getTarget().getX(), getTarget().getY()); int xSpeed = (int) (getSpd() * (getTarget().getX() - getX()) / dis); int ySpeed = (int) (getSpd() * (getTarget().getY() - getY()) / dis); if (!hitMinion(getX() + xSpeed, getY(), gameFrame.objList)) { setX(getX() + xSpeed); } if (!hitMinion(getX(), getY() + ySpeed, gameFrame.objList)) { setY(getY() + ySpeed); } } /** * @param x: 下一步的横坐标 * @param y: 下一步的纵坐标 * @param objList: 小兵列表 * @return 下一步位置与其他小兵是否碰撞 */ public boolean hitMinion(int x, int y, ArrayList<GameObject> objList) { // 新的区域生成的矩形 Rectangle r1 = new Rectangle(x - 16, y - 16, 45, 45); // 遍历列表 for (GameObject obj : objList) { if (obj.getClass() == this.getClass() && obj != this) { Rectangle r = obj.getRec(); if (recIntersectsRec(r1, r)) { return true; } } } return false; } public void createMinion(GameFrame gameFrame, ArrayList<GameObject> minionList) { if (nextLine) { if (nextMinion) { // 蓝色方小兵 if (minionList == this.gameFrame.blueList) { MinionBlue mb = new MinionBlue(gameFrame); gameFrame.objList.add(mb); minionList.add(mb); } // 红色方小兵 else { MinionRed mr = new MinionRed(gameFrame); gameFrame.objList.add(mr); minionList.add(mr); } minionCount++; new NextMinion().start(); } if (minionCount == 3) { minionCount = 0; new NextLine().start(); } } } // 每个小兵生成时间 class NextMinion extends Thread { public void run() { nextMinion = false; // 休眠1.5s try { Thread.sleep(1500); } catch (Exception e) { e.printStackTrace(); } nextMinion = true; // 线程终止 this.stop(); } } // 每波小兵生成时间 class NextLine extends Thread { public void run() { nextLine = false; // 休眠15s try { Thread.sleep(15000); } catch (Exception e) { e.printStackTrace(); } nextLine = true; // 线程终止 this.stop(); } } @Override public void paintSelf(Graphics g) { // TODO Auto-generated method stub // 生命值为0 if (getCurrentHp() <= 0) { setAlive(false); gameFrame.removeList.add(this); if (this instanceof MinionBlue) { gameFrame.blueList.remove(this); } else { gameFrame.redList.remove(this); } } else { // 添加生命值 if (this instanceof MinionBlue) { this.addHp(g, 17, 28, 45, 10, Color.GREEN); } else { this.addHp(g, 17, 28, 45, 10, Color.RED); } g.drawImage(getImg(), getX() - 16, getY() - 16, null); g.setColor(Color.RED); g.fillOval(getX(), getY(), 10, 10); g.drawRect(getX() - 16, getY() - 16, 45, 45); g.drawOval(getX() - 200, getY() - 200, 400, 400); // 小兵移动 if (!beControlled) { if (this instanceof MinionBlue) { move(gameFrame.redList); } else { move(gameFrame.blueList); } } } } @Override public Rectangle getRec() { // TODO Auto-generated method stub return new Rectangle(getX() - 16, getY() - 16, 45, 45); } /** * @return the ifFindTarget */ public boolean isIfFindTarget() { return ifFindTarget; } /** * @param ifFindTarget the ifFindTarget to set */ public void setIfFindTarget(boolean ifFindTarget) { this.ifFindTarget = ifFindTarget; } }
2.9 MinionBule
package com.sxt; import java.util.ArrayList; public class MinionBlue extends Minion { public MinionBlue(GameFrame gameFrame) { super(gameFrame); setImg("img/minion/blue.jpg"); setX(1325); setY(3750); // TODO Auto-generated constructor stub } @Override public void move(ArrayList<GameObject> objList) { // TODO Auto-generated method stub if (isIfFindTarget()) { // 离开检测范围 if (!recIntersectsCir(getTarget().getRec(), getX(), getY(), 200)) { setIfFindTarget(false); } else { if (!isHasTarget()) { moveToTarget(); } attack(objList); } } else { findTarget(objList); // 原路线移动 if (getX() < 4425) { setSpd(18); if (!hitMinion(getX() + getSpd(), getY(), gameFrame.blueList)) { setX(getX() + getSpd()); } } else if (getX() < 5100 && getX() >= 4425) { setSpd(20); if (!hitMinion(getX() + getSpd(), getY(), gameFrame.blueList)) { setX(getX() + getSpd()); } if (!hitMinion(getX(), getY() - getSpd(), gameFrame.blueList)) { setY(getY() - getSpd()); } } else if (getX() >= 4900) { setSpd(18); if (!hitMinion(getX() + getSpd(), getY() - getSpd(), gameFrame.blueList)) { setY(getY() - getSpd()); } } } } }
2.10 MinionRed
package com.sxt; import java.util.ArrayList; public class MinionRed extends Minion { public MinionRed(GameFrame gameFrame) { super(gameFrame); setImg("img/minion/red.jpg"); setX(5050); setY(1125); // TODO Auto-generated constructor stub } @Override public void move(ArrayList<GameObject> objList) { // TODO Auto-generated method stub if (isIfFindTarget()) { // 离开检测范围 if (!recIntersectsCir(getTarget().getRec(), getX(), getY(), 200)) { setIfFindTarget(false); } else { if (!isHasTarget()) { moveToTarget(); } attack(objList); } } else { findTarget(objList); // 原路线移动 if (getY() < 3125) { setSpd(28); if (!hitMinion(getX(), getY() + getSpd(), gameFrame.redList)) { setY(getY() + getSpd()); } } else if (getY() < 3750 && getY() >= 3125) { setSpd(20); if (!hitMinion(getX(), getY() + getSpd(), gameFrame.redList)) { setY(getY() + getSpd()); } if (!hitMinion(getX() - getSpd(), getY(), gameFrame.redList)) { setX(getX() - getSpd()); } } else if (getY() >= 3750) { setSpd(25); if (!hitMinion(getX() - getSpd(), getY(), gameFrame.redList)) { setX(getX() - getSpd()); } } } } }
2.11 Turret
package com.sxt; import java.awt.Color; import java.awt.Graphics; import java.awt.Rectangle; import java.util.ArrayList; public class Turret extends GameObject { ArrayList<Turret> turretList = new ArrayList<Turret>(); public Turret turretBlueOne; public Turret turretBlueTwo; public Turret turretBlueThree; public Turret turretBlueBase; public Turret turretRedOne; public Turret turretRedTwo; public Turret turretRedThree; public Turret turretRedBase; public Turret(GameFrame gameFrame) { super(gameFrame); setImg("img/turret.png"); // 初始化八个防御塔 turretList.add(turretBlueOne = new TurretBlue(1860, 3790, gameFrame)); turretList.add(turretBlueTwo = new TurretBlue(2650, 3820, gameFrame)); turretList.add(turretBlueThree = new TurretBlue(3995, 3830, gameFrame)); turretList.add(turretBlueBase = new TurretBlue(1130, 3650, gameFrame)); turretList.add(turretRedOne = new TurretRed(5100, 3030, gameFrame)); turretList.add(turretRedTwo = new TurretRed(5120, 2100, gameFrame)); turretList.add(turretRedThree = new TurretRed(5060, 1570, gameFrame)); turretList.add(turretRedBase = new TurretRed(4850, 1100, gameFrame)); // TODO Auto-generated constructor stub } public Turret(int x, int y, GameFrame gameFrame) { super(x, y, gameFrame); setImg("img/turret.png"); setHp(6000); setCurrentHp(getHp()); setAttackCoolDownTime(1000); setDis(300); } public void addTurret(GameFrame gameFrame) { /** * 添加到objList里会被绘制出来,添加到redList和blueList才会被攻击 前一个防御塔爆炸后再把后一个添加到列表里 */ if (turretBlueOne.isAlive() && turretBlueTwo.isAlive() && gameFrame.blueList.indexOf(gameFrame.turret.turretBlueTwo) == -1) { gameFrame.blueList.add(gameFrame.turret.turretBlueTwo); } if (!turretBlueTwo.isAlive() && turretBlueThree.isAlive() && gameFrame.blueList.indexOf(gameFrame.turret.turretBlueThree) == -1) { gameFrame.blueList.add(gameFrame.turret.turretBlueThree); } if (!turretBlueThree.isAlive() && turretBlueBase.isAlive() && gameFrame.blueList.indexOf(gameFrame.turret.turretBlueBase) == -1) { gameFrame.blueList.add(gameFrame.turret.turretBlueBase); } if (!turretBlueBase.isAlive()) { } if (!turretRedOne.isAlive() && turretRedTwo.isAlive() && gameFrame.redList.indexOf(gameFrame.turret.turretRedTwo) == -1) { gameFrame.redList.add(gameFrame.turret.turretRedTwo); } if (!turretRedTwo.isAlive() && turretRedThree.isAlive() && gameFrame.redList.indexOf(gameFrame.turret.turretRedThree) == -1) { gameFrame.redList.add(gameFrame.turret.turretRedThree); } if (!turretRedThree.isAlive() && turretRedBase.isAlive() && gameFrame.redList.indexOf(gameFrame.turret.turretRedBase) == -1) { gameFrame.redList.add(gameFrame.turret.turretRedBase); } if (!turretRedBase.isAlive()) { } } @Override public void paintSelf(Graphics g) { // 生命值为0 if (getCurrentHp() <= 0) { setAlive(false); gameFrame.removeList.add(this); if (this instanceof TurretBlue) { gameFrame.blueList.remove(this); } else { gameFrame.redList.remove(this); } } else { // 添加生命值 if (this instanceof TurretBlue) { this.addHp(g, 50, 130, 100, 20, Color.GREEN); attack(gameFrame.redList); } else { this.addHp(g, 50, 130, 100, 20, Color.RED); attack(gameFrame.blueList); } g.drawImage(getImg(), getX() - 50, getY() - 100, null); g.fillOval(getX(), getY(), 10, 10); g.drawRect(getX() - 50, getY() - 100, 100, 180); g.drawOval(getX() - 300, getY() - 300, 600, 600); } } @Override public Rectangle getRec() { // TODO Auto-generated method stub return new Rectangle(getX() - 50, getY() - 100, 100, 180); } }
2.12 TurretBule
package com.sxt; public class TurretBlue extends Turret { public TurretBlue(GameFrame gameFrame) { super(gameFrame); // TODO Auto-generated constructor stub } public TurretBlue(int x, int y, GameFrame gameFrame) { super(x, y, gameFrame); } }
2.13 TurretRed
package com.sxt; public class TurretRed extends Turret { public TurretRed(GameFrame gameFrame) { super(gameFrame); // TODO Auto-generated constructor stub } public TurretRed(int x, int y, GameFrame gameFrame) { super(x, y, gameFrame); } }
3.运行截图