资料来源:https://www.bilibili.com/video/BV1Aq4y1W79E?p=2
1、战斗机:HeroPlane
package cn.tx.ltzj;
import javax.swing.*;
import java.awt.*;
// 飞机在不断的监控按下的键盘,所以继承Thread,单独使用一个线程
public class HeroPlane extends Thread{
// 英雄机在画板上的位置
int x = 230, y = 600;
// 飞机大小
int width = 80, heigth = 80;
// 飞机移动的速度
int speed = 8;
// 飞机图像
Image image = new ImageIcon("img/10011.png").getImage();
// 定义键盘上方向键的标志
boolean up, down, left, right;
public HeroPlane(int x, int y, int width, int heigth) {
this.x = x;
this.y = y;
this.width = width;
this.heigth = heigth;
}
public HeroPlane() {
}
@Override
public void run() {
while (true){
if(up){
// y轴向上
y -= speed;
}
if(down){
// y轴向下
y += speed;
}
if(left){
x -= speed;
}
if(right){
x += speed;
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
2、敌机:EnemyPlane
package cn.tx.ltzj;
import javax.swing.*;
import java.awt.*;
// 敌机
public class EnemyPlane extends Thread{
public GameFrame gf;
// 敌机在画板上的位置
public int x, y;
// 飞机大小
public int width = 40, heigth = 40;
// 飞机移动的速度
public int speed = 1;
// 飞机图像
public Image image = new ImageIcon("img/10025.png").getImage();
public EnemyPlane(int x, int y, GameFrame gf) {
super();
this.gf = gf;
this.x = x;
this.y = y;
}
public EnemyPlane(int x, int y, int width, int heigth, GameFrame gf) {
super();
this.gf = gf;
this.x = x;
this.y = y;
this.width = width;
this.heigth = heigth;
}
// 飞翔的额逻辑,移动的逻辑都在这里
public void run(){
while (true){
// 向左走
// 碰撞到了
if(hit()){
System.out.println("hit........");
this.speed = 0;
// 敌机爆炸了
this.image = new ImageIcon("img/300350.png").getImage();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 从屏幕中移除被击毁的敌机
gf.enemyPlanes.remove(this);
break; // 飞机被子弹击毁的中断。中断当前敌机的线程
}
// 飞机没有被击毁,但已过边界
if(this.y >= 760){
break;
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// 检测碰撞
public boolean hit(){
// Swing技术中,已经提供
// 声明敌机的矩形
Rectangle myrect = new Rectangle(this.x, this.y, this.width, this.heigth);
// 声明子弹的矩形
Rectangle rect = null;
// 遍历所有的矩形
for (int i = 0; i < gf.bullets.size(); i++) {
Bullet bullet = gf.bullets.get(i);
System.out.println("test hit");
rect = new Rectangle(bullet.x, bullet.y - 1, bullet.width, bullet.heigth);
// 碰撞检测:子弹与敌机的碰撞
if(myrect.intersects(rect)){
return true;
}
}
return false;
}
@Override
public String toString() {
return "EnemyPlane{" +
"x=" + x +
", y=" + y +
", width=" + width +
", heigth=" + heigth +
'}';
}
}
3、玩家:Player
package cn.tx.ltzj;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
/**
* 定义一个玩家,继承键盘适配器
*/
public class Player extends KeyAdapter {
GameFrame gameFrame;
public Player(GameFrame gameFrame) {
this.gameFrame = gameFrame;
}
/**
* 按住键盘
* @param e
*/
@Override
public void keyPressed(KeyEvent e) {
// 获取敲击键盘时,具体键对应的数值
int keyCode = e.getKeyCode();
// 键盘上的上下左右键对应的值分别为:38、40、37、39
switch(keyCode){
case 38:
gameFrame.heroPlane.up = true;
break;
case 40:
gameFrame.heroPlane.down = true;
break;
case 37:
gameFrame.heroPlane.left = true;
break;
case 39:
gameFrame.heroPlane.right = true;
break;
case 66: // 装子弹
addBullut();
break;
}
System.out.println(keyCode);
}
/**
* 松开键盘
* @param e
*/
@Override
public void keyReleased(KeyEvent e) {
// 松开键盘时,具体键对应的数值
int keyCode = e.getKeyCode();
switch(keyCode){
case 38:
gameFrame.heroPlane.up = false;
break;
case 40:
gameFrame.heroPlane.down = false;
break;
case 37:
gameFrame.heroPlane.left = false;
break;
case 39:
gameFrame.heroPlane.right = false;
break;
}
}
/**
* 装弹
*/
public void addBullut(){
gameFrame.bullets.add(new Bullet(gameFrame.heroPlane.x + 5, gameFrame.heroPlane.y - 20));
}
}
4、子弹:Bullet
package cn.tx.ltzj;
import javax.swing.*;
import java.awt.*;
// 子弹
public class Bullet{
// 子弹在画板上的位置
int x, y;
// 飞机大小
int width = 50, heigth = 50;
// 子弹移动的速度
int speed = 10;
// 子弹图像
Image image = new ImageIcon("img/30025.png").getImage();
public Bullet(int x, int y, int width, int heigth) {
this.x = x;
this.y = y;
this.width = width;
this.heigth = heigth;
}
public Bullet(int x, int y) {
this.x = x;
this.y = y;
}
public Bullet() {
}
}
5、主类:GameFrame
package cn.tx.ltzj;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;
import java.util.Vector;
// Java做成图形界面,需要借助JFram
public class GameFrame extends JFrame {
HeroPlane heroPlane;
// 定义子弹的集合。Vector线程安全,需要销毁子弹
Vector<Bullet> bullets = new Vector<>();
// 敌机集合
Vector<EnemyPlane> enemyPlanes = new Vector<>();
GameFrame frame;
public GameFrame(){
frame = this;
// 创建英雄机
heroPlane = new HeroPlane();
heroPlane.start(); // 启动飞机单独的线程
// 设置窗体的宽高
this.setSize(500, 760);
// 标题
this.setTitle("雷霆战机");
this.setResizable(false);
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
// 窗口可见
this.setVisible(true);
// 单独启动一个线程,供画笔使用,画笔会一直执行
new Thread(new Runnable() {
@Override
public void run() {
while (true){
repaint(); // 不间断调用paint方法
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
// 产生敌机的线程,不断产生
new Thread(new Runnable() {
Random random = new Random();
@Override
public void run() {
while (true){
// 不断产生敌机,让X轴随机
EnemyPlane enemyPlane = new EnemyPlane(random.nextInt(500), 0, frame);
// 启动敌机:必须在生产敌机的时候就要启动敌机,而不是绘制敌机的时候启动,
// 否则报错Exception in thread "AWT-EventQueue-0" java.lang.IllegalThreadStateException
enemyPlane.start();
enemyPlanes.add(enemyPlane);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
/**
* 在窗口上画,内容,paint这个画笔的方法在窗口初始化的时候会默认的执行
* @param graphics 画笔
*/
public void paint(Graphics graphics){
// System.out.println("绘制画板");
// 画背景
BufferedImage image = (BufferedImage) this.createImage(this.getSize().width, this.getSize().height);
// 高效缓存的画笔
Graphics bi = image.getGraphics();
// 绘制背景图,在当前窗口的0, 0位置上
bi.drawImage(new ImageIcon("img/skypay_bg.png").getImage(),0,0,null);
// 绘制飞机
bi.drawImage(heroPlane.image, heroPlane.x, heroPlane.y, heroPlane.width, heroPlane.heigth,null);
// 绘制子弹
for (int i = 0; i < bullets.size(); i++) {
// System.out.println(bullets);
Bullet bullet = bullets.get(i);
if(bullet.y > 0){
bi.drawImage(bullet.image, bullet.x, bullet.y -= bullet.speed, bullet.width, bullet.heigth, null);
}else {
// 子弹到屏幕外了,删除子弹
bullets.remove(bullet);
}
}
// 绘制敌机
for (int i = 0; i < enemyPlanes.size(); i++) {
// System.out.println(enemyPlanes);
EnemyPlane ep = enemyPlanes.get(i);
if(ep.y < 760){
bi.drawImage(ep.image, ep.x, ep.y += ep.speed, ep.width, ep.heigth, null);
}else {
// 敌机到屏幕外了,删除敌机
bullets.remove(ep);
}
}
// 生效
graphics.drawImage(image,0,0,null);
}
public static void main(String[] args) {
GameFrame frame = new GameFrame();
Player player = new Player(frame);
// 在启动GameFrame后,启用player
frame.addKeyListener(player);
}
}