我們都知道,在諸如魔獸的很多戰(zhàn)略游戲中,會出現(xiàn)要求某A角色接近某B角色的情況(攻擊或是怎么著咱不考慮……),玩家很簡單的一步操作,卻會引發(fā)開發(fā)者“怎么走過去”這個“復(fù)雜”的算法問題,也就是所謂的“Path-finding”——尋徑。
好的尋徑算法,不但能避免不必要的資源損耗,而且能令游戲友好度增加。反之則會嚴(yán)重影響游戲的可玩性或諸如GIS等系統(tǒng)的可靠性。
在本次,我以Java為例,演示一個最簡單的尋徑系統(tǒng)——甚至可以說是偽尋徑系統(tǒng)的實現(xiàn)。 (^^)
首先,我們建立一個追蹤者(一說到這里我就想起了生化里的掠食者……)
package org.test.tracker;

import java.awt.Color;
import java.awt.Graphics;

/**
* <p>
* Title: LoonFramework
* </p>
* <p>
* Description:追蹤者。
* </p>
* <p>
* Copyright: Copyright (c) 2007
* </p>
* <p>
* Company: LoonFramework
* </p>
*
* @author chenpeng
* @email:ceponline@yahoo.com.cn
* @version 0.1
*/
public class Tracker {

private static final int SIZE = TrackerPanel.SIZE;

public int x;

public int y;

/**
* 析構(gòu)函數(shù),默認坐標(biāo)為0,0
*
*/
public Tracker() {
this(0, 0);
}

/**
* 析構(gòu)函數(shù),設(shè)定x,y坐標(biāo)
*
* @param x
* @param y
*/
public Tracker(int x, int y) {
this.x = x;
this.y = y;
}

/**
* 設(shè)定追蹤對象
*
* @param prey
*/
public void chase(Objective objective) {
//始終以目標(biāo)坐標(biāo)矯正追蹤者坐標(biāo)。
if (x > objective.x) {
x--;
} else if (x < objective.x) {
x++;
}

if (y > objective.y) {
y--;
} else if (y < objective.y) {
y++;
}
}

/**
* 繪制追蹤者
*
* @param g
*/
public void draw(Graphics g) {
g.setColor(Color.RED);
g.fillRect(x * SIZE, y * SIZE, SIZE, SIZE);
}
}
而后,我們建立一個被追蹤的目標(biāo)。
package org.test.tracker;

import java.awt.Color;
import java.awt.Graphics;

/**
* <p>
* Title: LoonFramework
* </p>
* <p>
* Description:被跟蹤的目標(biāo)對象。
* </p>
* <p>
* Copyright: Copyright (c) 2007
* </p>
* <p>
* Company: LoonFramework
* </p>
*
* @author chenpeng
* @email:ceponline@yahoo.com.cn
* @version 0.1
*/
public class Objective {

private static final int SIZE = TrackerPanel.SIZE;

private static final int UP = 0;

private static final int DOWN = 1;

private static final int LEFT = 2;

private static final int RIGHT = 3;

public int x;

public int y;

/**
* 析構(gòu)函數(shù),內(nèi)部轉(zhuǎn)換x,y坐標(biāo)。
*
*/
public Objective() {
x = TrackerPanel.COL / 2;
y = TrackerPanel.ROW / 2;
}
/**
* 析構(gòu)函數(shù),設(shè)定x,y坐標(biāo)。
*
*/
public Objective(int x, int y) {
this.x = x;
this.y = y;
}

/**
* 移動目標(biāo)
*
* @param dir
*/
public void move(int dir) {
switch (dir) {
case UP:
y--;
break;
case DOWN:
y++;
break;
case LEFT:
x--;
break;
case RIGHT:
x++;
break;
}
}

/**
* 繪制目標(biāo)
*
* @param g
*/
public void draw(Graphics g) {
g.setColor(Color.BLUE);
g.fillOval(x * SIZE, y * SIZE, SIZE, SIZE);
}
}
最后,我們建立一個面板,用以繪制圖形。
package org.test.tracker;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Panel;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;

/**
* <p>
* Title: LoonFramework
* </p>
* <p>
* Description:追蹤演示面板。
* </p>
* <p>
* Copyright: Copyright (c) 2007
* </p>
* <p>
* Company: LoonFramework
* </p>
*
* @author chenpeng
* @email:ceponline@yahoo.com.cn
* @version 0.1
*/
public class TrackerPanel extends Panel implements Runnable, KeyListener {
/**
*
*/
private static final long serialVersionUID = 1L;

// 設(shè)定窗體寬與高
private static final int WIDTH = 480;

private static final int HEIGHT = 480;

// 描繪的正方體大小
static final int SIZE = 8;

// 獲得對應(yīng)列數(shù),即將frame轉(zhuǎn)化為類數(shù)組的存在。
public static final int ROW = HEIGHT / SIZE;

public static final int COL = WIDTH / SIZE;

// 獲得對應(yīng)行數(shù)
private static final int UP = 0;

private static final int DOWN = 1;

private static final int LEFT = 2;

private static final int RIGHT = 3;

// 追蹤者
private Tracker tracker;

// 目標(biāo)
private Objective objective;

private Thread thread;

private Image screen = null;

private Graphics bg = null;

public TrackerPanel() {
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setFocusable(true);
addKeyListener(this);
screen = new BufferedImage(WIDTH, HEIGHT, 1);
bg = screen.getGraphics();
// 追蹤者初始位置,0行,0列
tracker = new Tracker(0, 0);
// 目標(biāo)初始位置,50行,50列
objective = new Objective(50, 50);
thread = new Thread(this);
thread.start();
}

public void paint(Graphics g) {
// 設(shè)定底色為白色,并清屏
bg.setColor(Color.white);
bg.fillRect(0, 0, WIDTH, HEIGHT);
// 繪制追蹤者
tracker.draw(bg);
// 繪制目標(biāo)
objective.draw(bg);
g.drawImage(screen, 0, 0, this);
g.dispose();
}

public void update(Graphics g) {
paint(g);
}

public void run() {
while (true) {
// 設(shè)定追擊的目標(biāo)。
tracker.chase(objective);
repaint();
try {
Thread.sleep(110);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public void keyTyped(KeyEvent e) {
}

public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
switch (key) {
case KeyEvent.VK_UP:
objective.move(UP);
break;
case KeyEvent.VK_DOWN:
objective.move(DOWN);
break;
case KeyEvent.VK_LEFT:
objective.move(LEFT);
break;
case KeyEvent.VK_RIGHT:
objective.move(RIGHT);
break;
}
repaint();
}

public void keyReleased(KeyEvent e) {
}

public static void main(String[] args) {
Frame frm = new Frame();
frm.setTitle("簡單的Java圖形尋徑追蹤實現(xiàn)(由Loonframework提供)");
frm.setSize(WIDTH, HEIGHT);
frm.setResizable(false);
frm.add(new TrackerPanel());
frm.setVisible(true);
}

}
這時,畫面上顯示的紅色正方體為追蹤者,藍色圓球為被追蹤目標(biāo),而無論籃球如何移動,紅色正方體都將始終向籃球靠攏。
實際上,通過代碼我們就可以知道,這時兩者間的移動路徑,被沒有經(jīng)過復(fù)雜的方法演算,而是以目標(biāo)的坐標(biāo)來決定的,頗有獨孤九劍那種,敵人若是只有一招,我也只有一招,他若是有千招萬招,我也自是千招萬招。但是,這種方法在實際的尋徑處理中,并不能很好的解決如障礙物,區(qū)域轉(zhuǎn)換等問題,所以只是一種[偽]尋徑,
或者說是在無障礙情況下的簡單解決方案。
如果關(guān)注尋徑算法在Java中的進一步實現(xiàn),還請繼續(xù)關(guān)注我的blog……
好的尋徑算法,不但能避免不必要的資源損耗,而且能令游戲友好度增加。反之則會嚴(yán)重影響游戲的可玩性或諸如GIS等系統(tǒng)的可靠性。
在本次,我以Java為例,演示一個最簡單的尋徑系統(tǒng)——甚至可以說是偽尋徑系統(tǒng)的實現(xiàn)。 (^^)
首先,我們建立一個追蹤者(一說到這里我就想起了生化里的掠食者……)
package org.test.tracker;
import java.awt.Color;
import java.awt.Graphics;
/**
* <p>
* Title: LoonFramework
* </p>
* <p>
* Description:追蹤者。
* </p>
* <p>
* Copyright: Copyright (c) 2007
* </p>
* <p>
* Company: LoonFramework
* </p>
*
* @author chenpeng
* @email:ceponline@yahoo.com.cn
* @version 0.1
*/
public class Tracker {
private static final int SIZE = TrackerPanel.SIZE;
public int x;
public int y;
/**
* 析構(gòu)函數(shù),默認坐標(biāo)為0,0
*
*/
public Tracker() {
this(0, 0);
}
/**
* 析構(gòu)函數(shù),設(shè)定x,y坐標(biāo)
*
* @param x
* @param y
*/
public Tracker(int x, int y) {
this.x = x;
this.y = y;
}
/**
* 設(shè)定追蹤對象
*
* @param prey
*/
public void chase(Objective objective) {
//始終以目標(biāo)坐標(biāo)矯正追蹤者坐標(biāo)。
if (x > objective.x) {
x--;
} else if (x < objective.x) {
x++;
}
if (y > objective.y) {
y--;
} else if (y < objective.y) {
y++;
}
}
/**
* 繪制追蹤者
*
* @param g
*/
public void draw(Graphics g) {
g.setColor(Color.RED);
g.fillRect(x * SIZE, y * SIZE, SIZE, SIZE);
}
}
而后,我們建立一個被追蹤的目標(biāo)。
package org.test.tracker;
import java.awt.Color;
import java.awt.Graphics;
/**
* <p>
* Title: LoonFramework
* </p>
* <p>
* Description:被跟蹤的目標(biāo)對象。
* </p>
* <p>
* Copyright: Copyright (c) 2007
* </p>
* <p>
* Company: LoonFramework
* </p>
*
* @author chenpeng
* @email:ceponline@yahoo.com.cn
* @version 0.1
*/
public class Objective {
private static final int SIZE = TrackerPanel.SIZE;
private static final int UP = 0;
private static final int DOWN = 1;
private static final int LEFT = 2;
private static final int RIGHT = 3;
public int x;
public int y;
/**
* 析構(gòu)函數(shù),內(nèi)部轉(zhuǎn)換x,y坐標(biāo)。
*
*/
public Objective() {
x = TrackerPanel.COL / 2;
y = TrackerPanel.ROW / 2;
}
/**
* 析構(gòu)函數(shù),設(shè)定x,y坐標(biāo)。
*
*/
public Objective(int x, int y) {
this.x = x;
this.y = y;
}
/**
* 移動目標(biāo)
*
* @param dir
*/
public void move(int dir) {
switch (dir) {
case UP:
y--;
break;
case DOWN:
y++;
break;
case LEFT:
x--;
break;
case RIGHT:
x++;
break;
}
}
/**
* 繪制目標(biāo)
*
* @param g
*/
public void draw(Graphics g) {
g.setColor(Color.BLUE);
g.fillOval(x * SIZE, y * SIZE, SIZE, SIZE);
}
}
最后,我們建立一個面板,用以繪制圖形。
package org.test.tracker;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Panel;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
/**
* <p>
* Title: LoonFramework
* </p>
* <p>
* Description:追蹤演示面板。
* </p>
* <p>
* Copyright: Copyright (c) 2007
* </p>
* <p>
* Company: LoonFramework
* </p>
*
* @author chenpeng
* @email:ceponline@yahoo.com.cn
* @version 0.1
*/
public class TrackerPanel extends Panel implements Runnable, KeyListener {
/**
*
*/
private static final long serialVersionUID = 1L;
// 設(shè)定窗體寬與高
private static final int WIDTH = 480;
private static final int HEIGHT = 480;
// 描繪的正方體大小
static final int SIZE = 8;
// 獲得對應(yīng)列數(shù),即將frame轉(zhuǎn)化為類數(shù)組的存在。
public static final int ROW = HEIGHT / SIZE;
public static final int COL = WIDTH / SIZE;
// 獲得對應(yīng)行數(shù)
private static final int UP = 0;
private static final int DOWN = 1;
private static final int LEFT = 2;
private static final int RIGHT = 3;
// 追蹤者
private Tracker tracker;
// 目標(biāo)
private Objective objective;
private Thread thread;
private Image screen = null;
private Graphics bg = null;
public TrackerPanel() {
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setFocusable(true);
addKeyListener(this);
screen = new BufferedImage(WIDTH, HEIGHT, 1);
bg = screen.getGraphics();
// 追蹤者初始位置,0行,0列
tracker = new Tracker(0, 0);
// 目標(biāo)初始位置,50行,50列
objective = new Objective(50, 50);
thread = new Thread(this);
thread.start();
}
public void paint(Graphics g) {
// 設(shè)定底色為白色,并清屏
bg.setColor(Color.white);
bg.fillRect(0, 0, WIDTH, HEIGHT);
// 繪制追蹤者
tracker.draw(bg);
// 繪制目標(biāo)
objective.draw(bg);
g.drawImage(screen, 0, 0, this);
g.dispose();
}
public void update(Graphics g) {
paint(g);
}
public void run() {
while (true) {
// 設(shè)定追擊的目標(biāo)。
tracker.chase(objective);
repaint();
try {
Thread.sleep(110);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void keyTyped(KeyEvent e) {
}
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
switch (key) {
case KeyEvent.VK_UP:
objective.move(UP);
break;
case KeyEvent.VK_DOWN:
objective.move(DOWN);
break;
case KeyEvent.VK_LEFT:
objective.move(LEFT);
break;
case KeyEvent.VK_RIGHT:
objective.move(RIGHT);
break;
}
repaint();
}
public void keyReleased(KeyEvent e) {
}
public static void main(String[] args) {
Frame frm = new Frame();
frm.setTitle("簡單的Java圖形尋徑追蹤實現(xiàn)(由Loonframework提供)");
frm.setSize(WIDTH, HEIGHT);
frm.setResizable(false);
frm.add(new TrackerPanel());
frm.setVisible(true);
}
}
這時,畫面上顯示的紅色正方體為追蹤者,藍色圓球為被追蹤目標(biāo),而無論籃球如何移動,紅色正方體都將始終向籃球靠攏。
實際上,通過代碼我們就可以知道,這時兩者間的移動路徑,被沒有經(jīng)過復(fù)雜的方法演算,而是以目標(biāo)的坐標(biāo)來決定的,頗有獨孤九劍那種,敵人若是只有一招,我也只有一招,他若是有千招萬招,我也自是千招萬招。但是,這種方法在實際的尋徑處理中,并不能很好的解決如障礙物,區(qū)域轉(zhuǎn)換等問題,所以只是一種[偽]尋徑,
或者說是在無障礙情況下的簡單解決方案。
如果關(guān)注尋徑算法在Java中的進一步實現(xiàn),還請繼續(xù)關(guān)注我的blog……

浙公網(wǎng)安備 33010602011771號