📄 742-746.html
字号:
<HTML>
<HEAD>
<META name=vsisbn content="1571690433"><META name=vstitle content="Black Art of Java Game Programming"><META name=vsauthor content="Joel Fan"><META name=vsimprint content="Sams"><META name=vspublisher content="Macmillan Computer Publishing"><META name=vspubdate content="11/01/96"><META name=vscategory content="Web and Software Development: Programming, Scripting, and Markup Languages: Java"><TITLE>Black Art of Java Game Programming:The Internet MahJong Server</TITLE>
<!-- HEADER --><STYLE type="text/css"> <!-- A:hover { color : Red; } --></STYLE><META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW"><script><!--function displayWindow(url, width, height) { var Win = window.open(url,"displayWindow",'width=' + width +',height=' + height + ',resizable=1,scrollbars=yes'); if (Win) { Win.focus(); }}//--></script><SCRIPT><!--function popUp(url) { var Win = window.open(url,"displayWindow",'width=400,height=300,resizable=1,scrollbars=yes'); if (Win) { Win.focus(); }}//--></SCRIPT><script language="JavaScript1.2"><!--function checkForQuery(fm) { /* get the query value */ var i = escape(fm.query.value); if (i == "") { alert('Please enter a search word or phrase'); return false; } /* query is blank, dont run the .jsp file */ else return true; /* execute the .jsp file */}//--></script></HEAD><BODY>
<TABLE border=0 cellspacing=0 cellpadding=0>
<tr>
<td width=75 valign=top>
<img src="../1571690433.gif" width=60 height=73 alt="Black Art of Java Game Programming" border="1">
</td>
<td align="left">
<font face="arial, helvetica" size="-1" color="#336633"><b>Black Art of Java Game Programming</b></font>
<br>
<font face="arial, helvetica" size="-1"><i>by Joel Fan</i>
<br>
Sams, Macmillan Computer Publishing
<br>
<b>ISBN:</b> 1571690433<b> Pub Date:</b> 11/01/96</font>
</td>
</tr>
</table>
<P>
<!--ISBN=1571690433//-->
<!--TITLE=Black Art of Java Game Programming//-->
<!--AUTHOR=Joel Fan//-->
<!--AUTHOR=Eric Ries//-->
<!--AUTHOR=Calin Tenitchi//-->
<!--PUBLISHER=Macmillan Computer Publishing//-->
<!--IMPRINT=Sams//-->
<!--CHAPTER=18//-->
<!--PAGES=742-746//-->
<!--UNASSIGNED1//-->
<!--UNASSIGNED2//-->
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="738-742.html">Previous</A></TD>
<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>
<TD><A HREF="746-749.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
<P><BR></P>
<P>The after_login() method is called when we successfully log in. Its job is to remove the login GUI and present a big window that will be the player’s workspace, or the <I>console</I>. I will take a moment here to explain what kind of GUI components the MahJong client uses for the console window. First of all, there is the menu bar. The most important menu items are probably File, which has a Quit item, and Table, which has Join, Leave, and Serve items. There are also two text panels that list all the players and tables on the server. These two lists are updated in real time from the server. We also need a text panel to hold all messages, and of course, a text input field plus a couple of buttons to allow sending messages. Finally, I reserve a big panel to hold subcomponents for the MahJong table. These AWT components are added as field variables, as shown below:</P>
<!-- CODE //-->
<PRE>
// field variables for AWT components
MenuBar menu_bar;
Menu file_menu;
Menu table_menu;
MenuItem m_file_quit;
MenuItem m_table_join;
MenuItem m_table_leave;
MenuItem m_table_serve;
TextArea player_list; // list of players
TextArea table_list; // list of tables
TextArea msg_list; // list of messages
TextField msg_out; // out-going message
Choice msg_choice; // to GOD, TABLE, ALL
Button msg_send; // send out a message
Panel table_panel; // mahjong table
</PRE>
<!-- END CODE //-->
<P>I use a GridBagLayout to lay out these AWT components. Figure 18-4 shows a reasonable way to lay them out, and Table 18-2 gives the appropriate values for GridBagConstraints fields. The components are all expanded to full grid size, by the way.
</P>
<P><A NAME="Fig4"></A><A HREF="javascript:displayWindow('images/18-04.jpg',640,793 )"><IMG SRC="images/18-04t.jpg"></A>
<BR><A HREF="javascript:displayWindow('images/18-04.jpg',640,793)"><FONT COLOR="#000077"><B>Figure 18-4</B></FONT></A> The client GUI illustrated</P>
<TABLE WIDTH="100%">
<CAPTION ALIGN=LEFT><B>Table 18-2</B> Laying out the console
<TR>
<TH COLSPAN="4"><HR>
<TR>
<TH WIDTH="30%" ALIGN="LEFT" VALIGN="BOTTOM">Component
<TH WIDTH="20%" ALIGN="LEFT" VALIGN="BOTTOM">gridx, gridy
<TH WIDTH="30%" ALIGN="LEFT" VALIGN="BOTTOM">gridwidth, gridheight
<TH WIDTH="20%" ALIGN="LEFT">weightx, weighty
<TR>
<TD COLSPAN="4"><HR>
<TR>
<TD>player_list
<TD>0, 0
<TD>1, 1
<TD>1.0, 0.0
<TR>
<TD>table_list
<TD>1, 0
<TD>3, 1
<TD>1.0, 0.0
<TR>
<TD>msg_list
<TD>0, 1
<TD>4, 1
<TD>0.0, 1.0
<TR>
<TD>msg_out
<TD>0, 2
<TD>2, 1
<TD>0.0, 0.0
<TR>
<TD>msg_choice
<TD>2, 2
<TD>1, 1
<TD>0.0, 0.0
<TR>
<TD>msg_send
<TD>3, 2
<TD>1, 1
<TD>0.0, 0.0
<TR>
<TD>table_panel
<TD>0, 3
<TD>4, 1
<TD>0.0, 0.0
<TR>
<TD COLSPAN="4"><HR>
</TABLE>
<P>Given the listing of components and Table 18-2, it is easy to write after_login() to create and arrange them. Note that the <I>m_table_leave</I> menu item should be disabled initially. Next, expand action() to let the player send messages and join/leave tables:</P>
<!-- CODE //-->
<PRE>
// in action()...
if (evt.target == msg_out || evt.target == msg_send) {
output(Packet.CPMessage(msg_choice.getSelectedItem(),
msg_out.getText()));
}
if (evt.target == m_table_serve) {
output(Packet.CPTableServe(null)); // no options yet
}
if (evt.target == m_table_leave) {
output(Packet.CPTableJoin((byte)-1, (byte)0));
}
if (evt.target == m_table_join) {
JoinTable jt = new JoinTable(this);
jt.show();
}
</PRE>
<!-- END CODE //-->
<P>To join a table, the user is presented a dialog window to input the table ID and choose whether he wants to join as a player or a spectator. This can be implemented with a class JoinTable that extends Dialog. I won’t go into details here.
</P>
<P>Finally, we need to update the player, table, and message lists whenever the server sends us the appropriate packets. I will show you how to implement the player list using the AWT component TextArea. Others are similar. The AWT component List can also be used for this purpose, if you can do without a horizontal scrollbar.</P>
<!-- CODE //-->
<PRE>
void hdJoin () {
int id;
String name;
// exercise: write Packet.SPJoin() and read it in here...
CPlayer him = g_players[id] = new CPlayer(id, name);
player_list.appendText(him.toString());
}
void hdLeave () {
int id;
// exercise: write Packet.SPLeave() and read it in here...
CPlayer him = g_players[id];
int i = player_list.getText().indexOf(him.getString());
int j = i + him.getString().length();
player_list.replaceText("", i, j);
}
void hdPlayerTable () {
int t_id, p_id, seat;
// exercise: write Packet.SPPlayerTable() and read it here...
CTable table = g_players[t_id];
CPlayer him;
if (p_id == -1) { // this player left the table
him = g_players[table.players[seat]];
him.table = null;
him.seat = -1;
table.players[seat] = null;
} else {
him = g_players[p_id];
him.table = table;
him.seat = seat;
table.players[seat] = him;
}
int i = player_list.getText().indexOf(him.getString());
int j = i + him.getString().length();
player_list.replaceText(him.toString(), i, j);
// update table list too...
}
</PRE>
<!-- END CODE //-->
<P>Here you see the use of storing the old string value of a player during the toString() call so it can be retrieved later with getString(), even though the player information may have changed already.
</P>
<P>At this point, we should have a functional server and client pair. This is what I suggest you do first if you are writing your own game. Although they don’t do much, it’s very important to debug them thoroughly, now!</P>
<H3><A NAME="Heading26"></A><FONT COLOR="#000077">Incorporating MahJong</FONT></H3>
<P>The following describes how to actually implement the MahJong game. We will start out on the client side, which mainly handles user-interface considerations, and eventually move to the server side, which actually handles the game play. This approach lets you see the game in action as soon as possible.
</P>
<H4 ALIGN="LEFT"><A NAME="Heading27"></A><FONT COLOR="#000077">Setting Up the MahJong Table on the Client</FONT></H4>
<P>In a graphical representation of the table, “myself” (he who runs the client) is always put in the “south” position. Other players’ positions are uniquely determined by this setup. See the lower half of Figure 18-4 for the layout of the MahJong table. (Note: In MahJong, the four words for compass directions have another meaning, so it’s important not to confuse players with overloaded notions. The server always refers to players by name rather than seat position.)
</P><P><BR></P>
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="738-742.html">Previous</A></TD>
<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>
<TD><A HREF="746-749.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
</BODY>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -