OPhone的Widget实例开发

SmilesOn--基于OPhone的Widget实例开发

OPhone平台开发, 2009-12-21 11:50:31

标签 : JIL Widget实现 SmilesOn html元素布局 css js

引用自:http://www.ophonesdn.com/article/show/131


 

       中国移动的OPhone支持JIL Widget,使我们可以像开发网页的方式来开发手机应用程序。这是一种比较容易上手和理解的开发方式,我们可以快速的把自己的一些想法用Widget的形式在手机上实现出来。

一.实例概述
       下面我们以一个实际的游戏实例来体验一下OPhone的Widget开发过程。

       我们的这个实例叫SmilesOn(开笑),是传统的LightsOff(关灯)游戏的一种表现形式,一个比较好玩的益智游戏。游戏的目标是:使画面上的所有表情符合都变成笑脸表情。操作方法为:点击其中任何一幅表情,这幅表情以及其上下左右的四幅表情(假如有的话)的状态都会变换,哭脸的会变为笑脸,笑脸的会变成哭脸。游戏设计了初级和高级两种模式,最主要的区别是初级模式有答案可以查看,高级模式没有提供答案。

       好了,我们先看一下游戏的整体效果,主要有四个界面,如下图所示:

        第一个界面是开始时的选择界面,第二个界面是初级游戏界面,第三个是高级模式,最后一个显示游戏帮助信息。

       下面就具体介绍一下这个游戏的设计过程,过程尽可能详细,因此如果你的电脑上安装了JIL开发工具,你就可以一步一步跟着做。

二.开发步骤详解

(一)创建工程
           首先打开JIL开发工具,选择File->New->Widget Project,创建以SmilesOn为工程名的工程,并记住工程的保存路径,创建完后如下图所示。

bin/SmilesOn.wgt:自动生成且自动和程序内容同步,程序的最终发布用的文件。
config.xml:程序配置文件,包含程序版本,高宽度,网络连接等各种配置,开始时按默认   配置即可。
Default.png:默认的背景图片,我们会使用自己的背景。
Icon.png:在手机上显示的程序图标。
SmilesOn.css:界面布局显示控制文件。
SmilesOn.html:程序主界面,用来存放及展示各种元素,我们的四个界面都在这里显示,其    实也是标准的网页程序。JIL开发工具自动为我们生成了对应的框架,包    括head和body部分,并且在head里已经增加了对css和js两个文件的    链接引用。
SmilesOn.Js:javascript文件,主要用来控制程序的流程及实现相关的逻辑功能。

(二)设计第一个界面


第一个界面很简单,主要放置了三个选择的按钮。
在代码部分要修改两处地方:

1.添加三个按钮的显示
(1)先删除掉html文件中的原来的body部分,用下面的代码代替

 

view plain copy to clipboard print ?
  1. <body> <div id= "menuView" > <form> <table> <tr> <input type= "button"  value= "初级"   class = "buttonMainview"  onclick= "juniorView()" /> </tr> <tr> <input type= "button"  value= "高级"   class = "buttonMainview"  onclick= "seniorView()" /> </tr> <tr> <input type= "button"  value= "帮助"   class = "buttonMainview"  onclick= "helpView()" /> </tr> </table> </form> </div> </body>  

 

       上述代码首先创建了一个div块并分配了一个id号menuView用来在css文件中控制其显示的样式,然后用表格的方式创建三行一列形式的按钮,并给他们设为同一个class名称buttonMainview,这样就可以在css里对这三个按钮的样式进行统一的控制,同时设置了按钮的显示内容value及点击后操作onclick,操作函数将在js文件里定义。

(2)接着也删除css文件里自动生成的内容,用下面的代码代替

view plain copy to clipboard print ?
  1. body{ height:  100 %; background-image:url(images/bg.png); background-repeat:no-repeat; } #menuView { margin-top: 20 %; } .buttonMainview { margin-left: 30 %; margin-top: 10 %; width: 40 %; height:50px; }  

        首先在body部分设定了背景图,接着设定div块距顶部距离为整体的20%,最后设置了三个按钮的放置的位置及其宽度和高度。

2.增加背景图
        因为我们用了自己添加景图片,所以得在硬盘上的工程目录文件夹下创建一个用来存放图片的文件夹images,在里面放入一个我们制作好的背景图片bg.png,


       图片的大小为320x480,因为不用默认的背景图片Default.png,所以删除。再回到JIL的左边的package explorer窗口按F5快捷键刷新或右键点击工程名后选择Refresh,就可以看到更新后的目录,增加了images文件夹及其下面的bg.png文件。如图5所示。

        完成后保存,右键点击工程名后选择Run AS->Widget Application,如图6所示,就可以在模拟器中看到第一个界面的显示了。(注:第一次启动模拟器,速度会比较慢,打开后就不必关闭了,代码修改后直接Run As即可)。

(三)设计第二个界面

         第二个界面最上面是放置一个标题用来显示当前游戏的关卡,中间是放置一组5x5的表情图片,最下面放置一栏操作选项,包括查看,选关和重置。

1.添加表情图片、关卡及返回箭头的显示
 (1)先来布局上面和中间部分
          在html文件中第一个div块的结束末尾</div>增加如下代码

view plain copy to clipboard print ?
  1. <div id= "gameViewJunior" > <form> <input type= "text"  id= "titleJ"  value= "关卡:1"  disabled /> <table> <tr> <td><img id= "imgJ0"  src= "" ></td> ...省略(完整代码请参考附件)... <td><img id= "imgJ4"  src= "" ></td> </tr> ...中间还有另外四组... </table> </form> </div>  

     这部分代码首先分配了一个id为gameViewJunior的div块,放置了一个显示了内容但禁止输入的id为titleJ的文本框作为标题栏,然后设置一个5行5列的表格来存放表情图片,并且给每个都设置了id用来在js文件中控制其切换。

   (2)然后也得添加css中的代码

 

view plain copy to clipboard print ?
  1. #gameViewJunior { margin-left:20px; } #titleJ { border:none; background-color:transparent; text-align:center; width: 100 %; }  

     首先设置这个div块距离左边20px,这样就留了一点边距,接着设置显示标题的文本框格式为没有边框,背景透明,文本居中显示。

      这样界面上就有了两个显示的div块,如果不加控制,则他们将一起显示出来,我们希望首先显示第一个界面,当点击了“初级”按钮后转到第二个界面,这样我们就要在js里增加控制。

      (3)先在body里增加一个最开始运行的初始化函数用来控制各个div块的显示,代码如下

 

view plain copy to clipboard print ?
  1. <body onload= "init()"  >  

     这表示在body里的内容装载完之后就调用init这个函数。

     同时因为有了两个界面,我们需要在他们之间切换,因此我们需要在最上方放置一个跳转箭头,以便在第二个界面时可以回到第一个界面。

 

view plain copy to clipboard print ?
  1. <div > <p> <img id= "backFlag"  src= "images/back.png"  onclick= "showBack();" ></img> </p> </div>  


        这个div块放置在body的下面,并在原先第一个div的前面,这样它的位置就会在最上面。这里主要放置了一个向后的箭头图片,

        并设置了其id为backFlag用来控制显示与否,和其被点击后的操作showBack()。


     (4)接下来我们就可以在js文件里实现相关的功能,首先添加init函数,同样先删除掉js里原来自动生成的代码,添加如下代码。

 

view plain copy to clipboard print ?
  1. function init() { document.getElementById( 'gameViewJunior' ).style.display= 'none' ; document.getElementById( 'menuView' ).style.display= 'block' ; document.getElementById( 'backFlag' ).style.display= 'none' ; }  

      这个函数的意思是显示'menuView'这个div块,隐藏'gameViewJunior'和'backFlag'代表的div块。这样初始显示的时候就不会显示出向后的箭头和第二个界面的内容,只有第一个界面了。

       我们在设计第一个界面的时候,给每个按钮都分配了一个onclick事件,现在我们就先实现第一个按钮对应的事件函数juniorView()。

       在js里添加如下代码

 

view plain copy to clipboard print ?
  1. function juniorView() { ...省略(完整代码请参考附件)... initJunior(); }  

       这个函数你应该很容易就看明白了,首先和init函数相反,在这里隐藏'menuView'对应的div块(即第一个界面),显示'backFlag'(即后退的箭头)和'gameViewJunior'块(即第二个界面)。之后调用了一个initJunior()函数。这个函数用来初始化第二个界面的5x5表情图片。

 

view plain copy to clipboard print ?
  1. function showBack() { ...省略... }  

        这个是点击箭头后的返回函数,也很简单,就是显示第一个界面。
(5)接着继续添加这个initJunior()函数的代码
         首先在js文件的头部添加两个变量

view plain copy to clipboard print ?
  1. var juniorRow= 5 ; var juniorCol= 5 ; 然后添加initJunior()函数 function initJunior() {  for (var i= 0 ;i<juniorRow;i++)  for (var j= 0 ;j<juniorCol;j++) { var number=i*juniorRow+j; document.getElementById( 'imgJ' +number).setAttribute( "src" , "images/SmilesOnJ.png"  ); } }  

       这个函数的意思是把5x5的表格全放上SmilesOnJ.png这幅图片。

         图片的样子为


(6)最后把这幅图片和上面的箭头图片一起拷到硬盘上这个工程目录下的images文件夹中,然后回到JIL中按F5刷新(和上一步是添加背景图片bg.png的操作一样)。

         接着就可以保存,Run AS运行,看下初步的效果了:

2.丰富表情图片的组合形式
       现在的表情图片都是笑脸,我们可以把一些笑脸改为哭脸,这样就能设计出一些结合的组合。我们设计一个二维数组,里面每一个数组里存放一组表示哭脸位置的数字,当显示时从数组里读取对应的位置,把笑脸改成哭脸,这样就能实现哭脸和笑脸结合的形式。
      (1)首先在js开头的变量定义部分添加

view plain copy to clipboard print ?
  1. //初级数组   
  2. var giveJuniorArray= new  Array(   
  3.         [ 8 , 12 , 13 , 14 , 18 ],   
  4.         ...还有另外 19 组...   
  5.     );  

      这个数组的数字代表在5x5共25个位置处,对应的位置上显示哭脸。
    (2)同时添加对应的表示当前关卡和总关卡的变量

view plain copy to clipboard print ?
  1. var roundJuniorNum= 0 ; //初级的关卡数记录   

       并在原来的initJunior()里添加用关卡数设置标题的一行代码。

view plain copy to clipboard print ?
  1. document.getElementById( 'titleJ' ).value= "关卡:" +parseInt(parseInt(roundJuniorNum)+ 1 );  

      (3)并且还添加一个函数调用creatRoundJunior(giveJuniorArray,roundJuniorNum);

        这个函数的意思是把当前5x5的一些由giveJuniorArray里的roundJuniorNum处的一组数字定义的位置上的笑脸用哭脸代替。

        具体的函数形式为

view plain copy to clipboard print ?
  1. function creatRoundJunior(sourceArray,round)   //生成新一关   
  2. {   
  3. ...省略(完整代码请参考附件)...   
  4.     document.getElementById( 'imgJ' +number).setAttribute( "src" , "images/SmilesOffJ.png"  );                       
  5. }  

    首先读取具体的数字表示的位置,然后把对应位置处的图片换成哭脸图片SmilesOffJ.png

    (4)同样把这幅图片放进images文件夹下,F5刷新。

       保存,Run As,看下新的效果

         不全是笑脸了,中间5个变为哭脸了。(注:如果有中文显示乱码,比如“关卡:1”显示出错,则关闭对应的js文件,到这个文件在硬盘的存储位置处选中,右键单击->打开方式中选择记事本,打开后选择文件->另存为,编码选择UTF-8,然后回到JIL按F5刷新,重新Run As即可)。

3.添加表情点击后的事件处理
       现在点击表情图片没反应,我们增加点击事件处理函数,使点击某个表情图片后,其自身及上下左右(如果有的话)5幅图片都会改变状态,即原来时哭脸的话变成笑脸,笑脸变成哭脸。
      (1)为了更好的获取每个位置处的表情状态,我们首先创建一个数组smileMatrix来存放表情状态。

view plain copy to clipboard print ?
  1. var smileMatrix= new  Array();  

       (2)在initJunior()函数里添加一行代码

 

view plain copy to clipboard print ?
  1. smileMatrix=creatAndValueSmileMatrix(juniorRow,juniorCol);  

        作用是创建存储表情状态的数组

 

view plain copy to clipboard print ?
  1. function creatAndValueSmileMatrix(row,col)  //生成幅值了的表情矩阵   
  2. {   
  3.     var smileMatrixInit= new  Array(row);   
  4.      for (var i= 0 ;i<row;i++)  //给表情矩阵赋值   
  5.     {   
  6.         smileMatrixInit[i]= new  Array(col);   
  7.          for (var j= 0 ;j<col;j++)   
  8.         {   
  9.             smileMatrixInit[i][j]= 1 //1代表笑脸   
  10.         }   
  11.     }              
  12.      return  smileMatrixInit;   
  13. }  

    同理,初始值都赋为1,代表笑脸。
 (3)同样在creatRoundJunior也增加一行代码,在按给定的数组把笑脸改成哭脸的同时,也把上述数组对应位置处改为2,代表哭脸

view plain copy to clipboard print ?
  1. smileMatrix[arrayRow][arrayCol]= 2 ;  

   (4)然后就可以在initJunior()函数里添加图片点击事件处理代码
document.getElementById('imgJ'+number).onclick=clickSmileJ;
这行代码的意思是为对应id处的元素注册一个点击后的事件处理函数clickSmileJ。

        事件处理函数为

view plain copy to clipboard print ?
  1. function clickSmileJ()   
  2. {   
  3.     var clickId= this .id;   
  4.     changeSmile(clickId);   
  5. }  

    首先获得当前元素的id,然后根据这个id改变其及上下左右的表情状态。

 

view plain copy to clipboard print ?
  1. function changeSmile(imgId)   
  2. {   
  3.     ...省略...   
  4.      if (rate== 'J' )   
  5.     {   
  6.         smilePointRow=imgLocation%juniorRow;   
  7.         smilePointCol=Math.floor(imgLocation/juniorRow);           
  8.          //1代表笑   
  9.      if (smileMatrix[smilePointRow][smilePointCol]== 1 )   
  10.         {   
  11.             number=smilePointRow+smilePointCol*juniorCol;   
  12.             document.getElementById( 'imgJ' +number).setAttribute( "src" , "images/SmilesOffJ.png"  );   
  13.             smileMatrix[smilePointRow][smilePointCol]= 2 ;   
  14.         }   
  15.          //2代表哭   
  16.          else   
  17.         {   
  18. ...省略...   
  19.         }                  
  20.          //改变上下左右周围表情的状态   
  21.          if ((smilePointRow- 1 )>= 0 )   
  22.         {   
  23.             smileAroundPoint=imgLocation- 1 ;   
  24.             changeSmileByPointJ(smileAroundPoint);             
  25.         }   
  26.         ...还有对其他三个位置的判断...     
  27.          return  ;   
  28.     }              
  29. }  

       其中changeSmileByPointJ(smilePoint)函数为改变某一具体位置处的表情状态

 

view plain copy to clipboard print ?
  1. function changeSmileByPointJ(smilePoint)   
  2. {   
  3. ...省略...   
  4.      //1代表笑   
  5.      if (smileMatrix[smilePointRow][smilePointCol]== 1 )   
  6.     {   
  7.         number=smilePointRow+smilePointCol*juniorCol;   
  8.         document.getElementById( 'imgJ' +number).setAttribute( "src" , "images/SmilesOffJ.png"  );   
  9.         smileMatrix[smilePointRow][smilePointCol]= 2 ;   
  10.          return ;   
  11.     }   
  12.      //2代表哭   
  13.      if (smileMatrix[smilePointRow][smilePointCol]== 2 )   
  14.     {   
  15. ...省略...   
  16.     }   
  17. }  

       好了,保存,Run As,点击对应的表情看下效果,有反应了。

4.添加过关的判断
       当经过点击把哭脸都变成笑脸之后就过关了,我们增加过关的判断,并当过关时弹出消息框进行提示,并且转到下一关。

       (1)首先增加判断游戏是否过关的函数,即存储表情状态的smileMatrix数组里是否还有代码哭脸的2。

view plain copy to clipboard print ?
  1. function isWin(Row,Col)  //判断游戏是否成功   
  2. {   
  3.      for (var i= 0 ;i<Row;i++)   
  4.     {   
  5.          for (var j= 0 ;j<Col;j++)   
  6.         {   
  7.              //2代表哭脸,如果还有哭脸存在,则还没成功   
  8.              if (smileMatrix[i][j]== 2 )   
  9.             {   
  10.                  return   0 ;   
  11.             }   
  12.         }   
  13.     }   
  14.      //如果没有了哭脸,则游戏成功,过关   
  15.      return   1 ;   
  16. }  

     (2)然后就可以在点击事件处理函数clickSmileJ()中判断是否过关

view plain copy to clipboard print ?
  1. if ( 1 ==isWin(juniorRow,juniorCol))   
  2. {   
  3.     alert( "        ^_^ 恭喜你,过关了!" );   
  4.     roundJuniorNum++;   
  5.      if (roundJuniorNum>(roundSumJunior- 1 ))   
  6.     {   
  7.         roundJuniorNum= 0 ;   
  8.     }   
  9.     initJunior();   
  10. }  

      这个函数的意思是判断是否过关,如果过关则弹出“ ^_^ 恭喜你,过关了!”的消息框,同时增加一个关卡数,并初始化显示下一关。

     (3)同时在js顶部定义一个代表所有关卡数的变量

view plain copy to clipboard print ?
  1. var roundSumJunior= 20 ; //初级总关数   

        好了,保存,Run As,看下效果

5.添加查看、选关及重置三个控制选项的显示

        现在第二个界面的大部分已经完成了,还剩下最下面的三个选择操作。

        (1)首先在html文件中第二个界面div块"gameViewJunior"的</table>和</form>中间添加

 

view plain copy to clipboard print ?
  1. <tr>   
  2.                     <td><input type= "button"  value= "查看"   class = "buttonViewJ"  onclick= "showAnswer()" /></td>   
  3.                     <td id= "roundNum" >   
  4.                         <select id= "roundJ"  onchange= "chooseRoundNum(this)"  >   
  5.                             <option value= "1" >选关-- 1 </option>   
  6.                             ...中间还有 18 关...   
  7.                             <option value= "20" >选关-- 20 </option>   
  8.                         </select>                    
  9.                     </td>   
  10.                     <td><input type= "button"  value= "重置"   class = "buttonViewJ"  onclick= "resetJ()" /></td>   
  11.                 </tr>  

    上述代码表示按一行三列布局,左右两边分别是“查看”和“重置”按钮,中间放置一个下拉选择框,并对这三个控件分别赋予了相关的id用来控制显示和对应的事件响应函数。

      (2)同时在css里添加

view plain copy to clipboard print ?
  1. .buttonViewJ   
  2. {   
  3.     margin-left:5px;   
  4.     height:50px;   
  5.     width:80px;    
  6. }   
  7. #roundJ   
  8. {   
  9.     margin-left:5px;   
  10.     height:30px;   
  11.     width:70px;   
  12. }  

     分别来控制上面这两个按钮和下拉选择框的位置及其宽度和高度。

       好了,保存,Run As,看下效果

6.添加控制选项对应的功能
      接下来我们在js中为最下方的操作选项添加对应的事件处理函数

      (1)首先是“重置”按钮的resetJ()函数

view plain copy to clipboard print ?
  1. function resetJ()   
  2. {   
  3.     initJunior();   
  4. }  

        重置操作只要重新调用初始函数即可。

        (2)接着是“查看”按钮的showAnswer()函数

 

view plain copy to clipboard print ?
  1. function showAnswer()  //查看答案   
  2. {   
  3.      //first reset   
  4.     resetJ();   
  5.        
  6.     var resultArray=answerJuniorArray[roundJuniorNum];   
  7.     var arrayLen=resultArray.length;   
  8.     var smilePointRow;   
  9.     var smilePointCol;     
  10.      for (var i= 0 ;i<arrayLen;i++)   
  11.     {   
  12.         smilePointRow=(resultArray[i]- 1 )%juniorCol;   
  13.         smilePointCol=Math.floor((resultArray[i]- 1 ) / juniorRow);   
  14.         var number=smilePointRow*juniorCol+smilePointCol;   
  15.          //1代表笑   
  16.          if (smileMatrix[smilePointCol][smilePointRow]== 1 )   
  17.         {   
  18.             document.getElementById( 'imgJ' +number).setAttribute( "src" , "images/SmilesOnAnswerJ.png"  );   
  19.             smileMatrix[smilePointCol][smilePointRow]= 11 ;   
  20.         }   
  21.          //2代表哭   
  22.          else   
  23.         {   
  24.             ...省略...       
  25.     }   
  26.   
  27. }  


          这个函数首先把游戏状态重置为开始的状态,然后从答案数组中读出需要过关需要点击的那些位置,然后把这些位置处的图片换成加了一个绿色的圈的图片SmilesOnAnswerJ.png或SmilesOffAnswerJ.png,

        同时在保存表情状态的smileMatrix数组中分别用11和22表示换成答案了的表情状态。

       (3)其中对应的答案数组为

 

view plain copy to clipboard print ?
  1. var answerJuniorArray= new  Array(   
  2.         [ 13 ],   
  3.         ...还有 19 组...   
  4.        
  5.     );  

 

       (3)换成了答案图片的表情如果因为其上下左右表情状态的改变而改变时,其前面的绿色圆圈应该还在,直到直接被点击了后才隐藏绿色的圆圈,因此changeSmile(imgId)函数里对当前点击处表情状态的判断需要修改为

 

view plain copy to clipboard print ?
  1. if ((smileMatrix[smilePointRow][smilePointCol]== 1 )||(smileMatrix[smilePointRow][smilePointCol]== 11 ))  

     在改变当前位置时,判断1和11都为笑脸,2和22都为哭脸。
  

     (4)同时在changeSmileByPointJ(smilePoint)这个函数里增加对11和22状态的判断。

 

view plain copy to clipboard print ?
  1. //11代表标了答案的笑   
  2. if (smileMatrix[smilePointRow][smilePointCol]== 11 )   
  3. {   
  4.     number=smilePointRow+smilePointCol*juniorCol;   
  5.     document.getElementById( 'imgJ' +number).setAttribute( "src" , "images/SmilesOffAnswerJ.png"  );   
  6.     smileMatrix[smilePointRow][smilePointCol]= 22 ;   
  7.      return ;   
  8. }   
  9. //2代表标了答案的哭   
  10. if (smileMatrix[smilePointRow][smilePointCol]== 22 )   
  11. {   
  12. ..省略...   
  13. }  


      5)同时也要在isWin函数中增加对22的判断

 

view plain copy to clipboard print ?
  1. if ((smileMatrix[i][j]== 2 )||(smileMatrix[i][j]== 22 ))  

      这样对“查看”按钮的事件处理函数就添加好了。

    (6)下面添加下拉框的事件处理函数

 

view plain copy to clipboard print ?
  1. function chooseRoundNum(object)   
  2. {   
  3.     var valueOption=object.options[object.options.selectedIndex].value;   
  4.     roundJuniorNum=valueOption- 1 ;   
  5.     initJunior();   
  6. }  


      这个函数比较好理解,先获得下拉框选择的关卡数,然后进行设置关卡,初始化显示对应关卡的界面。

       好了,保存,把标了答案的两幅图片放到images文件夹下,F5刷新,Run As,看下效果

         这样,“初级”模式下的功能我们都实现了,包括设置界面元素的位置及外观,相关的事件处理函数等,这已经是一个可以在OPhone中运行的程序了。

         当然我们在第一个界面上还有“高级”和“帮助”按钮没有实现,由于篇幅的限制,在这就不具体展开了。但是有了上面的详细过程,我们应该能对应实现了。

三.总结
        我们通过一个完整且比较有可玩性的益智游戏体验了Widget程序的设计过程,并对其中的html元素布局,css对显示的控制及js的函数添加及事件注册等做了大概的介绍。实际上常用的Widget程序的设计基本过程就是在html中放置显示的元素(当然也可以在js里动态创建,但开始时在html中放置更好理解),在css里控制html中元素的显示样式及整体布局,在js文件里控制程序的执行流程,并且在设计过程中这三个文件经常需要结合修改更新。

       上面的实例只介绍了能实现功能的主要部分,实际中应该还要对config.xml文件进行对应的设置,把单独的一个js大文件分为多个小文件便于管理,及在实现了功能后对代码进行部分修改优化等,我们可以在后面的学习过程中慢慢了解。

 

 

最后,我们介绍如何在实际手机上运行Widget。我们可以在项目的bin文件夹之下找到一个封装好的Widget,其扩展名为wgt。将这个文件复制到安装了Widget引擎的手机上,这样就能在实际设备上运行我们的Widget了。

 

 

你可能感兴趣的:(游戏,function,Class,div,button,OPhone)