游戏中的AI 一直是一个很热门的话题。笔者从事的手机游戏开发中,一般都是选择有限状态机来开发。最简单的例子比如:
switch(m_EnemyState)
{
case IDLE:
doIdle();
break;
case Attack:
doAttack();
break;
case Hurt:
doHurt();
break;
case Die:
doDie();
break;
}
但是这仅仅是个例子,但是说明了一个思路。比较好的状态机一般采用设计模式中的状态机模式开发。用类来模拟一个状态。
这方面的例子参见<<人工智能案例精粹>>。当然,这是一本我目前为止读过的描述AI最好的书籍了。
笔者用这样的例子开发过很多敌人或者主角的AI。但是代码写多了就会发现一个问题: 基本的AI大家都差不多的,比如Idle,
Attack, Hurt, Die等,只不过每个角色的动画不一致罢了。所以产生了一种AI模板的想法。
具体说来,就是定义一组通用操作,然后如果需要更加特殊的操作,可以采用继承的方式来扩充现有的AI接口。这样会形成不同的AI
策略,这样我们就得到不同AI驱动的敌人了。甚至同样的敌人角色,采用不同的AI,就有了不一致的行为。
代码采用Java描述。
AI_Common是通用的AI 接口, AI_Kill_Attack, AI_Rush_Attack则是扩展接口
AI_Common
|
doIdle
|
doAttack_Common
|
doAttack_Common_Wait
|
doDie
AI_Kill_Attack
|
doKillAttack
AI_Rush_Attack
|
doRushAttack
采用普通的接口实现的敌人只具备常用操作,而实现了特殊接口的AI则有了额外的实现。
上代码把:
===== AI_Common =====
public interface AI_Common {
void doIdle();
void doAttack_Common();
void doAttack_Common_Wait();
void doDie();
}
class AI_1 implements AI_Common
{
public AI_1(Enemy enemy_)
{
enemy = enemy_;
}
@Override
public void doIdle() {
enemy.showAnim( "IDLE" );
System. out .println("Now I am do Idle Operation" );
}
@Override
public void doAttack_Common() {
enemy.showAnim( "ATTACK" );
System. out .println("Now I am do common Attack Operation" );
}
@Override
public void doAttack_Common_Wait() {
enemy.showAnim( "ATTACK WAIT" );
System. out .println("Now I am do common wait Operation" );
}
@Override
public void doDie() {
enemy.showAnim( "DIE" );
System. out .println("Now I am do Die Operation" );
}
protected Enemy enemy ;
}
===== AI_Kill_Attack ====
public interface AI_Kill_Attack {
void doKillAttack();
}
class AI_2 extends AI_1 implements AI_Kill_Attack
{
public AI_2(Enemy enemy_) {
super (enemy_);
}
@Override
public void doKillAttack() {
enemy.showAnim( "KILL ATTACK" );
System. out .println(enemy .getName() + ": I am doing Kill Attack!");
}
}
===== AI_Rush_Attack =====
public interface AI_Rush_Attack {
void doRushAttack();
}
class AI_3 extends AI_1 implements AI_Rush_Attack
{
public AI_3(Enemy enemy_) {
super (enemy_);
}
@Override
public void doRushAttack() {
enemy.showAnim( "RUSH ATTACK" );
System. out .println(enemy .getName() + ": I am doing Rush Attack!");
}
}
===== Enemy =====
public class Enemy {
public Enemy(String name_) {
name = name_;
}
void showAnim(String anim)
{
System. out .println("Enemy is playing anim " + anim);
}
public String getName()
{
return name ;
}
private String name ;
}
我写了测试程序来模拟运行AI。
===== 主程序 =====
import java.util.Scanner;
public class TestBigMemory {
public static void main(String[] args) {
Enemy a = new Enemy("Enemy A" );
Enemy b = new Enemy("Enemy B" );
AI_2 KillAttack_Ai = new AI_2(a);
AI_3 RushAttack_Ai = new AI_3 (b);
RushAttack_Ai.doRushAttack();
KillAttack_Ai.doIdle();
Scanner input = new Scanner(System. in);
input.next();
KillAttack_Ai.doAttack_Common();
input.next();
KillAttack_Ai.doAttack_Common_Wait();
input.next();
KillAttack_Ai.doKillAttack();
input.next();
KillAttack_Ai.doDie();
}
}
虽然这仅仅是一个简单的Demo, 但是它的思想我觉得还是很有意思的。希望有兴趣的同学一起来探讨。