⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 328-331.html

📁 java game programming e-book
💻 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:Advanced Networking and Multiplayer Gaming Concepts</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,&nbsp;Macmillan Computer Publishing
    <br>
    <b>ISBN:</b>&nbsp;1571690433<b>&nbsp;&nbsp;&nbsp;Pub Date:</b>&nbsp;11/01/96</font>&nbsp;&nbsp;
</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=9//-->
<!--PAGES=328-331//-->
<!--UNASSIGNED1//-->
<!--UNASSIGNED2//-->

<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="326-328.html">Previous</A></TD>
<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>
<TD><A HREF="331-335.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
<P><BR></P>
<H4 ALIGN="CENTER"><A NAME="Heading24"></A><FONT COLOR="#000077">The sendMessage( ) Methods</FONT></H4>
<P>Next, let&#146;s write the two methods that will allow us to send messages to different clients. Both have the same name, but one is used for sending messages to all connected clients, while the second only sends the message to one specific client. Messages all have a &#147;type&#148; associated with them that tells the client how to handle them. Messages are sent in the form &#147;type||message&#148;. We again use &#147;||&#148; as a separator because it is relatively rare and easy to parse. Here&#146;s the code:
</P>
<!-- CODE //-->
<PRE>
/* send a message "msg", of type "type", to all Clients */
public void sendMessage(String msg, String type) &#123;
int x;

for(x=0; x&lt;theGroup.size(); x&#43;&#43;)
					((sClientThread)theGroup.&#8656;
elementAt(x)).message(type&#43;"||"&#43;msg);
/* remember that the format for messages is "type||message" */
&#125;

/* send a message "msg", of type "type", to the Client with alias "target" */
public void sendMessage(String msg, String target, String type) &#123;
int x;
sClientThread tempThread;

for(x=0; x&lt;theGroup.size(); x&#43;&#43;) &#123;
       tempThread=(sClientThread)theGroup.elementAt(x);
       if( tempThread.getAlias().equals(target) )
              tempThread.message(type&#43;"||"&#43;msg);
&#125;
&#125;
</PRE>
<!-- END CODE //-->

<TABLE BORDER="2" BORDERCOLOR="#0000" ALIGN="CENTER">
<TR><TD><FONT SIZE="+1"><B>Explicit Casting</B></FONT>
<P>When we access an element in <I>theGroup</I>, you may notice that sClientThread in parentheses immediately precedes it. This is called <I>explicit typecasting</I> and is used to convert Objects of different classes. If you&#146;ve programmed in C, you&#146;ve probably used this to do such things as convert integers to floats or characters to strings. In Java, you can do this for any object, so long as the two objects share at least one parent class. Vector is used to store any object that subclasses java.lang.Object. This allows the Vector to store objects of any type. However, when we access an object inside a Vector, we need to call methods that are unique to sClientThread. Thus, we must tell the Java compiler that the Object we are accessing is really an sClientThread. This can seem confusing if you&#146;ve not used a similar language before. If so, don&#146;t worry about all the details. Just remember that, to convert an object, you have to <I>cast</I> it.</TABLE>

</P>
<P>After that is finished, we must write the method that will be called, eventually, by sClientThread whenever it gets some input. There will be many sClientThreads connected at one time, but they will all still use the same protocol method, which is listed here:</P>
<!-- CODE //-->
<PRE>
/* here is where we handle any input received from a Client */
/* This method is called by sClientThread directly */
public void handleInput(String str, sClientThread T) &#123;
StringTokenizer st;

/* this next line is for debugging only. You would not include it in the
final product */
System.out.println("Got: "&#43;str&#43;" from "&#43;T.getAlias());

/* command to disconnect = "bye" */
if( str.startsWith("bye") ) &#123;
       T.stop();
       return;
       &#125;

st = new StringTokenizer( str, "||");

if(st != null ) &#123;
String cmd, val;

cmd = st.nextToken();
val = st.nextToken();

/* "login" = a new person is logging in. Set the alias, send a welcome
message, and then send everyone an updated list of Client names */
if(cmd.equals("login")) &#123;
       T.setAlias( val );
       sendMessage(T.getAlias()&#43;"||"&#43;T.getAlias()&#43;" has entered the
                  room.", cmd);
       sendMessage(calcList(), "list");
       return ;
       &#125;

/* "logout" = one of our clients is finished and wants to disconnect. Let
everyone know that and then stop the connection. The garbage collection
method will take care of removing them from the list. */
if(cmd.equals("logout")) &#123;
       sendMessage(T.getAlias()&#43;" has left the room.", cmd);
       T.stop();
       return ;
       &#125;

/* someone wants to "say" something to the whole room */
if(cmd.equals("say")) &#123;
       sendMessage(T.getAlias()&#43;" says: "&#43; val, cmd);
       return ;
       &#125;
/* someone wants to whisper something to a specific person only */
if(cmd.equals("whisper")) &#123;
       sendMessage(T.getAlias()&#43;" whispers to you:
                  "&#43;val,st.nextToken(),cmd);
       return ;
       &#125;
&#125;

&#125;
</PRE>
<!-- END CODE //-->
<P>handleInput() parses the message received and then takes the appropriate action. Input should always be of the form &#147;command||parameter1||parameter2&#148;. Two parameters are currently plenty for the commands we want to handle (remember that only the <I>whisper</I> command even takes that many), although a method that could handle any number of parameters could easily be developed based on this code.</P>
<H4 ALIGN="CENTER"><A NAME="Heading25"></A><FONT COLOR="#000077">The calcList( ) Method</FONT></H4>
<P>If you looked carefully, you probably noticed a new method, called calcList(), called when a new user connects and sends the <I>login</I> command (which takes the form &#147;login||name&#148;). When someone enters the room, after notifying everyone, a message of type <I>list</I> is sent with an updated list of everyone in the room. This is generated by the calcList() method below:</P>
<!-- CODE //-->
<PRE>
/* return a list of all currently connected users in the form
"name1&#38;name2&#38;name3" */
public String calcList() &#123;
int x;
StringBuffer buf = new StringBuffer();
String temp;
for(x=0; x&lt;theGroup.size(); x&#43;&#43;) &#123;
       temp = ((sClientThread) (theGroup.elementAt(x))).getAlias();
       if(temp != null)
              buf.append(temp).append('&#38;');
&#125;
if (buf.length() &gt;0 )
       buf.setLength(buf.length()-1);
return buf.toString();
&#125;
</PRE>
<!-- END CODE //-->
<H4 ALIGN="CENTER"><A NAME="Heading26"></A><FONT COLOR="#000077">The StringBuffer Class</FONT></H4>
<P>A brief mention of the StringBuffer class is important here. StringBuffers are like Strings, except they are designed to have things added and removed. Whenever you change a String, it is temporarily changed into a StringBuffer, operated on, and then returned to a String. The Java compiler takes care of all this transparently, so it&#146;s not something you normally need to worry about. However, if you know you are going to be making a lot of changes to a String (especially adding or removing large chunks), it is much more efficient to operate directly on a StringBuffer, which saves the compiler a lot of time later on. This is just a small optimization to make your code a bit faster.
</P><P><BR></P>
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="326-328.html">Previous</A></TD>
<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>
<TD><A HREF="331-335.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>


</BODY>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -