在学习java基础知识后,根据网上飞机大战的内容和代码改变,设计出飞机大战的奖励篇小游戏,后期可将飞机大战和奖励篇等设计成一个完整游戏。
项目描述:
游戏开始,会出现若干蓝色空心圆形物体视为奖励道具会在界面中弹射,数量可以自行设定,控制飞机移动将奖励吃完,计算所用时间。
运行效果图:
游戏源码
游戏主窗口类:
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Date;
/**
* 游戏主窗口
*/
public class MyGameFrame extends JFrame {
Image planeImg = GameUtil.getImage("images/plane.png");
Image bg = GameUtil.getImage("images/bg.jpg");
Plane p1 = new Plane(planeImg, 100, 100, 8);//飞机
Bonus[] bonuses = new Bonus[10];//奖励道具
Date start = new Date();//游戏开始的时间
Date end;//游戏结束的时间:飞奖励吃完的那一刻
long period = 0;//玩了多少秒
@Override
public void paint(Graphics g) {
//g当做是一致画笔
//画背景
g.drawImage(bg,0,0,500,500,null);
//画时间
drawTime(g);
//画飞机
p1.drawMyself(g);
//画奖励道具
for (int i = 0; i<bonuses.length;i++){
if(bonuses[i]!=null){
bonuses[i].drawMyself(g);
//碰撞检测。将所有的bonus和飞机进行检测,看有没有碰撞
boolean peng = bonuses[i].getRec().intersects(p1.getRec());
if (peng){
bonuses[i] = null;
}
}
}
}
public void drawTime(Graphics g){
//绘制时间的方法
Color c = g.getColor();
Font f = g.getFont();
g.setColor(Color.green);
if (!isNullOrEmptyArray(bonuses)){
period = (System.currentTimeMillis()-start.getTime())/1000;
g.drawString("游戏用时"+period+"秒",30,50);
}else{
if(end==null){
end = new Date();
period = (end.getTime()-start.getTime())/1000;
}
g.setColor(Color.red);
g.setFont(new Font("微软雅黑", Font.BOLD, 30));
g.drawString("游戏结束,最终所用时间:"+period+"秒", 45, 200);
}
g.setColor(c);
g.setFont(f);
}
public static boolean isNullOrEmptyArray(Object[] array) {
//判断奖励是否为空
if(array == null) {
return true;
}
if(array.length ==0) {
return true;
}
boolean eachItemIsNull = true;
for(Object item:array) {
if(item != null) {
eachItemIsNull = false;
}
}
return eachItemIsNull;
}
//初始化窗口
public void launchFrame(){
this.setTitle("飞机大战-小夏沫");
setVisible(true);//设置窗口是否可见
setSize(Constant.GAME_WIDTH,Constant.GAME_HEIGHT);//窗口大小
setLocation(560,100);//窗口打开的位置
//增加关闭窗口的动作
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);//正常退出程序
}
});
new PaintThread().start();//启动窗画窗口的线程
this.addKeyListener(new KeyMonitor());//启动键盘监听
//初始化创建bonus对象
for (int i =0;i<bonuses.length;i++){
bonuses[i] = new Bonus();
}
}
/**
* 定义一个重画窗口的线程类
* 定义成内部类是为了方便直接使用窗口类的相关方法
*/
class PaintThread extends Thread{
@Override
public void run() {
while(true){
repaint();//内部类可以直接使用外部类的成员
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//内部类,实现键盘的监听处理
class KeyMonitor extends KeyAdapter{
@Override
public void keyPressed(KeyEvent e) {
p1.addDirection(e);
}
@Override
public void keyReleased(KeyEvent e) {
//
p1.minusDirection(e);
}
}
private Image offScreenImage = null;
public void update(Graphics g){
if(offScreenImage==null){
offScreenImage = this.createImage(Constant.GAME_WIDTH, Constant.GAME_HEIGHT);//游戏窗口的宽度和高度
}
Graphics gOff = offScreenImage.getGraphics();
paint(gOff);
g.drawImage(offScreenImage, 0, 0, null);
}
public static void main(String[] args) {
MyGameFrame gameFrame = new MyGameFrame();
gameFrame.launchFrame();
}
}
飞机类:
import java.awt.*;
import java.awt.event.KeyEvent;
public class Plane extends GameObject{
boolean left, right, up, down;//飞机的方向控制
@Override
public void drawMyself(Graphics g) {
super.drawMyself(g);
//飞机飞行的算法,可以自行设定
// x+=speed;
if(left){
x -= speed;
}
if(right){
x += speed;
}
if(up){
y -= speed;
}
if(down){
y += speed;
}
}
public void addDirection(KeyEvent e){
switch(e.getKeyCode()){
case KeyEvent.VK_LEFT:
left = true;
break;
case KeyEvent.VK_RIGHT:
right = true;
break;
case KeyEvent.VK_UP:
up = true;
break;
case KeyEvent.VK_DOWN:
down = true;
break;
}
}
public void minusDirection(KeyEvent e){
switch (e.getKeyCode()){
case KeyEvent.VK_LEFT:
left = false;
break;
case KeyEvent.VK_RIGHT:
right = false;
break;
case KeyEvent.VK_UP:
up = false;
break;
case KeyEvent.VK_DOWN:
down = false;
break;
}
}
public Plane(Image img, double x, double y, int speed) {
super(img, x, y, speed);
}
}
常数类:
public class Constant {
//游戏窗口的宽度和高度
public static final int GAME_WIDTH = 500;
public static final int GAME_HEIGHT = 500;
}
奖励类:
import java.awt.*;
public class Bonus extends GameObject {
double degree;//角度。炮弹沿着指定的角度飞行
public Bonus(){
x=200;
y=300;
degree = Math.random()*Math.PI*2;
width = 10;
height = 10;
speed = 6;
}
@Override
public void drawMyself(Graphics g) {
Color c= g.getColor();//保存原来的颜色
g.setColor(Color.CYAN);//设置画笔为青色
g.drawOval((int)x,(int)y,width,height);
g.setColor(c);//还原为原来的颜色
//根据自己的算法指定移动的路径
x += speed*Math.cos(degree);
y += speed*Math.sin(degree);
//碰到边界改变方向
if(y>Constant.GAME_HEIGHT-this.height-9||y<35){
degree = -degree;
}
if(x<10||x>Constant.GAME_WIDTH-this.width-9){
degree = Math.PI-degree;
}
}
}
游戏根类:
import java.awt.*;
/**
* 游戏物体的根类
*/
public class GameObject {
Image img; //图片
double x,y; //物体的坐标
int speed; //物体移动的速度
int width,height; //物体的宽度和高度
public GameObject(Image img, double x, double y, int speed) {
this.img = img;
this.x = x;
this.y = y;
this.speed = speed;
this.width = img.getWidth(null);
this.height = img.getHeight(null);
}
public GameObject(){
}
public void drawMyself(Graphics g){
g.drawImage(img, (int)x, (int)y, width, height, null);
}
//所有的物体都是矩形。当你获得对应的矩形的时候,我们就可以做一些相关的判断操作!
public Rectangle getRec(){
return new Rectangle((int)x, (int)y, width, height);
}
}
工具类(加载图片):
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
/**
* 游戏的工具类
*/
public class GameUtil {
//构造器私有,防止别人创建本类的对象
private GameUtil(){
}
public static Image getImage(String path){
BufferedImage img = null;
URL u = GameUtil.class.getClassLoader().getResource(path);
try {
img = ImageIO.read(u);
} catch (IOException e) {
e.printStackTrace();
}
return img;
}
}
eg:仅为练习代码,游戏过程中可能会出现bug,代码有待完善。