雙緩沖技術(shù)解決閃爍問題
上節(jié),我們實現(xiàn)了動畫效果惠呼,但是發(fā)現(xiàn)窗口會不停的閃爍,體驗度非常差峦耘。在實際開發(fā)中剔蹋,繪制圖形是非常復(fù)雜的,繪圖可能需要幾秒甚至更長時間辅髓,也經(jīng)常發(fā)生閃爍現(xiàn)象泣崩, 為了解決這個問題,我們通常使用“雙緩沖技術(shù)”洛口。
1)“雙緩沖技術(shù)”的繪圖過程如下:
a. 在內(nèi)存中創(chuàng)建與畫布一致的緩沖區(qū)
b.?在緩沖區(qū)畫圖
c. 將緩沖區(qū)位圖拷貝到當前畫布上
e. 釋放內(nèi)存緩沖區(qū)
雙緩沖即在內(nèi)存中創(chuàng)建一個與屏幕繪圖區(qū)域一致的對象矫付,先將圖形繪制到內(nèi)存中的這個對象上,再一次性將這個對象上的圖形拷貝到屏幕上第焰,這樣能大大加快繪圖的速度买优。
我們只需將如下“雙緩沖”實現(xiàn)代碼,放入MyGrameFrame類中,即可:
【示例1】添加雙緩沖技術(shù)
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類設(shè)計
1) GameObject類的定義
我們發(fā)現(xiàn)杀赢,窗口中所有的對象(飛機烘跺、炮彈等等)都有很多共性:“圖片對象、坐標位置葵陵、運行速度液荸、寬度和高度”。為了方便程序開發(fā)脱篙,我們需要設(shè)計一個GameObject類娇钱,它可以作為所有游戲物體的父類,方便我們編程绊困。
【示例2】GameObject類
packagecn.sxt.game;
importjava.awt.Graphics;
importjava.awt.Image;
importjava.awt.Rectangle;
publicclassGameObject {
Imageimg;//該物體對應(yīng)的圖片對象
doublex,y;//該物體的坐標
intspeed;//該物體的運行速度
intwidth,height;//該物體所在矩形區(qū)域的寬度和高度
/**
*怎么樣繪制本對象
*@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() {
}
/**
*返回物體對應(yīng)矩形區(qū)域文搂,便于后續(xù)在碰撞檢測中使用
*@return
*/
publicRectangle getRect(){
returnnewRectangle((int)x,(int)y,width,height);
}
}
2)設(shè)計飛機類
有了GameObject這個父類,我們設(shè)計飛機類特別簡單秤朗,目前飛機類沒有特別復(fù)雜的要求煤蹭。我們只需簡單的繼承,即可使用:
【示例3】Plane類
packagecn.sxt.game;
importjava.awt.Graphics;
importjava.awt.Image;
publicclassPlaneextendsGameObject {
@Override
publicvoiddrawMySelf(Graphics g) {
super.drawMySelf(g);
this.x+=3;//飛機水平飛取视,我們也可以調(diào)整x硝皂、y算法,按照我們指定的路徑飛行
}
publicPlane(Image img,doublex,doubley) {
super(img,x,y);
}
}
通過繼承作谭,我們發(fā)現(xiàn)實現(xiàn)新的類稽物,爽了很多!
3) MyGameFrame類調(diào)用方式的調(diào)整
我們將Plane類封裝后折欠,也無需在MyGameFrame類中添加那么多飛機的屬性贝或,我們?nèi)糠庋b到了Plane類里面,因此锐秦,調(diào)用也變得更加簡單咪奖。
【示例4】封裝后的MyGameFrame類
publicclassMyGameFrameextendsFrame {
ImagebgImg= GameUtil.getImage("images/bg.jpg");
ImageplaneImg= GameUtil.getImage("images/plane.png");
Planeplane=newPlane(planeImg,300,300);
//paint方法作用是:畫出整個窗口及內(nèi)部內(nèi)容。被系統(tǒng)自動調(diào)用酱床。
@Override
publicvoidpaint(Graphics g) {
g.drawImage(bgImg, 0, 0,null);
plane.drawMySelf(g);//畫出飛機本身
}
//其余代碼羊赵,沒有任何變化,不在附上扇谣,自行參考上一個版本慷垮。
}
通過面向?qū)ο蠓庋b后,如果我們要再創(chuàng)建多個飛機揍堕,也變得異常簡單。
【示例5】創(chuàng)建多個飛機
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方法作用是:畫出整個窗口及內(nèi)部內(nèi)容汤纸。被系統(tǒng)自動調(diào)用衩茸。
@Override
publicvoidpaint(Graphics g) {
g.drawImage(bgImg, 0, 0,null);
plane.drawMySelf(g);//畫出飛機本身
plane2.drawMySelf(g);//畫出飛機本身
plane3.drawMySelf(g);//畫出飛機本身
}
//其余代碼,和上個版本一致贮泞,為節(jié)省篇幅突出重點楞慈,不在附上幔烛。
}
「全棧Java筆記」是一部能幫大家從零到一成長為全棧Java工程師系列筆記。筆者江湖人稱 Mr. G囊蓝,10年Java研發(fā)經(jīng)驗饿悬,曾在神州數(shù)碼、航天院某所研發(fā)中心從事軟件設(shè)計及研發(fā)工作聚霜,從小白逐漸做到工程師狡恬、高級工程師、架構(gòu)師蝎宇。精通Java平臺軟件開發(fā)弟劲,精通JAVAEE,熟悉各種流行開發(fā)框架姥芥。
筆記包含從淺入深的六大部分:
A-Java入門階段
B-數(shù)據(jù)庫從入門到精通
C-手刃移動前端和Web前端
D-J2EE從了解到實戰(zhàn)
E-Java高級框架精解
F-Linux和Hadoop