<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" 
      xmlns:thr="http://purl.org/syndication/thread/1.0">
  <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html" />
  <link rel="self" type="application/atom+xml" href="http://www.insideria.com/atom.xml" />
  <id>tag:www.insideria.com,2009://34/tag:www.insideria.com,2009://34.36369-</id>
  <updated>2009-11-20T18:50:52Z</updated>
  <title>Comments for Writing the Pac-Man Game in JavaFX - Part 4 (http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html)</title>
  <generator uri="http://www.sixapart.com/movabletype/">Movable Type 4.21-en</generator>
  <entry>
    <id>tag:www.insideria.com,2009://34.36369</id>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://blogs.oreilly.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=34/entry_id=36369" title="Writing the Pac-Man Game in JavaFX - Part 4" />
    <published>2009-06-04T16:00:00Z</published>
    <updated>2009-06-04T16:00:00Z</updated>
    <title>Writing the Pac-Man Game in JavaFX - Part 4</title>
    <summary>In the last article, we developed a preliminary version of the Pac-Man game. Four ghosts are randomly roaming the maze and a Pac-Man character can be controlled by a player. Now, we write some more code for the interaction between ghosts and the Pac-Man: 

Pac-Man eats a ghost after he gobbles a magic dot.
A ghost eats the Pac-Man when it touches him. 

</summary>
    <author>
      <name>Haining Henry Zhang</name>
      
    </author>
    
    <category term="Features" />
    
    <content type="html" xml:lang="en" xml:base="http://www.insideria.com/">
      <![CDATA[<p><b>Haining Henry Zhang with <a href="http://learnjavafx.typepad.com" target="_blank">James L. Weaver</a></b></p>

<p>
<strong>Previous parts in the Pac-Man series</strong><br/>
<a href="http://www.insideria.com/2009/05/writing-the-pac-man-game-in-ja.html">Writing the Pac-Man Game in JavaFX - Part 1</a><br/>
<a href="http://www.insideria.com/2009/05/writing-the-pac-man-game-in-ja-1.html">Writing the Pac-Man Game in JavaFX - Part 2</a><br/>
<a href="http://www.insideria.com/2009/05/writing-the-pac-man-game-in-ja-2.html">Writing the Pac-Man Game in JavaFX - Part 3</a><br/>
</p>

<p>In the last article, we developed a preliminary version of the Pac-Man game. Four ghosts are randomly roaming the maze and a Pac-Man character can be controlled by a player. Now, we write some more code for the interaction between ghosts and the Pac-Man: 
<oL>
<li>Pac-Man eats a ghost after he gobbles a magic dot.</lI>
<li>A ghost eats the Pac-Man when it touches him. </lI>
</ol>
</p>


<p><b>Pac-Man eats Ghosts</b></p>

In the function <b><tt>moveOneStep()</tt></b>, we add in code to check if the Pac-Man character has
gobbled a magic dot. If he has, we change the ghosts into a hollow state. When the Pac-Man character
meets a ghost, he can eat the ghost if it is hollow. Let's add three functions into <b><tt>Maze.fx</tt></b>.

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre> 
<span class="category1">public</span> <span class="category1">class</span> Maze <span class="category1">extends</span> CustomNode {
 
   <span class="linecomment">// counter for ghosts eaten</span>
   <span class="category1">var</span> ghostEatenCount : Integer;
 
   <span class="linecomment">// text to be displayed for score of eating a ghost</span>
   <span class="category1">var</span> scoreText = [
     ScoreText {
        content: "<span class="quote">200</span>"
        <span class="category2">visible</span>: <span class="category1">false</span>;
      },
     ScoreText {
          content: "<span class="quote">400</span>"
          <span class="category2">visible</span>: <span class="category1">false</span>;
      },
     ScoreText {
          content: "<span class="quote">800</span>"
          <span class="category2">visible</span>: <span class="category1">false</span>;
      },
     ScoreText {
          content: "<span class="quote">1600</span>"
          <span class="category2">visible</span>: <span class="category1">false</span>;
      },
   ];
 
   . . . . . .
 
   <span class="category1">var</span> group : Group =
   Group {
      content: [
      (retangles <span class="category1">for</span> drawing the maze)
      . . . . . .,
      scoreText
    ];
  
    . . . . . .
  
    <span class="linecomment">// determine if pacman meets a ghost</span>
    <span class="category1">public</span> <span class="category1">function</span> hasMet(g:Ghost): <span class="category2">Boolean</span> {
   
       def distanceThreshold = 22;
   
       <span class="category1">var</span> x1 = g.imageX;
       <span class="category1">var</span> x2 = pacMan.imageX;
   
       <span class="category1">var</span> diffX = <span class="category2">Math</span>.<span class="category2">abs</span>(x1-x2);
   
       <span class="category1">if</span> ( diffX &gt;= distanceThreshold ) <span class="category1">return</span> <span class="category1">false</span>;
   
       <span class="category1">var</span> y1 = g.imageY;
       <span class="category1">var</span> y2 = pacMan.imageY;
       <span class="category1">var</span> diffY = <span class="category2">Math</span>.<span class="category2">abs</span>(y1-y2);
   
       <span class="category1">if</span> ( diffY &gt;= distanceThreshold ) <span class="category1">return</span> <span class="category1">false</span>;
   
       <span class="linecomment">// calculate the distance to see if pacman touches the ghost</span>
       <span class="category1">if</span> ( diffY*diffY + diffX*diffX &lt;= distanceThreshold*distanceThreshold )
         <span class="category1">return</span> <span class="category1">true</span>;
   
       <span class="category1">return</span> <span class="category1">false</span>;
     }
  
    <span class="category1">public</span> <span class="category1">function</span> pacManMeetsGhosts() {
   
       <span class="category1">for</span> ( g <span class="category1">in</span> ghosts )
         <span class="category1">if</span> ( hasMet(g) )
           <span class="category1">if</span> ( g.isHollow ) {
              pacManEatsGhost(g);
            }
     }
  
    <span class="category1">public</span> <span class="category1">function</span> pacManEatsGhost(g: Ghost) {
         
       ghostEatenCount++;
   
       <span class="category1">var</span> s = 1;
       <span class="category1">for</span> ( i <span class="category1">in</span> [1..ghostEatenCount] ) s = s + s;
   
       pacMan.scores += s*100;
   
       <span class="category1">var</span> st = scoreText[ghostEatenCount-1];
       st.<span class="category2">x</span> = g.imageX - 10;
       st.<span class="category2">y</span> = g.imageY;
   
       g.<span class="category2">stop</span>();
       g.resetStatus();
       g.trapCounter = -10;
   
       st.showText();
     }
 }</pre>
</code>

</div></div> 

<p>The function <b><tt>hasMet()</tt></b> computes the distance between the Pac-Man and a ghost. If they touch
each other, this function returns <b><tt>true</tt></b>. The distance between two objects can be calculated as
</P>
<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre> 
d = <span class="category2">sqrt</span>( (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2) )</pre>
</code>

</div></div> 

<p>If the distance is below a threshold, we consider two objects overlapping eath other. Since this function
will be invoked very frequently during the game, we optimize the function to make it run a bit faster. We replace 
using the expensive <b><tt>Math.sqrt()</tt></b> function by an equivalent equation:

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre> 
<span class="category1">if</span> ( diffY*diffY + diffX*diffX &lt;= distanceThreshold*distanceThreshold ) 
             <span class="category1">return</span> <span class="category1">true</span>;</pre>
</code>

</div></div> 

Further, when the Pac-Man and a ghost is far away from each other, we can simplify the algorithm by applying two 
checkings before the expensive distance calculation: 

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre> 
<span class="category1">if</span> ( diffY &gt;= distanceThreshold ) <span class="category1">return</span> <span class="category1">false</span>;
<span class="category1">if</span> ( diffX &gt;= distanceThreshold ) <span class="category1">return</span> <span class="category1">false</span>;</pre>
</code>

</div></div> 

<p>The function <b><tt>pacManEatsGhost()</tt></b> eliminates a eaten ghost from the maze. The ghost instance
then gets reset and thrown back to the cage. In the original game, a pair of ghost's eyes are traversing the maze
before they reach the cage and turn back into a ghost. For simplicity, we do not implement this part and just
put the ghost directly back to the cage.
</p>

<p>The class <b><tt>ScoreText</tt></b> is a subclass of <b><tt>Text</tt></b> and it displays the score when a ghost
is eaten by the Pac-Man. The score remains visible for 2 seconds and then disappears. The code of 
the class <b><tt>ScoreText</tt></b> is as below. An instance of <b><tt>Timeline</tt></b> hides the text at
the end of its animation.
</p>


<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre> 
<span class="blockcomment">/*
 * ScoreText.fx
 *
 * Created on 2009-2-6, 17:52:42
 *
 * text object for showing scores of eating a ghost, then disappears after 2s
 *
 */</span>

package pacman;

<span class="category1">import</span> javafx.animation.KeyFrame;
<span class="category1">import</span> javafx.animation.Timeline;
<span class="category1">import</span> javafx.scene.<span class="category2">text</span>.Font;
<span class="category1">import</span> javafx.scene.<span class="category2">text</span>.Text;
<span class="category1">import</span> javafx.scene.paint.<span class="category2">Color</span>;

<span class="blockcomment">/**
 * @author Henry Zhang
 */</span>

<span class="category1">public</span> <span class="category1">class</span> ScoreText <span class="category1">extends</span> Text{
   override <span class="category1">var</span> <span class="category2">font</span> = Font { <span class="category2">size</span>: 11 };
 
   override <span class="category1">var</span> fill = <span class="category2">Color</span>.YELLOW;
 
   <span class="category1">var</span> timeline= Timeline {
      repeatCount: 1
      keyFrames: [
        KeyFrame {
           <span class="category2">time</span>: 2s
           action: <span class="category1">function</span>() {
              <span class="category2">visible</span> = <span class="category1">false</span>;
            }
         }
      ]
      };
 
 
   <span class="category1">public</span> <span class="category1">function</span> showText() {
      <span class="category2">visible</span> = <span class="category1">true</span>;
      timeline.<span class="category2">stop</span>();
      timeline.<span class="category2">play</span>();
    }
}</pre>
</code>

</div></div> 

<p>In function <b><tt>moveOneStep()</tt></b> of <b><tt>PacMan</tt></b>, we add in a line at the end:

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre> 
  <span class="category1">public</span> override <span class="category1">function</span> moveOneStep() {
 
     <span class="linecomment">// handle keyboard input only when pac-man is at a point of the grid</span>
     <span class="category1">if</span> ( currentImage == 0 )
       handleKeyboardInput();
 
     <span class="category1">if</span> ( state == MOVING) {
        <span class="category1">if</span> ( xDirection != 0 )
          moveHorizontally();
  
        <span class="category1">if</span> ( yDirection != 0 )
          moveVertically();
  
        <span class="linecomment">// switch to the image of the next frame</span>
        <span class="category1">if</span> ( currentImage &lt; ANIMATION_STEP - 1  )
          currentImage++
        <span class="category1">else</span> {
           currentImage=0;
           updateScores();
         }
      }
     maze.pacManMeetsGhosts();
   }</pre>
</code>

</div></div> 

<p>Run the program now and we get a "never-die" version of PacMan game. Pac-Man can eat ghosts but not
vice versa. Click on the below button and enjoy this special edition of the Pac-Man Game. 

</p>

<p><a href="http://www.javafxgame.com/v8/pacman.jnlp">
<img src="http://www.insideria.com/upload/2009/05/maze9.png" border=0><br><br>
<img src="http://www.insideria.com/upload/2009/05/launch.gif" border=0></a>
</p>


<p><b>Ghost eats Pac-Man</b></p>

<p>If a ghost touches the Pac-Man character, he loses a life. An animation shows the dying of the Pac-Man
character. This animation displays a pie and shrinks into nothing at the end (see below figure).</P>

<p><img src="http://www.insideria.com/upload/2009/05/dyingman.png"></p>

<p>We create a class <b><tt>DyingPacMan</tt></b> to perform this animation. Since the pie can be drawn by a 
standard shape class <b><tt>Arc</tt></b> in JavaFX, we just subclass the class <b><tt>Arc</tt></b> and 
add in some animation to it. The source code is listed below:
</p>

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre> 
<span class="blockcomment">/*
 * DyingPacMan.fx
 *
 * Created on 2009-2-6, 17:52:42
 */</span>

package pacman;

<span class="category1">import</span> javafx.animation.Interpolator;
<span class="category1">import</span> javafx.animation.KeyFrame;
<span class="category1">import</span> javafx.animation.Timeline;
<span class="category1">import</span> javafx.scene.shape.Arc;

<span class="blockcomment">/**
 * @author Henry Zhang
 */</span>

<span class="category1">public</span> <span class="category1">class</span> DyingPacMan <span class="category1">extends</span> Arc {
 
   <span class="category1">public</span> <span class="category1">var</span> maze : Maze;
 
   <span class="category1">var</span> timeline = Timeline {
      repeatCount: 1
      keyFrames: [
      
        KeyFrame {
           <span class="category2">time</span>: 600ms
           action: <span class="category1">function</span>() {
              <span class="linecomment">// hide the pacMan character and ghosts before the animation</span>
              maze.pacMan.<span class="category2">visible</span> = <span class="category1">false</span>;
              
              <span class="category1">for</span> ( g <span class="category1">in</span> maze.ghosts ) {
                 g.<span class="category2">hide</span>();
               }
    
              <span class="category2">visible</span> = <span class="category1">true</span>;
            }
           values: [ startAngle =&gt; 90, <span class="category2">length</span>=&gt;360 ];  
         },
  
        KeyFrame {
           <span class="category2">time</span>: 1800ms
           action: <span class="category1">function</span>() {
              <span class="category2">visible</span> = <span class="category1">false</span>;
            }
           values: [ startAngle =&gt; 270 tween Interpolator.LINEAR,
                     <span class="category2">length</span> =&gt; 0 tween Interpolator.LINEAR ]
         },
      ]
    }
 
   <span class="category1">public</span> <span class="category1">function</span> <span class="category2">startAnimation</span>(<span class="category2">x</span>: <span class="category2">Number</span>, <span class="category2">y</span>: <span class="category2">Number</span>) : Void {
  
      startAngle = 90;
      centerX = <span class="category2">x</span>;
      centerY = <span class="category2">y</span>;
  
      timeline.<span class="category2">play</span>();
    }
}</pre>
</code>

</div></div> 

<p>We create an instance of <b><tt>Timeline</tt></b>. It defines two instances of <b><tt>keyFrame</tt></b>. 
To make the game pause for a short while after a ghost captures the Pac-Man, we
let the first <b><tt>keyFrame</tt></b> start at 600ms. This <b><tt>keyFrame</tt></b> has two tasks: 
</p>

<p>
a) Hide the Pac-Man character and all the ghosts, then make the dying PacMan animation visible. The 
<b><tt>action</tt></b> attribute contains a function for this purpose.<br>
b) Initialize the variable <b><tt>startAngle</tt></b> and <b><tt>length</tt></b>. They are inherited from 
the <b><tt>Arc</tt></b> class. By changing their values, we can achieve the animation effect of a
shrinking pie.
</p>

<p>In the second <b><tt>keyFrame</tt></b>, we define the interpolation of two variables. Interpolation is another animation feature
provided by JavaFX. During the
animation, from 600ms to 1800ms, <b><tt>startAngle</tt></b> changes from 90 to 270, 
while <b><tt>length</tt></b> changes from 360 to 0. The interpolation method defined by the <b><tt>tween</tt></b>
keyword is <b><tt>Interpolator.LINEAR</tt></b>.
It allows the value of a variable evenly(i.e. linearly) changes between two frames. JavaFX API takes care of the adjustment
of the values between two adjacent <b><tt>keyFrames</tt></b>. The below figure illustrates how
the two variables change to control the shape of the pie.<p>
<p>
<img src="http://www.insideria.com/upload/2009/05/pieanimation.png">
</p>

<p>The next step is to put an instance of <b><tt>DyingPacMan</tt></b> into the maze and start the animation when
a ghost captures the Pac-Man.

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre> 
<span class="category1">public</span> <span class="category1">class</span> Maze <span class="category1">extends</span> CustomNode {
 
   . . . . . .
   <span class="category1">public</span> <span class="category1">var</span> dyingPacMan =
     DyingPacMan {
        maze: <span class="category1">this</span>
        centerX: 0 
        centerY: 0
        radiusX: 13  
        radiusY: 13
        startAngle: 90
        <span class="category2">length</span>: 360
        <span class="category2">type</span>: ArcType.ROUND
        fill: <span class="category2">Color</span>.YELLOW
        <span class="category2">visible</span>: <span class="category1">false</span>
     } ;
   . . . . . .
 
   <span class="category1">var</span> group : Group =
   Group {
      content: [
  
        . . . . . .
  
        scoreText, 
        dyingPacMan
      ]
    }; <span class="linecomment">// end Group</span>
 
   . . . . . . 
 
   <span class="category1">public</span> <span class="category1">function</span> pacManMeetsGhosts() {
  
      <span class="category1">for</span> ( g <span class="category1">in</span> ghosts )
        <span class="category1">if</span> ( hasMet(g) )
          <span class="category1">if</span> ( g.isHollow ) {
             pacManEatsGhost(g);
           }
          <span class="category1">else</span> {
             <span class="category1">for</span> ( ghost <span class="category1">in</span> ghosts )
               ghost.<span class="category2">stop</span>();
   
             pacMan.<span class="category2">stop</span>();
   
             dyingPacMan.<span class="category2">startAnimation</span>(pacMan.imageX, pacMan.imageY);
             <span class="category1">break</span>;
           }
    }
 
   . . . . . .
}</pre>
</code>

</div></div> 

</p>

<p><b>Game Levels</b></p>

<p>So far, we have completed most of the coding. It is a fair game now because the Pac-Man and ghosts both have the ability to eat each other. 
The remain task is to give three lives to the Pac-Man character and have some levels of the game. If the Pac-Man
character eats up all the dots, the game enters into the next level. If Pac-Man character dies during a game, the
life count is decreased by 1. When the player's score exceeds 10000, a bonus life is awarded.
If all lives are used, the game is over. We reset the status of all objects and
restart the game. The source code of <b><tt>Maze.fx</tt></b> and <b><tt>PacMan.fx</tt></b> are modified.
The changes are highlighted in bold text below.<p>

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre> 
<span class="blockcomment">/*
 * Maze.fx
 *
 * Created on 2008-12-20, 20:22:15
 */</span>

package pacman;

<span class="category1">import</span> javafx.scene.CustomNode;
<span class="category1">import</span> javafx.scene.Group;
<span class="category1">import</span> javafx.scene.Node;
<span class="category1">import</span> javafx.scene.paint.<span class="category2">Color</span>;
<span class="category1">import</span> javafx.scene.shape.Line;
<span class="category1">import</span> javafx.scene.shape.Rectangle;
<span class="category1">import</span> pacman.MazeData;
<span class="category1">import</span> pacman.PacMan;
<span class="category1">import</span> pacman.WallBlackLine;
<span class="category1">import</span> pacman.WallBlackRectangle;
<span class="category1">import</span> pacman.WallRectangle;
<span class="category1">import</span> javafx.scene.<span class="category2">input</span>.*;
<span class="category1">import</span> javafx.scene.<span class="category2">text</span>.Text;
<span class="category1">import</span> javafx.scene.<span class="category2">text</span>.Font;
<span class="category1">import</span> javafx.scene.image.Image;
<span class="category1">import</span> javafx.scene.image.ImageView;
<span class="category1">import</span> java.lang.<span class="category2">Math</span>;
<span class="category1">import</span> javafx.scene.shape.ArcType;
<span class="category1">import</span> javafx.animation.KeyFrame;
<span class="category1">import</span> javafx.animation.Timeline;

<span class="blockcomment">/**
 * @author Henry Zhang
 */</span>

<span class="category1">public</span> <span class="category1">class</span> Maze <span class="category1">extends</span> CustomNode {
 
   <span class="linecomment">// counter for ghosts eaten</span>
   <span class="category1">var</span> ghostEatenCount : Integer;
 
   <span class="linecomment">// text to be displayed for score of eating a ghost</span>
   <span class="category1">var</span> scoreText = [
     ScoreText {
        content: "<span class="quote">200</span>"
        <span class="category2">visible</span>: <span class="category1">false</span>;
      },
     ScoreText {
          content: "<span class="quote">400</span>"
          <span class="category2">visible</span>: <span class="category1">false</span>;
      },
     ScoreText {
          content: "<span class="quote">800</span>"
          <span class="category2">visible</span>: <span class="category1">false</span>;
      },
     ScoreText {
          content: "<span class="quote">1600</span>"
          <span class="category2">visible</span>: <span class="category1">false</span>;
      },
   ];
 
   <span class="linecomment">// Pac Man Character</span>
   <span class="category1">public</span> <span class="category1">var</span> pacMan : PacMan = PacMan{ maze:<span class="category1">this</span> <span class="category2">x</span>:15 <span class="category2">y</span>:18 } ;
 
   <span class="category1">public</span> <span class="category1">var</span> ghostBlinky = Ghost {
      defaultImage1: Image {
         <span class="category2">url</span>: "<span class="quote">{__DIR__}images/ghostred1.png</span>"
       }
  
      defaultImage2: Image {
         <span class="category2">url</span>: "<span class="quote">{__DIR__}images/ghostred2.png</span>"
       }
  
       maze: <span class="category1">this</span>
       pacMan: pacMan
       <span class="category2">x</span>: 17
       <span class="category2">y</span>: 15
       xDirection: 0
       yDirection: -1
       trapTime: 1
      };
 
    <span class="category1">public</span> <span class="category1">var</span> ghostPinky = Ghost {
       defaultImage1:Image {
           <span class="category2">url</span>: "<span class="quote">{__DIR__}images/ghostpink1.png</span>"
        }
  
       defaultImage2:Image {
          <span class="category2">url</span>: "<span class="quote">{__DIR__}images/ghostpink2.png</span>"
        }
       
       maze: <span class="category1">this</span>
       pacMan: pacMan
       <span class="category2">x</span>: 12
       <span class="category2">y</span>: 14
       xDirection: 0 
       yDirection: 1
       trapTime: 10
     };
 
    <span class="category1">public</span> <span class="category1">var</span> ghostInky = Ghost {
       defaultImage1:Image {
          <span class="category2">url</span>: "<span class="quote">{__DIR__}images/ghostcyan1.png</span>"
        }
       defaultImage2:Image {
          <span class="category2">url</span>: "<span class="quote">{__DIR__}images/ghostcyan2.png</span>"
        }
  
       maze: <span class="category1">this</span>
       pacMan: pacMan
       <span class="category2">x</span>: 13
       <span class="category2">y</span>: 15
       xDirection: 1
       yDirection: 0
       trapTime: 20
     };
 
    <span class="category1">public</span> <span class="category1">var</span> ghostClyde = Ghost {
       defaultImage1:Image {
           <span class="category2">url</span>: "<span class="quote">{__DIR__}images/ghostorange1.png</span>"
        }
       defaultImage2:Image {
          <span class="category2">url</span>: "<span class="quote">{__DIR__}images/ghostorange2.png</span>"
        }
  
       maze: <span class="category1">this</span>
       pacMan: pacMan
       <span class="category2">x</span>: 15
       <span class="category2">y</span>: 14
       xDirection: -1
       yDirection: 0
       trapTime: 30
     };
 
   <span class="category1">public</span> <span class="category1">var</span> ghosts = [ghostBlinky, ghostPinky, ghostInky, ghostClyde];
 
   <span class="category1">public</span> <span class="category1">var</span> dyingPacMan =
     DyingPacMan {
        maze: <span class="category1">this</span>
        centerX: 0
        centerY: 0
        radiusX: 13
        radiusY: 13
        startAngle: 90
        <span class="category2">length</span>: 360
        <span class="category2">type</span>: ArcType.ROUND
        fill: <span class="category2">Color</span>.YELLOW
        <span class="category2">visible</span>: <span class="category1">false</span>;
     } ;
 
   <span class="linecomment">// the pac man image</span>
   <span class="category1">var</span> pacmanImage =Image {
      <span class="category2">url</span>: "<span class="quote">{__DIR__}images/left1.png</span>"
    }
 
   <span class="linecomment">// images showing how many lives remaining</span>
   <span class="category1">var</span> livesImage = [
     ImageView {
        image: pacmanImage
        <span class="category2">x</span>: MazeData.calcGridX(18)
        <span class="category2">y</span>: MazeData.calcGridY(30)
        <span class="category2">visible</span>: bind livesCount &gt; 0
      },
     ImageView {
        image: pacmanImage
        <span class="category2">x</span>: MazeData.calcGridX(16)
        <span class="category2">y</span>: MazeData.calcGridY(30)
        <span class="category2">visible</span>: bind livesCount &gt; 1
      },
     ImageView {
        image: pacmanImage
        <span class="category2">x</span>: MazeData.calcGridX(14)
        <span class="category2">y</span>: MazeData.calcGridY(30)
        <span class="category2">visible</span>: bind livesCount &gt; 2
      }
   ];
 
   <span class="linecomment">// level of the game</span>
   <span class="category1">public</span> <span class="category1">var</span> level : Integer = 1;
 
   <span class="linecomment">// flag to add a life to the player if the first time scores exceed 10000</span>
   <span class="category1">var</span> addLifeFlag: <span class="category2">Boolean</span> = <span class="category1">true</span>;
 
   <span class="linecomment">// current lives of the player</span>
   <span class="category1">var</span> livesCount = 2;
 
   <span class="linecomment">// message to start a game</span>
   <span class="category1">var</span> waitForStart: <span class="category2">Boolean</span> = <span class="category1">true</span>;
   <span class="category1">var</span> messageBox = Group {
      content: [
        Rectangle {
           <span class="category2">x</span>: MazeData.calcGridX(5)
           <span class="category2">width</span>: MazeData.GRID_GAP * 19
           <span class="category2">y</span>: MazeData.calcGridY(21)
           <span class="category2">height</span>: MazeData.GRID_GAP *5
           stroke: <span class="category2">Color</span>.RED
           strokeWidth: 5
        
           fill: <span class="category2">Color</span>.CYAN
           opacity: 0.75
           arcWidth: 25
           arcHeight: 25
         },
        Text {
           <span class="category2">font</span>: Font { <span class="category2">size</span>: 19 }
           <span class="category2">x</span>: MazeData.calcGridX(7)
           <span class="category2">y</span>: MazeData.calcGridY(24)
   
           content: "<span class="quote">PRESS ANY KEY TO START</span>"
           fill: <span class="category2">Color</span>.RED
         }
      ]
    };
 
  <span class="linecomment">// whether the last finished game is won by the player</span>
  <span class="category1">var</span> lastGameResult: <span class="category2">Boolean</span> = <span class="category1">false</span>;
 
  <span class="linecomment">// text of game winning</span>
  <span class="category1">var</span> gameResultText =
    Text {
       <span class="category2">font</span>: Font { <span class="category2">size</span>: 20
                    }
       <span class="category2">x</span>: MazeData.calcGridX(11)
       <span class="category2">y</span>: MazeData.calcGridY(11)+8
  
       content: bind <span class="category1">if</span> ( lastGameResult )
                       "<span class="quote"> YOU WIN </span>"
                     <span class="category1">else</span>
                       "<span class="quote">GAME OVER</span>";
       fill: <span class="category2">Color</span>.RED
       <span class="category2">visible</span>: <span class="category1">false</span>;
     } ;
 
  <span class="category1">var</span> flashingCount: Integer = 0;
  <span class="category1">var</span> flashingTimeline: Timeline =
    Timeline {
       repeatCount: 5
       keyFrames : [
         KeyFrame {
            <span class="category2">time</span> : 500ms
            action: <span class="category1">function</span>() {
               gameResultText.<span class="category2">visible</span> = <span class="category1">not</span> gameResultText.<span class="category2">visible</span>;
               <span class="category1">if</span> ( ++flashingCount == 5) {
                  messageBox.<span class="category2">visible</span> = <span class="category1">true</span>;
                  waitForStart = <span class="category1">true</span>;
                }
             }
          }
       ]
     };
 
   <span class="category1">var</span> group : Group =
   Group {
      content: [
        Rectangle {
           <span class="category2">x</span>:0
           <span class="category2">y</span>:0
           <span class="category2">width</span>: MazeData.calcGridX(MazeData.GRID_SIZE + 2)
           <span class="category2">height</span>: MazeData.calcGridY(MazeData.GRID_SIZE + 3)
           fill: <span class="category2">Color</span>.BLACK
         },
  
        WallRectangle{ x1:0 y1:0 x2:MazeData.GRID_SIZE y2:MazeData.GRID_SIZE },
  
        WallRectangle { x1:14 y1:-0.5 x2:15 y2:4 },
        WallBlackRectangle { x1:13.8 y1:-1 x2:15.3 y2:0 },
  
        WallRectangle { x1:2 y1:2 x2:5 y2:4 },
        WallRectangle { x1:7 y1:2 x2:12 y2:4 },
        WallRectangle { x1:17 y1:2 x2:22 y2:4 },
        WallRectangle { x1:24 y1:2 x2:27 y2:4 },
        WallRectangle { x1:2 y1:6 x2:5 y2:7 },
  
        WallRectangle { x1:14 y1:6.2 x2:15 y2:10 },
        WallRectangle { x1:10 y1:6 x2:19 y2:7 },
        WallBlackLine { x1:14 y1:7 x2:15 y2:7 },
  
        WallRectangle { x1:7.5 y1:9 x2:12 y2:10 },
        WallRectangle { x1:7 y1:6 x2:8 y2:13 },
        WallBlackLine { x1:8 y1:9 x2:8 y2:10 },
  
        WallRectangle { x1:17 y1:9 x2:21.5 y2:10 },
        WallRectangle { x1:21 y1:6 x2:22 y2:13 },
        WallBlackLine { x1:21 y1:9 x2:21 y2:10 },
  
        WallRectangle { x1:24 y1:6 x2:27 y2:7 },
  
        WallRectangle { x1:-1 y1:9 x2:5 y2:13 },
        WallRectangle { x1:24 y1:9 x2:MazeData.GRID_SIZE + 1 y2:13 },
        WallBlackLine { x1:0 y1:13 x2:0 y2:15  },
        WallBlackLine { x1:MazeData.GRID_SIZE y1:13 x2:MazeData.GRID_SIZE y2:15},
  
        <span class="linecomment">//cage and the gate</span>
        WallRectangle { x1:10 y1:12 x2:19 y2:17 },
        WallRectangle { x1:10.5 y1:12.5 x2:18.5 y2:16.5 },
        Rectangle {
           <span class="category2">x</span>: MazeData.calcGridX(13)
           <span class="category2">width</span>: MazeData.GRID_GAP * 3
           <span class="category2">y</span>: MazeData.calcGridY(12)
           <span class="category2">height</span>: MazeData.GRID_GAP / 2
           stroke: <span class="category2">Color</span>.GREY
           fill: <span class="category2">Color</span>.GREY
         },
  
        WallRectangle { x1:7.5 y1:19 x2:12 y2:20 },
        WallRectangle { x1:7 y1:15 x2:8 y2:23 },
        WallBlackLine { x1:8 y1:19 x2:8 y2:20 },
  
        WallRectangle { x1:17 y1:19 x2:21.5 y2:20 },
        WallRectangle { x1:21 y1:15 x2:22 y2:23 },
        WallBlackLine { x1:21 y1:19 x2:21 y2:20 },
  
        WallRectangle { x1:14 y1:19 x2:15 y2:27 },
        WallRectangle { x1:10 y1:22 x2:19 y2:23 },
        WallBlackLine { x1:14 y1:22 x2:15 y2:22 },
        WallBlackLine { x1:14 y1:23 x2:15 y2:23 },
  
        WallRectangle { x1:2 y1:25 x2:5 y2:27 },
        WallRectangle { x1:17 y1:25 x2:22 y2:27 },
  
        WallRectangle { x1:7 y1:25 x2:12 y2:27 },
        WallRectangle { x1:24 y1:25 x2:27 y2:27 },
  
        WallRectangle { x1:-1 y1:15 x2:5 y2:17 },
        WallRectangle { x1:4 y1:19 x2:5 y2:23 },
        WallRectangle { x1:2 y1:19 x2:4.5 y2:20 },
        WallBlackRectangle { x1:4 y1:19.05 x2:5 y2:20.2 },
        WallRectangle { x1:-1 y1:22 x2:2 y2:23 },
  
        WallRectangle { x1:24 y1:15 x2:MazeData.GRID_SIZE + 1 y2:17 },
        WallRectangle { x1:24 y1:19 x2:25 y2:23 },
        WallRectangle { x1:24.5 y1:19 x2:27 y2:20 },
        WallBlackRectangle { x1:24 y1:19.05 x2:25 y2:20.2 },
        WallRectangle { x1:27 y1:22 x2:MazeData.GRID_SIZE + 1 y2:23 },
  
        WallBlackRectangle { x1:-2 y1:8 x2:0 y2:MazeData.GRID_SIZE },
        WallBlackRectangle {
            x1:MazeData.GRID_SIZE
            y1:8
            x2:MazeData.GRID_SIZE + 2
            y2:MazeData.GRID_SIZE
         },
  
        Rectangle {
           <span class="category2">x</span>: MazeData.calcGridX(-0.5)
           <span class="category2">y</span>: MazeData.calcGridY(-0.5)
           <span class="category2">width</span>: (MazeData.GRID_SIZE + 1) * MazeData.GRID_GAP
           <span class="category2">height</span>: (MazeData.GRID_SIZE + 1) * MazeData.GRID_GAP
           strokeWidth: MazeData.GRID_STROKE
           stroke: <span class="category2">Color</span>.BLUE
           fill: <span class="category1">null</span>
           arcWidth: 12
           arcHeight: 12
         },
        Line {
           startX: MazeData.calcGridX(-0.5)
           endX: MazeData.calcGridX(-0.5)
           startY: MazeData.calcGridY(13)
           endY: MazeData.calcGridY(15)
           stroke: <span class="category2">Color</span>.BLACK
           strokeWidth: MazeData.GRID_STROKE + 1
         },
        Line {
           startX: MazeData.calcGridX(MazeData.GRID_SIZE + 0.5)
           endX: MazeData.calcGridX(MazeData.GRID_SIZE + 0.5)
           startY: MazeData.calcGridY(13)
           endY: MazeData.calcGridY(15)
           stroke: <span class="category2">Color</span>.BLACK
           strokeWidth: MazeData.GRID_STROKE + 1
         },
        Line {
           startX: MazeData.calcGridX(-0.5)
           endX: MazeData.calcGridX(0)
           startY: MazeData.calcGridY(13)
           endY: MazeData.calcGridY(13)
           stroke: <span class="category2">Color</span>.BLUE
           strokeWidth: MazeData.GRID_STROKE
         },
        Line {
           startX: MazeData.calcGridX(-0.5)
           endX: MazeData.calcGridX(0)
           startY: MazeData.calcGridY(15)
           endY: MazeData.calcGridY(15)
           stroke: <span class="category2">Color</span>.BLUE
           strokeWidth: MazeData.GRID_STROKE
         },
        Line {
           startX: MazeData.calcGridX(MazeData.GRID_SIZE + 0.5)
           endX: MazeData.calcGridX(MazeData.GRID_SIZE)
           startY: MazeData.calcGridY(13)
           endY: MazeData.calcGridY(13)
           stroke: <span class="category2">Color</span>.BLUE
           strokeWidth: MazeData.GRID_STROKE
         },
        Line {
           startX: MazeData.calcGridX(MazeData.GRID_SIZE + 0.5)
           endX: MazeData.calcGridX(MazeData.GRID_SIZE)
           startY: MazeData.calcGridY(15)
           endY: MazeData.calcGridY(15)
           stroke: <span class="category2">Color</span>.BLUE
           strokeWidth: MazeData.GRID_STROKE
         },
        Text {
           <span class="category2">font</span>: Font {
                  <span class="category2">size</span>: 20
                  }
           <span class="category2">x</span>: MazeData.calcGridX(0), 
           <span class="category2">y</span>: MazeData.calcGridY(MazeData.GRID_SIZE + 2)
           content: bind "<span class="quote">SCORES: {pacMan.scores} </span>"
           fill: <span class="category2">Color</span>.YELLOW
         },
        scoreText,
        dyingPacMan,
       livesImage,
        gameResultText,
        Text { 
           <span class="category2">font</span>: Font { <span class="category2">size</span>: 20
                        }
           <span class="category2">x</span>: MazeData.calcGridX(22)
           <span class="category2">y</span>: MazeData.calcGridY(MazeData.GRID_SIZE + 2)
           content: bind "<span class="quote">LEVEL: {level}</span>"
           fill: <span class="category2">Color</span>.YELLOW
         },
  
      ]
    }; <span class="linecomment">// end Group</span>
 
   <span class="linecomment">// put dots into the maze</span>
   postinit {
      putDotHorizontally(2,13,1);
      putDotHorizontally(16,27,1);
      putDotHorizontally(2,27,5);
      putDotHorizontally(2,27,28);
  
      putDotHorizontally(2,13,24);
      putDotHorizontally(16,27,24);
  
      putDotHorizontally(2,5,8);
      putDotHorizontally(9,13,8);
      putDotHorizontally(16,20,8);
      putDotHorizontally(24,27,8);
  
      putDotHorizontally(2,5,18);
      putDotHorizontally(9,13,21);
      putDotHorizontally(16,20,21);
      putDotHorizontally(24,27,18);
  
      putDotHorizontally(2,3,21);
      putDotHorizontally(26,27,21);
  
      putDotVertically(1,1,8);
      putDotVertically(1,18,21);
      putDotVertically(1,24,28);
  
      putDotVertically(28,1,8);
      putDotVertically(28,18,21);
      putDotVertically(28,24,28);
  
      putDotVertically(6,2,27);
      putDotVertically(23,2,27);
  
      putDotVertically(3,22,23);
      putDotVertically(9,22,23);
      putDotVertically(20,22,23);
      putDotVertically(26,22,23);
  
      putDotVertically(13,25,27);
      putDotVertically(16,25,27);
  
      putDotVertically(9,6,7);
      putDotVertically(20,6,7);
  
      putDotVertically(13,2,4);
      putDotVertically(16,2,4);
  
      insert pacMan into group.content;
  
      insert ghosts into group.content;
  
      insert WallBlackRectangle{ x1:-3, y1:13, x2:0, y2:15} into group.content;
      insert WallBlackRectangle{ x1:29, y1:13, x2:31, y2:15} into group.content;
  
      insert messageBox into group.content;
    }
 
   <span class="category1">public</span> override <span class="category1">function</span> create(): Node {
      <span class="category1">return</span> group;
    } <span class="linecomment">// end create()</span>
 
   <span class="category1">public</span> override <span class="category1">var</span> onKeyPressed = <span class="category1">function</span> ( e: KeyEvent ) : Void {
      <span class="linecomment">// wait for the player's keyboard input to start the game</span>
      <span class="category1">if</span> ( waitForStart ) {
         waitForStart = <span class="category1">false</span>;
         startNewGame();
         <span class="category1">return</span>;
       }
  
      <span class="category1">if</span> ( e.code == KeyCode.VK_DOWN )
        pacMan.setKeyboardBuffer( pacMan.MOVE_DOWN )
      <span class="category1">else</span>
        <span class="category1">if</span> ( e.code == KeyCode.VK_UP )
          pacMan.setKeyboardBuffer( pacMan.MOVE_UP )
        <span class="category1">else</span>
          <span class="category1">if</span> ( e.code == KeyCode.VK_RIGHT )
            pacMan.setKeyboardBuffer( pacMan.MOVE_RIGHT )
          <span class="category1">else</span>
            <span class="category1">if</span> ( e.code == KeyCode.VK_LEFT )
              pacMan.setKeyboardBuffer( pacMan.MOVE_LEFT );
    }
 
 
   <span class="linecomment">// create a Dot GUI object</span>
   <span class="category1">public</span> <span class="category1">function</span> createDot( x1: <span class="category2">Number</span>,  y1:<span class="category2">Number</span>, <span class="category2">type</span>:Integer ): Dot {
      <span class="category1">var</span> d = Dot {
         <span class="category2">x</span>: MazeData.calcGridX(x1)
         <span class="category2">y</span>: MazeData.calcGridY(y1)
         dotType: <span class="category2">type</span>
         <span class="category2">visible</span>: <span class="category1">true</span>
         }
  
      <span class="category1">if</span> ( d.dotType == MazeData.MAGIC_DOT )
        d.playTimeline();
  
      <span class="linecomment">// set the dot type in data model</span>
      MazeData.<span class="category2">setData</span>( x1, y1, <span class="category2">type</span> );
  
      <span class="linecomment">// set dot reference</span>
      MazeData.setDot( x1, y1, d );
  
      <span class="category1">return</span> d;
    }
 
   <span class="linecomment">// put dots into the maze as a horizontal line</span>
   <span class="category1">public</span> <span class="category1">function</span> putDotHorizontally(x1: Integer, x2: Integer, <span class="category2">y</span>: <span class="category2">Number</span> ) {
  
      <span class="category1">var</span> dots =
      <span class="category1">for</span> ( <span class="category2">x</span> <span class="category1">in</span> [ x1..x2] )
      <span class="category1">if</span> ( MazeData.<span class="category2">getData</span>(<span class="category2">x</span>,<span class="category2">y</span>) == MazeData.EMPTY ) {
         <span class="category1">var</span> dotType: Integer;
   
         <span class="category1">if</span> ( (<span class="category2">x</span> == 28 <span class="category1">or</span> <span class="category2">x</span> == 1) <span class="category1">and</span> (<span class="category2">y</span> == 3 <span class="category1">or</span> <span class="category2">y</span> == 26) )
           dotType = MazeData.MAGIC_DOT
         <span class="category1">else</span>
           dotType = MazeData.NORMAL_DOT;
   
         createDot( <span class="category2">x</span>, <span class="category2">y</span>, dotType )
       }
      <span class="category1">else</span>   [] ;
  
      insert dots into group.content;
    }
 
   <span class="linecomment">// put dots into the maze as a vertical line</span>
   <span class="category1">public</span> <span class="category1">function</span> putDotVertically(<span class="category2">x</span>: Integer, y1: Integer, y2: <span class="category2">Number</span> ) {
  
      <span class="category1">var</span> dots =
      <span class="category1">for</span> ( <span class="category2">y</span> <span class="category1">in</span> [ y1..y2] )
      <span class="category1">if</span> ( MazeData.<span class="category2">getData</span>(<span class="category2">x</span>,<span class="category2">y</span>) == MazeData.EMPTY ) {
         <span class="category1">var</span> dotType: Integer;
   
         <span class="category1">if</span> ( (<span class="category2">x</span> == 28 <span class="category1">or</span> <span class="category2">x</span> == 1) <span class="category1">and</span> (<span class="category2">y</span> == 3 <span class="category1">or</span> <span class="category2">y</span> == 26) )
           dotType = MazeData.MAGIC_DOT
         <span class="category1">else</span>
           dotType = MazeData.NORMAL_DOT;
   
         createDot( <span class="category2">x</span>, <span class="category2">y</span>, dotType )
       }
      <span class="category1">else</span>  [];
  
      insert dots into group.content;
    }
 
   <span class="category1">public</span> <span class="category1">function</span> makeGhostsHollow() {
   
      ghostEatenCount = 0;
  
      <span class="category1">for</span> ( g <span class="category1">in</span> ghosts )
        g.changeToHollowGhost();
    }
 
   <span class="linecomment">// determine if pacman meets a ghost</span>
   <span class="category1">public</span> <span class="category1">function</span> hasMet(g:Ghost): <span class="category2">Boolean</span> {
  
      def distanceThreshold = 22;
  
      <span class="category1">var</span> x1 = g.imageX;
      <span class="category1">var</span> x2 = pacMan.imageX;
  
      <span class="category1">var</span> diffX = <span class="category2">Math</span>.<span class="category2">abs</span>(x1-x2);
  
      <span class="category1">if</span> ( diffX &gt;= distanceThreshold ) <span class="category1">return</span> <span class="category1">false</span>;
  
      <span class="category1">var</span> y1 = g.imageY;
      <span class="category1">var</span> y2 = pacMan.imageY;
      <span class="category1">var</span> diffY = <span class="category2">Math</span>.<span class="category2">abs</span>(y1-y2);
  
      <span class="category1">if</span> ( diffY &gt;= distanceThreshold ) <span class="category1">return</span> <span class="category1">false</span>;
  
      <span class="linecomment">// calculate the distance to see if pacman touches the ghost</span>
      <span class="category1">if</span> ( diffY*diffY + diffX*diffX &lt;= distanceThreshold*distanceThreshold )
        <span class="category1">return</span> <span class="category1">true</span>;
  
      <span class="category1">return</span> <span class="category1">false</span>;
    }
 
   <span class="category1">public</span> <span class="category1">function</span> pacManMeetsGhosts() {
  
      <span class="category1">for</span> ( g <span class="category1">in</span> ghosts )
        <span class="category1">if</span> ( hasMet(g) )
          <span class="category1">if</span> ( g.isHollow ) {
             pacManEatsGhost(g);
           }
          <span class="category1">else</span> {
             <span class="category1">for</span> ( ghost <span class="category1">in</span> ghosts )
               ghost.<span class="category2">stop</span>();
   
             pacMan.<span class="category2">stop</span>();
   
             dyingPacMan.<span class="category2">startAnimation</span>(pacMan.imageX, pacMan.imageY);
             <span class="category1">break</span>;
           }
    }
 
   <span class="category1">public</span> <span class="category1">function</span> pacManEatsGhost(g: Ghost) {
        
      ghostEatenCount++;
  
      <span class="category1">var</span> s = 1;
      <span class="category1">for</span> ( i <span class="category1">in</span> [1..ghostEatenCount] ) s = s + s;
  
      pacMan.scores += s*100;
      <span class="category1">if</span> ( addLifeFlag <span class="category1">and</span> pacMan.scores &gt;= 10000 ) {
         addLife();
       }
  
      <span class="category1">var</span> st = scoreText[ghostEatenCount-1];
      st.<span class="category2">x</span> = g.imageX - 10;
      st.<span class="category2">y</span> = g.imageY;
  
      g.<span class="category2">stop</span>();
      g.resetStatus();
      g.trapCounter = -10;
  
      st.showText();
    
    }
 
   <span class="linecomment">// reset status and start a new game</span>
   <span class="category1">public</span> <span class="category1">function</span> startNewGame() {
  
      messageBox.<span class="category2">visible</span> = <span class="category1">false</span>;
      pacMan.resetStatus();
  
      gameResultText.<span class="category2">visible</span> = <span class="category1">false</span>;
  
      <span class="category1">if</span> ( lastGameResult == <span class="category1">false</span> ) {
         level = 1;
         addLifeFlag = <span class="category1">true</span>;
         pacMan.scores = 0;
         pacMan.dotEatenCount = 0;
   
         livesCount = 2;
       }
      <span class="category1">else</span> { 
         lastGameResult = <span class="category1">false</span>;
         level ++;
       }
  
      <span class="category1">for</span> ( <span class="category2">x</span> <span class="category1">in</span> [1..MazeData.GRID_SIZE] )
        <span class="category1">for</span> ( <span class="category2">y</span> <span class="category1">in</span> [1..MazeData.GRID_SIZE] ) {
           <span class="category1">var</span> dot : Dot = MazeData.getDot( <span class="category2">x</span>, <span class="category2">y</span> ) as Dot ;
   
           <span class="category1">if</span> ( dot != <span class="category1">null</span> <span class="category1">and</span> <span class="category1">not</span> dot.<span class="category2">visible</span> ) 
             dot.<span class="category2">visible</span> = <span class="category1">true</span>;
         }
  
      <span class="category1">for</span> ( g <span class="category1">in</span> ghosts ) {
         g.resetStatus();
       }
    }
 
   <span class="linecomment">// reset status and start a new level</span>
   <span class="category1">public</span> <span class="category1">function</span> startNewLevel() {
  
      lastGameResult = <span class="category1">true</span>;
  
      pacMan.<span class="category2">hide</span>();
      pacMan.dotEatenCount = 0;
  
      <span class="category1">for</span> ( g <span class="category1">in</span> ghosts ) {
         g.<span class="category2">hide</span>();
       }
  
      flashingCount = 0;
      flashingTimeline.playFromStart();
    }
 
   <span class="linecomment">// reset status and start a new life</span>
   <span class="category1">public</span> <span class="category1">function</span> startNewLife() {
  
      <span class="linecomment">// reduce a life of Pac-Man</span>
      <span class="category1">if</span> ( livesCount &gt; 0 ) {
         livesCount--;
       }
      <span class="category1">else</span> {
         lastGameResult = <span class="category1">false</span>;
         flashingCount = 0;
         flashingTimeline.playFromStart();
         <span class="category1">return</span>;
       }
  
      pacMan.resetStatus();
  
      <span class="category1">for</span> ( g <span class="category1">in</span> ghosts ) {
         g.resetStatus();
       }
    }
 
   <span class="category1">public</span> <span class="category1">function</span> addLife():Void {
  
      <span class="category1">if</span> ( addLifeFlag ) {
         livesCount ++;
         addLifeFlag = <span class="category1">false</span>;
       }
    }
}</pre>
</code>

</div></div> 


<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre> 
<span class="blockcomment">/*
 * PacMan.fx
 *
 * Created on 2009-1-1, 11:50:58
 */</span>

package pacman;

<span class="category1">import</span> javafx.scene.CustomNode;
<span class="category1">import</span> javafx.scene.image.Image;
<span class="category1">import</span> javafx.scene.image.ImageView;
<span class="category1">import</span> javafx.scene.Node;
<span class="category1">import</span> javafx.scene.transform.Rotate;
<span class="category1">import</span> pacman.MazeData;
<span class="category1">import</span> pacman.MovingObject;

<span class="blockcomment">/**
 * @author Henry Zhang
 */</span>

<span class="category1">public</span> <span class="category1">class</span> PacMan <span class="category1">extends</span> CustomNode, MovingObject {
 
   <span class="category1">public</span> <span class="category1">var</span> defaultImage: Image = Image {
      <span class="category2">url</span>: "<span class="quote">{__DIR__}images/left1.png</span>"
    };
 
   <span class="linecomment">// images for animation</span>
   def images = [
     defaultImage,
     Image {
        <span class="category2">url</span>: "<span class="quote">{__DIR__}images/left2.png</span>"
      },
     defaultImage,
     Image {
        <span class="category2">url</span>: "<span class="quote">{__DIR__}images/round.png</span>"
      }
   ];
 
   <span class="linecomment">// the number of dots eaten</span>
   <span class="category1">public</span> <span class="category1">var</span> dotEatenCount : Integer = 0;
 
   <span class="linecomment">// scores of the game</span>
   <span class="category1">public</span> <span class="category1">var</span> scores: Integer = 0;
     
   <span class="linecomment">// angles of rotating the images</span>
   def rotationDegree = [0, 90, 180, 270];
 
   <span class="linecomment">// GUI image of the man</span>
   <span class="category1">var</span> pacmanImage : ImageView = ImageView {
      <span class="category2">x</span>: bind imageX - 13
      <span class="category2">y</span>: bind imageY - 13
      image: bind images[currentImage]
      transforms: Rotate {
         angle: bind rotationDegree[currentDirection]
         pivotX: bind imageX
         pivotY: bind imageY
         }
     }
 
   <span class="linecomment">// buffer to keep the keyboard input</span>
   <span class="category1">var</span> keyboardBuffer: Integer = -1;
 
   <span class="linecomment">// current direction of Pacman</span>
   <span class="category1">var</span> currentDirection: Integer = MOVE_LEFT;
 
   postinit {
      imageX = MazeData.calcGridX(<span class="category2">x</span>);
      imageY = MazeData.calcGridX(<span class="category2">y</span>);
      
      xDirection = -1;
      yDirection = 0;
  
    }
 
 
   <span class="category1">public</span> override <span class="category1">function</span> create(): Node {
      <span class="category1">return</span> pacmanImage;
    }
 
   <span class="linecomment">// moving horizontally</span>
   <span class="category1">public</span> <span class="category1">function</span> moveHorizontally() {
  
      moveCounter++;
  
      <span class="category1">if</span> ( moveCounter &lt; ANIMATION_STEP ) {
         imageX += xDirection * MOVE_SPEED;
       }
      <span class="category1">else</span> {
         moveCounter = 0;
         <span class="category2">x</span> += xDirection;
         
         imageX = MazeData.calcGridX(<span class="category2">x</span>);
   
         <span class="linecomment">// the X coordinate of the next point in the grid</span>
         <span class="category1">var</span> nextX = xDirection + <span class="category2">x</span>;
   
         <span class="category1">if</span> ( <span class="category2">y</span> == 14 <span class="category1">and</span> ( nextX &lt;= 1 <span class="category1">or</span> nextX &gt;= 28) ) {
            <span class="category1">if</span> ( nextX &lt; - 1 <span class="category1">and</span> xDirection &lt; 0 ) {
               <span class="category2">x</span> = MazeData.GRID_SIZE;
               imageX = MazeData.calcGridX(<span class="category2">x</span>);
             }
            <span class="category1">else</span>
            <span class="category1">if</span> ( nextX &gt; 30 <span class="category1">and</span> xDirection &gt; 0) {
               <span class="category2">x</span> = 0;
               imageX = MazeData.calcGridX(<span class="category2">x</span>);
             }
          }
         <span class="category1">else</span> <span class="linecomment">// check if the character hits a wall</span>
         <span class="category1">if</span> ( MazeData.<span class="category2">getData</span>(nextX, <span class="category2">y</span>) == MazeData.BLOCK ) {
            state = STOP;
          }
       }
    }
 
   <span class="linecomment">// moving vertically</span>
   <span class="category1">public</span> <span class="category1">function</span> moveVertically() {
        
      moveCounter++;
  
      <span class="category1">if</span> ( moveCounter &lt; ANIMATION_STEP ) {
         imageY += yDirection * MOVE_SPEED;
       }
      <span class="category1">else</span> {
         moveCounter = 0;
         <span class="category2">y</span> += yDirection;
         imageY = MazeData.calcGridX(<span class="category2">y</span>);
   
         <span class="linecomment">// the Y coordinate of the next point in the grid</span>
         <span class="category1">var</span> nextY = yDirection + <span class="category2">y</span>;
   
         <span class="linecomment">// check if the character hits a wall</span>
         <span class="category1">if</span> ( MazeData.<span class="category2">getData</span>(<span class="category2">x</span>, nextY) == MazeData.BLOCK ) {
            state = STOP;
          }
       }
    }
 
   <span class="linecomment">// turn pac-man to the right</span>
   <span class="category1">public</span> <span class="category1">function</span> moveRight(): Void {
  
      <span class="category1">if</span> ( currentDirection == MOVE_RIGHT )  <span class="category1">return</span>;
  
      <span class="category1">var</span> nextX = <span class="category2">x</span> + 1;
  
      <span class="category1">if</span> ( nextX &gt;= MazeData.GRID_SIZE)  <span class="category1">return</span>;
  
      <span class="category1">if</span> ( MazeData.<span class="category2">getData</span>(nextX, <span class="category2">y</span>) == MazeData.BLOCK )   <span class="category1">return</span>;
  
      xDirection = 1;
      yDirection = 0;
  
      keyboardBuffer = -1;
      currentDirection = MOVE_RIGHT;
  
      state = MOVING;
    }
 
   <span class="linecomment">// turn pac-man to the left</span>
   <span class="category1">public</span> <span class="category1">function</span> moveLeft(): Void {
  
      <span class="category1">if</span> ( currentDirection == MOVE_LEFT )   <span class="category1">return</span>;
  
      <span class="category1">var</span> nextX = <span class="category2">x</span> - 1;
  
      <span class="category1">if</span> ( nextX &lt;= 1)  <span class="category1">return</span>;
  
      <span class="category1">if</span> ( MazeData.<span class="category2">getData</span>(nextX, <span class="category2">y</span>) == MazeData.BLOCK )   <span class="category1">return</span>;
  
      xDirection = -1;
      yDirection = 0;
  
      keyboardBuffer = -1;
      currentDirection = MOVE_LEFT;
  
      state = MOVING;
    }
 
   <span class="linecomment">// turn pac-man going up</span>
   <span class="category1">public</span> <span class="category1">function</span> moveUp(): Void {
  
      <span class="category1">if</span> ( currentDirection == MOVE_UP )  <span class="category1">return</span>;
  
      <span class="category1">var</span> nextY = <span class="category2">y</span> - 1;
  
      <span class="category1">if</span> ( nextY &lt;= 1)   <span class="category1">return</span>;
  
      <span class="category1">if</span> ( MazeData.<span class="category2">getData</span>(<span class="category2">x</span>,nextY) == MazeData.BLOCK )  <span class="category1">return</span>;
  
      xDirection = 0;
      yDirection = -1;
  
      keyboardBuffer = -1;
      currentDirection = MOVE_UP;
  
      state = MOVING;
    }
 
   <span class="linecomment">// turn pac-man going down</span>
   <span class="category1">public</span> <span class="category1">function</span> moveDown(): Void {
  
      <span class="category1">if</span> ( currentDirection == MOVE_DOWN ) <span class="category1">return</span>;
  
      <span class="category1">var</span> nextY = <span class="category2">y</span> + 1;
  
      <span class="category1">if</span> ( nextY &gt;= MazeData.GRID_SIZE )  <span class="category1">return</span>;
  
      <span class="category1">if</span> ( MazeData.<span class="category2">getData</span>(<span class="category2">x</span>,nextY) == MazeData.BLOCK )  <span class="category1">return</span>;
  
      xDirection = 0;
      yDirection = 1;
  
      keyboardBuffer = -1;
      currentDirection = MOVE_DOWN;
  
      state = MOVING;
    }
 
   <span class="linecomment">// handle keyboard input</span>
   <span class="category1">public</span> <span class="category1">function</span> handleKeyboardInput(): Void {
      <span class="category1">if</span> ( keyboardBuffer &lt; 0)
      <span class="category1">return</span>;
  
      <span class="category1">if</span> ( keyboardBuffer == MOVE_LEFT )
        moveLeft()
      <span class="category1">else</span>
        <span class="category1">if</span> ( keyboardBuffer == MOVE_RIGHT )
          moveRight()
        <span class="category1">else</span>
          <span class="category1">if</span> ( keyboardBuffer == MOVE_UP )
            moveUp()
          <span class="category1">else</span>
            <span class="category1">if</span> ( keyboardBuffer == MOVE_DOWN )
              moveDown();
    }
 
   <span class="category1">public</span> <span class="category1">function</span> setKeyboardBuffer( k: Integer): Void {
      keyboardBuffer = k;
    }
 
   <span class="linecomment">// update scores if a dot is eaten</span>
   <span class="category1">public</span> <span class="category1">function</span> updateScores() : Void {
      <span class="category1">if</span> ( <span class="category2">y</span> != 14 <span class="category1">or</span> ( <span class="category2">x</span> &gt; 0 <span class="category1">and</span> <span class="category2">x</span> &lt; MazeData.GRID_SIZE ) ) {
         <span class="category1">var</span> dot : Dot = MazeData.getDot( <span class="category2">x</span>, <span class="category2">y</span> ) as Dot ;
   
         <span class="category1">if</span> ( dot != <span class="category1">null</span> <span class="category1">and</span> dot.<span class="category2">visible</span> ) {
            scores += 10;
            dot.<span class="category2">visible</span> = <span class="category1">false</span>;
            dotEatenCount ++;
    
            <span class="category1">if</span> ( scores &gt;= 10000 ) {
               maze.addLife();
             }
    
            <span class="category1">if</span> ( dot.dotType == MazeData.MAGIC_DOT ) {
               maze.makeGhostsHollow();
             }
    
            <span class="linecomment">// check if the player wins and should start a new level</span>
            <span class="category1">if</span> ( dotEatenCount &gt;= MazeData.DOT_TOTAL )
              maze.startNewLevel();
          }
       }
    }
 
   <span class="category1">public</span> <span class="category1">function</span> <span class="category2">hide</span>() {
      <span class="category2">visible</span>=<span class="category1">false</span>;
      timeline.<span class="category2">stop</span>();
    }
 
   <span class="linecomment">// handle animation of one tick</span>
   <span class="category1">public</span> override <span class="category1">function</span> moveOneStep() {
  
      <span class="linecomment">// handle keyboard input only when pac-man is at a point of the grid</span>
      <span class="category1">if</span> ( currentImage == 0 )
        handleKeyboardInput();
  
      <span class="category1">if</span> ( state == MOVING) {
         <span class="category1">if</span> ( xDirection != 0 )
           moveHorizontally();
   
         <span class="category1">if</span> ( yDirection != 0 )
           moveVertically();
   
         <span class="linecomment">// switch to the image of the next frame</span>
         <span class="category1">if</span> ( currentImage &lt; ANIMATION_STEP - 1  )
           currentImage++
         <span class="category1">else</span> {
            currentImage=0;
            updateScores();
          }
       }
  
      maze.pacManMeetsGhosts();    
    }
 
   <span class="linecomment">// place Pac-Man at the startup position for a new game</span>
   <span class="category1">public</span> <span class="category1">function</span> resetStatus() {
      state = MOVING;
      currentDirection = MOVE_LEFT;
      xDirection = -1;
      yDirection = 0;
      
      keyboardBuffer = -1;
      currentImage = 0;
      moveCounter = 0;
  
      <span class="category2">x</span>=15;
      <span class="category2">y</span>=18;
  
      imageX = MazeData.calcGridX(<span class="category2">x</span>);
      imageY = MazeData.calcGridY(<span class="category2">y</span>);
  
      <span class="category2">visible</span> = <span class="category1">true</span>;
      <span class="category2">start</span>();
    }
}</pre>
</code>

</div></div> 


<p>You can click on the below picture and play the completed game now. As we mentioned in previous article,
the ghosts are moving in a random fashion. This makes the game less challenging. 
In the next article, we will discuss
a better algorithm of the ghost's moving behavior. 
</p>

<p><a href="http://www.javafxgame.com/v9.5/pacman.jnlp">
<img src="http://www.insideria.com/upload/2009/05/maze11.png" border=0><br><br>
<img src="http://www.insideria.com/upload/2009/05/launch.gif" border=0></a>
</p>


<p><a href="http://www.insideria.com/upload/2009/05/javafxsource4.zip">Download Source Code</a></p>
]]>
      
    </content>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36369-comment:2061807</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36369" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html#comment-2061807" />
    <title>Comment from sinh on 2009-06-05</title>
    <author>
        <name>sinh</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>It not work JavaFx 1.2.<br />
It corresponds to JavaFx. Ver.1.2</p>]]>
    </content>
    <published>2009-06-05T08:46:44Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36369-comment:2061811</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36369" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html#comment-2061811" />
    <title>Comment from Patrick Webster on 2009-06-05</title>
    <author>
        <name>Patrick Webster</name>
        <uri>http://patrickwebster.blogspot.com/</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://patrickwebster.blogspot.com/">
        <![CDATA[<p>To get Pac-Man working with JavaFX 1.2, make the following 2 changes:</p>

<p>1. In MovingObject.fx line 18, change the declaration of the MovingObject class from "abstract" to "mixin". So change this:</p>

<p>public abstract class MovingObject {</p>

<p>to this:</p>

<p>public mixin class MovingObject {</p>

<p><br />
2. The code will now compile, but still won't handle key events. To fix the key inputs, in Maze.fx line 484, add a call to requestFocus(). So change this:</p>

<p>  public override function create(): Node {<br />
    return group;<br />
  } // end create()</p>

<p>to this:</p>

<p>  public override function create(): Node {<br />
    requestFocus();<br />
    return group;<br />
  } // end create()</p>

<p>That is what worked for me using NetBeans 6.5.1 on Mac OS X 32-bit Intel with J2SE 5.0.</p>]]>
    </content>
    <published>2009-06-05T10:41:11Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36369-comment:2061858</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36369" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html#comment-2061858" />
    <title>Comment from Henry Zhang on 2009-06-05</title>
    <author>
        <name>Henry Zhang</name>
        <uri>http://www.javafxgame.com</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://www.javafxgame.com">
        <![CDATA[<p>The code in the articles are for JavaFX 1.0/1.1. So it won't work for JavaFX 1.2 without modification.  JavaFX 1.2 removed multi inheritance so we need to use "mixin" instead. </p>

<p>Patrick, thanks for the quick fix. </p>]]>
    </content>
    <published>2009-06-06T03:42:55Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36369-comment:2070846</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36369" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html#comment-2070846" />
    <title>Comment from Ryan on 2009-08-21</title>
    <author>
        <name>Ryan</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>The code looks pretty cool. Being a video game lover, I have played so much pac man since my childhood. Now, I work for a <a href="http://hintcafe.com">free web dating</a> site but sometime do squeeze in time to play tetris now and then.</p>

<p>I never thought of developing the game from scratch though, but involved in javascript UI, the animation ideas you have used in dying pacman can be used in moving, sliding, wiping divs around too.</p>]]>
    </content>
    <published>2009-08-21T22:02:32Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36369-comment:2071110</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36369" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html#comment-2071110" />
    <title>Comment from anhela on 2009-08-27</title>
    <author>
        <name>anhela</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>Very nice review! I searched for some tutorials at <a href="http://www.picktorrent.com">http://www.picktorrent.com</a> , but found nothing informative, your article helped me much!</p>]]>
    </content>
    <published>2009-08-27T09:07:52Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36369-comment:2089156</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36369" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html#comment-2089156" />
    <title>Comment from Crash Cages on 2009-09-08</title>
    <author>
        <name>Crash Cages</name>
        <uri>http://fatbikez.com/body-work/crash-cages.html</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://fatbikez.com/body-work/crash-cages.html">
        <![CDATA[<p>very cool but the question is why you want to do this rather then code a newer game ?</p>]]>
    </content>
    <published>2009-09-08T22:24:10Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36369-comment:2089157</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36369" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html#comment-2089157" />
    <title>Comment from johny on 2009-09-08</title>
    <author>
        <name>johny</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>I really like this alot but you need to be careful and have your  <a href="http://fatbikez.com/body-work/crash-cages.html"> Crash Cage </a> installed correctly </p>]]>
    </content>
    <published>2009-09-08T22:27:35Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36369-comment:2089881</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36369" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html#comment-2089881" />
    <title>Comment from Enterprise Managed Services on 2009-09-09</title>
    <author>
        <name>Enterprise Managed Services</name>
        <uri>http://www.enterprisemanagedservices.com/</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://www.enterprisemanagedservices.com/">
        <![CDATA[<p>I love PacMan, it's incredible how now-a-days it's still a fun game to play despite all those highly advanced 3D games!</p>

<p>Bookmarked :)</p>]]>
    </content>
    <published>2009-09-09T10:33:27Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36369-comment:2091497</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36369" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html#comment-2091497" />
    <title>Comment from Oyun on 2009-09-10</title>
    <author>
        <name>Oyun</name>
        <uri>http://oyun-turkiye.blogspot.com</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://oyun-turkiye.blogspot.com">
        <![CDATA[<p>really good and useful tutorial.very thanks</p>]]>
    </content>
    <published>2009-09-10T11:56:17Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36369-comment:2091908</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36369" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html#comment-2091908" />
    <title>Comment from John Williams on 2009-09-10</title>
    <author>
        <name>John Williams</name>
        <uri>http://www.acrobatusers.com/users/johnwilliams451</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://www.acrobatusers.com/users/johnwilliams451">
        <![CDATA[<p>This brings back memories of when I used to program back in the 1980s but sadly my programming skills are now lacking. </p>

<p>Pacman - one of the all time best games that always had that intensity and excitement. </p>]]>
    </content>
    <published>2009-09-10T17:06:41Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36369-comment:2101445</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36369" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html#comment-2101445" />
    <title>Comment from John on 2009-09-16</title>
    <author>
        <name>John</name>
        <uri>http://prolinehockeypicks.com</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://prolinehockeypicks.com">
        <![CDATA[<p>I can recall playing this game on the old Commodore Vic20. How many can remember that? </p>

<p><a href="http://prolinehockeypicks.com">Hockey Picks</a></p>]]>
    </content>
    <published>2009-09-16T22:49:28Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36369-comment:2102590</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36369" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html#comment-2102590" />
    <title>Comment from Sott on 2009-09-17</title>
    <author>
        <name>Sott</name>
        <uri>http://www.movies.ie/movies</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://www.movies.ie/movies">
        <![CDATA[<p>Great tutorial. Recently rediscovered PacMan thru an Iphone app. Such a simple game yet it produces so much game play. Many of todays games could benefit from such game play!</p>

<p>Keep up the good Work<br />
Scott<br />
<a href="http://www.movies.ie/movies">Irish Cinema Site</a><br />
</p>]]>
    </content>
    <published>2009-09-17T14:45:50Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36369-comment:2106787</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36369" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html#comment-2106787" />
    <title>Comment from Doug on 2009-09-20</title>
    <author>
        <name>Doug</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>The game is great and always has been.  I place it on my  Blackberry every day still! <br />
<a href="http://fatbikez.com/pazzo-racing-.html"> Pazzo </a></p>]]>
    </content>
    <published>2009-09-20T17:47:47Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36369-comment:2115230</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36369" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html#comment-2115230" />
    <title>Comment from Johny on 2009-09-24</title>
    <author>
        <name>Johny</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>If pacman was Aval on the new blackberry stom, that would be awesome!<br />
<a href="http://trackdaiz.com"> Track Time </a></p>]]>
    </content>
    <published>2009-09-24T22:01:31Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36369-comment:2117817</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36369" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html#comment-2117817" />
    <title>Comment from Andreas and Paul on 2009-09-26</title>
    <author>
        <name>Andreas and Paul</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>Pac the Pac-Man!  It's a great game. Thanks for write in java.</p>

<p>Suchmaschineneintrag  ║  Linkaufbau  ║  Pressebericht  ║  Suchmaschinenoptimierung  ║ Webdesign</p>]]>
    </content>
    <published>2009-09-26T16:59:39Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36369-comment:2120202</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36369" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html#comment-2120202" />
    <title>Comment from gices on 2009-09-28</title>
    <author>
        <name>gices</name>
        <uri>http://www.fancyacar.co.uk/</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://www.fancyacar.co.uk/">
        <![CDATA[<p>Don't understand why you need a distance threshold? When pacman touches or the ghost or vice versa, is the distance threshold not equal to zero?</p>]]>
    </content>
    <published>2009-09-28T20:02:27Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36369-comment:2120492</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36369" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html#comment-2120492" />
    <title>Comment from Henry Zhang on 2009-09-28</title>
    <author>
        <name>Henry Zhang</name>
        <uri>http://www.javafxgame.com</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://www.javafxgame.com">
        <![CDATA[<p>hi gices, </p>

<p>Thanks for your comments.</p>

<p>The distance is caculated between the center of two objects. So when their borders touch each other, their centersmay not be necessary at the same location. So this thredhold should be greater than zero. For more info, you can check out <a href="http://www.javafxgame.com">JavaFX Game Applications</a>.<br />
</p>]]>
    </content>
    <published>2009-09-29T00:28:03Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36369-comment:2123859</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36369" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html#comment-2123859" />
    <title>Comment from JIN on 2009-10-01</title>
    <author>
        <name>JIN</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>Hello.</p>

<p>Can i run this code in Blue J ???</p>

<p>thank you.</p>]]>
    </content>
    <published>2009-10-01T14:01:57Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36369-comment:2126474</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36369" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html#comment-2126474" />
    <title>Comment from Autoradio on 2009-10-03</title>
    <author>
        <name>Autoradio</name>
        <uri>http://ttp://www.powernetshop.at/adapter/</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://ttp://www.powernetshop.at/adapter/">
        <![CDATA[<p>this is so cool how you write this in javafx. This is one of these games that will never die. I will have to try this.<br />
</p>]]>
    </content>
    <published>2009-10-03T19:34:53Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36369-comment:2128034</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36369" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html#comment-2128034" />
    <title>Comment from Arthur on 2009-10-04</title>
    <author>
        <name>Arthur</name>
        <uri>http://www.LordsAndMinions.com</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://www.LordsAndMinions.com">
        <![CDATA[<p>Jesus, I loved Pacman so much! Now thanks to you everyone could build their own version.</p>]]>
    </content>
    <published>2009-10-05T03:00:21Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36369-comment:2129871</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36369" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html#comment-2129871" />
    <title>Comment from Bob on 2009-10-06</title>
    <author>
        <name>Bob</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>really good tutorial. <a href="http://dietguru.org">very useful information</a></p>]]>
    </content>
    <published>2009-10-06T17:22:01Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36369-comment:2133435</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36369" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html#comment-2133435" />
    <title>Comment from Statii Beton on 2009-10-09</title>
    <author>
        <name>Statii Beton</name>
        <uri>http://www.statii-beton.ro</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://www.statii-beton.ro">
        <![CDATA[<p>Pacman was a great game in my youth. Loving to see a solution to revive the game in JavaFX. Thanks for the guide</p>]]>
    </content>
    <published>2009-10-09T17:18:20Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36369-comment:2135274</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36369" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html#comment-2135274" />
    <title>Comment from Pete on 2009-10-10</title>
    <author>
        <name>Pete</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>wicked .. gonna have a crack myself as just a simple PHP coder my self :)<br />
Always a classic game and nice little bit of coding son :)</p>

<p>@John - Yep I can remember playing on aVIC20 :) Old Skool mate</p>

<p>Pete</p>]]>
    </content>
    <published>2009-10-10T22:33:43Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36369-comment:2145989</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36369" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html#comment-2145989" />
    <title>Comment from Fred on 2009-10-18</title>
    <author>
        <name>Fred</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>Thanks for Source Code...</p>

<p>Fred<br />
<a href="http://www.seoprom.de">http://www.seoprom.de</a></p>]]>
    </content>
    <published>2009-10-19T06:52:37Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36369-comment:2148402</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36369" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html#comment-2148402" />
    <title>Comment from Andrew on 2009-10-20</title>
    <author>
        <name>Andrew</name>
        <uri>http://www.brokerage-review.com</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://www.brokerage-review.com">
        <![CDATA[<p>Oh, man! It brings back the memories. It's been a while but I still remember the countless hours wasted playing it! Thanks for the code.<br />
<a href="http://www.brokerage-review.com/">brokerage reviews</a></p>]]>
    </content>
    <published>2009-10-21T00:57:08Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36369-comment:2149919</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36369" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html#comment-2149919" />
    <title>Comment from Singapore on 2009-10-22</title>
    <author>
        <name>Singapore</name>
        <uri>http://www.premium-gifts.com.sg/other01/</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://www.premium-gifts.com.sg/other01/">
        <![CDATA[<p>I've got played so way percent man since my childhood. Currently, I work for a <a href="http://www.premium-gifts.com.sg/">corporate gift</a> website but someday do squeeze in time to play tetris now and then.</p>]]>
    </content>
    <published>2009-10-22T08:47:22Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36369-comment:2155608</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36369" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html#comment-2155608" />
    <title>Comment from hi3w on 2009-10-25</title>
    <author>
        <name>hi3w</name>
        <uri>http://blog.csdn.net/hi3wsem</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://blog.csdn.net/hi3wsem">
        <![CDATA[<p>That's as great as <a href="http://blog.csdn.net/hi3wsem">sem</a>~</p>]]>
    </content>
    <published>2009-10-25T17:03:15Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36369-comment:2177066</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36369" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html#comment-2177066" />
    <title>Comment from Mike on 2009-11-08</title>
    <author>
        <name>Mike</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>Thanks for posting this code!</p>

<p><a href="http://www.hip-hoppen.de">Hip Hop</a></p>]]>
    </content>
    <published>2009-11-08T12:02:54Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36369-comment:2192481</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36369" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html#comment-2192481" />
    <title>Comment from Magnet on 2009-11-18</title>
    <author>
        <name>Magnet</name>
        <uri>http://www.xspyz.com</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://www.xspyz.com">
        <![CDATA[<p>Very nice review! I searched for some tutorials at <a href="http://www.btscene.com">http://www.btscene.com</a> , but found nothing informative, your article helped me much!</p>]]>
    </content>
    <published>2009-11-18T20:17:12Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36369-comment:2193944</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36369" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html#comment-2193944" />
    <title>Comment from Audio Note on 2009-11-20</title>
    <author>
        <name>Audio Note</name>
        <uri>http://www.audionote.com.my/</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://www.audionote.com.my/">
        <![CDATA[<p>I never thought of developing the game from scratch though, however involved in javascript UI, the animation ideas you have used in dying pacman will be employed in moving, sliding, wiping divs around too, it's like our <a href="http://www.audionote.com.my/tube-amp-a-sound-above-all-sounds/">tube amp</a>.</p>]]>
    </content>
    <published>2009-11-20T08:51:21Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36369-comment:2194440</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36369" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/06/writing-the-pac-man-game-in-ja-3.html#comment-2194440" />
    <title>Comment from Klebefolie on 2009-11-20</title>
    <author>
        <name>Klebefolie</name>
        <uri>http://www.selbstklebefolien.com/</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://www.selbstklebefolien.com/">
        <![CDATA[<p>Thanks for posting this code! Best Regards by 
<a href="http://www.mywandtattoo.de/">Wall Decal</a></p>
]]>
    </content>
    <published>2009-11-20T18:50:43Z</published>
  </entry>

</feed
