使用工具:Eclipse
游戏效果:
目录 结构:
结构介绍:
GameFrame:主程序入口
GameUtil:工具类,用来导入图片
GameObject:游戏物体的父类(物体图片、物体速度、物体宽高、坐标xy、碰撞)
Constant:常量
Plane:飞机类
Stone:石头类(游戏生成的陨石)
Bullet:子弹类(点击空格键就可以发射子弹)
Boom:爆炸类(飞机死亡后的一个爆炸效果)
Live:生命类(左下角显示的爱心)
按顺序贴出代码
GameFrame
package cn.claire.game;
import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Date;
@SuppressWarnings("serial")
public class GameFrame extends Frame {
Image backgroundImg1 = GameUtil.getIamge("images/background.jpg");// 游戏背景
Image backgroundImg2 = GameUtil.getIamge("images/background.jpg");
int bgY = 0;// 背景图的纵坐标
Image planeImg = GameUtil.getIamge("images/plane.png");
Plane plane = new Plane(planeImg, 240, 600);
Image[] stoneImgs = { GameUtil.getIamge("images/stone0.png"), GameUtil.getIamge("images/stone1.png"),
GameUtil.getIamge("images/stone2.png") };
Stone[] stones = new Stone[15];// 障碍物--石头
Image livesImg = GameUtil.getIamge("images/live.png");
int lives = Constant.PLANE_LIVES;// 飞机的生命数
Live planeLive;// 飞机生命
Image bulletImg = GameUtil.getIamge("images/bullet.png");
Bullet bullet;
Boom boom;// 爆炸对象
// 时间
Date startTime = new Date();
Date endTime;
int period;// 游戏持续的时间
int score = 0;// 得分
/* 绘制窗口 */
@Override
public void paint(Graphics g) {
super.paint(g);
// 保存默认的画笔与字体
Color cOrigin = g.getColor();
Font fOrigin = g.getFont();
// 背景图滚动
{
g.drawImage(backgroundImg1, 0, bgY, null);
g.drawImage(backgroundImg1, 0, bgY - 800, null);
bgY += Constant.BACKGROUND_SPEED;
if (bgY == 800) {
bgY = 0;
}
}
if (plane != null) {
plane.drawSelf(g);// 画飞机
}
// 画石头
for (int i = 0; i < stones.length; i++) {
if (plane != null) {
// 检测飞机与石头的碰撞
boolean crushed = stones[i].getRect().intersects(plane.getRect());
if (crushed) {
lives--;
stones[i].img = stoneImgs[(int) (Math.random() * 3)];// 石头重画
stones[i].x = Math.random() * 400 + 40;
stones[i].y = 30;
boom = new Boom(plane.x - 10, plane.y);// 爆炸对象
if (0 == lives) {
System.out.println("飞机死亡");
plane.live = false;
plane = null;
}
crushed = false;
if (score >= 1) {
score -= 1;// 如果得分超过1分,则减分
}
}
}
// 检测子弹是否打中石头
if (bullet != null) {
boolean hitted = stones[i].getRect().intersects(bullet.getRect());
if (hitted) {
boom = new Boom(stones[i].x, stones[i].y);// 爆炸对象
stones[i].img = stoneImgs[(int) (Math.random() * 3)];// 石头重画
stones[i].x = Math.random() * 400 + 40;
stones[i].y = 30;
hitted = false;
bullet = null;// 子弹没了
score += 3;// 得分增加3分
}
}
stones[i].draw(g);
}
if (plane != null) {// 得分
g.setColor(Color.YELLOW);
g.setFont(new Font("宋体", Font.BOLD, 20));
g.drawString("得分: " + score + "分", 380, 780);
} else {
g.setColor(Color.RED);
g.setFont(new Font("宋体", Font.BOLD, 40));
g.drawString("游戏结束", 150, 400);
g.drawString("总得分:" + score + "分", 150, 450);
}
if (boom != null) {// 画爆炸对象
boom.draw(g);
}
// 生命增加
if (((int) (((new Date()).getTime() - startTime.getTime())) / 1000) % 10 == 0 && planeLive == null) {
planeLive = new Live(livesImg);
}
if (planeLive != null) {
planeLive.draw(g);
if (plane != null) {
boolean getLive = planeLive.getRect().intersects(plane.getRect());
if (getLive && planeLive != null) {
planeLive = null;
lives++;// 飞机加一条命
if (lives >= 3) {
lives = 3;
}
}
}
}
// 飞机生命数显示
for (int i = 0; i < lives; i++) {
g.drawImage(livesImg, 10 + 50 * i, 750, null);
}
// 画子弹:在飞机存在的情况下
if (plane != null && bullet != null) {
bullet.draw(g);
if (bullet.y < 10) {// 飞到上空的时候,子弹消失
bullet = null;
}
}
// 归为初始的画笔与字体
g.setColor(cOrigin);
g.setFont(fOrigin);
}
/* 反复重画窗口 */
class PaintThread extends Thread {
@Override
public void run() {
super.run();
while (true) {
repaint();// 重画
try {
Thread.sleep(40);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/* 初始化窗口 */
public void launchFranme() {
this.setTitle("雷电");
this.setVisible(true);
this.setSize(Constant.SCREEN_WIDTH, Constant.SCREEN_HEIGHT);
this.setLocation(500, 20);
// 关闭窗口
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
super.windowClosing(e);
System.exit(0);
}
});
for (int i = 0; i < stones.length; i++) {
stones[i] = new Stone(stoneImgs[(int) (Math.random() * 3)]);
}
new PaintThread().start();// 启动重画窗口的线程
addKeyListener(new KeyMonitor());// 启动键盘监听
}
/* 键盘监听 */
class KeyMonitor extends KeyAdapter {
@Override
public void keyPressed(KeyEvent e) {
super.keyPressed(e);
if (plane != null) {
plane.addDirection(e);
}
}
@Override
public void keyReleased(KeyEvent e) {
super.keyReleased(e);
if (plane != null) {
plane.minusDirection(e);
if (e.getKeyCode() == KeyEvent.VK_SPACE && bullet == null) {// 抬起空格并且没有子弹,则生成子弹
bullet = new Bullet(bulletImg, (double) plane.x + 10, (double) plane.y);
}
}
}
}
/* 双缓冲解决闪烁 */
private Image offScreenImage = null;
public void update(Graphics g) {
if (offScreenImage == null) {
offScreenImage = this.createImage(Constant.SCREEN_WIDTH, Constant.SCREEN_HEIGHT);
}
Graphics gOff = offScreenImage.getGraphics();
paint(gOff);
g.drawImage(offScreenImage, 0, 0, null);
}
/* 程序入口 */
public static void main(String[] args) {
GameFrame game = new GameFrame();
game.launchFranme();
}
}
GameUtil
package cn.claire.game;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.net.URL;
import javax.imageio.ImageIO;
public class GameUtil {
private GameUtil() {
}
/**
* 返回指定文件的图片对象
*
* @param path
* @return
*/
public static Image getIamge(String path) {
BufferedImage bi = null;
try {
URL u = GameUtil.class.getClassLoader().getResource(path);
bi = ImageIO.read(u);
} catch (Exception e) {
e.printStackTrace();
}
return (BufferedImage) bi;
}
}
GameObject
package cn.claire.game;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
/**
* 游戏物体的父类
*
* @author Lenovo
*
*/
public class GameObject {
Image img;
int speed;// 物体速度
int width, height;// 宽高
double x, y;// 坐标
// 在画布中画出该物体
public void drawSelf(Graphics g) {
g.drawImage(img, (int) x, (int) y, null);
}
/**
* 返回物体所在的矩形便于后续的碰撞检测
*
* @return
*/
public Rectangle getRect() {
return new Rectangle((int) x, (int) y, width, height);
}
public GameObject(Image img, int speed, int width, int height, double x, double y) {
super();
this.img = img;
this.speed = speed;
this.width = width;
this.height = height;
this.x = x;
this.y = y;
}
public GameObject(Image img, int x, int y) {
super();
this.img = img;
this.x = x;
this.y = y;
}
public GameObject() {
}
}
Constant
package cn.claire.game;
public class Constant {
public static final int SCREEN_WIDTH = 500;// 屏幕宽
public static final int SCREEN_HEIGHT = 800;// 屏幕高
public static final int BACKGROUND_SPEED = 5;// 背景滚动速度
public static final int PLANE_SPEED = 10;// 飞机的速度
public static final int STONE_SPEED = 5;// 陨石飞行速度
public static final int PLANE_LIVES = 3;// 飞机生命条数
public static final int BULLET_SPEED = 15;// 子弹飞行速度
}
Plane
package cn.claire.game;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
/**
* 飞机类
*
* @author Lenovo
*
*/
public class Plane extends GameObject {
int speed = Constant.PLANE_SPEED;// 飞机速度
boolean left, up, right, down;// 飞机方向
boolean live = true;// 飞机存活
/* 按下键,改变方向 */
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;
default:
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;
default:
break;
}
}
@Override
public void drawSelf(Graphics g) {
if (live) {
g.drawImage(img, (int) x, (int) y, null);
if (left && x > 0) {
x -= speed;
}
if (right && x < Constant.SCREEN_WIDTH - img.getWidth(null)) {
x += speed;
}
if (up && y > 30) {
y -= speed;
}
if (down && y < Constant.SCREEN_HEIGHT - img.getHeight(null)) {
y += speed;
}
}
}
// 构造器
public Plane(Image img, double x, double y) {
this.img = img;
this.x = x;
this.y = y;
this.speed = Constant.PLANE_SPEED;
this.width = img.getWidth(null);
this.height = img.getHeight(null);
}
}
Stone
package cn.claire.game;
import java.awt.Graphics;
import java.awt.Image;
/**
* 障碍物
*
* @author Lenovo
*
*/
public class Stone extends GameObject {
double degree;// 飞行角度
boolean live = true;// 是否存在
public Stone(Image img) {
x = Math.random() * 400 + 40;
y = 30;
this.img = img;
width = img.getWidth(null);
height = img.getHeight(null);
speed = Constant.STONE_SPEED;// 陨石飞行速度
degree = Math.random() * Math.PI * 2;
}
public void draw(Graphics g) {
if (live) {
g.drawImage(img, (int) x, (int) y, null);
x += speed * Math.cos(degree);
y += speed * Math.sin(degree);
if (x < 10 || x > Constant.SCREEN_WIDTH - width) {
degree = Math.PI - degree;
}
if (y < 30 || y > Constant.SCREEN_HEIGHT - height) {
degree = -degree;
}
}
}
}
Bullet
package cn.claire.game;
import java.awt.Graphics;
import java.awt.Image;
public class Bullet extends GameObject {
public Bullet(Image img, double x, double y) {
this.img = img;
this.x = x;
this.y = y;
width = img.getWidth(null);
height = img.getHeight(null);
speed = Constant.BULLET_SPEED;// 子弹飞行速度
}
public void draw(Graphics g) {
g.drawImage(img, (int) x, (int) y, null);
y -= speed;
}
}
Boom
package cn.claire.game;
import java.awt.Graphics;
import java.awt.Image;
public class Boom extends GameObject {
double x, y;
static Image[] imgs = new Image[16];
static {
for (int i = 0; i < imgs.length; i++) {
imgs[i] = GameUtil.getIamge("images/e" + (i + 1) + ".png");
}
}
int count;
public void draw(Graphics g) {
if (count <= 15) {
g.drawImage(imgs[count], (int) x, (int) y, null);
count++;
}
}
public Boom(double x, double y) {
this.x = x;
this.y = y;
}
}
Live
package cn.claire.game;
import java.awt.Graphics;
import java.awt.Image;
public class Live extends GameObject {
double degree;// 飞行角度
boolean live = true;// 是否存在
public Live(Image img) {
x = Math.random() * 400 + 40;
y = 30;
this.img = img;
width = img.getWidth(null);
height = img.getHeight(null);
speed = Constant.STONE_SPEED + 10;// 血条飞行速度
degree = Math.random() * Math.PI * 2;
}
public void draw(Graphics g) {
if (live) {
g.drawImage(img, (int) x, (int) y, null);
x += speed * Math.cos(degree);
y += speed * Math.sin(degree);
if (x < 10 || x > Constant.SCREEN_WIDTH - width) {
degree = Math.PI - degree;
}
if (y < 30 || y > Constant.SCREEN_HEIGHT - height) {
degree = -degree;
}
}
}
}
贴一下图片素材(基本都是网上找的,然后自己PS处理的,有喜欢别的可以自行更换)