Java解决游戏界面闪屏
Posted YQS_Love
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java解决游戏界面闪屏相关的知识,希望对你有一定的参考价值。
一、问题描述
我们在做有关于图形绘制方面的问题非常之多。比如,有时我们用普通的方法去绘制图形,会产生闪屏的现象,导致我们所做的游戏或者是别的项目效果非常差,这完全不是我们想要的结果。那么,有没有一种技术,实现不闪屏的效果,特别是在多线程环境下。答案是有的,这就是Java的什么技术——双缓冲技术。
图1 双缓冲技术效果图
二、实现方法
1、首先,我们定义一个类继承JFrame,要自定义绘图,我们就要实现JFrame的paint()方法,如下:
@Override
public void paint(Graphics g)
2、创建一个缓冲区画笔;
public BufferedImage(int width,
int height,
int imageType)
width 缓冲区的宽度
height 缓冲区的高度
imageType 缓冲图形模式
// 创建一个缓冲区
BufferedImage paint = new BufferedImage(width, height,
BufferedImage.TYPE_3BYTE_BGR);
// 得到缓冲区的画笔
Graphics g2 = paint.getGraphics();
3、将你想要绘制的图形绘制在缓冲区内;
// 将想要绘制的图形绘制到缓冲区
g2.drawImage(GameImage.getInstance().game_main_bg, 0, 0, width, height,
this);
4、将缓冲区的图形绘制到显示面板上;
g.drawImage(paint, 0, 0, this);
经过上面四步之后,我们就解决了闪屏的问题,现在放心大胆的去做你的游戏吧!
三、项目源码
由于项目过大,源码只给出了双缓冲技术得用法,具体的实现并没有做。如果想验证源码的,可以联系我要项目所用到的图片,也可以上网查找。
由于技术和能力有限,文中难免会有错误之处,还望指正,谢谢合作!
1、程序入口类Main.java
/**
* 主函数入口
* @author Admin
*
*/
public class Main
public static void main(String[] args)
new MainGameFrame();
2、游戏主界面类MainGameFrame.java
/**
* 游戏主面板
*
* @author Admin
*
*/
public class MainGameFrame extends JFrame implements Runnable
private int width = 1200;
private int height = 600;
private BufferedImage clickGame;
private List<PlantAutoMoveInfo> allPlant;
private boolean isRunnableStart;
public MainGameFrame()
isRunnableStart = true;
new Thread(this).start();
init();
newPlant();
/**
* 创造植物
*/
private void newPlant()
allPlant = new ArrayList<PlantAutoMoveInfo>();
//如果你想让所有的植物都不是相同的动作,
//你可以在PlantAutoMoveInfo去控制它切换图片的时机
// constructor sunflower
PlantAutoMoveInfo plantObj = new PlantAutoMoveInfo(new Point(300, 100),
Constants.SUNFLOWER, GameImage.getInstance().sunflower);
allPlant.add(plantObj);
plantObj = new PlantAutoMoveInfo(new Point(300, 250),
Constants.SUNFLOWER, GameImage.getInstance().sunflower);
allPlant.add(plantObj);
// constructor pea
plantObj = new PlantAutoMoveInfo(new Point(400, 100), Constants.PEA,
GameImage.getInstance().pea);
allPlant.add(plantObj);
plantObj = new PlantAutoMoveInfo(new Point(400, 250), Constants.PEA,
GameImage.getInstance().pea);
allPlant.add(plantObj);
// constructor nut
plantObj = new PlantAutoMoveInfo(new Point(500, 100), Constants.NUT,
GameImage.getInstance().nut);
allPlant.add(plantObj);
plantObj = new PlantAutoMoveInfo(new Point(500, 250), Constants.NUT,
GameImage.getInstance().nut);
allPlant.add(plantObj);
/**
* 绘制图像
*/
@Override
public void paint(Graphics g)
// 创建一个缓冲区
BufferedImage paint = new BufferedImage(width, height,
BufferedImage.TYPE_3BYTE_BGR);
// 得到缓冲区的画笔
Graphics g2 = paint.getGraphics();
// 将想要绘制的图形绘制到缓冲区
// draw background image
g2.drawImage(GameImage.getInstance().game_main_bg, 0, 0, width, height,
this);
// 绘制植物
for (PlantAutoMoveInfo obj : allPlant)
g2.drawImage(obj.getShowImage(), (int) obj.getPos().getX(),
(int) obj.getPos().getY(), this);
// 将缓冲区的图形绘制到显示面板上
g.drawImage(paint, 0, 0, this);
private void init()
this.setTitle("植物大战僵尸");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setLocation(200, 200);
this.setSize(width, height);
this.setVisible(true);
/**
* 当游戏界面图形变化时,我们要不断的刷新显示
*/
@Override
public void run()
while (isRunnableStart)
this.repaint();
try
Thread.sleep(50);
catch (InterruptedException e)
e.printStackTrace();
3、图片获取类GameImage.java
/**
* 获取图片
* @author Admin
*
*/
public class GameImage
//plant
public static List<BufferedImage> sunflower;
public static List<BufferedImage> nut;
public static List<BufferedImage> pea;
//game main bg
public static BufferedImage game_main_bg;
private static GameImage instance = null;
/**
* 提供对外接口,并加上同步锁
* @return
*/
public static GameImage getInstance()
if(instance == null)
synchronized(GameImage.class)
if(instance == null)
instance = new GameImage();
return instance;
private GameImage()
sunflower = new ArrayList<BufferedImage>();
nut = new ArrayList<BufferedImage>();
pea = new ArrayList<BufferedImage>();
try
game_main_bg = ImageIO.read(new File("image\\\\bk1.jpg"));
//plant
for(int i=1;i<=11;i++)
nut.add(ImageIO.read(new File("image\\\\plant\\\\p_3_0"+i+".png")));
if(i <= 8)
sunflower.add(ImageIO.read(new File("image\\\\plant\\\\p_1_0"+i+".png")));
pea .add(ImageIO.read(new File("image\\\\plant\\\\p_2_0"+i+".png")));
catch (IOException e)
e.printStackTrace();
4、植物信息保存类PlantAutoMoveInfo.java
/**
* 植物信息业务类
* @author Admin
*
*/
public class PlantAutoMoveInfo implements Runnable
//植物对象的坐标
private Point pos;
//线程执行标识
private boolean isStart;
//将要显示的图片
private BufferedImage showImage;
//显示图片索引值
private int index;
//构造植物对象的类型
private int type;
//阳光每隔多少秒产生
private int SUNTIME;
//阳光产生剩余时间
private int tempTime;
//判断是否可以生产阳光
private boolean isProduction;
//产生植物动画的所有图片
private List<BufferedImage> plantImage;
public PlantAutoMoveInfo(Point pos,int type,List<BufferedImage> gameImage)
this.pos = pos;
this.plantImage = gameImage;
SUNTIME = Constants.PRODUCTION_SUNNING_TIME;
index = 0;
tempTime = 0;
showImage = plantImage.get(index);
this.type = type;
isStart = true;
isProduction = false;
new Thread(this).start();
public PlantAutoMoveInfo()
public void stopSunflowerThread(boolean bool)
isStart = bool;
public boolean isProduction()
return isProduction;
public int getType()
return type;
public void setType(int type)
this.type = type;
public void setProduction(boolean isProduction)
this.isProduction = isProduction;
public Point getPos()
return pos;
public void setPos(Point pos)
this.pos = pos;
public boolean isStart()
return isStart;
public void setStart(boolean isStart)
this.isStart = isStart;
public BufferedImage getShowImage()
return showImage;
public void setShowImage(BufferedImage showImage)
this.showImage = showImage;
public int getTempTime()
return tempTime;
public void setTempTime(int tempTime)
this.tempTime = tempTime;
@Override
public void run()
while(isStart)
index++;
showImage = plantImage.get(index % plantImage.size());
try
Thread.sleep(150);
catch (InterruptedException e)
e.printStackTrace();
if(type == Constants.SUNFLOWER && !isProduction)
tempTime++;
if((tempTime * 150) >= SUNTIME * 1000)
isProduction = true;
6、常量类Constants.java
/**
* 常量类
* @author Admin
*
*/
public class Constants
public final static int SUNFLOWER = 0x0002;
public final static int PEA = 0x0004;
public final static int NUT = 0x0008;
public final static int PRODUCTION_SUNNING_TIME = 0;
以上是关于Java解决游戏界面闪屏的主要内容,如果未能解决你的问题,请参考以下文章