雙緩沖技術解決閃爍問題
上節,我們實現了動畫效果,但是發現窗口會不停的閃爍,體驗度非常差。在實際開發中,繪制圖形是非常復雜的,繪圖可能需要幾秒甚至更長時間,也經常發生閃爍現象, 為了解決這個問題,我們通常使用“雙緩沖技術”。
1)“雙緩沖技術”的繪圖過程如下:
a. 在內存中創建與畫布一致的緩沖區
b.?在緩沖區畫圖
c. 將緩沖區位圖拷貝到當前畫布上
e. 釋放內存緩沖區
雙緩沖即在內存中創建一個與屏幕繪圖區域一致的對象,先將圖形繪制到內存中的這個對象上,再一次性將這個對象上的圖形拷貝到屏幕上,這樣能大大加快繪圖的速度。
我們只需將如下“雙緩沖”實現代碼,放入MyGrameFrame類中,即可:
【示例1】添加雙緩沖技術
privateImageoffScreenImage=null;
publicvoidupdate(Graphics g) {
if(offScreenImage==null)
offScreenImage=this.createImage(500,500);//這是游戲窗口的寬度和高度
Graphics gOff =offScreenImage.getGraphics();
paint(gOff);
g.drawImage(offScreenImage, 0, 0,null);
}
GameObject類設計
1) GameObject類的定義
我們發現,窗口中所有的對象(飛機、炮彈等等)都有很多共性:“圖片對象、坐標位置、運行速度、寬度和高度”。為了方便程序開發,我們需要設計一個GameObject類,它可以作為所有游戲物體的父類,方便我們編程。
【示例2】GameObject類
packagecn.sxt.game;
importjava.awt.Graphics;
importjava.awt.Image;
importjava.awt.Rectangle;
publicclassGameObject {
Imageimg;//該物體對應的圖片對象
doublex,y;//該物體的坐標
intspeed;//該物體的運行速度
intwidth,height;//該物體所在矩形區域的寬度和高度
/**
*怎么樣繪制本對象
*@paramg
*/
publicvoiddrawMySelf(Graphics? g){
g.drawImage(img, (int)x, (int)y,null);
}
publicGameObject(Image img,doublex,doubley) {
this.img= img;
this.x= x;
this.y= y;
if(img!=null){
this.width= img.getWidth(null);
this.height= img.getHeight(null);
}
}
publicGameObject(Image img,doublex,doubley,intspeed,intwidth,
intheight) {
this.img= img;
this.x= x;
this.y= y;
this.speed= speed;
this.width= width;
this.height= height;
}
publicGameObject() {
}
/**
*返回物體對應矩形區域,便于后續在碰撞檢測中使用
*@return
*/
publicRectangle getRect(){
returnnewRectangle((int)x,(int)y,width,height);
}
}
2)設計飛機類
有了GameObject這個父類,我們設計飛機類特別簡單,目前飛機類沒有特別復雜的要求。我們只需簡單的繼承,即可使用:
【示例3】Plane類
packagecn.sxt.game;
importjava.awt.Graphics;
importjava.awt.Image;
publicclassPlaneextendsGameObject {
@Override
publicvoiddrawMySelf(Graphics g) {
super.drawMySelf(g);
this.x+=3;//飛機水平飛,我們也可以調整x、y算法,按照我們指定的路徑飛行
}
publicPlane(Image img,doublex,doubley) {
super(img,x,y);
}
}
通過繼承,我們發現實現新的類,爽了很多!
3) MyGameFrame類調用方式的調整
我們將Plane類封裝后,也無需在MyGameFrame類中添加那么多飛機的屬性,我們全部封裝到了Plane類里面,因此,調用也變得更加簡單。
【示例4】封裝后的MyGameFrame類
publicclassMyGameFrameextendsFrame {
ImagebgImg= GameUtil.getImage("images/bg.jpg");
ImageplaneImg= GameUtil.getImage("images/plane.png");
Planeplane=newPlane(planeImg,300,300);
//paint方法作用是:畫出整個窗口及內部內容。被系統自動調用。
@Override
publicvoidpaint(Graphics g) {
g.drawImage(bgImg, 0, 0,null);
plane.drawMySelf(g);//畫出飛機本身
}
//其余代碼,沒有任何變化,不在附上,自行參考上一個版本。
}
通過面向對象封裝后,如果我們要再創建多個飛機,也變得異常簡單。
【示例5】創建多個飛機
publicclassMyGameFrameextendsFrame {
ImagebgImg= GameUtil.getImage("images/bg.jpg");
ImageplaneImg= GameUtil.getImage("images/plane.png");
Planeplane=newPlane(planeImg,300,300);
Planeplane2=newPlane(planeImg,300,350);
Planeplane3=newPlane(planeImg,300,400);
//paint方法作用是:畫出整個窗口及內部內容。被系統自動調用。
@Override
publicvoidpaint(Graphics g) {
g.drawImage(bgImg, 0, 0,null);
plane.drawMySelf(g);//畫出飛機本身
plane2.drawMySelf(g);//畫出飛機本身
plane3.drawMySelf(g);//畫出飛機本身
}
//其余代碼,和上個版本一致,為節省篇幅突出重點,不在附上。
}
「全棧Java筆記」是一部能幫大家從零到一成長為全棧Java工程師系列筆記。筆者江湖人稱 Mr. G,10年Java研發經驗,曾在神州數碼、航天院某所研發中心從事軟件設計及研發工作,從小白逐漸做到工程師、高級工程師、架構師。精通Java平臺軟件開發,精通JAVAEE,熟悉各種流行開發框架。
筆記包含從淺入深的六大部分:
A-Java入門階段
B-數據庫從入門到精通
C-手刃移動前端和Web前端
D-J2EE從了解到實戰
E-Java高級框架精解
F-Linux和Hadoop