制作实时多人AndEngine游戏(译文)
By robot-v1.0
本文链接 https://www.kyfws.com/games/make-realtime-multiplayer-andengine-games-zh/
版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 6 分钟阅读 - 2800 个词 阅读量 0制作实时多人AndEngine游戏(译文)
原文地址:https://www.codeproject.com/Articles/611201/Make-Realtime-Multiplayer-AndEngine-Games
原文作者:daljeet Mehta
译文由本站 robot-v1.0 翻译
前言
Adding realtime multiplayer game play and virtual rooms logic to your AndEngine games
在您的AndEngine游戏中添加实时多人游戏和虚拟房间逻辑
介绍(Introduction)
引擎(AndEngine) 是一个免费的Android 2D OpenGL游戏引擎.使用(is a free Android 2D OpenGL Game Engine. Using) AppWarp(AppWarp) ,您可以将实时多人游戏和虚拟房间逻辑添加到您的(, you can add realtime multiplayer game play and virtual rooms logic to your) AndEngine
游戏.在本文中,我们将逐步完成一个名为Fruity Monster的简单演示游戏的集成步骤.玩家可以连接到AppWarp云,可以创建房间或加入现有房间.进入房间后,玩家可以看到彼此实时移动并将水果放置到房间的四个角落.(games. In this post, we will walk through the integration steps for a simple demo game called Fruity Monster. Players connect to AppWarp cloud, can create rooms or join existing rooms. Once inside a room, players can see each other move in realtime and place fruits to the four corners of the room.)
使用代码(Using the Code)
让我们浏览一下(Let’s browse through the) 源代码(source code) 并逐步了解构建此简单游戏的一些关键概念.(and walk through some of the key concepts in building this simple game.)
第一次编辑(First edit)**Constants.java(Constants.java)**与您的文件(file with your) AppWarp
按键如下所示:(keys as indicated below:)
public static String apiKey = "Your API Key Here";
public static String secretKey = "Your Secret Key Here";
现在,让我们遍历每个屏幕并检查集成代码.(Now let’s walk through each screen and examine the integration code.)
MainActivity.java(MainActivity.java)
在此屏幕中,我们初始化(In this screen, we initialize) WarpClient
与我们在其中定义的开发人员的API密钥和秘密密钥(with the developer’s API key and secret key that we have defined in)Constants.java(Constants.java).然后,我们保留将在本活动中使用的该实例的引用.(. We then keep a reference of this instance that we will use in this activity.)
private void init(){
WarpClient.initialize(Constants.apiKey, Constants.secretKey);
try {
theClient = WarpClient.getInstance();
} catch (Exception ex) {
Utils.showToastAlert(this, "Exception in Initialization");
}
}
一旦(Once) WarpClient
初始化后,我们继续进行连接(is initialized, we go ahead and connect with) AppWarp
云服务.当用户选择一个怪物,输入名称并单击播放按钮时,就会发生这种情况.为了从connect操作接收回调结果,我们需要添加一个连接请求侦听器.我们做(Cloud Service. This happens when the user selects a monster, enters a name and clicks on the play button. In order to receive callback result from the connect operation, we need to add a connection request listener. We make the) MainActivity
类实现(class implement the) ConnectionRequestListener
并实施所需的方法.(and implement the required methods.)
theClient.connectWithUserName(userName);
如果我们成功完成了此操作的回调,请继续输入(If we get a successful callback for this operation, we go ahead and enter the) 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(RoomListActivity.java)
该屏幕向用户显示了活动游戏室的列表.该列表包含至少有一个用户的房间.我们使用配对API来构建此列表.(This screen shows a list of active game rooms to the user. The list contains rooms with at least one user. We use our matchmaking API to build this list.)
theClient.getRoomWithNUser(1);// trying to get room with at least one user
用户可以选择从此列表加入会议室,也可以开始新会议室.(The user has the option to either join a room from this list or to start a new room.)
加入现有房间(Join An Existing Room)
要接收上述请求的回调,我们需要添加区域请求侦听器,因为这是区域级别的请求.我们做(To receive the callback for the above request, we need to add a zone request listener as this is a zone level request. We make the) RoomlistActivity
实现区域请求侦听器接口并将其自身添加为侦听器.在回调中,我们使用所有匹配房间的房间ID设置列表适配器.(implement the zone request listener interface and add itself as the listener. In the callback, we set up the list adapter with the room ids of all the matched rooms.)
@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();
}
}
});
}
加入新房间(Join a New Room)
要加入新房间,我们首先需要在定义房间之前创建具有定义属性的房间.在此游戏中,我们定义一个房间中的四个位置,这些位置将在稍后的游戏中使用.这将简单地创建一个由用户指定名称(在这种情况下为随机)的新房间并指定(To join a new room, we first need to create a room with the defined properties before joining it. In this game, we are defining four locations in a room which will be used later in the game play. This will simply create a new room with the name given (random in this case) by the user and specify) maxUsers
作为4,将本地用户作为所有者.请求的结果将在我们的区域请求侦听器接口上调用.(as 4 and the local user as the owner. The result of the request will be invoked on our zone request listener interface.)
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并加入该会议室.同样,如果用户单击列表中一个房间的加入按钮,我们将继续发送加入房间请求.(Once the room is created successfully, we extract the room id from the event and join that room. Similarly, if the user clicks on the join button of one of the rooms from the list, we go ahead and send a join room request.)
theClient.joinRoom(roomId);
请求的结果将在我们的房间请求侦听器界面上调用.如果成功,我们将进行下一个活动.(The result of the request will be invoked on our room request listener interface. If successful, we move to the next activity.)
@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(AndEngineTutorialActivity.java)
该屏幕代表(This screen represents) SimpleBaseGameActivity(andengine)
.在此,我们定义了(. In this, we have defined) hashmap
来维护正在这个房间玩游戏的在线用户.我们初始化(to maintain online users that are playing game in this room. We initialize) andengine
在(in) onCreateEngineOptions()
并加载游戏中使用的所有资源(and load all resources used in game in) onCreateResources()
为了处理游戏中的所有事件,我们使用了(To handle all events in game, we have used)**EventHandler.java(EventHandler.java)**实施(which implements) RoomRequestListener
和(and) NotifyListener
注册并收听所有相关的游戏事件.每当用户点击屏幕时,我们都需要将其移动通知房间中的其他玩家.为此,我们只需构造一个表示坐标的json对象,然后使用(to register and listens to all the relevant game events. Whenever the user taps on the screen, we need to notify other players in the room of its movement. We do this by simply constructing a json object representing the coordinates and send that using the) WarpClient
聊天API.(chat 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());
}
}
上面的代码将触发一个聊天事件,该聊天事件的通知将由(The above code will trigger a chat event whose notification will be received by all those inside the room in)EventHandler.java(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();
}
}
}
现在,玩家可以将水果移到房间的四个角落,其他人可以实时看到所有这些情况.为此,用户选择一种水果,然后在必须放置水果的任何角落上按一下.然后我们发送一个(Now players can move fruits to the four corners of the rooms and others can see all this happen in realtime. To do this, the user selects a fruit and then presses on any corner where he has to put the fruit. Then we send an) updateRoomProperty
我们在其中更新其键代表目的地的属性的请求,例如((request in which we update the property whose key represent destination e.g.() topLeft
),值是水果的指标.() and value is index of fruit.)
private void updateProperty(String position, String objectType){
Hashtable table = new Hashtable();
table.put(position, objectType);
theClient.updateRoomProperties(roomId, table, null);
}
最后,所有用户都会在(Finally, all users get a notification in)**EventHandler.java(EventHandler.java)**房间的属性发生变化时.如果该属性由远程用户更新,则我们根据事件中的属性值使用此新值更新UI.(when a property of the room changes. It the property is updated by a remote user, then we update UI with this new value according to the property values in the event.)
@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);
}
}
历史(History)
- 25(25)日(th)2013年6月:初始版本(June, 2013: Initial version)
许可
本文以及所有相关的源代码和文件均已获得The Code Project Open License (CPOL)的许可。
Java cloud Dev 新闻 翻译