Top

Drench Game

In this guide you will learn how to develop a funny game: Drench. The goal is to clear the board with the lowest possible number of moves, using the different colors.

By referring to this guide, you will be able to:

  • Use sections bound to the data model.
  • Use $dataReady statement.
  • Use the aria templates DOM event.
  • Use foreach statement.

Tutorial

Step 1

Create a file using your favourite editor and call it index.html. This will be the bootstrap for your app.

Save it inside the root of your project (e.g. /guides/drench/).

Step 2

Inside index.html you will have to load the aria templates framework, define the container div and load the template that you will create.

To load the framework:

<script type="text/javascript" src="/aria/ariatemplates-1.2.0.js"></script>
<script type="text/javascript" src="/aria/css/atskin-1.2.0.js"></script>

To define the div container:

<div id="output"></div>
To load the template:
<script type="text/javascript">
Aria.loadTemplate({
  classpath:'ariadoc.guides.drench.view.Main',
  div:"output"
});
</script>

Step 3

Create a file and call it Main.tpl. This is the template that will be used to display the Drench user interface.

Save it inside the view folder inside your project (/guides/drench/view/).

Step 4

Define the classpath of your template and that it has a script.
{Template {
    $classpath: "ariadoc.guides.drench.view.Main",
    $hasScript: true
}}
Define inside the main macro the div to display the level counter and the timer, using two different sections bound to the data model:
<h1>Clean the board!</h1>
    <div class="timer">Level
        <strong>
            {section {
                 id: "level",
                 type: "span",
                 bindRefreshTo: [{to:"level",inside:data}]
             }}
                 ${data.level}
            {/section}
        </strong>
        <span style="float:right">Time
           <strong>
               {section {
                   id: "timer",
                   type: "span",
                   bindRefreshTo: [{to:"timer",inside:data}]
                }}
                   ${("00"+data.timer).slice(-3)}
                {/section}
           </strong>
        </span>
    </div>
Define the div to dispaly the board with a section bound to the data model and with two foreach to cover the image with different colors:
<div {on click "startGame"/}>
  {section {
      id: "board",
      type: "div",
      bindRefreshTo: [{to:"moves",inside:data}],
          attributes: {style: "width:"+BOARDSIZE*25+"px"}
  }}
     {foreach line inArray data.board}
         <div class="line">
            {foreach cell inArray line}
                        <span data-x="${cell_index}" data-y="${line_index}" {if cell==-1}class="fade"{else/}style="background:${COLORS[cell]}"{/if}>
                        </span>
                  {/foreach}
         </div>
     {/foreach}
  {/section}
</div>
Define the section to display:
  • the initial message to start the game;
  • the message if the user wins/fails with the Next Level/Restart button;
  • the clickable colors to play;
{section {
     id: "banner",
     type: "div",
     bindRefreshTo: [{to:"moves",inside:data}]
}}
    {if !data.gameStarted}
        <div class="msg">You have <span>${data.moves}</span> moves to clean the board.<br />Pick a place to start</div>
    {else/}
       {if data.cleaned==TOTAL}
           <div class="msg">${win()}</div>
           <div class="inset"><button type="button">Next level</button></div>
       {elseif data.moves==0/}
           <div class="msg">${fail()}</div>
           <div class="inset"><button type="button">Again! Again!</button></div>
       {else/}
           <div class="msg"><span>${data.moves}</span> ${(data.moves>1 ? "moves" : "move")} left</div>
           {for var c=1; c<COLORS.length; c++}
               <span class="color"></span>
           {/for}
       {/if}
    {/if}
{/section}

Note: To get more info about sections take a look at this page.

Step 5

Create a file and call it MainScript.js.

Save it inside the view folder inside your project (/guides/drench/view/).

Step 6

Define the classpath, the statics to declare the different colors and the constructor:
Aria.tplScriptDefinition({
  $classpath: "ariadoc.guides.drench.view.MainScript",
  $statics : {
      BOARDSIZE: 14,
      MAXMOVES: 30,
      COLORS: [
          "transparent",
          "#66CC00", //green
          "#9999FF", // blue
          "#743EF4", // purple
          "#CCFFCC", // cyan
          "#FF0000", // red
          "#FFCC00"  // yellow
      ]
  },
  $constructor : function() {
      this.TOTAL=this.BOARDSIZE*this.BOARDSIZE;
  }
Call the initialization function when the data has been loaded and the module associated to the template has been initialized:
$dataReady : function() {
    this.data = {};
    this.initGameData(1, 0);
},

initGameData : function(lvl, time) {
    var b = this.data.board = [];
    for (var i=0; i<this.BOARDSIZE; i++) {
       b[i] = [];
       for (var j=0; j<this.BOARDSIZE; j++)
          b[i][j]=parseInt(Math.random()*(this.COLORS.length-1))+1;
       }
       this.data.gameStarted = false;
       this.$json.setValue(this.data, "level", lvl);
       this.$json.setValue(this.data, "moves", this.MAXMOVES-lvl+1);
       if (time!=undefined) this.$json.setValue(this.data, "timer", time);
         this.interval = setInterval(function(t){t.$json.setValue(t.data,"timer",t.data.timer+1)}, 1000, this);
    }

Note: To check how to use $dataReady take a look at this page.

Define the startGame() function:
startGame : function(e) {
  if (this.data.gameStarted) return;
  if (e.target.getData("x") && e.target.getData("y")) {
     this.data.x = e.target.getData("x")*1;
     this.data.y = e.target.getData("y")*1;
     this.data.gameStarted = true;
     this.spread(this.data.x, this.data.y,
     this.data.board[this.data.y][this.data.x]);
  }
}
Define the newGame() function to re-initializate the game or to increase the level:
newGame : function(e, levelUp) {
   if (levelUp) this.initGameData(this.data.level+1);
       else this.initGameData(1, 0);
}
Define the functions to manage the spreads on the board when the user clicks a color:
spread : function(x, y, c) {
    this.data.cleaned = 0;
    this.convert(0, -1, c);
    this.spread2(this.data.x, this.data.y, c);
    this.convert(-2, -1, c);
    this.$json.setValue(this.data, "moves", this.data.moves-1);
}
spread2 : function(x, y, c) {
    var b = this.data.board;
    if (b[y][x]==c)  { b[y][x]=-2; this.data.cleaned++; }
    else if (b[y][x]==-1) { b[y][x]=0;  this.data.cleaned++; }
    else return;
    //top
    if (y-1>=0) this.spread2(x, y-1, c);
    //right
    if (x+1<this.BOARDSIZE) this.spread2(x+1, y, c);
    //bottom
    if (y+1=0) this.spread2(x-1, y, c);
}
clean : function(e, c) {
   this.spread(this.data.x, this.data.y, c);
}
convert : function(from, to, c) {
   var b = this.data.board;
   for (var i=0; i<this.BOARDSIZE; i++)
       for (var j=0; j<this.BOARDSIZE; j++)
          if (b[i][j]==from) b[i][j]=to;
}
Define the functions to display the message if the user finish the level or not:
fail : function() {
   clearInterval(this.interval);
   return "You failed miserably at level "+this.data.level+" after "+this.data.timer+"s of struggle.";
},

win : function() {
   clearInterval(this.interval);
   return "Wooohooo! You cleaned the board in "+(this.MAXMOVES-this.data.level+1-this.data.moves)+" moves! :)";
}

Step 7

Create a file and call it global.css.

Save it inside the view folder inside your project (/guides/drench/view).

Step 8

Give some style to your todo app.

Step 9

That's it! Open the index.html with your favourite browser (e.g. Chrome) and enjoy.