헤석부탁

히힛마스터 2005.01.25 15:39 조회 수 : 184

For two computer to communicate they will need some connection protocol. Like most games, Game Maker offers four different types of connections: IPX, TCP/IP, Modem, and Serial. The IPX connection (to be more precise, it is a protocol) is almost completely transparent. It can be used to play games with other people on the same local area network. It needs to be installed on your computer to be used. (If it does not work, consult the documentation of Windows. Or go to the Network item in the control panel of Windows and add the IPX protocol.) TCP/IP is the internet protocol. It can be used to play with other players anywhere on the internet, assuming you know their IP address. On a local network you can use it without providing addresses. A modem connection is made through the modem. You have to provide some modem settings (an initialization string and a phone number) to use it. Finally, when using a serial line (a direct connection between the computers) you need to provide a number of port settings. There are four GML functions that can be used for initializing these connections:

mplay_init_ipx() initializes an IPX connection.
mplay_init_tcpip(addr) initializes a TCP/IP connection. addr is a string containing the web address or IP address, e.g. 'www.gameplay.com' or '123.123.123.12', possibly followed by a port number (e.g. ':12'). Only when joining a session (see below) do you need to provide an address. On a local area network no addresses are necessary.
mplay_init_modem(initstr,phonenr) initializes a modem connection. initstr is the initialization string for the modem (can be empty). phonenr is a string that contains the phone number to ring (e.g. '0201234567'). Only when joining a session (see below) do you need to provide a phone number.
mplay_init_serial(portno,baudrate,stopbits,parity,flow) initializes a serial connection. portno is the port number (1-4). baudrate is the baudrate to be used (100-256K). stopbits indicates the number of stopbits (0 = 1 bit, 1 = 1.5 bit, 2 = 2 bits). parity indicates the parity (0=none, 1=odd, 2=even, 3=mark). And flow indicates the type of flow control (0=none, 1=xon/xoff, 2=rts, 3=dtr, 4=rts and dtr). Returns whether successful. A typical call is mplay_init_serial(1,57600,0,0,4). Give 0 as a first argument to open a dialog for the user to change the settings.

Your game should call one of these functions exactly once. All functions report whether they were successful. They are not successful if the particular protocol is not installed or supported by your machine. To check whether there is a successful connection available you can use the following function


mplay_connect_status() returns the status of the current connection. 0 = no connection, 1 = IPX connection, 2 = TCP/IP connection, 3 = modem connection, and 4 = serial connection.

To end the connection call


mplay_end() ends the current connection.

When using a TCP/IP connection you might want to tell the person you want to play the game with what the ip address of your computer is. The following function helps you here:


mplay_ipaddress() returns the IP address of your machine (e.g. '123.123.123.12') as a string. You can e.g. display this somewhere on the screen. Note that this routine is slow so don't call it all the time.

Creating and joining sessions
When you connect to a network, there can be multiple games happening on the same network. We call these sessions. These different sessions can correspond to different games or to the same game. A game must uniquely identify itself on the network. Fortunately, Game Maker does this for you. The only thing you have to know is that when you change the game id in the options form this identification changes. In this way you can avoid that people with old versions of your game will play against people with new versions.
If you want to start a new multiplayer game you need to create a new session. For this you can use the following routine:


mplay_session_create(sesname,playnumb,playername) creates a new session on the current connection. sesname is a string indicating the name of the session. playnumb is a number that indicates the maximal number of players allowed in this game (use 0 for an arbitrary number). playname is your name as player. Returns whether successful.

One instance of the game must create the session. The other instance(s) of the game should join this session. This is slightly more complicated. You first need to look at what sessions are available and then choose the one to join. There are three important routines for this:


mplay_session_find() searches for all sessions that still accept players and returns the number of sessions found.
mplay_session_name(numb) returns the name of session number numb (0 is the first session). This routine can only be called after calling the previous routine.
mplay_session_join(numb,playername) makes you join session number numb (0 is the first session). playername is your name as a player. Returns whether successful.

There is one more routine that can change the session mode. It should be called before creating a session:


mplay_session_mode(move) sets whether or not to move the session host to another computer when the host ends. move should either be true or false (the default).

To check the status of the current session you can use the following function


mplay_session_status() returns the status of the current session. 0 = no session, 1 = created session, 2 = joined session.

A player can stop a session using the following routine:


mplay_session_end() ends the session for this player.

Each instance of the game that joins a session is a player. As indicated above, players have names. There are three routines that deal with players.

mplay_player_find() searches for all players in the current session and returns the number of players found.
mplay_player_name(numb) returns the name of player number numb (0 is the first player, which is always yourself). This routine can only be called after calling the previous routine.
mplay_player_id(numb) returns the unique id of player number numb (0 is the first player, which is always yourself). This routine can only be called after calling the first routine. This id is used in sending and receiving messages to and from individual players.

Shared data communication is probably the easiest way to synchronize the game. All communication is shielded from you. There is a set of 1000000 values that are common to all entities of the game (preferably only use the first few to save memory). Each entity can set values and read values. Game Maker makes sure that each entity sees the same values. A value can either be a real or a string. There are just two routines:

mplay_data_write(ind,val) write value val (string or real) into location ind (ind between 0 and 1000000).
mplay_data_read(ind) returns the value in location ind (ind between 0 and 1000000). Initially all values are 0.

To synchronize the data on the different machines you can either use a guaranteed mode that makes sure that the change arrives on the other machine (but which is slow) or non-guaranteed. To change this use the following routine:


mplay_data_mode(guar) sets whether or not to use guaranteed transmission for shared data. guar should either be true (the default) or false.


The second communication mechanism that Game Maker supports is the sending and receiving of messages. A player can send messages to one or all other players. Players can see whether messages have arrived and take action accordingly. Messages can be sent in a guaranteed mode in which you are sure they arrive (but this can be slow) or in a non-guaranteed mode, which is faster.
The following messaging routines exist:


mplay_message_send(player,id,val) sends a message to the indicated player (either an identifier or a name; use 0 to send the message to all players). id is an integer message identifier and val is the value (either a real or a string). The message is sent in non-guaranteed mode. If val contains a string the maximal string length allowed is 30000 characters.
mplay_message_send_guaranteed(player,id,val) sends a message to the indicated player (either an identifier or a name; use 0 to send the message to all players). id is an integer message identifier and val is the value (either a real or a string). This is a guaranteed send. If val contains a string the maximal string length allowed is 30000 characters.
mplay_message_receive(player) receives the next message from the message queue that came from the indicated player (either an identifier or a name). Use 0 for messages from any player. The routine returns whether there was indeed a new message. If so you can use the following routines to get its contents:
mplay_message_id() Returns the identifier of the last received message.
mplay_message_value() Returns the value of the last received message.
mplay_message_player() Returns the player who sent the last received message.
mplay_message_name() Returns the name of the player who sent the last received message.
mplay_message_count(player) Returns the number of messages left in the queue from the player (use 0 to count all message).
mplay_message_clear(player) Removes all messages left in the queue from the player (use 0 to remove all message).

A few remarks are pertinent here. First of all, if you want to send a message to a particular player only, you will need to know the player's unique id. As indicated earlier you can obtain this with the function mplay_player_id(). This player identifier is also used when receiving messages from a particular player. Alternatively, you can give the name of the player as a string. If multiple players have the same name, only the first will get the message.

Secondly, you might wonder why each message has an integer identifier. The reason is that this helps your application to send different types of messages. The receiver can check the type of message using the id and take appropriate actions. (Because messages are not guaranteed to arrive, sending id and value in different messages would cause serious problems.)


This functionality is only available in the registered version of Game Maker.
In those cases were the functionality of GML is not enough for your wishes, you can actually extend the possibilities by using plug-ins. A plug-in comes in the form of a DLL file (a Dynamic Link Library). In such a DLL file you can define functions. Such functions can be programmed in any programming language that supports the creation of DLL's (e.g. Delphi, C, C++, etc.) You will though need to have some programming skill to do this. Plug-in functions must have a specific format. They can have between 0 and 11 arguments, each of which can either be a real number (double in C) or a null-terminated string. (For more than 4 arguments, only real arguments are supported at the moment.) They must return either a real or a null-terminated string.

In Delphi you create a DLL by first choosing New from the File menu and then choosing DLL. Here is an example of a DLL you can use with Game Maker written in Delphi. (Note that this is Delphi code, not GML code!)


library MyDLL;

uses SysUtils, Classes;

function MyMin(x,y:double):double;  cdecl;
begin
  if x<y then Result := x else Result := y;
end;

var res : array[0..1024] of char;

function DoubleString(str:PChar):PChar; cdecl;
begin
  StrCopy(res,str);
  StrCat(res,str);
  Result := res;
end;

exports MyMin, DoubleString;

begin
end.

This DLL defines two functions: MyMin that takes two real arguments and returns the minimum of the two, and DoubleString that doubles the string. Note that you have to be careful with memory management. That is why I declared the resulting string global. Also notice the use of the cdecl calling convention. You can either use cdecl or stdcall calling conventions. Once you build the DLL in Delphi you will get a file MyDLL.DLL. This file must be placed in the running directory of your game. (Or any other place where Windows can find it.)

To use this DLL in Game Maker you first need to specify the external functions you want to use and what type of arguments they take. For this there is the following function in GML:


external_define(dll,name,calltype,restype,argnumb,arg1type,arg2type, ...) Defines an external function. dll is the name of the dll file. name is the name of the functions. calltype is the calling convention used. For this use either dll_cdecl or dll_stdcall. restype is the type of the result. For this use either ty_real or ty_string. argnumb is the number of arguments (0-11). Next, for each argument you must specify its type. For this again use either ty_real or ty_string. When there are more than 4 arguments all of them must be of type ty_real.

This function returns the id of the external function that must be used for calling it. So in the above example, at the start of the game you would use the following GML code:


{
  global.mmm = external_define('MYOWN.DLL','MyMin',dll_cdecl,
                                     ty_real,2,ty_real,ty_real);
  global.ddd = external_define('MYOWN.DLL','DoubleString',dll_cdecl,
                                     ty_string,1,ty_string);
}

Now whenever you need to call the functions, you use the following function:


external_call(id,arg1,arg2,...) Calls the external function with the given id, and the given arguments. You need to provide the correct number of arguments of the correct type (real or string). The function returns the result of the external function.

So, for example, you would write:


{
  aaa = external_call(global.mmm,x,y);
  sss = external_call(global.ddd,'Hello');
}

If you don't need to use the DLL anymore you had better free it.


external_free(dll) Frees the DLL with the given name. This is in particular necessary if the game should remove the DLL. As long as the DLL is not freed it cannot be removed. Best do this e.g. in an end of game event.

You might wonder how to make a function in a DLL that does something in the game. For example, you might want to create a DLL that adds instances of objects to your game. The easiest way is to let your DLL function return a string that contains a piece of GML code. This string that contains the piece of GML can be executed using the GML function


execute_string(str) Execute the piece of code in the string str.

Alternatively you can let the DLL create a file with a script that can be executed (this function can also be used to later modify the behavior of a game).


execute_file(fname) Execute the piece of code in the file.

Now you can call an external function and then execute the resulting string, e.g. as follows:


{
  ccc = external_call(global.ddd,x,y);
  execute_string(ccc);
}

In some rare cases your DLL might need to know the handle of the main graphics window for the game. This can be obtained with the following function and can then be passed to the DLL:


window_handle() Returns the window handle for the main window.

Note that DLLs cannot be used in secure mode.

Using external DLLs is an extremely powerful mechanism. But please only use it if you know what you are doing.


번호 제목 글쓴이 날짜 조회 수
공지 로그인이 안되는 경우.. 가오파 2021.02.20 1105
공지 주소 복구했습니다. - 수정 가오파 2019.01.20 4903
공지 채팅 IRC말고 DISCORD로 넘어감 사자 2016.08.19 3751
공지 자유게시판 [127] 배삼룡 2004.11.11 6119
2853 즐엿 [3] 곰쓰나이트 2005.01.25 303
» 헤석부탁 [5] 히힛마스터 2005.01.25 184
2851 사랑하지 마세요~ [6]  無  2005.01.25 307
2850 강추 흐흐흐 꼭보셈 답이안나오죠! [4] 熱血少女 2005.01.25 304
2849 답이안나오죠... [3] 熱血少女 2005.01.25 361
2848 쿠하하ㅏ [3] 손님상 2005.01.25 203
2847 졸림 ㅜ.ㅜ [9]  無  2005.01.24 350
2846 원피스 또보고싶어 또보고싶어 [1] 면상 2005.01.24 260
2845 삼룡슈터 0.4 [3] 히힛마스터 2005.01.24 318
2844 b-tool에 그려논것을 다끼어마췄다 히힛마스터 2005.01.24 340
2843 마.....망했다....... [4] 곰쓰나이트 2005.01.24 309
2842 먹을게 없음... [3] 누구게 2005.01.24 320
2841 메가페스 아이디스크 업권한 [1] 장현주 2005.01.24 316
2840 3D maul 카스 초고수 [3] 포쿠테 2005.01.24 357
2839 미씨는 남자? [1] 개굴개굴 2005.01.24 248
2838 (sac)fish clan 크로우핑거 영상 [1] 포쿠테 2005.01.24 534
2837 카스무비 mop clan - On your mark [2] 포쿠테 2005.01.24 351
2836 정모 후 소감.. [1] 나의名風 2005.01.24 287
2835 워록의 정체 [1] 배삼룡 2005.01.24 296
2834 카스vs스포vs워록 [3] 포쿠테 2005.01.24 318