版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、*GameMID。Java/* * To change this template, choose Tools | Templates * and open the template in the editor. */import javax.microedition.lcdui.Display;import javax.microedition.midlet.*;/* * author Administrator */public class GameMID extends MIDlet private Display display; private GameWorld gw=null;
2、public GameMID() display = Display.getDisplay(this); /獲取Display gw=new GameWorld(this); /創(chuàng)建游戲畫布 display.setCurrent(gw); /設(shè)置游戲畫布為當(dāng)前顯示畫面 public void startApp() if(gw!=null) gw.start(); /游戲開始執(zhí)行 public void pauseApp() if(gw!=null)gw.setPaused(true); /游戲暫停執(zhí)行 public void destroyApp(boolean unconditional)
3、/* 退出程序 */ public void exit() try destroyApp(false); catch(Exception e) notifyDestroyed(); *GameWorld。Javaimport java.io.IOException;import javax.microedition.lcdui.Font;import javax.microedition.lcdui.Graphics;import javax.microedition.lcdui.Image;import javax.microedition.lcdui.game.GameCanvas;imp
4、ort javax.microedition.lcdui.game.Sprite;import javax.microedition.lcdui.game.TiledLayer;/* * To change this template, choose Tools | Templates * and open the template in the editor. */* * * author Administrator */public class GameWorld extends GameCanvas implements Runnable GameMID mid; /游戲MIDlet T
5、hread MainThread; /游戲主線程 private final int MS_PER_FRAME=30; /設(shè)置一次游戲循環(huán)所需時(shí)間,單位為毫秒(ms),每秒游戲幀數(shù)約為1000/MS_PER_FRAME private int cps; /游戲幀速 private boolean isPaused; /游戲暫停狀態(tài) private boolean running; /游戲運(yùn)行狀態(tài) Graphics g; /游戲繪圖對(duì)象 public static int ScreenWidth; /游戲屏幕寬度,設(shè)置為靜態(tài)成員,方便外部訪問 public static int ScreenHe
6、ight; /游戲屏幕高度 public static int GameState; /游戲狀態(tài),1為暫停,2為游戲進(jìn)行中,3為游戲失敗 public static int KeyState; /按鍵狀態(tài) private Image imgEnemy,imgBoy;/精靈圖像 private Sprite sprEnemy; /定義敵人精靈 private MySprite sprBoy; /用擴(kuò)展的精靈類來定義玩家精靈 /定義三個(gè)不同方向的玩家精靈幀序列,右方向可由左方向鏡像變換得到 int LSequ=3,4,3,5; /定義左方向精靈幀序列 int USequ=6,7,6,8; /定義上
7、方向精靈幀序列 int DSequ=0,1,0,2; /定義下方向精靈幀序列 int enemyX,enemyY; /敵人精靈坐標(biāo) int enemySpeedX; /敵人精靈速度,這里設(shè)置為只能水平移動(dòng) boolean isColl; /碰撞標(biāo)志 long CollTextTime; /碰撞文本顯示時(shí)間 TiledBg tbg; /創(chuàng)建貼圖層應(yīng)用類 TiledLayer tl; /創(chuàng)建貼圖層類/定義字體private Font largeFont=Font.getFont(Font.FACE_SYSTEM,Font.STYLE_BOLD, Font.SIZE_LARGE); private
8、Font mediumFont=Font.getFont(Font.FACE_SYSTEM,Font.STYLE_BOLD, Font.SIZE_MEDIUM); public GameWorld(GameMID midlet) super(true); this.mid=midlet; /獲取MIDlet this.setFullScreenMode(true); /設(shè)置為全屏模式 ScreenWidth=getWidth(); /獲取屏幕大小 ScreenHeight=getHeight(); g=this.getGraphics(); /獲取繪圖對(duì)象 running=false; /設(shè)置
9、游戲運(yùn)行狀態(tài) isPaused=false; GameInit(); /游戲初始化 /* 游戲初始化 */ private void GameInit() try imgBoy = Image.createImage(/Boy.png); imgEnemy=Image.createImage(/enemy.png); catch (IOException ex) ex.printStackTrace(); / 使用Image對(duì)象,幀寬度、幀高度,速度,限制范圍矩形左上角的X坐標(biāo)、Y坐標(biāo)、高度和寬度來構(gòu)造自定義精靈 sprBoy=new MySprite(imgBoy,32,48,3,0,0,S
10、creenWidth,ScreenHeight); sprBoy.setFrameSequence(LSequ); /設(shè)置初始化時(shí)的精靈幀序列和方向 sprBoy.setDir( MySprite.LEFT); /設(shè)置初始化時(shí)精靈方向 sprBoy.defineReferencePixel(sprBoy.getWidth()/2, sprBoy.getHeight()/2); /設(shè)置參考點(diǎn) sprBoy.setRefPixelPosition(ScreenWidth/2, ScreenHeight/2); /通過參考點(diǎn)定位精靈 int sw=sprBoy.getWidth(); int sh=
11、sprBoy.getHeight(); sprBoy.defineCollisionRectangle(sw/10, sh/10, sw*8/10,sh*8/10); /重設(shè)精靈的碰撞矩形范圍為原來的80 /創(chuàng)建敵人精靈 sprEnemy=new Sprite(imgEnemy,imgEnemy.getWidth()/3,imgEnemy.getHeight()/3); sprEnemy.setFrameSequence(LSequ); /設(shè)置精靈循環(huán)序列 enemyX=50; /設(shè)置敵人精靈的坐標(biāo) enemyY=200; enemySpeedX=-2; /設(shè)置敵人精靈速度 tbg=new T
12、iledBg(); /創(chuàng)建TiledBg對(duì)象 tl=tbg.getTiledbg(); /獲取貼圖層 /* 游戲運(yùn)行 */ public void run() int cyclesThisSecond=0; /當(dāng)前1秒內(nèi)的循環(huán)次數(shù) long cycleStartTime; /循環(huán)開始時(shí)間 long lastCPSTime=0; /上次計(jì)算幀速的時(shí)間 long cycleEndTime=0; /循環(huán)結(jié)束時(shí)間 long cycleTimes=0; /一次游戲循環(huán)熱所花的時(shí)間 boolean bSkip = false; /游戲是否跳幀 cps=0; System.out.println(游戲開始)
13、;/在控制臺(tái)輸出開始信息,可屏蔽 /* 游戲主循環(huán) */ while(running) /檢查是否運(yùn)行 cycleStartTime = System.currentTimeMillis();/記錄游戲循環(huán)開始時(shí)間 / 下面語句用于處理游戲內(nèi)容,如果游戲設(shè)置為跳幀, / 則本次循環(huán)不處理游戲內(nèi)容 if(!bSkip) GameInput(); /處理輸入消息 GameCycle(); /處理游戲邏輯 render(g); /渲染游戲畫面 flushGraphics(); /更新畫面 /* 下面語句用于計(jì)算游戲循環(huán)時(shí)間,并進(jìn)行相應(yīng)處理 */ cycleEndTime=System.current
14、TimeMillis(); /記錄游戲循環(huán)結(jié)束時(shí)間 cycleTimes=cycleEndTime-cycleStartTime; /計(jì)算循環(huán)時(shí)間 /如果循環(huán)時(shí)間間隔小于MS_PER_FRAME,則通過休眠,使其不小于rate, /并能讓系統(tǒng)有空閑轉(zhuǎn)去處理其他事務(wù) if(cycleTimes 1000) /檢查距上次計(jì)算幀數(shù)的/時(shí)間是否經(jīng)過1000ms lastCPSTime=System.currentTimeMillis(); /設(shè)定lastCPS為當(dāng)前時(shí)間 cps = cyclesThisSecond; / System.out.println(cps:+cps); /輸出每秒的幀數(shù) c
15、yclesThisSecond = 0; /重置幀數(shù) else cyclesThisSecond+; /幀數(shù)遞增 System.out.println(游戲結(jié)束!); release(); /釋放資源 exit(); /退出游戲 /* 啟動(dòng)游戲進(jìn)程 */ public void start() /檢查游戲循環(huán)是否處于運(yùn)行狀態(tài),如果未運(yùn)行,則創(chuàng)建線程并啟動(dòng) /如果游戲處于運(yùn)行狀態(tài),則表示是暫停后的繼續(xù)執(zhí)行,僅設(shè)置暫停狀態(tài)即可 if(!running) running=true; MainThread=new Thread(this); MainThread.start(); GameState=
16、2; else GameState=2; setPaused(false); /退出游戲 private void exit() mid.exit(); /退出游戲 /* 停止游戲 */ private void stop() running=false; /終止游戲循環(huán) /* 釋放游戲資源 */ private void release() /此處為釋放游戲資源的代碼 imgEnemy=null; imgBoy=null; sprBoy=null; sprEnemy=null; tbg=null; tl=null; System.gc(); /*獲取暫停狀態(tài) */ public boolea
17、n getPaused() return isPaused; /* 設(shè)置暫停狀態(tài) */ public void setPaused(boolean isPaused) this.isPaused = isPaused; /* 處理游戲輸入信息 */ private void GameInput() int keyStates = this.getKeyStates(); /獲取按鍵狀態(tài) /* 下面是對(duì)按鍵事件的具體處理,應(yīng)根據(jù)游戲需要進(jìn)行修改*/ KeyState=0; /Fire if(keyStates & FIRE_PRESSED )!=0) KeyState=FIRE_PRESSED;
18、 / Left if (keyStates & LEFT_PRESSED) != 0) KeyState=LEFT_PRESSED; / Right if (keyStates & RIGHT_PRESSED) !=0 ) KeyState=RIGHT_PRESSED; / Up if (keyStates & UP_PRESSED) != 0) KeyState=UP_PRESSED; / Down if (keyStates & DOWN_PRESSED) !=0) KeyState=DOWN_PRESSED; /Game_A if(keyStates & GAME_A_PRESSED)!
19、=0) KeyState=GAME_A_PRESSED; /Game_B if(keyStates & GAME_B_PRESSED)!=0) KeyState=GAME_B_PRESSED; /Game_C if(keyStates & GAME_C_PRESSED)!=0) KeyState=GAME_C_PRESSED; /Game_D if(keyStates & GAME_D_PRESSED)!=0) KeyState=GAME_D_PRESSED; /* 渲染游戲畫面 */ private void render(Graphics g) /* 填充背景 */ g.setColor(
20、0 xffffff); g.fillRect(0, 0, ScreenWidth,ScreenHeight); /* 下面是對(duì)游戲渲染的具體處理,應(yīng)根據(jù)游戲需要進(jìn)行修改*/ tl.paint(g); /繪制貼圖層 / g.drawImage(imgBuild,100, 50, Graphics.LEFT|Graphics.TOP); sprEnemy.paint(g); /繪制敵人精靈 sprBoy.paint(g); /繪制精靈 /當(dāng)敵人精靈和玩家角色相碰撞時(shí),繪制下面的內(nèi)容 if(isColl) g.setColor(0 xccbbcc); g.fillRect(50, 0, 120, 2
21、0); g.setColor(0 xffffff); g.setFont(largeFont); g.drawString(被敵人撞上啦!,60,0, Graphics.LEFT| Graphics.TOP); /* 游戲邏輯處理*/ private void GameCycle() switch(GameState) case 1: /游戲暫停狀態(tài)時(shí)的處理 /根據(jù)按鍵狀態(tài)執(zhí)行相應(yīng)功能 switch(KeyState) case GAME_A_PRESSED: /按下GAME_A鍵時(shí)的處理 GameState=4; /設(shè)置游戲狀態(tài)會(huì)結(jié)束程序 break; case FIRE_PRESSED:
22、/按下FIRE鍵時(shí)的處理 if(getPaused() GameState=2; setPaused(false); break; break; case 2: /游戲處于運(yùn)行狀態(tài)時(shí)的處理 /根據(jù)按鍵狀態(tài)執(zhí)行相應(yīng)功能 /根據(jù)按鍵狀態(tài)進(jìn)行計(jì)算 switch(KeyState) case FIRE_PRESSED: /按下Fire鍵時(shí) GameState=1; /設(shè)置游戲狀態(tài)為暫停 setPaused(true); /設(shè)置暫停 break; case GAME_A_PRESSED: /按下Game_A鍵時(shí) GameState=4; /設(shè)置游戲狀態(tài)為退出 break; case GAME_B_PRE
23、SSED: /按下Game_B鍵時(shí) sprBoy.setFrame(2); break; default: update(); /更新數(shù)據(jù) break; break; case 3: /游戲失敗的處理 break; case 4: /游戲退出時(shí)的處理 stop(); /停止運(yùn)行 break; /* 更新數(shù)據(jù) */ private void update() /敵人的運(yùn)動(dòng) enemyX+=enemySpeedX; /計(jì)算坐標(biāo) if(enemyX=ScreenWidth+sprEnemy.getWidth() & enemySpeedX0) enemySpeedX=-enemySpeedX; /改
24、變速度方向 sprEnemy.setTransform(Sprite.TRANS_NONE); if(enemyX+sprEnemy.getWidth()=0 & enemySpeedXsprBoy.getX() sprBoy.move(-sprBoy.getSpeed(), 0); /移動(dòng)玩家角色精靈 sprEnemy.setTransform(Sprite.TRANS_MIRROR); /設(shè)置敵人精靈方向 enemyX+=sprEnemy.getWidth(); /重設(shè)敵人精靈坐標(biāo) enemySpeedX=2; /設(shè)置敵人精靈速度方向 else sprBoy.move(sprBoy.get
25、Speed(), 0); /移動(dòng)玩家角色精靈 sprEnemy.setTransform(Sprite.TRANS_NONE); /設(shè)置敵人精靈方向 enemyX-=sprEnemy.getWidth(); /重設(shè)敵人精靈坐標(biāo) enemySpeedX=-2; /設(shè)置敵人精靈速度方向 sprEnemy.setRefPixelPosition(enemyX, enemyY); /重設(shè)敵人位置 isColl=true; /設(shè)置碰撞標(biāo)志 CollTextTime=120; /設(shè)置碰撞文本顯示時(shí)間 else if(CollTextTime=0) isColl=false; CollTextTime-;
26、/設(shè)置碰撞文本顯示時(shí)間遞減 /根據(jù)按鍵狀態(tài)計(jì)算玩家角色精靈與貼圖層數(shù)據(jù) switch(KeyState) case LEFT_PRESSED: /按下Left鍵時(shí) /檢查原來是否為左方向的精靈幀序列,如果不是則設(shè)置為左方向精靈幀序列 if(sprBoy.getDir()!=MySprite.LEFT) sprBoy.setFrameSequence(LSequ); /設(shè)置左方向精靈序列 sprBoy.setTransform(MySprite.TRANS_NONE); /設(shè)置為不變換 if(sprBoy.move(MySprite.LEFT) /向左移動(dòng),如果到屏幕邊緣則移動(dòng)貼圖層 tbg.m
27、ove(sprBoy.getSpeed(), 0); break; case RIGHT_PRESSED: /按下Right鍵時(shí) /檢查原來是否為右方向的精靈幀序列,如果不是則設(shè)置為右方向精靈幀序列 if(sprBoy.getDir()!=MySprite.RIGHT) sprBoy.setFrameSequence(LSequ); /設(shè)置左方向精靈幀序列 sprBoy.setTransform(MySprite.TRANS_MIRROR); /設(shè)置為鏡像變換 /向右移動(dòng),如果到屏幕邊緣則移動(dòng)貼圖層 if(sprBoy.move(MySprite.RIGHT) tbg.move(-sprBoy
28、.getSpeed(), 0); break; case UP_PRESSED: /按下Up鍵時(shí) /檢查原來是否為上方向的精靈幀序列,如果不是則設(shè)置為上方向精靈幀序列 if(sprBoy.getDir()!=MySprite.UP) sprBoy.setFrameSequence(USequ); /向上移動(dòng),如果到屏幕邊緣則移動(dòng)貼圖層 if(sprBoy.move(MySprite. UP) tbg.move(0,sprBoy.getSpeed() ); break; case DOWN_PRESSED: /按下Right鍵時(shí) /檢查原來是否為下方向的精靈幀序列,如果不是則設(shè)置為下方向精靈幀序
29、列 if(sprBoy.getDir()!=MySprite.DOWN) sprBoy.setFrameSequence(DSequ); /向下移動(dòng),如果到屏幕邊緣則移動(dòng)貼圖層 if( sprBoy.move(MySprite.DOWN) tbg.move(0,-sprBoy.getSpeed() ); break; tbg.update(); /更新動(dòng)態(tài)貼圖 *MySprite.javaimport javax.microedition.lcdui.Image;import javax.microedition.lcdui.game.Sprite;/* * To change this te
30、mplate, choose Tools | Templates * and open the template in the editor. */* * * author Administrator */public class MySprite extends Sprite private int speed; /速度 private int dir; /方向 private int RoundX; /限制矩形范圍的左上角坐標(biāo) private int RoundY; private int RoundWidth; /限制矩形范圍寬度 private int RoundHeight; /限制
31、矩形范圍高度 /定義各方向靜態(tài)常量 public final static int LEFT=1; /左 public final static int RIGHT=2; /右 public final static int UP=3; /上 public final static int DOWN=4; /下 /* 使用Image對(duì)象,幀寬度w和幀高度h構(gòu)造精靈*/ public MySprite(Image img,int w,int h) super(img,w,h); /使用基類(即Sprite)構(gòu)造方法創(chuàng)建精靈 this.speed=1; /設(shè)置默認(rèn)速度 setDir(DOWN);
32、/設(shè)置默認(rèn)方向 setRoundRect(0,0,240,309); /設(shè)置缺省時(shí)的限制矩形 /* 使用Image對(duì)象,幀寬度w、幀高度h和速度speed構(gòu)造精靈 */ public MySprite(Image img,int w,int h,int speed) super(img,w,h); this.speed=speed; setDir(DOWN); /設(shè)置默認(rèn)方向 /* 使用Image對(duì)象,幀寬度、幀高度,速度,限制范圍矩形左上角的X坐標(biāo)、Y坐標(biāo)、高度和寬度來構(gòu)造精靈 */ public MySprite(Image img,int w,int h,int speed,int rx
33、,int ry,int rw,int rh) super(img,w,h); this.speed=speed; /設(shè)置速度 setDir(DOWN); /設(shè)置默認(rèn)方向 setRoundRect(rx,ry,rw,rh); /設(shè)置限制范圍矩形 /* 設(shè)置限制范圍矩形 */ public void setRoundRect(int rx,int ry,int rw,int rh) setRoundX(rx); setRoundY(ry); setRoundWidth(rw); setRoundHeight(rh); /* 向dir方向移動(dòng)精靈,并返回是否已到達(dá)范圍矩形邊框*/ public bo
34、olean move(int dir) boolean isRound; isRound=false; int moveX=0; int moveY=0; this.setDir(dir); /設(shè)置方向 switch(dir) /通過方向,按設(shè)置的速度距離移動(dòng)精靈 case LEFT: moveX=-getSpeed(); break; case RIGHT: moveX=getSpeed(); break; case UP: moveY=-getSpeed(); break; case DOWN: moveY=getSpeed(); break; /下面語句用于將移動(dòng)點(diǎn)在范圍矩形內(nèi) if(
35、getX()+moveXgetRoundX()+getRoundWidth() moveX=getRoundX()+getRoundWidth()-getX()-getWidth(); isRound=true; if( getY()+moveYgetRoundY()+getRoundHeight() moveY=getRoundY()+getRoundHeight()-getY()-getHeight(); isRound=true; super.nextFrame(); super.move(moveX, moveY); /調(diào)用基類方法移動(dòng)精靈 return isRound; /* 獲取速
36、度 */ public int getSpeed() return speed; /* 設(shè)置速度 */ public void setSpeed(int speed) this.speed = speed; /* 獲取方向 */ public int getDir() return dir; /* 設(shè)置方向 */ public void setDir(int dir) this.dir = dir; /* 獲取限制框X坐標(biāo) */ public int getRoundX() return RoundX; /* 設(shè)置限制框X坐標(biāo) */ public void setRoundX(int Roun
37、dX) this.RoundX = RoundX; /* 獲取限制框Y坐標(biāo) */ public int getRoundY() return RoundY; /* 設(shè)置限制框Y坐標(biāo) */ public void setRoundY(int RoundY) this.RoundY = RoundY; /* 獲取限制框?qū)挾?*/ public int getRoundWidth() return RoundWidth; /* 設(shè)置限制框?qū)挾?*/ public void setRoundWidth(int RoundWidth) this.RoundWidth = RoundWidth; /* 獲
38、取限制框高度 */ public int getRoundHeight() return RoundHeight; /* 設(shè)置限制框高度 */ public void setRoundHeight(int RoundHeight) this.RoundHeight = RoundHeight; *TiledBg.java/* * To change this template, choose Tools | Templates * and open the template in the editor. */import javax.microedition.lcdui.*;import ja
39、vax.microedition.lcdui.game.*;import java.io.IOException;/* * author Administrator */public class TiledBg private Image tiled; /貼圖源圖 private TiledLayer tiledbg; /定義貼圖層 int AnimSeq=14,21,28; /動(dòng)態(tài)貼圖序列 int AnimTiled; /動(dòng)態(tài)貼圖號(hào) int AnimIndex; /記錄當(dāng)前動(dòng)態(tài)貼圖序號(hào) int AnimTimes; /用于計(jì)算動(dòng)態(tài)貼圖時(shí)間間隔 public TiledBg() try / w
40、rite pre-init user code here tiled = Image.createImage(/tiled.png); /獲取源圖 catch (IOException ex) ex.printStackTrace(); AnimIndex=0; /初始化 AnimTimes=0; /* 獲取貼圖源圖像*/ public Image getTiled() return this.tiled; /* 更新動(dòng)態(tài)貼圖 */ public void update() /檢測(cè)動(dòng)態(tài)貼圖時(shí)間間隔,每5次循環(huán)更新一次動(dòng)態(tài)貼圖 if(AnimTimes%5=0) AnimIndex+; /動(dòng)態(tài)貼
41、圖序號(hào)遞增if(AnimIndex=AnimSeq.length) /檢查動(dòng)態(tài)貼圖序號(hào)是否超出下標(biāo)范圍AnimIndex=0; /重置動(dòng)態(tài)貼圖序號(hào) /設(shè)置動(dòng)態(tài)貼圖tiledbg.setAnimatedTile(AnimTiled, AnimSeqAnimIndex); AnimTimes+; /動(dòng)態(tài)貼圖時(shí)間間隔遞增 /* 創(chuàng)建并返回動(dòng)態(tài)貼圖*/ public TiledLayer getTiledbg() /檢查貼圖層是否已創(chuàng)建,如未創(chuàng)建則先創(chuàng)建 if (tiledbg = null) tiledbg = new TiledLayer(20, 10, tiled, 32, 32); /創(chuàng)建貼圖
42、層 AnimTiled= tiledbg.createAnimatedTile(AnimSeq 0); /定義貼圖序號(hào)數(shù)組 int tiles = 3, 3, 2, 2, 2, 2, 2, 15, 7, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 2 , 2, 2, 2, 2, 2, 4, 2, 15, 2, 2, 2, 2, 2, 6, 2, 2, AnimTiled, 2, 3, 2 , 7, 2, 2, 26, 2, 2, 2, 17, 10, 9, 10, 9, 11, 2, 2, 2, 13, 2, 3, 7 , 9, 9, 9, 9, 11, 19, 2, 2, 2
43、, 2, 2, 2, 15, 2, 12, 2, 8, 9, 9, 9 , 2, 2, 2, AnimTiled, 15, 2, 2, 2, 2, 7, 2, 20, 22, 2, 2, 2, 15, 2, 3, 2 , 4, 2, 2, 2, 17, 10, 9, 10, 9, 24, 10, 9, 18, 2, 2, 2, 15, 2, 3, 4 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 15, 2, 2, 26, 19, 19, 2, 15, 2, 3, 2 , 2, 2, 13, 2, 2, 2, 2, 20, 2, 15, AnimTiled, 2, 2, 19, 1
44、9, 3, 15, 3, 3, 2 , 2, 2, 2, 2, 2, 8, 10, 9, 10, 16, 10, 9, 10, 9, 10, 9, 18, 3, 3, 2 , 4, 2, 2, 27, 7, 15, 2, 2, 2, 7, 2, AnimTiled, 2, 2, 4, 2, 2, 6, 3, 2 ; /通過雙重循環(huán)設(shè)置貼圖 for (int row = 0; row 10; row+) for (int col = 0; col =0 & x0) tiledbg.setPosition(0, tiledbg.getY(); return; /檢查是否到達(dá)貼圖層右邊緣,如果是,則
45、設(shè)置為緊貼右邊緣 if(tiledbg.getX()=GameWorld.ScreenWidth-tiledbg.getWidth() & x=0 & y0) tiledbg.setPosition(tiledbg.getX(), 0); return; /檢查是否到達(dá)貼圖層下邊緣,如果是,則設(shè)置為緊貼下邊緣 if( tiledbg.getY()=GameWorld.ScreenHeight-tiledbg.getHeight() & y0) tiledbg.setPosition(tiledbg.getX(), GameWorld.ScreenHeight-tiledbg.getHeight
46、(); return; tiledbg.move(x,y); /移動(dòng)貼圖層 附錄資料:如何處理Java異常及常見異常六種異常處理的陋習(xí)你覺得自己是一個(gè)Java專家嗎?是否肯定自己已經(jīng)全面掌握了Java的異常處理機(jī)制?在下面這段代碼中,你能夠迅速找出異常處理的六個(gè)問題嗎? 1 OutputStreamWriter out = . 2 java.sql.Connection conn = . 3 try / 4 Statement stat = conn.createStatement(); 5 ResultSet rs = stat.executeQuery( 6 select uid, nam
47、e from user); 7 while (rs.next() 8 9 out.println(ID: + rs.getString(uid) / 10 ,姓名: + rs.getString(name); 11 12 conn.close(); / 13 out.close(); 14 15 catch(Exception ex) / 16 17 ex.printStackTrace(); /, 18 作為一個(gè)Java程序員,你至少應(yīng)該能夠找出兩個(gè)問題。但是,如果你不能找出全部六個(gè)問題,請(qǐng)繼續(xù)閱讀本文。 本文討論的不是Java異常處理的一般性原則,因?yàn)檫@些原則已經(jīng)被大多數(shù)人熟知。我們要做的
48、是分析各種可稱為“反例”(anti-pattern)的違背優(yōu)秀編碼規(guī)范的常見壞習(xí)慣,幫助讀者熟悉這些典型的反面例子,從而能夠在實(shí)際工作中敏銳地察覺和避免這些問題。 反例之一:丟棄異常 代碼:15行-18行。 這段代碼捕獲了異常卻不作任何處理,可以算得上Java編程中的殺手。從問題出現(xiàn)的頻繁程度和禍害程度來看,它也許可以和C/C+程序的一個(gè)惡名遠(yuǎn)播的問題相提并論?不檢查緩沖區(qū)是否已滿。如果你看到了這種丟棄(而不是拋出)異常的情況,可以百分之九十九地肯定代碼存在問題(在極少數(shù)情況下,這段代碼有存在的理由,但最好加上完整的注釋,以免引起別人誤解)。 這段代碼的錯(cuò)誤在于,異常(幾乎)總是意味著某些事情
49、不對(duì)勁了,或者說至少發(fā)生了某些不尋常的事情,我們不應(yīng)該對(duì)程序發(fā)出的求救信號(hào)保持沉默和無動(dòng)于衷。調(diào)用一下printStackTrace算不上“處理異?!?。不錯(cuò),調(diào)用printStackTrace對(duì)調(diào)試程序有幫助,但程序調(diào)試階段結(jié)束之后, printStackTrace就不應(yīng)再在異常處理模塊中擔(dān)負(fù)主要責(zé)任了。 丟棄異常的情形非常普遍。打開JDK的ThreadDeath類的文檔,可以看到下面這段說明:“特別地,雖然出現(xiàn)ThreadDeath是一種正常的情形,但ThreadDeath類是Error而不是Exception的子類,因?yàn)樵S多應(yīng)用會(huì)捕獲所有的Exception然后丟棄它不再理睬?!边@段話的意
50、思是,雖然ThreadDeath代表的是一種普通的問題,但鑒于許多應(yīng)用會(huì)試圖捕獲所有異常然后不予以適當(dāng)?shù)奶幚?,所以JDK把 ThreadDeath定義成了Error的子類,因?yàn)镋rror類代表的是一般的應(yīng)用不應(yīng)該去捕獲的嚴(yán)重問題??梢姡瑏G棄異常這一壞習(xí)慣是如此常見,它甚至已經(jīng)影響到了Java本身的設(shè)計(jì)。 那么,應(yīng)該怎樣改正呢?主要有四個(gè)選擇: 1、處理異常。針對(duì)該異常采取一些行動(dòng),例如修正問題、提醒某個(gè)人或進(jìn)行其他一些處理,要根據(jù)具體的情形確定應(yīng)該采取的動(dòng)作。再次說明,調(diào)用printStackTrace算不上已經(jīng)“處理好了異?!薄?2、重新拋出異常。處理異常的代碼在分析異常之后,認(rèn)為自己不能處
51、理它,重新拋出異常也不失為一種選擇。 3、把該異常轉(zhuǎn)換成另一種異常。大多數(shù)情況下,這是指把一個(gè)低級(jí)的異常轉(zhuǎn)換成應(yīng)用級(jí)的異常(其含義更容易被用戶了解的異常)。 4、不要捕獲異常。 結(jié)論一:既然捕獲了異常,就要對(duì)它進(jìn)行適當(dāng)?shù)奶幚怼2灰东@異常之后又把它丟棄,不予理睬。 反例之二:不指定具體的異常 代碼:15行。 許多時(shí)候人們會(huì)被這樣一種“美妙的”想法吸引:用一個(gè)catch語句捕獲所有的異常。最常見的情形就是使用catch(Exception ex)語句。但實(shí)際上,在絕大多數(shù)情況下,這種做法不值得提倡。為什么呢? 要理解其原因,我們必須回顧一下catch語句的用途。catch語句表示我們預(yù)期會(huì)出現(xiàn)某
52、種異常,而且希望能夠處理該異常。異常類的作用就是告訴 Java編譯器我們想要處理的是哪一種異常。由于絕大多數(shù)異常都直接或間接從java.lang.Exception派生,catch (Exception ex)就相當(dāng)于說我們想要處理幾乎所有的異常。 再來看看前面的代碼例子。我們真正想要捕獲的異常是什么呢?最明顯的一個(gè)是SQLException,這是JDBC操作中常見的異常。另一個(gè)可能的異常是IOException,因?yàn)樗僮鱋utputStreamWriter。顯然,在同一個(gè)catch塊中處理這兩種截然不同的異常是不合適的。如果用兩個(gè)catch塊分別捕獲SQLException和IOExce
53、ption就要好多了。這就是說,catch語句應(yīng)當(dāng)盡量指定具體的異常類型,而不應(yīng)該指定涵蓋范圍太廣的Exception類。 另一方面,除了這兩個(gè)特定的異常,還有其他許多異常也可能出現(xiàn)。例如,如果由于某種原因,executeQuery返回了null,該怎么辦?答案是讓它們繼續(xù)拋出,即不必捕獲也不必處理。實(shí)際上,我們不能也不應(yīng)該去捕獲可能出現(xiàn)的所有異常,程序的其他地方還有捕獲異常的機(jī)會(huì)?直至最后由JVM處理。 結(jié)論二:在catch語句中盡可能指定具體的異常類型,必要時(shí)使用多個(gè)catch。不要試圖處理所有可能出現(xiàn)的異常。 反例之三:占用資源不釋放 代碼:3行-14行。 異常改變了程序正常的執(zhí)行流程。
54、這個(gè)道理雖然簡(jiǎn)單,卻常常被人們忽視。如果程序用到了文件、Socket、JDBC連接之類的資源,即使遇到了異常,也要正確釋放占用的資源。為此,Java提供了一個(gè)簡(jiǎn)化這類操作的關(guān)鍵詞finally。 finally是樣好東西:不管是否出現(xiàn)了異常,F(xiàn)inally保證在try/catch/finally塊結(jié)束之前,執(zhí)行清理任務(wù)的代碼總是有機(jī)會(huì)執(zhí)行。遺憾的是有些人卻不習(xí)慣使用finally。 當(dāng)然,編寫finally塊應(yīng)當(dāng)多加小心,特別是要注意在finally塊之內(nèi)拋出的異常?這是執(zhí)行清理任務(wù)的最后機(jī)會(huì),盡量不要再有難以處理的錯(cuò)誤。 結(jié)論三:保證所有資源都被正確釋放。充分運(yùn)用finally關(guān)鍵詞。反例之
55、四:不說明異常的詳細(xì)信息 代碼:3行-18行。 仔細(xì)觀察這段代碼:如果循環(huán)內(nèi)部出現(xiàn)了異常,會(huì)發(fā)生什么事情?我們可以得到足夠的信息判斷循環(huán)內(nèi)部出錯(cuò)的原因嗎?不能。我們只能知道當(dāng)前正在處理的類發(fā)生了某種錯(cuò)誤,但卻不能獲得任何信息判斷導(dǎo)致當(dāng)前錯(cuò)誤的原因。 printStackTrace的堆棧跟蹤功能顯示出程序運(yùn)行到當(dāng)前類的執(zhí)行流程,但只提供了一些最基本的信息,未能說明實(shí)際導(dǎo)致錯(cuò)誤的原因,同時(shí)也不易解讀。 因此,在出現(xiàn)異常時(shí),最好能夠提供一些文字信息,例如當(dāng)前正在執(zhí)行的類、方法和其他狀態(tài)信息,包括以一種更適合閱讀的方式整理和組織printStackTrace提供的信息。 結(jié)論四:在異常處理模塊中提供適
56、量的錯(cuò)誤原因信息,組織錯(cuò)誤信息使其易于理解和閱讀。 反例之五:過于龐大的try塊 代碼:3行-14行。 經(jīng)??梢钥吹接腥税汛罅康拇a放入單個(gè)try塊,實(shí)際上這不是好習(xí)慣。這種現(xiàn)象之所以常見,原因就在于有些人圖省事,不愿花時(shí)間分析一大塊代碼中哪幾行代碼會(huì)拋出異常、異常的具體類型是什么。把大量的語句裝入單個(gè)巨大的try塊就象是出門旅游時(shí)把所有日常用品塞入一個(gè)大箱子,雖然東西是帶上了,但要找出來可不容易。 一些新手常常把大量的代碼放入單個(gè)try塊,然后再在catch語句中聲明Exception,而不是分離各個(gè)可能出現(xiàn)異常的段落并分別捕獲其異常。這種做法為分析程序拋出異常的原因帶來了困難,因?yàn)橐淮蠖未?/p>
57、碼中有太多的地方可能拋出Exception。 結(jié)論五:盡量減小try塊的體積。 反例之六:輸出數(shù)據(jù)不完整 代碼:7行-11行。 不完整的數(shù)據(jù)是Java程序的隱形殺手。仔細(xì)觀察這段代碼,考慮一下如果循環(huán)的中間拋出了異常,會(huì)發(fā)生什么事情。循環(huán)的執(zhí)行當(dāng)然是要被打斷的,其次, catch塊會(huì)執(zhí)行?就這些,再也沒有其他動(dòng)作了。已經(jīng)輸出的數(shù)據(jù)怎么辦?使用這些數(shù)據(jù)的人或設(shè)備將收到一份不完整的(因而也是錯(cuò)誤的)數(shù)據(jù),卻得不到任何有關(guān)這份數(shù)據(jù)是否完整的提示。對(duì)于有些系統(tǒng)來說,數(shù)據(jù)不完整可能比系統(tǒng)停止運(yùn)行帶來更大的損失。 較為理想的處置辦法是向輸出設(shè)備寫一些信息,聲明數(shù)據(jù)的不完整性;另一種可能有效的辦法是,先緩沖
58、要輸出的數(shù)據(jù),準(zhǔn)備好全部數(shù)據(jù)之后再一次性輸出。 結(jié)論六:全面考慮可能出現(xiàn)的異常以及這些異常對(duì)執(zhí)行流程的影響。 改寫后的代碼 根據(jù)上面的討論,下面給出改寫后的代碼。也許有人會(huì)說它稍微有點(diǎn)?嗦,但是它有了比較完備的異常處理機(jī)制。 OutputStreamWriter out = . java.sql.Connection conn = . try Statement stat = conn.createStatement(); ResultSet rs = stat.executeQuery( select uid, name from user); while (rs.next() out.pr
59、intln(ID: + rs.getString(uid) + ,姓名: + rs.getString(name); catch(SQLException sqlex) out.println(警告:數(shù)據(jù)不完整); throw new ApplicationException(讀取數(shù)據(jù)時(shí)出現(xiàn)SQL錯(cuò)誤, sqlex); catch(IOException ioex) throw new ApplicationException(寫入數(shù)據(jù)時(shí)出現(xiàn)IO錯(cuò)誤, ioex); finally if (conn != null) try conn.close(); catch(SQLException s
60、qlex2) System.err(this.getClass().getName() + .mymethod - 不能關(guān)閉數(shù)據(jù)庫(kù)連接: + sqlex2.toString(); if (out != null) try out.close(); catch(IOException ioex2) System.err(this.getClass().getName() + .mymethod - 不能關(guān)閉輸出文件 + ioex2.toString(); 本文的結(jié)論不是放之四海皆準(zhǔn)的教條,有時(shí)常識(shí)和經(jīng)驗(yàn)才是最好的老師。如果你對(duì)自己的做法沒有百分之百的信心,務(wù)必加上詳細(xì)、全面的注釋。 另一方面,不
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 血腫的應(yīng)急處理
- 應(yīng)收會(huì)計(jì)年終總結(jié)
- 2023年氣相色譜儀資金需求報(bào)告
- 病例討論周圍神經(jīng)病
- 3.3.3離子反應(yīng) 課件高一上學(xué)期化學(xué)蘇教版(2019)必修第一冊(cè)
- 背影教案反思
- 好玩的冰說課稿
- 開展我為同學(xué)辦實(shí)事活動(dòng)
- 神經(jīng)病學(xué)臨床案例分享
- 安全生產(chǎn)變更索賠管理細(xì)則
- 國(guó)家文化安全教育課件
- 提升員工參與度的方法與技巧
- 九年級(jí)Unit9大單元教學(xué)設(shè)計(jì)
- 《水字演變及成語》課件
- 山東省汽車維修工時(shí)定額(T-SDAMTIA 0001-2023)
- 電腦故障檢測(cè)報(bào)告
- 春節(jié)期間的傳統(tǒng)煙花和焰火表演
- 綠植花卉租擺及園林養(yǎng)護(hù)服務(wù) 投標(biāo)方案(技術(shù)方案)
- 2023年6月天津高考英語第二次試卷真題重點(diǎn)詞匯清單
- 會(huì)展概論-來逢波-習(xí)題答案
- 廣東小學(xué)生詩詞大賽備考試題庫(kù)400題(三四年級(jí)適用)
評(píng)論
0/150
提交評(píng)論