-
继承Frame绘制类
-
初始化窗口
设置标题、宽高、位置
添加窗口监听器,当达到某个条件时,将窗口关闭 -
图形和文本绘制
使用print()函数绘制图形和文本
imageIO实现图片加载技术
-
多线程重画窗口
-
设置飞机坐标移动
-
面向对象思想设计游戏物体类、飞机类
-
加入键盘键位控制,启动键盘监听,关联飞机移动位置
-
炮弹设计
-
增加双闪烁解决方案
-
矩形边界碰撞检测
-
爆炸效果实现
-
飞机死亡和计时功能
附代码
package org.jinjin.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;
/**
* 飞机小游戏
* 实现效果
* 使用windows窗口实现,小飞机可以通过键盘键位控制,
* 初始产生随机方向炮弹,当炮弹碰撞到边界时会自动回弹,
* 当小飞机碰撞到炮弹时,小飞机爆炸,显示小飞机存活时间
* 1.绘制窗口--完成
* 2.将背景图片和小飞机图片加载到窗口中--完成
* 3.使小飞机可以通过键位控制进行位置移动--完成
* 4.炮弹设计以及边界回弹--完成
* 5.碰撞后小飞机爆炸效果--完成
* 6.碰撞后时间显示--完成
* 7.新增游戏开始操作--完成
*/
public class MyGameFrame extends Frame {
Image planeImg=GameImgUtil.getImage("images/plane.png");
Image bgImg=GameImgUtil.getImage("images/bg.jpg");
BackGround bg=new BackGround(bgImg,0,0);
Plane plane = new Plane(planeImg,400,400);
Shell[] shells = new Shell[50];
Explode bao;
Date startTime=new Date();
Date endTime;
int period;
boolean isStart=false;
//2.将背景图片和小飞机图片加载到窗口中
boolean peng=false;
@Override
public void paint(Graphics g) {
System.out.println("绘制一次窗口");
//绘制图片背景
bg.drawSelf(g);
if(!isStart){
Color c = g.getColor();
g.setColor(Color.WHITE);
g.setFont(new Font("宋体", Font.BOLD,40));
g.drawString("按下enter键开始游戏",(int)Constant.WIDTH/3,(int)Constant.HEIGHT/2);
g.setColor(c);
}else{
//绘制飞机
plane.drawSelf(g);
//绘制炸弹
for (int i = 0; i < shells.length; i++) {
shells[i].draw(g);
//碰撞条件
peng = shells[i].getRect().intersects(plane.getRect());
if(peng){
shells=new Shell[0];
endTime=new Date();
period= (int)((endTime.getTime()-startTime.getTime())/1000);
break;
}
}
if(peng){
plane.live=false;
if(bao==null){
bao=new Explode(plane.x,plane.y);
}
bao.draw(g);
Color c = g.getColor();
g.setColor(Color.RED);
g.setFont(new Font("宋体", Font.BOLD,50));
g.drawString("您存活了"+period+"秒",(int)Constant.WIDTH/3,(int)Constant.HEIGHT/2);
g.setColor(c);
}
}
}
//1.绘制窗口以及窗口刷新
public void launchFrame(){
//绘制窗口要素
this.setTitle("飞机小游戏");
this.setVisible(true);
this.setSize(Constant.WIDTH,Constant.HEIGHT);
this.setLocation(300,50);
//添加窗口监听
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
//手动点击窗口上的X,程序监听到窗口关闭,则关闭程序
System.exit(0);
}
});
//添加窗口自动刷新
new PaintThread().start();
//添加按键监听
addKeyListener(new keyMonitor());
//添加50个炮弹
for (int i = 0; i < 50; i++) {
shells[i]=new Shell();
}
}
private Image offScreenImage = null;
public void update(Graphics g) {
if(offScreenImage == null)
offScreenImage = this.createImage(Constant.WIDTH,Constant.HEIGHT);
Graphics gOff = offScreenImage.getGraphics();
paint(gOff);
g.drawImage(offScreenImage, 0, 0, null);
}
class PaintThread extends Thread{
@Override
public void run() {
while (true){
repaint();
try {
Thread.sleep(40);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class keyMonitor extends KeyAdapter{
@Override
public void keyPressed(KeyEvent e) {
plane.addDirection(e);
if(e.getKeyCode()== KeyEvent.VK_ENTER&!isStart){
isStart=true;
}
}
@Override
public void keyReleased(KeyEvent e) {
plane.minusDirection(e);
}
}
public static void main(String[] args) {
MyGameFrame myGameFrame = new MyGameFrame();
myGameFrame.launchFrame();
}
}
package org.jinjin.game;
import javax.imageio.ImageIO;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
public class GameImgUtil {
private GameImgUtil(){}
public static Image getImage(String filePath){
BufferedImage read = null;
try {
URL resource = new File(filePath).toURL();
// URL resource = GameImgUtil.class.getClassLoader().getResource(filePath);
System.out.println("根据'"+filePath+"'当前获取到的图片路径为:"+resource.toString());
read = ImageIO.read(resource);
} catch (IOException e) {
e.printStackTrace();
}
return read;
}
}
package org.jinjin.game;
public class Constant {
static int WIDTH=900;
static int HEIGHT=900;
}
package org.jinjin.game;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
public class GameObject {
Image img;
double x,y;
int speed;
int width;
int height;
public void drawSelf(Graphics g){
g.drawImage(img,(int)x,(int)y,null);
}
public Rectangle getRect(){
return new Rectangle((int)x,(int)y,width,height);
}
public GameObject(Image img, double x, double y, int speed, int width, int height) {
this.img = img;
this.x = x;
this.y = y;
this.speed = speed;
this.width = width;
this.height = height;
}
public GameObject(Image img, double x, double y) {
this.img = img;
this.x = x;
this.y = y;
}
public GameObject() {
}
}
package org.jinjin.game;
import java.awt.Image;
public class BackGround extends GameObject{
public BackGround(Image img, double x, double y) {
super(img, x, y);
}
}
package org.jinjin.game;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
public class Plane extends GameObject{
boolean left,up,right,down;
boolean live=true;
public Plane(Image img, double x, double y) {
this.img=img;
this.x=x;
this.y=y;
this.speed = 5;
this.width=img.getWidth(null);
this.height=img.getHeight(null);
}
@Override
public void drawSelf(Graphics g) {
if(live){
super.drawSelf(g);
if(left&&x>0+width/2){
x-=speed;
}
if(right&&x<Constant.WIDTH-width/2*3){
x+=speed;
}
if(up&&y>32){
y-=speed;
}
if(down&&y<Constant.HEIGHT-height/2*3){
y+=speed;
}
}
}
public void addDirection(KeyEvent e) {
switch (e.getKeyCode()){
case KeyEvent.VK_LEFT:left=true;break;
case KeyEvent.VK_UP:up=true;break;
case KeyEvent.VK_RIGHT:right=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_UP:up=false;break;
case KeyEvent.VK_RIGHT:right=false;break;
case KeyEvent.VK_DOWN:down=false;break;
}
}
}
package org.jinjin.game;
import java.awt.Color;
import java.awt.Graphics;
public class Shell extends GameObject{
double degree;
public Shell(){
x=200;
y=200;
width=10;
height=10;
speed=3;
degree= Math.random()*Math.PI*2;
}
public void draw(Graphics g){
Color c = g.getColor();
g.setColor(Color.YELLOW);
g.fillOval((int)x,(int)y,width,height);
x+=speed*Math.cos(degree);
y+=speed*Math.sin(degree);
if(x<0||x>Constant.WIDTH-width){
degree = Math.PI - degree;
}
if(y<30||y>Constant.HEIGHT-height){
degree = -degree;
}
g.setColor(c);
}
}
package org.jinjin.game;
import java.awt.Graphics;
import java.awt.Image;
public class Explode{
double x,y;
static Image[] imgs=new Image[16];
static {
for (int i = 0; i < 16; i++) {
imgs[i] = GameImgUtil.getImage("images/explode/e"+(i+1)+".gif");
imgs[i].getWidth(null);
}
}
public Explode(double x,double y){
this.x = x;
this.y = y;
}
int count;
public void draw(Graphics g){
if(count<=15){
g.drawImage(imgs[count], (int)x,(int)y,null);
count++;
}
}
}
附游戏效果图