随笔-95  评论-31  文章-10  trackbacks-0

      玩游戏的时候,会有关卡以及boss,通过boss战后,获得新装备,新开启关卡,并会提示存储当前进度,以便以后可以再重玩当前boss战,比如生化危机,鬼泣等等杀完一个boss爽了,然后存储下当前进度,但是这种存储都是需要介质持久化,如果需要在内存中长久驻留,那么就要采用一些方式存储。
      当玩家创建一个角色的时候,与该角色相关的东西都会附加上,比如装备,角色外貌,场景等等,这些东西封装为一个对象,然后将对象状态保存在外部,就是备忘录模式了,下面为第一版简略类图:
Roll是角色,RollState是角色附加的东西:装备,场景,杀了几个boss,获得的新装备等等也就是当前角色的状态,GameState是用来存储角色状态的类,GameStateManager是角色状态管理类,但是这种方式,只能针对不同角色存储一种状态的情况,
比如鬼泣主角:但丁  当第一关通过后,获得新装备,新关卡,此时存储下来,即GameStateManager.setGameState()方法,内部用map存储即manager.put("但丁",gameState),但是用map只能存储但丁的一个状态,如果再有另外一个角色:恶魔但丁,同样会只能存储一个状态,上面类图只针对不同角色,当前状态,以及上一个状态之间的切换。如果一个角色有多个状态,状态之间跳跃,比如打完第6关,玩家想切换回第3关玩,如果遇见这种情况,那么将GameStateManager的map泛型第二个参数改为聚集即可。第二版类图如下:

GameStateManager成员变量第二个泛型参数改为Collection<GameState>,里面参数即可根据角色名字和第几个关卡获取状态,代码如

package designpattern.memento;

public class Roll
{
    
private RollState rollState = new RollState("默认装备""默认样子""出生场景");

    
private String name;

    
public Roll(String name)
    
{
        
this.name = name;
    }


    
public void killBossA()
    
{
        System.out.println(
"杀了boss1,获得新装备,开启关卡2");
        rollState.setEquipment(
"新装备");
        rollState.setAppearance( 
"获得新外型");
        rollState.setScene(
"开启关卡2");
    }


    
public void killBossB()
    
{
        System.out.println( 
"杀了boss2,获得更好的装备,开启更难关卡");
        rollState.setEquipment( 
"更强装备");
        rollState.setAppearance( 
"获得更酷外型");
        rollState.setScene(name 
+ "开启关卡3");
    }


    
public RollState getRollState()
    
{
        
return rollState;
    }


    
public void setRollState(RollState rollState)
    
{
        
this.rollState = rollState;
    }


    
public String getName()
    
{
        
return name;
    }


    
public void setName(String name)
    
{
        
this.name = name;
    }


    
/**
     * 创建备份点
     * 
     * 
@return
     
*/

    
public GameState createGameState()
    
{
        
return new GameState(rollState);
    }


    
/**
     * 获得上次备份点
     * 
     * 
@param gameState
     
*/

    
public void restoreGameState(GameState gameState)
    
{
        
this.rollState = gameState.getRollState();
    }


    @Override
    
public String toString()
    
{
        
return name+":"+this.getRollState().getEquipment()+""+this.getRollState().getAppearance()+""+this.getRollState().getScene();
    }

}

 

package designpattern.memento;

/**
 * 
@author Administrator 角色状态类
 
*/

public class RollState
{

    
private String equipment;
    
private String appearance;
    
private String scene;

    
public RollState()
    
{
    }


    
public RollState(String equipment, String appearance, String scene)
    
{
        
this.equipment = equipment;
        
this.appearance = appearance;
        
this.scene = scene;
    }


    
public String getEquipment()
    
{
        
return equipment;
    }


    
public void setEquipment(String equipment)
    
{
        
this.equipment = equipment;
    }


    
public String getAppearance()
    
{
        
return appearance;
    }


    
public void setAppearance(String appearance)
    
{
        
this.appearance = appearance;
    }


    
public String getScene()
    
{
        
return scene;
    }


    
public void setScene(String scene)
    
{
        
this.scene = scene;
    }


}

 

package designpattern.memento;

public class GameState
{
    
private RollState rollState;

    
public GameState(RollState rollState)
    
{
        
this.rollState = rollState;
    }


    
public RollState getRollState()
    
{
        
return rollState;
    }


    
public void setRollState(RollState rollState)
    
{
        
this.rollState = rollState;
    }


}

 

package designpattern.memento;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class GameStateManager
{
    
private Map<String, ArrayList<GameState>> managers = new HashMap<String,ArrayList<GameState>>();

    
public GameState getGameState(String rollName, int indexBoss)
    
{
        
return managers.get(rollName).get(indexBoss);
    }


    
public void setGameState(String rollName, GameState gameState)
    
{
        ArrayList
<GameState> list = null;
        
if ((list = managers.get(rollName)) != null)
        
{
            list.add(gameState);
        }
 else
        
{
            managers.put(rollName,
new ArrayList<GameState>(Arrays.asList(gameState)));
        }

        System.err.println(managers.get(rollName));
    }

    
}

 

package designpattern.memento;

public class Client
{
    
public static void main(String[] args)
    
{
        Roll roll 
= new Roll( "但丁");
        GameStateManager states 
= new GameStateManager();
        
//玩家初始场景,即出生点
        states.setGameState(roll.getName(), roll.createGameState());
        
        
        roll.killBossA();
        
//杀完bossA 存储
        states.setGameState(roll.getName(), roll.createGameState());
        
        roll.killBossB();
        
//杀完bossB存储
        states.setGameState(roll.getName(), roll.createGameState());
        
        
//玩家想返回杀bossA之前场景  内部使用线性表存储 0即代表玩家出生点,初始场景,一般游戏里面会对每个boss战场景标记
        roll.restoreGameState(states.getGameState(roll.getName(), 0));
        System.out.println(roll.toString());
        
        roll.restoreGameState(states.getGameState(roll.getName(), 
1));
        System.out.println(roll.toString());
        
        
    }

}


这跟事物原理一致 
上面有个bug,Roll类里面killBossA方法应该改为:
//  rollState.setEquipment("新装备A");
//  rollState.setAppearance("获得新外型A");
//  rollState.setScene("开启关卡2");
rollState = new RollState("新装备A","获得新外型A","开启关卡2");
killBossB方法应该改为:
  rollState = new RollState("更强装备B","获得更酷外型B","开启关卡3");
//  rollState.setEquipment("更强装备B");
//  rollState.setAppearance("获得更酷外型B");
//  rollState.setScene(name + "开启关卡3");

否则都传递的是引用,修改的是同一个引用,保存的都是同一个状态。
因为roll角色的状态是通过RollState引用来保存,而不是基本变量和string类型



 




 
 
          


posted on 2013-09-28 14:57 朔望魔刃 阅读(253) 评论(0)  编辑  收藏 所属分类: 设计模式&&数据结构

只有注册用户登录后才能发表评论。


网站导航: