65.9K
CodeProject 正在变化。 阅读更多。
Home

制作实时多人 AndEngine 游戏

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2013年6月25日

CPOL

4分钟阅读

viewsIcon

23490

为您的 AndEngine 游戏添加实时多人游戏玩法和虚拟房间逻辑。

引言

AndEngine是一个免费的Android 2D OpenGL游戏引擎。使用AppWarp,您可以为您的AndEngine游戏添加实时多人游戏和虚拟房间逻辑。 在这篇文章中,我们将逐步介绍一个名为Fruity Monster的简单演示游戏的集成步骤。 玩家连接到AppWarp云端,可以创建房间或加入现有房间。 进入房间后,玩家可以实时看到彼此的移动,并将水果放置在房间的四个角落。

Using the Code

让我们浏览一下源代码,并逐步了解构建这个简单游戏的一些关键概念。

首先,使用您的AppWarp密钥编辑Constants.java文件,如下所示

public static String apiKey = "Your API Key Here";
public static String secretKey =  "Your Secret Key Here";

现在让我们逐步了解每个屏幕并检查集成代码。

MainActivity.java

在此屏幕中,我们使用开发人员的API密钥和在Constants.java中定义的密钥初始化WarpClient。然后,我们保留此实例的引用,将在本活动中使用它。

private void init(){
    WarpClient.initialize(Constants.apiKey, Constants.secretKey);
    try {
        theClient = WarpClient.getInstance();
    } catch (Exception ex) {
        Utils.showToastAlert(this, "Exception in Initialization");
    }
}

初始化WarpClient后,我们继续与AppWarp云服务连接。当用户选择一个怪物、输入一个名称并点击播放按钮时,就会发生这种情况。为了接收来自连接操作的回调结果,我们需要添加一个连接请求监听器。我们使MainActivity类实现ConnectionRequestListener并实现所需的方法。

theClient.connectWithUserName(userName);

如果我们为此操作收到成功的回调,我们将继续进入RoomlistActivity

@Override
public void onConnectDone(final ConnectEvent event) {
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            progressDialog.dismiss();
            if(event.getResult()==WarpResponseResultCode.SUCCESS){// go to room  list 
                Intent intent = new Intent(MainActivity.this, RoomlistActivity.class);
                startActivity(intent);
            }else{
                Utils.showToastAlert(MainActivity.this, "connection failed ");
            }
        }
    });
}

RoomListActivity.java

此屏幕向用户显示活动游戏房间的列表。该列表包含至少有一个用户的房间。我们使用我们的匹配 API 构建此列表。

theClient.getRoomWithNUser(1);// trying to get room with at least one user

用户可以选择从这个列表中加入一个房间,或者开始一个新的房间。

加入现有房间

要接收上述请求的回调,我们需要添加一个区域请求监听器,因为这是一个区域级别的请求。我们使RoomlistActivity实现区域请求监听器接口并将其自身添加为监听器。在回调中,我们使用所有匹配房间的房间 ID 设置列表适配器。

@Override
public void onGetMatchedRoomsDone(final MatchedRoomsEvent event) {
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            RoomData[] roomDataList = event.getRoomsData();
            if(roomDataList.length>0){
                roomlistAdapter.setData(roomDataList);
                listView.setAdapter(roomlistAdapter);
            }else{
                roomlistAdapter.clear();
            }
        }
    });
}

加入新房间

要加入新房间,我们需要在加入之前先使用定义的属性创建一个房间。在这个游戏中,我们在一个房间中定义了四个位置,这些位置将在稍后的游戏中使用。 这将简单地创建一个新房间,并使用用户给定的名称(在本例中为随机名称)指定maxUsers为 4,并将本地用户指定为所有者。 请求的结果将在我们的区域请求监听器接口上调用。

Hashtable<String, Object> properties = new Hashtable<String, Object>();
properties.put("topLeft", "");
properties.put("topRight", "");
properties.put("bottomLeft", "");
properties.put("bottomRight", "");
theClient.createRoom(""+System.currentTimeMillis(), "owner", 4, properties);

成功创建房间后,我们从事件中提取房间 ID 并加入该房间。 同样,如果用户单击列表中其中一个房间的加入按钮,我们将继续发送加入房间的请求。

theClient.joinRoom(roomId); 

该请求的结果将在我们的房间请求监听器接口上调用。 如果成功,我们将进入下一个活动。

@Override
public void onJoinRoomDone(final RoomEvent event) {
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            progressDialog.dismiss();
            Log.d("onJoinRoomDone", ""+event.getResult());
            if(event.getResult()==0){// Room created successfully
                goToGameScreen(event.getData().getId());
            }else{
                Utils.showToastAlert(RoomlistActivity.this, "Room joining failed");
            }
        }
    });
}

AndEngineTutorialActivity.java

此屏幕代表SimpleBaseGameActivity(andengine)。 在此,我们定义了hashmap来维护正在该房间中玩游戏的在线用户。 我们在onCreateEngineOptions()中初始化andengine,并在onCreateResources()中加载游戏中使用的所有资源

为了处理游戏中的所有事件,我们使用了EventHandler.java,它实现了RoomRequestListenerNotifyListener来注册和监听所有相关的游戏事件。 每当用户点击屏幕时,我们需要通知房间中的其他玩家其移动情况。 我们只需构造一个表示坐标的json对象,并使用WarpClient聊天API发送即可。

private void sendUpdateEvent(float xCord, float yCord){
    try{
        JSONObject object = new JSONObject();
        object.put("X", xCord+"");
        object.put("Y", yCord+"");
        theClient.sendChat(object.toString());
    }catch(Exception e){
        Log.d("sendUpdateEvent", e.getMessage());
    }
}

上面的代码将触发一个聊天事件,其通知将被房间内的所有人在EventHandler.java中接收。

@Override
public void onChatReceived(ChatEvent event) {
    String sender = event.getSender();
    if(sender.equals(Utils.userName)==false){// if not same user
        String message = event.getMessage();
        try{
            JSONObject object = new JSONObject(message);
            float xCord = Float.parseFloat(object.get("X")+"");
            float yCord = Float.parseFloat(object.get("Y")+"");
            gameScreen.updateMove(sender, xCord, yCord);
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

现在玩家可以将水果移动到房间的四个角落,其他人可以看到所有这些实时发生。为此,用户选择一个水果,然后按下一个他必须放置水果的角落。然后我们发送一个updateRoomProperty请求,其中我们更新属性,其键表示目的地,例如(topLeft),值是水果的索引。

private void updateProperty(String position, String objectType){
	Hashtable table = new Hashtable();
	table.put(position, objectType);
	theClient.updateRoomProperties(roomId, table, null);
} 

最后,当房间的属性发生变化时,所有用户都会在EventHandler.java中收到通知。如果该属性由远程用户更新,那么我们根据事件中的属性值使用此新值更新 UI。

@Override
public void onUserChangeRoomProperty(RoomData roomData, String userName,Hashtable properties) {
    if(userName.equals(Utils.userName)){
        properties = tableProperties;
        return;
    }
    Enumeration keyEnum = properties.keys();
    while(keyEnum.hasMoreElements()){
        String key = keyEnum.nextElement();
        String value = properties.get(key).toString();
        int fruitId = Integer.parseInt(value);
        gameScreen.placeObject(fruitId, key, userName);
    }
}

历史

  • 2013年6月25日:初始版本
© . All rights reserved.