目录

我的学习分享

记录精彩的程序人生

X

acuigame-test

20200406

引入gdx-backend-headless同时要引入natives

        api "com.badlogicgames.gdx:gdx-backend-headless:$gdxVersion"
        api "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop"

20200408

主要游戏逻辑放在服务器端,客户端仅执行一些简单的校验逻辑。客户端整个程序结构需要理一理。
服务器端使用Box2D进行物理计算,并将计算结果同步到所有客户端。

image.png

20200409

服务器端是靠IRPRuleProcessor中的 beginTurn()endTurn()来驱动的;通过 execute()执行action,相当于通过网络获得远程输入,从而对实体施加影响。服务端向客户端发送 Perception是自动进行的,参见 RPServerManager.run()方法。所谓感知,其实就是被改变的对象,包括

  • 增加的RPObejct
  • 删除的RPObject
  • 其他

每回合的时间固定为40毫秒(每秒25帧)。
在IRPRuleProcessor中实例化world对象,并在回合执行过程中调用其 step()方法模拟。具体的计算完全由Box2D物理引擎负责。我的需要做的是在每回合 step()执行之前,增加或销毁刚体,或改变刚体属性。

客户端通过 ClientFrameworksend()方法想服务器端发送RPAction ,通过回调onPerception`接收服务端发送的Perception。


先说说服务端几个重要的数据结构及处理流程。

RPWorld

RPWorld代表整个世界。RPWorld按区域(IRPZone)划分,世界就是有相互独立的区域组成的。RPWorld基于单例模式,默认实现比较简单,三个成员变量:

  • 包含所有区域的哈希表 zones
  • 包玩家的容器 playerContainer
  • 默认区域 defaultZone
    /**
     * A map containing the zones.
     */
    Map<IRPZone.ID, IRPZone> zones;

    /**
     * The all-mighty player container.
     */
    PlayerEntryContainer playerContainer;

    IRPZone defaultZone;

RPWorld提供 onInit()onFinish()方法用于服务器启动和终止,其中 onInit()没有默认实现,onFinish()默认会依次调用所有 IRPZoneonFinish()方法。

RPWorld还提供了对区域进行操作的若干方法 addRPZone()getDefaultZone()setDefaultZone()hasRPZone()getRPZone()removeRPZone()

RPWorld还提供了对RPObject进行操作的若干方法 add()requestSync()get()has()remove(),其中 requestSync()表示玩家进入新区域时要求同步感知(感知的两种类型之一)时调用。

RPWorld提供的其他方法包括 iterator()modify()changeZone()nextTurn()size()

  • iterator()获得区域列表的迭代器
  • modify()通知区域对象被修改
  • changeZone()使玩家/对象改变区域。
  • nextTurn()将世界移动到下一轮,依次调用每个zone的nextTurn方法
  • size()返回增加到世界中的对象数量

实际上该类只是区(IRPZone)的容器,RPWorld通过下面几个方法以帮助RPZone的处理。

    // 服务器启动和结束时调用
    public void onInit() throws Exception
    public void onFinish() throws Exception

    // 增加和遍历区
    public void addRPZone(IRPZone zone)
    public IRPZone getRPZone(IRPZone.ID zoneid)
    public IRPZone getRPZone(RPObject.ID objectid)
    public Iterator<IRPZone> iterator()
    public int size()

    // 增加、获得、测试存在性、移除和修改对象
    public void add(RPObject object) throws NoRPZoneException, RPObjectInvalidException  
    public RPObject get(RPObject.ID id) throws NoRPZoneException, RPObjectInvalidException  
    public boolean has(RPObject.ID id) throws NoRPZoneException, RPObjectInvalidException  
    public RPObject remove(RPObject.ID id) throws NoRPZoneException, RPObjectNotFoundException  
    public void modify(RPObject object) throws NoRPZoneException

    // 改变对象的区,使用changeZone可以避免手动处理
    public void changeZone(IRPZone.ID oldzoneid, IRPZone.ID newzoneid, RPObject object) throws NoRPZoneException
    public void changeZone(String oldzone, String newzone, RPObject object) throws NoRPZoneException

IRPZone

IRPZone是处理世界内容和感知的接口,大多数情况下你需要使用MarauroaRPZone实现并扩展它。

  /** This method is called when the zone is created to populate it */
  public void onInit() throws Exception;

  /** This method is called when the server finish to save the content of the zone */
  public void onFinish() throws Exception;

  /** This method adds an object to the Zone */
  public void add(RPObject object) throws RPObjectInvalidException;

  /** This method tag an object of the Zone as modified */
  public void modify(RPObject object) throws RPObjectInvalidException;

  /** This method removed an object of the Zone and return it.*/
  public RPObject remove(RPObject.ID id) throws RPObjectNotFoundException;

  /** This method returns an object of the Zone */
  public RPObject get(RPObject.ID id) throws RPObjectNotFoundException;

  /** This method returns true if the object exists in the Zone */
  public boolean has(RPObject.ID id);

  /** This method create a new RPObject with a valid id */
  public RPObject create();

  /** Iterates over the elements of the zone */
  public Iterator iterator();

  /** Returns the number of elements of the zone */
  public long size();

  /** This method return the perception of a zone for a player */
  public Perception getPerception(RPObject.ID id, byte type);

  /** This method is called to take zone to the next turn */
  public void nextTurn();

  /** Method to create the map to send to player's client */
  public java.util.List buildMapObjectsList(RPObject.ID id);

image.png

image.png

20200410

必须找一些实例来做了,Stendhal有点过于复杂了。

先找一些有源码的例子改造一下。下面是一些可选的项目(使用了libgdx+box2d):