目前学习的示例代码是做一个飞机大战。参照其实现方法希望可以实现一个泡泡龙的游戏。
当前进度实现了
1.飞机的键盘监听(即用键盘控制我放飞机的移动)
2.子弹的自动发射
3.背景移动
4.定时器线程生成敌方飞机,自动落下)
待实现功能:
1.随机生成宝箱对子弹进行强化
2.子弹和飞机的碰撞,
3.我机和奖励宝箱的碰撞
4.子弹对象会因为宝箱产生攻击力和载入图片效果的变化
5.给定我方飞机,地方飞机的生命值
会在这里持续更新代码和遇到的问题,以及如何解决的思路。
当前实现效果图
代码如下
/**
* 飞机类,用于发射子弹的小球
*/
public class Aircraft extends MoveBall {
//游戏界面的大小
//初始化飞机的位置
public Aircraft(){
setX(370);
setY(700);
setSize(60);
}
}
/**
* 子弹类
*/
public class Bullet extends MoveBall {
//重载构造方法
public Bullet(int x,int y){
setX(x - 13);
setY(y);
setSize(25);
setVy(-5);
}
//子弹的碰撞效果
}
//敌机类
public class Enemy extends MoveBall {
public Enemy(int x,int y){
setX(x - 13);
setY(y);
setVy(5);
}
}
import javax.swing.*;
import java.awt.*;
/**
界面
本次板本希望解决如下问题
1、闪烁问题
1)问题原因
当我们利用普通画笔的时候是实时进行画图,
当我们利用一个画笔同时在画飞机子弹类和背景类的时候,
就会出现延迟,即当我在用画笔画背景的时候,
此时没有画笔在画飞机,这个时候飞机就会消失,
因为时间间隔很短,所以也就是所谓的闪屏,会出现图片的闪动。
2)问题解决
而利用缓存画笔则巧妙的解决了这个问题,
这个相当于一次性让画笔画完一整张图,
然后再一次性呈现出来,这样就解决了闪屏。
2.碰撞问题
*/
public class GameBallUI {
public void showGameBall(){
JFrame jf = new JFrame();
jf.setTitle("飞机大战v2.0");
jf.setSize(800, 800);
jf.setLocationRelativeTo(null);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//不能直接调用jf.setBackground()因为JFrame中用许多面板,这样才有效
jf.getContentPane().setBackground(Color.white);
jf.setLayout(new FlowLayout());
// JButton add = new JButton("add");
// jf.add(add);
// JButton start = new JButton("start");
// jf.add(start);
jf.setVisible(true);
//给窗体添加键盘监听器方法
GameListener gl = new GameListener(jf);
jf.addKeyListener(gl);//给窗体添加键盘监听器方法
jf.requestFocus();//让窗体获取焦点,没有焦点java无法获取键盘
}
public static void main(String[] args) {
new GameBallUI().showGameBall();
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.List;
/**
监听器
*/
public class GameListener implements KeyListener {
// private JFrame jf;
private Aircraft aircraft;//利用键盘控制小球对象,该类为飞机类
private Graphics g;
// private Ball ball;//发射器
public List<MoveBall> moveBallList = new ArrayList<>();//保存到列表中
public List<Enemy> enemyList = new ArrayList<>();//保存到列表中
private GameThread gmThread;//子弹
public JFrame jf;
public GameListener(JFrame jf) {
this.jf=jf;
g = jf.getGraphics();
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
// 获取当前的按键
int key = e.getKeyCode();
//System.out.println("按下 : " + key);
switch (key) {
case KeyEvent.VK_W:
// ball.setVy(-5);
aircraft.setVy(-5);
break;
case KeyEvent.VK_A:
// ball.setVx(-5);
aircraft.setVx(-5);
break;
case KeyEvent.VK_S:
// ball.setVy(5);
aircraft.setVy(5);
break;
case KeyEvent.VK_D:
// ball.setVx(5);
aircraft.setVx(5);
break;
// 发射子弹的按键
case KeyEvent.VK_J:
//启动游戏,创建子弹对象
// MoveBall ba = new MoveBall(g,ball.getX()+10,ball.getY());
Bullet bullet = new Bullet(aircraft.getX(), aircraft.getY());
//保存到moveBallList
moveBallList.add(bullet);
// //启动线程画子弹
if(gmThread == null){
// gmThread = new GameThread(ba);
// new Thread(gmThread).start();
}
break;
case KeyEvent.VK_SPACE:
System.out.println("启动游戏");
//绘制游戏动画的线程
if(gmThread == null){
//启动游戏,创建小球对象
aircraft = new Aircraft();
//启动线程
gmThread = new GameThread(moveBallList,g,aircraft,enemyList,jf);
new Thread(gmThread).start();
//启动定时任务线程
TimeThread time = new TimeThread(aircraft,moveBallList,enemyList);
new Thread(time).start();
}
break;
}
}
@Override
public void keyReleased(KeyEvent e) {
//要将WASD四个键全部置为0,这样方向键不会斜着走
int key = e.getKeyCode();
switch (key) {
case KeyEvent.VK_W:
aircraft.setVy(0);
break;
case KeyEvent.VK_A:
aircraft.setVx(0);
break;
case KeyEvent.VK_S:
aircraft.setVy(0);
break;
case KeyEvent.VK_D:
aircraft.setVx(0);
break;
}
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.List;
/*
游戏线程类
*/
public class GameThread implements Runnable{
public List<MoveBall> moveBallList; // 子弹对象的list
public List<Enemy> enemyList;
public Graphics g;
private Aircraft aircraft;//键盘控制的对象
private ImageIcon bgimage;//背景图片
private ImageIcon apimage;//飞机图片
private ImageIcon blimage;//子弹图片
private ImageIcon enimage;//敌机图片
public int imageX,imageY;//背景图的起始点坐标(图片左上角的位置坐标)
// private MoveBall ba; //子弹对象
public JFrame jf;
// public BufferedImage bf;
//初始化属性
public GameThread(List<MoveBall> moveBallList, Graphics g, Aircraft aircraft, List<Enemy>enemyList,JFrame jf) {
this.moveBallList = moveBallList;
this.g = g;
this.aircraft = aircraft;
this.enemyList=enemyList;
this.jf=jf;
}
//重写run方法
@Override
public void run() {
//初始化背景图片
bgimage = new ImageIcon("C:\\Users\\Sky\\IdeaProjects\\new pr\\imgs\\背景.png");
apimage = new ImageIcon("C:\\Users\\Sky\\IdeaProjects\\new pr\\imgs\\Aplane.png");
blimage = new ImageIcon("C:\\Users\\Sky\\IdeaProjects\\new pr\\imgs\\红豆.png");
enimage = new ImageIcon("C:\\Users\\Sky\\IdeaProjects\\new pr\\imgs\\我机.png");
//建立缓存图片
System.out.println("jf="+jf);
BufferedImage bf = new BufferedImage(jf.getWidth(),jf.getHeight(),BufferedImage.TYPE_INT_RGB);
//获取缓存图片上的画笔
Graphics ng =bf.getGraphics();
while (true){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
//绘制背景效果
//绘制两张图进行连接,第二张图的起始点的纵坐标比窗口界面高一个图片的高度,故为:imageY-image.getIconHeight()
// g.drawImage(image.getImage(),0,0,800,800,null);
ng.drawImage(bgimage.getImage(),imageX,imageY,null);
ng.drawImage(bgimage.getImage(),imageX,imageY-bgimage.getIconHeight(),null);
imageY++;
//让两张图片循环使用:当第二张图片的左上角位置几乎快靠近窗体的左上角位置时,将第一张图片的起始位置设为0 if(imageY-image.getIconHeight() >= 0){
if(imageY- bgimage.getIconHeight() >= 0){
imageY = 0;
}
//遍历moveBallList
for (int i = 0; i < moveBallList.size(); i++) {
MoveBall bullet = moveBallList.get(i);
//g.setColor(Color.DARK_GRAY);
//bullet.drawBall(g);
//用子弹图片代替子弹小球
bullet.drawPlane(ng, blimage);
bullet.move();
}
for (int i = 0; i < enemyList.size(); i++) {
MoveBall enemy = enemyList.get(i);
//g.setColor(Color.DARK_GRAY);
//bullet.drawBall(g);
//用子弹图片代替子弹小球
enemy.drawPlane(ng, enimage);
enemy.move();
}
//控制角色
//g.setColor(Color.black);
//aircraft.drawBall(g);
//用图片代替小球
aircraft.drawPlane(ng, apimage);
aircraft.move();
g.drawImage(bf,0,0,null);
}
}
}
import javax.swing.*;
import java.awt.*;
/**
* 是个移动对象,作为各类飞行物体的父类
*/
public class MoveBall {
private int x, y;//小球的起始位置
private int vx, vy;//小球的运动速度,运动方向
private int size;//小球直径
// private Graphics g;
// Random random = new Random();
//创建子弹的构造方法
//根据移动的对象初始化子弹位置
public MoveBall(){
x = 370;
y = 700;
size = 60;
}
// int a = random.nextInt(255);//给小球设置随机颜色
// int b = random.nextInt(255);
// int c = random.nextInt(255);
//小球的绘制
public void drawBall(Graphics g) {
// //绘制小球
// g.setColor(Color.WHITE);
// g.fillOval(x, y, size, size);
// //小球移动
// x += vx;
// y += vy;
// g.setColor(new Color(a,b,c));
g.fillOval(x, y, size, size);
// //小球边界问题
// if(x >= 800-size || y >= 800-size || x<= 0 || y <= 65){
// vx = -vx;
// vy = -vy;
// }
//小球碰撞问题
}
public void drawPlane(Graphics g, ImageIcon imageIcon){
g.drawImage(imageIcon.getImage(),x,y,null);
x+=vx;
y+=vy;
}
public void drawEnemy(Graphics g, ImageIcon imageIcon){
g.drawImage(imageIcon.getImage(),x,y,null);
x+=vx;
y+=vy;
}
//移动的方法
public void move(){
x += vx;
y += vy;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
//提供速度的get、set方法
public int getVx() {
return vx;
}
public void setVy(int vy) {
this.vy = vy;
}
public int getVy() {
return vy;
}
public void setVx(int vx) {
this.vx = vx;
}
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;
}
}
import java.util.List;
import java.util.Random;
/**
* 定时任务线程:每隔一段时间就创建一个新的子弹对象
* 定时任务线程:每隔一段时间就创建一个新的敌机对象
*/
public class TimeThread implements Runnable {
public long time = 400;//任务的间隔时间
public Aircraft aircraft ;//飞机对象
public List<MoveBall> moveBallList;
public List<Enemy> enemyList;
Random random = new Random();
//初始化飞机对象/保存子弹list
public TimeThread(Aircraft aircraft, List<MoveBall> moveBallList, List<Enemy>enemyList){
this.aircraft = aircraft;
this.moveBallList = moveBallList;
this.enemyList = enemyList;
}
@Override
public void run() {
while (true){
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
//创建子弹对象,根据我方飞机位置实时创建子弹对象
int x = aircraft.getX() + aircraft.getSize()/2+6;
int y = aircraft.getY() + aircraft.getSize()/-100;
int a = random.nextInt(800);
Enemy enemy = new Enemy(a,40);
enemyList.add(enemy);
Bullet bullet = new Bullet(x,y);
moveBallList.add(bullet);
}
}
}