繼續,考慮到日后擴充的需要,開始將代碼模塊化重構,將原有MyPanel分解成Common,GameMap,GameHandle及MyPanel等4個子模塊,逐步實現Sprite操作。
0-5講源碼下載地址如下,已打包。
http://www.3adisk.com/?onlinezero
或者把這個X的gif文件另存為rar格式
由于沒有什么變化,就不多說了,我今天繼續郁悶,什么都不管了,繼續郁悶……
Common類:
package org.loon.chair.example5;
/**
*
* @author chenpeng
* @email ceponline@yahoo.com.cn
*
* Loon Framework in Game
*
*/
public interface Common {
//此處我們添加一組常數,用以區別左右上下按鍵的觸發,
//之所以采用數字進行區別,原因大家都很清楚^^,數字
//運算效率高嘛~
public static final int LEFT = 0;
public static final int RIGHT = 1;
public static final int UP = 2;
public static final int DOWN = 3;
//單個圖像大小,我默認采用32x32圖形,可根據需要調整比例。
//當時,始終應和窗體大小比例協調;比如32x32的圖片,如何
//一行設置15個,那么就是480,也就是本例子默認的窗體大小,
//當然,我們也可以根據ROW*CS,COl*CS在初始化時自動調整
//窗體大小,以后的例子中會用到類似情況。總之一句話,編程
//是[為目的而存在的],所有的方法,大家都可任意嘗試和使用。
public static final int CS = 32;
}
GameMap類:
package org.loon.chair.example5;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
/**
*
* @author chenpeng
* @email ceponline@yahoo.com.cn
*
* Loon Framework in Game
*
*/
public class GameMap implements Common{
//設定背景方格默認行數
private static final int ROW = 15;
//設定背景方格默認列數
private static final int
//設定地圖,通常在rpg類型游戲開發中,以[二維數組]對象為
//基礎進行地圖處理,用以描繪出X坐標和Y坐標。實際上,即令
//再華麗的RPG類游戲,都是從這些簡單的X,Y坐標開始的。
//PS:所謂[數組],大家可以簡單的理解為即數據的集合,一維數組
//僅包含X軸,而二維是由X,Y兩個軸組成的,X與Y的交織點,即為
//一條數據。
private int[][] map = {
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,1,1,1,1,1,0,0,0,0,1},
{1,0,0,0,0,1,0,0,0,1,0,0,0,0,1},
{1,0,0,0,0,1,0,0,0,1,0,0,0,0,1},
{1,0,0,0,0,1,0,0,0,1,0,0,0,0,1},
{1,0,0,0,0,1,1,0,1,1,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}};
//設定顯示圖像對象
private Image floorImage;
private Image wallImage;
// 游戲所使用面板
private MyPanel panel;
public GameMap(MyPanel panel) {
// 初始化圖像
loadImage();
}
public void draw(Graphics g) {
//在Java或任何游戲開發中,算法都是最重要的一步,本例盡使用
//簡單的雙層for循環進行地圖描繪,
for (int x = 0; x < ROW; x++) {
for (int j = 0; j <
// switch作為java中的轉換器,用于執行和()中數值相等
// 的case操作。請注意,在case操作中如果不以break退出
// 執行;switch函數將持續運算到最后一個case為止。
switch (map[x][j]) {
case 0 : //map的標記為0時畫出地板
//在指定位置[描繪]出我們所加載的圖形,以下同
//在Example5開始,所有this由特定面板對象panel取代
g.drawImage(floorImage, j * CS, x * CS, panel);
break;
case 1 : //map的標記為1時畫出城墻
g.drawImage(wallImage, j * CS, x * CS, panel);
break;
//我們可以依次類推出無數的背景組合,如定義椅子為2、寶座為3等
//很容易即可勾勒出一張背景地圖。
default: //當所有case值皆不匹配時,將執行此操作。
break;
}
}
}
}
/**
* 用于判定是否允許移動的發生,被move()函數調用,在Example5開始變更為公有
* @param x
* @param y
* @return
*/
public boolean isAllow(int x, int y) {
// 以(x,y)交點進行數據判定,我們都知道,
// 在本例中我僅以0作為地板的參數,1作為
// 墻的參數,由于我們的主角是[人類],而
// 不是[幽靈],所以當他要[撞墻]時,我們
// 當然不會允許,至少,是我講到劇情的觸發
// 以前……
if (map[y][x] == 1) {
// 不允許移動時,返回[假]
return false;
}
// 允許移動時時,返回[真]
return true;
}
private void loadImage() {
ImageIcon icon = new ImageIcon(getClass().getResource("image/floor.gif"));
floorImage = icon.getImage();
icon = new ImageIcon(getClass().getResource("image/wall.gif"));
wallImage = icon.getImage();
}
}
GameHandle類:
package org.loon.chair.example5;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
/**
*
* @author chenpeng
* @email ceponline@yahoo.com.cn
*
* Loon Framework in Game
*
*/
public class GameHandle implements Common{
// 用于獲得加載圖像的實例
private Image image;
//角色坐標
private int x, y;
//增加計步器
private int count;
//新增變量,用以確認角色所對方向,對應按鍵觸發
private int direction;
//用于處理角色動畫的線程
private Thread threadAnime;
//游戲地圖
private GameMap map;
//面板
private MyPanel panel;
/**
* 構造函數,拼合所需素材
* @param x
* @param y
* @param filename
* @param map
* @param panel
*/
public GameHandle(int x, int y, String filename, GameMap map, MyPanel panel) {
this.x = x;
this.y = y;
direction = DOWN;
count = 0;
this.map = map;
this.panel = panel;
//加指定圖像
loadImage(filename);
//實例化內部線程AnimationThread
threadAnime = new Thread(new AnimationThread());
threadAnime.start();
}
public void draw(Graphics g) {
//以count作為圖像的偏移數值,并于Example4中添加direction以獲取所處圖像塊位置
g.drawImage(image, x * CS, y * CS, x * CS + CS, y * CS + CS,
count * CS, direction * CS, count * CS + CS, direction * CS + CS, panel);
}
/**
* 判斷移動事件,關聯isAllow()函數
* 在Example4中,添加了對于移動方向的整型記錄變量direction
* @param event
*/
public void move(int event) {
//以轉換器判斷相關事件,僅執行符合[規范]的操作。
switch (event) {
case LEFT:
//依次判定事件
if (map.isAllow(x-1, y)) x--;
direction = LEFT;
break;
case RIGHT:
if (map.isAllow(x+1, y)) x++;
direction = RIGHT;
break;
case UP:
if (map.isAllow(x, y-1)) y--;
direction = UP;
break;
case DOWN:
if (map.isAllow(x, y+1)) y++;
direction = DOWN;
break;
default:
break;
}
}
private void loadImage(String filename) {
ImageIcon icon = new ImageIcon(getClass().getResource(filename));
image = icon.getImage();
}
// 內部類,用于處理計步動作。
private class AnimationThread extends Thread {
public void run() {
while (true) {
// count計步
if (count == 0) {
count = 1;
} else if (count == 1) {
count = 0;
}
// 重繪畫面。
panel.repaint();
// 每300毫秒改變一次動作。
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
MyPane類:
package org.loon.chair.example5;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
/**
*
* @author chenpeng
* @email ceponline@yahoo.com.cn
*
* Loon Framework in Game
*
*/
public class MyPanel extends JPanel implements KeyListener, Common {
/**
*
*/
private static final long serialVersionUID = 1L;
//窗體的寬與高
private static final int WIDTH = 480;
private static final int HEIGHT = 480;
//游戲地圖
private GameMap map;
//角色控制
private GameHandle role;
public MyPanel() {
//設定初始構造時面板大小
setPreferredSize(new Dimension(WIDTH, HEIGHT));
//設定焦點在本窗體并付與監聽對象
setFocusable(true);
addKeyListener(this);
//獲得地圖實例
map = new GameMap(this);
//獲得角色實例
role = new GameHandle(1, 1, "image/hero.gif", map, this);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
//描繪地圖
map.draw(g);
//描繪角色
role.draw(g);
}
public void keyPressed(KeyEvent e) {
//獲得按鍵編號
int keyCode = e.getKeyCode();
//通過轉換器匹配事件
switch (keyCode) {
//當觸發Left時
case KeyEvent.VK_LEFT :
//進行left操作,僅符合move()中[規范]時執行,以下相同
role.move(LEFT);
break;
//當觸發Right時
case KeyEvent.VK_RIGHT :
role.move(RIGHT);
break;
//當觸發Up時
case KeyEvent.VK_UP :
role.move(UP);
break;
//當觸發Down時
case KeyEvent.VK_DOWN :
role.move(DOWN);
break;
}
// 重新繪制窗體圖像
// PS:在此例程中,僅進行了角色的簡單移動處理
// ,關于避免閃爍及限制活動區域問題,請見后續
// 案例。
repaint();
}
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
}
潦倒不甘廿五年,柔腸百轉繞指尖。若遂恨天鯤鵬志,翼翮江海龍神啖!
浙公網安備 33010602011771號