TA的每日心情 | 开心 2021-3-12 23:18 |
---|
签到天数: 2 天 [LV.1]初来乍到
|
以前我都用双缓存显示动画,没有用过BufferStrategy类。今天我在《java游戏编程》上看了一个例子,书上讲:双缓存、翻页及显示器刷新等待都可由BufferStrategy类自动处理,它会根据系统功能选择最佳的缓存方法:翻页或双缓存且翻页之前会等待显示器刷新完毕。以下是简化整理后的例子,我的显卡是GeforceII Mx,程序运行正常。有兴趣可下载本程序和原程序分析。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.image.BufferStrategy;
public class FullAnimationTest{
private Image bgImage;//背景图
private Animation anim;//动画对象
static FullScreenWindow myWindow;
private static final long DEMO_TIME = 5000;//动画演示时间
public static void main(String[] args){
GraphicsEnvironment ge =GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gd = ge.getDefaultScreenDevice();//取得GraphicsDevice,显示卡
//显示模式:分辨率,颜色,刷新率
DisplayMode displayMode=new DisplayMode(800,600,24,DisplayMode.REFRESH_RATE_UNKNOWN);
//用JFrmae作为全屏窗口
if ( gd.isFullScreenSupported() ){
myWindow= new FullScreenWindow();
gd.setFullScreenWindow(myWindow);//全屏工作
if(gd.isDisplayChangeSupported()){
try{
gd.setDisplayMode(displayMode);//设置显示方式
try{
EventQueue.invokeAndWait(new Runnable(){
public void run(){
myWindow.createBufferStrategy(2);//生成BufferStrategy,至少要有2个缓存区
}
});
}catch(Exception ex){}
FullAnimationTest test=new FullAnimationTest();
test.run();
}catch(IllegalArgumentException e){}
}
}else
System.out.println("Unsupported full screen.");
}
public void loadImages() {
// 装入图像
bgImage = loadImage("images/background.jpg");
Image player1 = loadImage("images/player1.png");
Image player2 = loadImage("images/player2.png");
Image player3 = loadImage("images/player3.png");
// 生成动画
anim = new Animation();
anim.addFrame(player1, 250);
anim.addFrame(player2, 150);
anim.addFrame(player1, 150);
anim.addFrame(player2, 150);
anim.addFrame(player3, 200);
anim.addFrame(player2, 150);
}
private Image loadImage(String fileName) {
return new ImageIcon(fileName).getImage();
}
public void run() {
loadImages();
animationLoop();
}
public void animationLoop() {
long startTime = System.currentTimeMillis();
long currTime = startTime;
while (currTime - startTime < DEMO_TIME) {
long elapsedTime =System.currentTimeMillis() - currTime;//流逝的时间
currTime += elapsedTime;//已动画时间
// update animation
anim.update(elapsedTime);//是否需要更新图像
// 绘制屏幕
BufferStrategy strategy=myWindow.getBufferStrategy();
Graphics2D g=(Graphics2D)strategy.getDrawGraphics();
draw(g);
g.dispose();
if(!strategy.contentsLost()){
strategy.show();//屏幕更新
}
Toolkit.getDefaultToolkit().sync();
try {
Thread.sleep(20);
}
catch (InterruptedException ex) { }
}
}
public void draw(Graphics g) {
g.drawImage(bgImage, 0, 0, null);
g.drawImage(anim.getImage(), 0, 0, null);
}
}
class FullScreenWindow extends JFrame{
public FullScreenWindow(){
setUndecorated(true);//隐藏JFrame上的Title bar
setIgnoreRepaint(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
//setBackground(Color.blue);
this.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent evt){
dispose();
System.exit(0);
}
});
}
public void quit(){
this.dispose();
}
}
import java.awt.Image;
import java.util.ArrayList;
/**
Animation类管理一系列图像(帧)和每个帧显示的时间量
*/
public class Animation {
private ArrayList frames;//用来存放动画帧AnimFrame对象
private int currFrameIndex;//当前帧的索引
private long animTime;//动画已运动时间
private long totalDuration;//所有图像总的持续时间,是各个图像显示时间的和。
/**
生成新的空白Animation.
*/
public Animation() {
frames = new ArrayList();
totalDuration = 0;
start();
}
/**
将指定显示时间的图像加进动画中.
*/
public synchronized void addFrame(Image image,
long duration)
{
totalDuration += duration;
frames.add(new AnimFrame(image, totalDuration));
}
/**
从头开始重新启动这个动画.
*/
public synchronized void start() {
animTime = 0;
currFrameIndex = 0;
}
/**
必要时更新这个动画的当前图像(帧)
*/
public synchronized void update(long elapsedTime) {
if (frames.size() > 1) {
animTime += elapsedTime;
if (animTime >= totalDuration) {//如果动画运动的时间大于各个图像显示时间的和。即所有图像已显示一遍。
animTime = animTime % totalDuration;
currFrameIndex = 0;
}
while (animTime > getFrame(currFrameIndex).endTime) {//如果动画运动时间大于当前图像显示结束时间
currFrameIndex++;//下一帧
}
}
}
/**
取这个Animation的当前图像,如果没有,返回null.
*/
public synchronized Image getImage() {
if (frames.size() == 0) {
return null;
}
else {
return getFrame(currFrameIndex).image;
}
}
private AnimFrame getFrame(int i) {//取第i个动画帧
return (AnimFrame)frames.get(i);
}
private class AnimFrame {//动画帧,一个动画帧包含图像和结束显示时间量
Image image;
long endTime;
public AnimFrame(Image image, long endTime) {
this.image = image;
this.endTime = endTime;
}
}
}
源码下载:http://file.javaxxz.com/2014/10/29/235559875.zip |
|