28/01/2014 MCAFEE SECURE 認證的網站

https://www.mcafeesecure.com/RatingVerify?ref=www.HongKongCupid.com

2013年6月21日 星期五

**~硬碟備份**~還原工具光碟----V11 **自動備份還原光碟 __V1.21*

**~硬碟備份**~還原工具光碟 --
--V11 **自動備份還原光碟 __V1.21*

*【軟體名稱】:硬碟備份還原工具光碟  V11 --
自動備份還原光碟 V1.21 
【軟體語言】:繁體中文
【軟體類型】:硬碟備份還原工具光碟 
【檔案格式】:RAR/zip 
【檔案大小】:15.2MB (解壓縮後 58.7MB)
【運行環境】:DOS,光碟開機執行  **
*讓論壇成員測試使用,希望對大家有所幫助*
*光碟開機LOGO及宣告(預設5秒進入光碟選單 --
--或按 Enter 直接進入) **

*自動備份還原光碟選單(預設60秒無選擇任何--
--項目自動從硬碟開機)   **

*[H] 從硬碟開機 (預設值,或按 Enter 直接執行)
  [F1],[1] 自動備份 C: 到 D: (1:2) (單一硬碟或第一顆硬碟)
  [F2],[2] 自動從 D: (1:2) 還原 C: (單一硬碟或第一顆硬碟)
  [F3],[3] 自動備份 C: 到 E: (1:3) (單一硬碟或第一顆硬碟)
  [F4],[4] 自動從 E: (1:3) 還原 C: (單一硬碟或第一顆硬碟)
  [F5],[5] 自動備份 C: 到 F: (1:4) (單一硬碟或第一顆硬碟)
  [F6],[6] 自動從 F: (1:4) 還原 C: (單一硬碟或第一顆硬碟)
  [F7],[7] 自動備份 C: 到 (2:1) (第二顆硬碟)
  [F8],[8] 自動從 (2:1) 還原 C: (第二顆硬碟)
  [F9],[9] 自動備份 C: 到 (2:2) (第二顆硬碟)
  [F10],[0] 自動從 (2:2) 還原 C: (第二顆硬碟)
  [F11],[J] 自動備份 C: 到 (2:3) (第二顆硬碟)
  [F12],[Q] 自動從 (2:3) 還原 C: (第二顆硬碟)
  [D] MS-DOS (多重開機選單)
  [T] 進入工具程式選單
  [R] 重新開機

  按 [括號] 中的功能鍵或英數鍵"單鍵"執行選項,
  或按↑↓鍵(Tab 鍵亦可)移動選項,再按 Enter (空白鍵亦可)執行。

  光碟支援 PS2 滑鼠選擇項目,移動滑鼠或按 Tab、↑、↓ 等鍵選單計時立即停止。

  按[F1]或[1]備份後,按[F2]或[2]還原電腦。
  按[F3]或[3]備份後,按[F4]或[4]還原電腦。
  按[F5]或[5]備份後,按[F6]或[6]還原電腦。
  按[F7]或[7]備份後,按[F8]或[8]還原電腦。
  按[F9]或[9]備份後,按[F10]或[0]還原電腦。
  按[F11]或[J]備份後,按[F12]或[Q]還原電腦。

  您的桌機或是筆電如按功能鍵會啟動該機原廠的特定功能時,請按英數鍵執行。
  備份還原每個單鍵選項會設定 2 個按鍵都可執行的目的就是防止這情形發生。
  品牌電腦的桌機或筆電多半有隱藏磁區存放還原資料,以原廠還原光碟開機引導讀取
  隱藏磁區還原C槽,不建議使用本光碟備份或還原,儘量使用原廠光碟進行還原。
  **
  請注意:
  按 [F1]、[F3]、[F5] 備份時,映像檔分別存放於第一 
顆硬碟的第二/三/四磁區中  **
  電腦如為單一硬碟,直接對應磁碟機 D:、E:、F:。 
((**電腦有兩顆硬碟時,第一顆硬碟  ~~~
  不一定對應磁碟機代號 D:、E、:F:,請於檔案總管下--
--檢視磁碟機代號。
  尤其是 NTFS 和 FAT32 混合磁區狀態於 DOS 之下時。

    單一硬碟     第一顆硬碟   +   第二顆硬碟  
  =========  =====================
  (1:1)C:       (1:1)C:     (2:1)D:[F7/7]
  (1:2)D:[F1/1]   (1:2)E:[F1/1]  (2:2)I:[F9/9]   
  (1:3)E:[F3/3]   (1:3)F:[F3/3]  (2:3)J:[F11/11]
  (1:4)F:[F5/5]   (1:4)G:[F5/5]   (2:4)K:
  (1:5)G:       (1:5)H:     (2:5)L:

  1:2 指第一顆硬碟第二磁區:1 指硬碟編號,2 指磁區編號。
*

*自動備份還原光碟工具程式選單---
---(預設60秒無任何動作自動返回光碟選單)   **~!

*[1],[F1] 回前頁(預設值,或按 Enter 直接執行)
  [2],[F2] Partition Magic V8.0 繁體中文版 (硬碟分割及硬碟容量調整)
  [3],[F3] Lformat (通用硬碟低階格式化)
  [4],[F4] Memory Test (記憶體測試)
  [5],[F5] MHDD V4.6 (硬碟壞軌修復)
  [6],[F6] Active Password Changer 3.0 (重置修改系統管理員和使用者密碼)
  [7],[F7] Active Partition Recovery 3.0 (硬碟磁區相關資料備份和救援)
  [8],[F8] 從軟碟開機
  [9],[F9] 直接從硬碟開機
  [R] 重新開機

  按 [括號] 中的功能鍵或英數鍵"單鍵"執行選項,
  或按↑↓鍵(Tab 鍵亦可)移動選項,再按 Enter (空白鍵亦可)執行。

  註:
  1.工具程式皆為 MS-DOS 之下-
-執行的軟體。
  2.部分程式對硬碟具更動後無法恢復--
-的摧毀力,不了解程式使用請勿輕易嘗試執行。
  3.為容納 GHOST V11 於 2.88MB 軟碟--
--映像檔,本光碟另建 [DOS] 目錄做 DOS 指 
   令程式補遺。路徑已設定指向 X:\DOS,
較完整的包含一些常用的 DOS 指令和驅動 
   程式。(DOS 開機時已於開機檔中指定--
--光碟機代號為 X: )                *
*DOS 多重開機選單 (預設 60 秒--
--無選擇任何項目自動返回光碟選單)
*
*1.GHOST 11.0.2:手動操作 GHOST,
自動載入滑鼠驅動程式,離開時自動釋放。
  2.SPFDISK 2000-3V:開機啟動管理--
--及硬碟分割程式。
  3.NTFSDOS Professional for --
--DOS 5.0:DOS 下辨識 NTFS 磁區,
以處理 NTFS --磁區中的檔案。
以本項開機DOS --
--系統先賦予 FAT32 磁碟機代號,
NTFSFOS 執行--時再接續 DOS 磁碟機代號--
--賦予 NTFS 磁區於 DOS 下之--
--磁碟機代號。(支援長檔名)
   註:與 UDVD.sys 相衝,
無法顯示光碟資料夾或檔案,
以 VIDE-CDD.sys 取代。
  4.DOS with USB driver:DOS 開機載入 USBASPI.SYS、DI1000DD.SYS、
   USBCD.SYS,便利使用 USB --
--外接裝置手動操作處理檔案。
   註:為相容起見 UDVD.sys 以 --
--VIDE-CDD.sys 取代。
  5.DOS with ET3 Chinese system:
DOS 開機後載入中文系統,可看見 FAT32--
-- 8.3 格式的中文資料夾和檔案。
(不支援長檔名) 
 6.DOS PROMPT:僅載入 DOS 磁碟作業系統。
  7.Back to CoolCafe Backup/Restore -
CD Menu:返回自動備份還原光碟選單。
   選單預設 60 秒,沒按↑↓鍵移動選擇--
--項目,自動返回備份還原光碟選單。

  註:
  1.DOS 多重開機選單第 1~6 項,
皆可於 DOS 提示號之下:
   輸入 E 再按 Enter,返回自動備份--
--還原光碟選單。
   輸入 R 再按 Enter,重新開機。
   輸入 S 再按 Enter,電腦關機。
  2.光碟選單 [F1]~[F12] 單鍵執行如--
--發生錯誤,可按 [Tab] 鍵跳動選擇--
-- [Cancel] 再按 Enter,出現 [OK]--
-- 再按一次 Enter,回到 DOS 提示號後,
可執行上述 E/R/S  ~!!*
 【注意事項】:

  
      1.下載解壓縮後,以燒錄映像檔方式選擇---
--- MyCD_V1.21.ISO 燒錄光碟,BIOS 設 定光碟開機,
置入本光碟開機使用 !!! 

 
      2.您的電腦如支援 USB 開機,可嘗試將隨身碟模擬 --
--CD-ROM 置入本光碟 ISO 內容測試使用。
**古董老電腦沒支援 USB 開機項目,無從測試***

  3.本光碟單鍵備份還原不適用"整顆"硬碟之備份還原。
整顆硬碟之備份,請按 [D]
   進入 DOS 多重開機選單,選擇第 1 項 --

--GHOST 11.0.2 手動操作。
   亦不適用硬碟有一個以上之主分割的多重作業系統,

也請以上述方式手動處理。

  4.光碟僅測試 XP(x86),Win9X/ME/2000 應該也沒問題。
VISTA/Windows 7 無從測試。硬體上 P3/P4 的電腦幾乎都適用,
至於 SATA 設備的硬碟和光碟機之較新電腦已於驅動程式上--
--的更新和指令參數上的修正努力--
--做到相容性,如果無法適用也就---
   愛莫能助了,也只好請您使用視窗版的備份還原軟體進行囉。
   在您試用單鍵自動備份還原之前,請先自行先手動--

--操作測試 GHOST 製作備份映像
   檔,以免誤失造成電腦無法使用或不能處理的遺憾。


  5.光碟製作和測試的硬體環境: 
   (1)P3-866
   (2)TNT2 M64 32MB 4X AGP
   (3)512MB SDRAM
   (4)HDS728080PLAT20 80GB IDE
   (5)Hanns.G HW216D 16:10 LCD
   (6)PS2 Moues/Keyboard
   (7)PIONEER DVD-RW DVR-116 IDE
   作業系統及製作/測試軟體:
   (1)Windows XP SP3 Pro MSDN(x86)
   (2)EasyBoot 5.1.0.565,選項配置螢幕解析度為1024*768。
   (3)Winimage 8.0
   (4)VMWare 6.0.3 Build 80004
**
42,377 KB

*Download*  All my 2SHARDED
download  PW : 1q2q   *~*

*本光碟僅供測試研究使用!嚴禁用於商業用途*
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

2013年6月20日 星期四

~*SD/SDHC/SDXC Formatter* ---完美格式化並加速*~!**SD Formatter provides quick and easy access to the---- full capabilities of your SD, SDHC and SDXC memory cards*~!軟體版本: 4.0**軟體語言: *繁体字(Traditional Chinese) | English |日本(Japanese) | 簡(Simplified Chinese) !*~*

* SD/SDHC/SDXC Formatter* --
-完美格式化並加速*
*This software formats all SD memory cards,
SDHC memory cards and SDXC memory cards.
 **SD Formatter provides quick and easy access to the--
-- full capabilities of your SD, SDHC and SDXC memory cards*~!
*軟體名稱: Formatter**軟體版本: 4.0*
*軟體語言: *繁体字(Traditional Chinese) | English | **
*軟體網站: http://www.sdcard.org   *** 
*軟體簡介: 現在數位相機、照相手機﹑遊戲機PSP﹑NDS﹑--
手提電腦幾乎是人手一台(也有好幾台的),除了某些*..
*品牌的機器使用了自家的記憶卡之外,幾乎大多數的產品都是用SD卡;*..
*所以今天便來介紹一個實用的小程式,這程式可以將SD卡低階格式化*..
*能避免你的資料流失,不小心被善心人士作檔案修復而外流喔,
聽說使用了這個程式格式化後,SD Card 讀取速度也快了很多…*~!
*Using SDXC Memory Cards*
*Down the SD Card Formatter*
*Which SD standard memory cards works with your device?*
*About SD Speed Class*
**
*SDFormatter 圖文教學
Driver:讀卡機磁碟名稱***
Size:現在的SD卡容量         
而按鈕功能分別為:
【Refresh】- 換卡的時候如果沒有正常讀到新卡,可以按refresh。
【Option】- 要更改格式化的方式,就點Option進去調整,詳情請接下圖。
【Format】- 按下去就開始格式化了SD協會為一個全球性的產業體系 *~!

*致力於制訂引領產業發展的記憶卡技術 !!
SD 記憶卡與SD主機裝置為--
--所有記憶卡或內建SD規格--
--產品的通稱。SD記憶卡技術可多元化使用--
--於各種格式、容量與速度。
目前,全球有400多個品牌遵循SD規格,
產製超過8,000種的消費性電子產品~!**
*

SD Formatter 4.0格式化軟體─

SD/SDHC/SDXC記憶卡

**
SD Formatter 4.0格式化軟體支援所有--
--SD記憶卡、SDHC記憶卡及SDXC記憶卡--
--之格式化,能幫助您快速、
簡單地發揮SD、SDHC與SDXC記憶卡--
--的完整效能。
SD Formatter專為所有使用SD/SDHC/SDXC--
--標準規格之記憶卡開發設計。
因此,我們強烈建議您使用SD Formatter所--
--提供的格式化程式,來取代作業系統內建的--
--格式化功能,以因應電腦多樣化的儲存媒體,
避免讓一式通用的格式化功能,
降低您的記憶卡最佳效能。
在SD規格的安全功能中,
所有SD/SDHC/SDXC記憶卡皆設有「保護區」
;因此,SD Formatter將不會格式化--
「保護區」內的內容。
若您欲格式化「保護區」之內容,
請使用適合的應用軟體、或具有提供--
--記憶卡保護區格式化功能的SD相容裝置,
來格式化您的記憶卡保護區。

系統需求*
SD/SDHCSDXC

WindowsWindows 8
Windows 7
Windows Vista
Windows XP
Windows 8
Windows 7
Windows Vista (SP1 or later)
Windows XP (SP2 or later) with the exFAT file system update (KB955704)
Mac OSMac OS X(v10.8 Mountain Lion)
Mac OS X(v10.7 Lion)
Mac OS X(v10.6 Snow Leopard)
Mac OS X(v10.5 Leopard for Intel Mac)
Mac OS X(v10.8 Mountain Lion)
Mac OS X (v10.7 Lion)
Mac OS X (v10.6.5 Snow Leopard or later) with the exFAT file system update
*
SD/SDHCSDXC

WindowsWindows 8
Windows 7
Windows Vista
Windows XP
Windows 8
Windows 7
Windows Vista (SP1 or later)
Windows XP (SP2 or later) with the exFAT file system update (KB955704)
Mac OSMac OS X(v10.8 Mountain Lion)
Mac OS X(v10.7 Lion)
Mac OS X(v10.6 Snow Leopard)
Mac OS X(v10.5 Leopard for Intel Mac)
Mac OS X(v10.8 Mountain Lion)
Mac OS X (v10.7 Lion)
Mac OS X (v10.6.5 Snow Leopard or later) with the exFAT file system update
請注意 : 如直接將您的SDXC記憶卡插入-
-電腦SD插槽,電腦可能另須-
-安裝SDXC驅動程式
若將您的SDXC記憶卡插入電腦SD插槽,
而未事先安裝驅動程式,記憶卡恐無法被-
-電腦正確辨識;且可能出現「立刻格式化」-
-訊息。若發生此情況,切勿立即格式化您-
-的SDXC記憶卡;否則恐將SDXC記憶卡中-
-的資料全部清空,並將您的SDXC記憶卡--
--格式化成不同的檔案格式,使該SDXC記憶--
--卡與SDXC裝置不相容。

SD介面裝置 

SD/SDHC/SDXC記憶卡可於下列-
-介面裝置中存取使用:
  • 電腦SD插槽
  • USB SD讀卡機
  • PC卡、CarBus或ExpressCard等SD轉接器
在格式化SD、SDHC 或 SDXC記憶之前,
請務必確認您使用的介面裝置是否與記憶卡相容。

SD Formatter 4.0使用者手冊

請點選以下按鈕,下載適合您的SD
Formatter使用者手冊:
(pdf, 337k)
(pdf, 332k)
(pdf, 517k)
(pdf, 423k)

下載SD Formatter 4.0


著作權聲明

Microsoft與Windows均為註冊商標或為--
--微軟公司所有之商標,在美國及其它-
國家均有註冊。
Apple、Mac、Mac OS及Mac OS標識均為-
-註冊商標或為蘋果電腦公司所有之商標,
在美國及其它國家均有註冊。
*
**欲深入了解SD技術如何運作、
下載規格說明、或是加入SD協會,
歡迎您參閱技術總覽專區開發者資源專區   !!*
https://www.sdcard.org/cht/home/   *
https://www.sdcard.org/chs/home/   *
https://www.sdcard.org/jp/home       *
https://www.sdcard.org/home/          *

*
  • SD Association Standardizes Wi-Fi Cards    *
  • SD Association Adds Wi-Fi to SD Card Standard     *
  • Wi-Fi on SD cards standardised        *
  • Wireless LAN SD standard aims to give every SD-
  • - card that Eye-Fi flair                     
    *SDHC**miniSD* *SDXC*
    **     &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

    **~PC修復專用工具~***KVTOOLS 2.0版**~!

    **~PC修復專用工具~*
    **KVTOOLS 2.0版**~!

    *★這是一套綜合板的TOOL,
    有包含常用系統修復的工具~!*
    *以及目前最佳的隨身碟病毒--清除工具 **
    ~~非常適合大家使用*



    **雖說台灣也有很多厲害的人會寫類似的程式,但是卻會因為一些--
    --問題而停罷或是無法發揚光大,畢竟單人與團隊經營的方式是不同的~!*
    *而且某些人所寫的程式,樣本採集不夠多,其實殺毒能力算是有限  !**

    *做電腦知識的自我提升,同時也提供一個專業化的管道來服務更多朋友*

    *下面是程式圖片介紹:     *
    *工具使用需知:            *

    *
    *系統修復工具:適合電腦維修同行使用.............*
    **
    *
    隨身碟病毒清除工具:直接執行全盤掃描清除即可
    排除目前較夯的隨身碟變種病毒。建議每次
    使用之前,執行一次"特徵碼更新工具"的動作~!*

    *
    *












    *電腦資訊修改工具:可以自己掛上喜歡的LOGO圖示*
    **
    **關於本程式:           **













    *
    程式使用需知:
    1.此版已置入線上更新病毒碼功能,建議每次使用之前,
    執行一次"特徵碼更新工具"的動作。
    2.此程式只是專門排除隨身碟病毒之功能,建議格友們--
    --電腦也要有一套正式的防毒軟體來做掃毒。
    3.971023,AVG、AVAST及其它套等部份防毒軟體會誤判--
    --程式中的檔案,如果您的防毒有偵測到木馬訊息,
    請選擇略過或是新增信任,否則一旦刪除的話,
    KVTOOLS就無法啟動!!解決方法就是將防毒軟體暫時關閉//
    //移除再重新安裝,讓它去重新判斷。如果不相信我們,
    請不要使用,避免不必要的爭議
    (也可以暫時關閉防毒軟體,讓KVTOOLS開啟掃描) 
    4.此程式支援VISTA系統,第一次使用時---
    ---請用"系統管理員身份"去執行**
    *(滑鼠按右鍵,選擇"以系統管理員身份執行")  **
    5.在做全盤掃描時,一開始可能會稍微停住,電腦過舊--
    --的人可能會當住或是等比較久一點,正常現像。
    6.執行完掃描後,建議重新開機一次做第二次的掃描。
    若發現有相同病毒的話,請直接到安全模式做重新殺毒
    即可。進入方法:開機時按F8(一直按按按),再選項第
    一項(安全模式)即可。
    7.如果您啟動KVTOOLS時,Run-time erro "339"錯誤訊息,
    有可能是系統的問題,也有可能被防毒軟體刪除或擋住,
    可以下載TABCTL32.OCX檔案,放進KVTOOLS資料夾內,
    取代原先的檔案,看看是否可執行,若還是不行的話,
    那就沒辨法哩!!                 *
    *請隨時做文章的資料更新``*

    *程式下載:               *
    *
    753 KB2013-06-20Download
    *2shared - file upload and sharing**
    KVTOOLS 2.0.rar

    KVTOOLS 2.0.rar download  

    *  All  my 2sharded PW :  1q2q    *
    使用方法:
    *嚴重建議先將自己的防毒軟體先關閉,再進行下面步驟,
    免得部份防毒軟體會擋KVTOOLS程式,而造成執行錯誤。
    1.程式下載完,經解壓縮後,執行資料夾內的KVTOOLS檔。
    2.在USB病毒清除工具中,執行全盤掃描清除,即可排除--
    --目前較夯的隨身碟變種病毒。
    *建議每次使用之前,執行一次"特徵碼更新工具"的動作。
    (如果您的電腦沒有安裝WINRAR解壓縮程式,請先下載-
    -WINRAR解壓縮軟體並做安裝後,才能解壓縮程式)  *
    *
    ◎由於隨身碟病毒會不斷的變種,也常造成作者在修改上--
    --的困擾,如果要讓您的電腦不一直受病毒影響的話,
    最好的方法就是改善使用隨身碟及收信的方式才行。
    ☉隨身碟是kavo病毒的最大來源之一,如果要使用隨身碟-
    -之前,千萬一定要先做掃毒的動作,才可以開啟隨身碟。
    ☉Mail收信,盡量不要開啟別人夾帶的檔案,若要開啟,
    請在下載完一定要先做掃毒的動作才行。
    ☉電腦一定要安裝掃毒較強的軟體,如果裝的是中看不中用-
    -的話,只會增加重灌的機會而已。
    電腦從來沒有中過KAVO隨身碟病毒,
    只要使用觀念正確,您也可以是免疫達人!!~**


    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

    2013年6月19日 星期三

    **SMASHING MAGAZINE's*^How to Design A Moblie Game With HTML5**~!

    **SMASHING MAGAZINE's*^How to Design A Moblie Game With HTML5**~!

    *A handful of game developers are pushing the envelope of mobile HTML5 games at the moment. Check out the likes of   Nutmeg and Lunch Bug for some shining examples. The great thing about these titles is that they work equally well on         both mobile and desktop using the same code.  
    Could HTML5 finally fulfill the holy grail of “write once, run anywhere”?*

    *Getting Started
    Before you start sketching the next Temple 
     Run or Angry Birds, you should be aware of  
     a few things that could  
    dampen your excitement:  *

    *Performance 
    Mobile browsers are not traditionally 
    known for their blazing JavaScript  
    engines. With iOS 6 and Chrome beta  
    for Android, though,  
     things are improving fast.
  • Resolution
    A veritable cornucopia of Android 
  • devices sport a wide range of   
  • resolutions. Not to mention the  
  •  increased resolution and pixel density 
  • of the iPhone 4 and iPad 3         *
  • *Audio
    Hope you enjoy the sound of silence.
    Audio support in mobile browsers is poor,
     to say the least. Lag is a major problem,
    as is the fact that most devices offer only
     a single channel. iOS won’t even load a    
    sound until the user initiates the action.   
    My advice is to hold tight and wait for    
    browser vendors to sort this out.                *
    *
    Now, as a Web developer you’re used to
     dealing with the quirks of certain      
    browsers and degrading gracefully and   
    dealing with fragmented platforms. So,  
    a few technical challenges won’t put you 
    off, right? What’s more, all of these     
    performance and audio problems are    
    temporary. The mobile browser landscape 
    is changing so quickly that these concerns 
    will soon be a distant memory.
    In this tutorial, we’ll make a relatively  
    simple game that takes you through the  
    basics and steers you away from pitfalls.
    The result will look like this:                         *

    *
    Screenshot of finished demo*

    *
  • Play the demo. 5
  • Download the demo  (ZIP).   *

  • *It’s a fairly simple game, in which the 
    user bursts floating bubbles before they 
    reach the top of the screen. Imaginatively, 
     I’ve titled our little endeavour Pop.        *
    *We’ll develop this in a number  
     of distinct stages:                     *

    *
    1. Cater to the multitude of viewports
    2. and optimize for mobile;
    3. Look briefly at using the canvas API
    4. to draw to the screen;
    5. Capture touch events;
    6. Make a basic game loop;
    7. Introduce sprites, or game “entities”;
    8. Add collision detection and some
    9. simple maths to spice things up;
    10. Add a bit of polish and some basic
    11. particle effects.    *
    *1. Setting The Stage
    Enough of the background story. Fire up
     your favorite text editor, pour a strong
    brew of coffee, and let’s get our 
    hands dirty.
    As mentioned, there is a plethora of  
    resolution sizes and pixel densities    
    across devices. This means we’ll have to  
    scale our canvas to fit the viewport.  
    This could come at the price of a loss 
    in quality, but one clever trick is to make  
    the canvas small and then scale up, which  
     provides a performance boost.
    Let’s kick off with a basic HTML shim:         *
    *
    <!DOCTYPE HTML>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    
    <meta name="viewport" content=
    "width=device-width, 
    
        user-scalable=no, initial-scale=1, 
    maximum-scale=1, user-scalable=0" /> 
    
    <meta name="apple-mobile-web-app-
    capable" content="yes" /> 
    
    <meta name="apple-mobile-web-app-
    status-bar-style" content="black-translucent" /> 
    
    <style type="text/css">
    body { margin: 0; padding: 0; background: #000;} 
    canvas { display: block; margin: 0 auto; 
     background: #fff; } 
    
    </style>
    
    </head>
    
    <body>
    
    <canvas> </canvas>
    <script>
    // all the code goes here 
    </script>
    
    </body> 
    </html> 
    The meta viewport tag tells mobile  
     browsers to disable user scaling and to
     render at full size rather than shrink   
    the page down.
    The subsequent apple-    prefixed meta  
    tags allow the game to be bookmarked. 
    On the iPhone, bookmarked apps do not 
    display the toolbar at the bottom of the
     page, thus freeing up valuable real estate.
    Take a look at the following:                  *

    *
    // namespace our game 
    var POP = { 
    
        // set up some initial values 
        WIDTH: 320, 
        HEIGHT:  480, 
        // we'll set the rest of these 
        // in the init function 
        RATIO:  null,
        currentWidth:  null,
        currentHeight:  null,
        canvas: null,
        ctx:  null,
    
        init: function() { 
    
            // the proportion of width to height 
            POP.RATIO = POP.WIDTH / POP.HEIGHT;
            // these will change when the 
    screen is resized
            POP.currentWidth = POP.WIDTH;
            POP.currentHeight = POP.HEIGHT;
            // this is our canvas element
            POP.canvas = document.
    getElementsByTagName('canvas')[0];
            // setting this is important 
            // otherwise the browser will 
            // default to 320 x 200 
            POP.canvas.width = POP.WIDTH; 
            POP.canvas.height = POP.HEIGHT; 
            // the canvas context enables us to 
            // interact with the canvas api 
            POP.ctx = POP.canvas.getContext('2d'); 
    
            // we're ready to resize 
            POP.resize(); 
    
        }, 
    
        resize: function() { 
    
            POP.currentHeight = window.innerHeight;
            // resize the width in proportion
            // to the new height
            POP.currentWidth =
     POP.currentHeight * POP.RATIO;
    
            // this will create some extra 
    space on the
            // page, allowing us to scroll past
            // the address bar, thus hiding it.
            if (POP.android || POP.ios) {
                document.body.style.height =
     (window.innerHeight + 50) + 'px';
            }
    
            // set the new canvas style 
    width and height
            // note: our canvas is still 
    320 x 480, but
            // we're essentially scaling 
    it with CSS
            POP.canvas.style.width =
     POP.currentWidth + 'px';
            POP.canvas.style.height =
     POP.currentHeight + 'px';
    
            // we use a timeout here because 
    some mobile
            // browsers don't fire if there is not 
            // a short delay 
            window.setTimeout(function() { 
                    window.scrollTo(0,1); 
            }, 1);
        } 
    
    };
    
    window.addEventListener 
    ('load', POP.init, false); 
    window.addEventListener 
    ('resize', POP.resize, false); 
    First, we create the POP namespace for
     our game. Being good developers,   
    we don’t want to pollute the global 
    namespace. In keeping good practice, 
     we will declare all variables at the  
    start of the program.
    Most of them are obvious: canvas  
    refers to the canvas    element in the HTML,
     and ctx    enables us to access it via the   
    JavaScript canvas API. 
    In POP.init,    we grab a reference to
    our canvas element, get its context 
    and adjust the canvas element’s     
    dimensions to 480 × 320.
     The resize     function, which is fired on 
    resize and load events, adjusts the  
     canvas’ style    attribute for width and
    height accordingly while maintaining 
    the ratio. Effectively, the canvas is   
    still the same dimensions but has been 
    scaled up using CSS. Try resizing your  
    browser and you’ll see the canvas scale to fit.
    If you tried that on your phone, you’ll 
     notice that the address bar is still     
    visible. Ugh! We can fix this by adding 
    a few extra pixels to the document and 
    then scrolling down to hide  
    the address bar, like so: 
    // we need to sniff out Android and iOS
    // so that we can hide the address bar in
    // our resize function
    POP.ua = navigator.userAgent.toLowerCase();
    
    POP.android = POP.ua.indexOf('android') >
     -1 ? true : false;
    
    POP.ios = ( POP.ua.indexOf('iphone') >
     -1 || POP.ua.indexOf('ipad') > -1  ) ? 
        true : false;
    The code above sniffs out the user
    agent, flagging for Android and iOS
    if present. Add it at the end of POP.init
    before the call to POP.resize().             *

    *Then, in the resize    function,
     if android    or ios    is true,    we add  
    another 50 pixels to the document’s  
    height — i.e. enough extra space to be 
    able to scroll down past the address bar.
    // this will create some extra space on the 
    // page, enabling us to scroll past 
    // the address bar, thus hiding it. 
    if (POP.android || POP.ios) { 
        document.body.style.height =
     (window.innerHeight + 50) + 'px';
    } 
    Notice that we do this only for Android
    and iOS devices; otherwise,
     nasty scroll bars will appear. Also,
     we need to delay the firing of scrollTo   
    to make sure it doesn’t get ignored  
    on mobile Safari.  *

    *2. A Blank Canvas
    Now that we’ve scaled our canvas  
    snuggly to the viewport, let’s add   
    the ability to draw some shapes.
    *Note: In this tutorial, we’re going to 
     stick with basic geometric shapes.  
    iOS 5 and Chrome beta for Android can 
     handle a lot of image sprites at a high 
    frame rate. Try that on Android 3.2 or  
    lower and the frame rate will 
    drop exponentially.
     Luckily, there is not much overhead 
    when drawing circles,
     so we can have a lot of bubbles in our 
    game without hampering performance   
    on older devices.
    Below, we’ve added a basic Draw    object  
    that allows us to clear the screen, draw a 
    rectangle and circle, and add some text.
    Nothing mind-blowing yet.  
    Mozilla Developers Network has excellent  
     resources as always,   

    *
    // abstracts various canvas operations into 
    // standalone functions 
    POP.Draw = { 
    
        clear: function() { 
            POP.ctx.clearRect 
    (0, 0, POP.WIDTH, POP.HEIGHT); 
        },
    
        rect: function(x, y, w, h, col) { 
            POP.ctx.fillStyle = col;
            POP.ctx.fillRect(x, y, w, h);
        },
    
        circle: function(x, y, r, col) { 
            POP.ctx.fillStyle = col;
            POP.ctx.beginPath();
            POP.ctx.arc 
    (x + 5, y + 5, r, 0,  Math.PI * 2, true);
            POP.ctx.closePath(); 
            POP.ctx.fill(); 
        },
    
        text: function(string, x, y, size, col) { 
            POP.ctx.font =
     'bold '+size+'px Monospace'; 
            POP.ctx.fillStyle = col; 
            POP.ctx.fillText(string, x, y); 
        } 
    
    };
    Our Draw object has methods for clearing 
     the screen and drawing rectangles, 
     circles and text.  
    The benefit of abstracting these  
    operations is that we don’t have to  
    remember the exact canvas API calls,
     and we can now draw a circle with  
    one line of code, rather than five.
    Let’s put it to the test: 
    // include this at the end of POP.init function 
    POP.Draw.clear(); 
    POP.Draw.rect(120,120,150,150, 'green'); 
    POP.Draw.circle(100, 100, 50, 'rgba(255,0,0,0.5)');
    POP.Draw.text('Hello World', 100, 100, 10, '#000');
    Include the code above at the end  
    of the POP.init        
    function, and you should see a couple 
    of shapes drawn to the canvas.

    3. The Magic Touch 

    Just as we have the click event, 
    mobile browsers provide methods 
     for catching touch events.
    The interesting parts of the code below
     are the touchstart, touchmove     
    and touchend                   events.
    With the standard click      event, we can
     get the coordinates from e.pageX    
    and e.pageY.     Touch events are slightly 
     different. They contain a touches     
    array, each element of which contains  
     touch coordinates and other data.
    We only want the first touch,
     and we access it like so: e.touches[0].    
    Note: Android provides JavaScript   
    access to multi-touch actions only  
    since version 4.
    We also call e.preventDefault();     when
    each event is fired to disable scrolling,
     zooming and any other action that  
    would interrupt the flow of the game.
    Add the following code  
    to the POP.init      function.
    // listen for clicks 
    window.addEventListener('click', function(e) { 
        e.preventDefault(); 
        POP.Input.set(e); 
    }, false); 
    
    // listen for touches 
    window.addEventListener('touchstart', function(e) { 
        e.preventDefault(); 
        // the event object has an array 
        // named touches; we just want 
        // the first touch 
        POP.Input.set(e.touches[0]);
    }, false);
    window.addEventListener('touchmove', function(e) { 
        // we're not interested in this,
        // but prevent default behaviour 
        // so the screen doesn't scroll 
        // or zoom 
        e.preventDefault();
    }, false); 
    window.addEventListener('touchend', function(e) { 
        // as above 
        e.preventDefault(); 
    }, false); 
    You probably noticed that the code  
    above passes the event data to   
    an Input object, which we’ve yet 
     to define. Let’s do that now:
    // + add this at the bottom of your code,
    // before the window.addEventListeners 
    POP.Input = { 
    
        x: 0,
        y: 0,
        tapped :false,
    
        set: function(data) { 
            this.x = data.pageX; 
            this.y = data.pageY; 
            this.tapped = true; 
    
            POP.Draw.circle 
    (this.x, this.y, 10, 'red'); 
        } 
    
    };
    Now, try it out. Hmm, the circles are 
    not appearing. A quick scratch of the 
    head and a lightbulb moment! Because
     we’ve scaled the canvas, we need to  
    account for this when mapping the  
    touch to the screen’s position.
    First, we need to subtract the offset  
    from the coordinates.
    var offsetTop = POP.canvas.offsetTop, 
        offsetLeft = POP.canvas.offsetLeft; 
    
    this.x = data.pageX - offsetLeft; 
    this.y = data.pageY - offsetTop;                      *
     
    *Diagram showing canvas offset relative to the browser window*
    *
    Then, we need to take into account the
    factor by which the canvas has been
    scaled so that we can plot to the actual
    canvas (which is still 320 × 480).
    var offsetTop = POP.canvas.offsetTop,
        offsetLeft = POP.canvas.offsetLeft;
        scale = POP.currentWidth / POP.WIDTH; 
    
    this.x = ( data.pageX - offsetLeft ) / scale; 
    this.y = ( data.pageY - offsetTop ) / scale;             *
     
    *Difference between CSS scaled canvas and actual dimensions *

    *
    If your head is starting to hurt, a practical
    example should provide some relief. Imagine
    the player taps the 500 × 750 canvas above
    at 400,400. We need to translate that
    to 480 × 320 because, as far as the JavaScript
    is concerned, those are the dimensions of the
    canvas. So, the actual x coordinate is 400
    divided by the scale; in this case
    , 400 ÷ 1.56 = 320.5.
    Rather than calculating this on each touch
    event, we can calculate them after resizing.
    Add the following code to the start of the
    program, along with the other
    variable declarations:
    // let's keep track of scale 
        // along with all initial declarations 
        // at the start of the program 
        scale:  1,
        // the position of the canvas 
        // in relation to the screen 
        offset = {top: 0, left: 0}, 
    In our resize function, after adjusting the
    canvas’ width and height, we make note of
    the current scale and offset:
    // add this to the resize function.
    POP.scale = POP.currentWidth / POP.WIDTH; 
    POP.offset.top = POP.canvas.offsetTop; 
    POP.offset.left = POP.canvas.offsetLeft; 
    Now, we can use them in the set method of
    our POP.Input class:
    this.x = 
    (data.pageX - POP.offset.left) / POP.scale; 
    this.y = 
    (data.pageY - POP.offset.top) / POP.scale;              *
     
    **

    4. In The Loop

    A typical game loop goes something like this:
    1. Poll user input,
    2. Update characters and process collisions,
    3. Render characters on the screen,
    4. Repeat.
    We could, of course, use setInterval, but
    there’s a shiny new toy in town named
    requestAnimationFrame. It promises smoother
    animation and is more battery-efficient.
    The bad news is that it’s not supported
    consistently across browsers. But Paul Irish
    has come to the rescue with a handy shim.
    Let’s go ahead and add the shim to the start
    of our current code base.
    // http://paulirish.com/2011/ 
    requestanimationframe-for-smart-animating 
    // shim layer with setTimeout fallback 
    window.requestAnimFrame = (function(){
      return  window.requestAnimationFrame       || 
              window.webkitRequestAnimationFrame || 
              window.mozRequestAnimationFrame    || 
              window.oRequestAnimationFrame      || 
              window.msRequestAnimationFrame     || 
              function( callback ){ 
                window.setTimeout 
    (callback, 1000 / 60); 
              }; 
    })(); 
    And let’s create a rudimentary game loop:
    // Add this at the end of POP.init; 
    // it will then repeat continuously 
    POP.loop(); 
    
    // Add the following functions after POP.init: 
    
    // this is where all entities will be moved 
    // and checked for collisions, etc.
    update: function() { 
    
    },
    
    // this is where we draw all the entities 
    render: function() { 
    
       POP.Draw.clear(); 
    },
    
    // the actual loop 
    // requests animation frame, 
    // then proceeds to update 
    // and render 
    loop: function() { 
    
        requestAnimFrame( POP.loop ); 
    
        POP.update(); 
        POP.render(); 
    } 
    We call the loop at the end of POP.init.
    The POP.loop function in turn calls our POP.
    update and POP.render methods.
    requestAnimFrame ensures that the loop is
    called again, preferably at 60 frames per
    second. Note that we don’t have to worry
    about checking for input in our loop because
    we’re already listening for touch and click
    events, which is accessible through our POP.
    Input class.
    The problem now is that our touches from the
    last step are immediately wiped off the screen.
    We need a better approach to remember what was
    drawn to the screen and where. **

    *

    5. Spritely Will Do It

    First, we add an entity array to keep track
    of all entities. This array will hold a
    reference to all touches, bubbles,
    particles and any other dynamic thing we
    want to add to the game.
    // put this at start of program 
    entities: [], 
    Let’s create a Touch class that draws a
    circle at the point of contact, fades it out
    and then removes it.
    POP.Touch = function(x, y) { 
    
        this.type = 'touch';    // we'll 
    need this later 
        this.x = x;             // the x coordinate 
        this.y = y;             // the y coordinate 
        this.r = 5;             // the radius 
        this.opacity = 1;       // initial 
    opacity; the dot will fade out 
        this.fade = 0.05;       // amount by
     which to fade on each game tick 
        this.remove = false;    // flag for
     removing this entity. POP.update 
                                // will take
     care of this 
    
        this.update = function() { 
            // reduce the opacity accordingly  
            this.opacity -= this.fade; 
            // if opacity if 0 or less, 
     flag for removal 
            this.remove =
     (this.opacity < 0) ? true : false; 
        }; 
    
        this.render = function() { 
            POP.Draw.circle
    (this.x, this.y, this.r, 'rgba
    (255,0,0,'+this.opacity+')'); 
        }; 
    
    }; 
    The Touch class sets a number of properties
    when initiated. The x and y coordinates are
    passed as arguments, and we set the radius
    this.r to 5 pixels. We also set an initial
    opacity to 1 and the rate by which the
    touch fades to 0.05. There is also a remove
    flag that tells the main game loop whether
    to remove this from the entities array.
    Crucially, the class has two main methods:
    update and render. We will call these from
    the corresponding part of our game loop.
    We can then spawn a new instance of Touch in
    the game loop, and then move them via
    the update method:
    // POP.update function 
    update: function() { 
    
        var i; 
    
        // spawn a new instance of Touch 
        // if the user has tapped the screen 
        if (POP.Input.tapped) { 
            POP.entities.push(new POP.Touch 
    (POP.Input.x, POP.Input.y)); 
            // set tapped back to false 
            // to avoid spawning a new touch 
            // in the next cycle 
            POP.Input.tapped = false; 
        } 
    
        // cycle through all entities and  
    update as necessary 
        for (i = 0; i < POP.entities.
    length; i += 1) { 
            POP.entities[i].update(); 
    
            // delete from array if remove property 
            // flag is set to true 
            if (POP.entities[i].remove) { 
                POP.entities.splice(i, 1); 
            } 
        } 
    
    }, 
    Basically, if POP.Input.tapped is true,
    then we add a new instance of POP.Touch to
    our entities array. We then cycle through the
    entities array, calling the update method
    for each entity. Finally, if the entity is
    flagged for removal, we delete it from the array.
    Next, we render them in the POP.render function.
    // POP.render function 
    render: function() { 
    
        var i; 
    
       POP.Draw.rect(0, 0, POP.WIDTH, 
     POP.HEIGHT, '#036');
    
        // cycle through all entities and  
    render to canvas 
        for (i = 0; i < POP.
    entities.length; i += 1) { 
            POP.entities[i].render(); 
        } 
    
    }, 
    Similar to our update function, we cycle
    through the entities and call their render
    method to draw them to the screen.
    So far, so good. Now we’ll add a Bubble class
    that will create a bubble that floats up for
    the user to pop.
    POP.Bubble = function() { 
    
        this.type = 'bubble'; 
        this.x = 100; 
        this.r =
     5;                // the radius of the bubble 
        this.y = POP.HEIGHT +
     100; // make sure it starts off screen 
        this.remove = false; 
    
        this.update = function() { 
    
            // move up the screen by 1 pixel 
            this.y -= 1; 
    
            // if off screen, flag for removal 
            if (this.y < -10) { 
                this.remove = true; 
            } 
    
        }; 
    
        this.render = function() { 
    
            POP.Draw.circle 
    (this.x, this.y, this.r, 'rgba(255,255,255,1)'); 
        }; 
    
    }; 
    The POP.Bubble class is very similar to the
    Touch class, the main differences being that
    it doesn’t fade but moves upwards. The motion
    is achieved by updating the y position,
    this.y, in the update function. Here, we also
    check whether the bubble is off screen; if so,
    we flag it for removal.
    Note: We could have created a base Entity class
    that both Touch and Bubble inherit from. But,
    I’d rather not open another can of worms about
    JavaScript prototypical inheritance versus
    classic at this point.
    // Add at the start of the program 
    // the amount of game ticks until 
    // we spawn a bubble 
    nextBubble: 100, 
    
    // at the start of POP.update 
    // decrease our nextBubble counter 
    POP.nextBubble -= 1; 
    // if the counter is less than zero 
    if (POP.nextBubble < 0) { 
        // put a new instance of bubble into 
     our entities array 
        POP.entities.push(new POP.Bubble());
         // reset the counter with a random value 
        POP.nextBubble =
     ( Math.random() * 100 ) + 100; 
    } 
    Above, we have added a random timer to our
    game loop that will spawn an instance of
    Bubble at a random position. At the start
    of the game, we set nextBubble with a value
    of 100. This is subtracted on each game tick
    and, when it reaches 0, we spawn a bubble and
    reset the nextBubble counter.

    6. Putting It Together

    First of all, there is not yet any notion of
    collision detection. We can add that with a
    simple function. The math behind this is
    basic geometry, which you can
    // this function checks if two circles overlap 
    POP.collides = function(a, b) { 
    
            var distance_squared =
     ( ((a.x - b.x) * (a.x - b.x)) + 
                                    ((a.y - b.y)
     * (a.y - b.y))); 
    
            var radii_squared =
     (a.r + b.r) * (a.r + b.r); 
    
            if (distance_squared < radii_squared) { 
                return true; 
            } else { 
                return false; 
            } 
    }; 
    
    // at the start of POP.update, we set a  
    flag for checking collisions 
        var i, 
            checkCollision = false; // we only 
     need to check for a collision
                                    // if the user
     tapped on this game tick
    
    // and then incorporate into the main logic 
    
    if (POP.Input.tapped) { 
        POP.entities.push(new POP.Touch 
    (POP.Input.x, POP.Input.y)); 
        // set tapped back to false 
        // to avoid spawning a new touch 
        // in the next cycle 
        POP.Input.tapped = false; 
        checkCollision = true; 
    
    } 
    
    // cycle through all entities and  
    update as necessary 
    for (i = 0; i < POP.entities.length; i += 1) { 
        POP.entities[i].update();
    
        if (POP.entities[i].type ===
     'bubble' && checkCollision) {
            hit = POP.collides(POP.entities[i], 
                                {x: POP.Input. 
    x, y: POP.Input.y, r: 7});
            POP.entities[i].remove = hit; 
        } 
    
        // delete from array if remove property 
        // is set to true
        if (POP.entities[i].remove) { 
            POP.entities.splice(i, 1); 
        } 
    } 
    The bubbles are rather boring; they all
    travel at the same speed on a very predictable
    trajectory. Making the bubbles travel at
    random speeds is a simple task:
    POP.Bubble = function() { 
    
        this.type = 'bubble'; 
        this.r = (Math.random() * 20) + 10; 
        this.speed = (Math.random() * 3) + 1; 
    
        this.x = (Math.
    random() * (POP.WIDTH) - this.r); 
        this.y = POP.HEIGHT +
     (Math.random() * 100) + 100; 
    
        this.remove = false; 
    
        this.update = function() { 
    
            this.y -= this.speed; 
    
        // the rest of the class is unchanged 
    And let’s make them oscillate from side to
    side, so that they are harder to hit:
    // the amount by which the bubble 
        // will move from side to side 
        this.waveSize = 5 + this.r; 
        // we need to remember the original 
        // x position for our sine wave calculation 
        this.xConstant = this.x; 
    
        this.remove = false; 
    
        this.update = function() { 
    
            // a sine wave is commonly a 
     function of time 
            var time = new Date().getTime() * 0.002; 
    
            this.y -= this.speed;
            // the x coordinate to follow a sine wave 
            this.x = this.waveSize *
     Math.sin(time) + this.xConstant; 
    
        // the rest of the class is unchanged 
    Again, we’re using some basic geometry to
    achieve this effect; in this case, a sine wave.
    While you don’t need to be a math whiz to
    make games, basic understanding goes a long way.
    The article
    Animations With JavaScript"

    should get you started.
    Let’s also show some statistics on screen.
    To do this, we will need to track various
    actions throughout the game.
    Put the following code, along with all of
    the other variable declarations, at the beginning
    of the program.
    // this goes at the start of the program 
    // to track players's progress 
    POP.score = { 
        taps: 0, 
        hit: 0, 
        escaped: 0, 
        accuracy: 0 
    }, 
    Now, in the Bubble class we can keep track
    of POP.score.escaped when a bubble goes off screen.
    // in the bubble class, when a bubble makes it to 
    // the top of the screen
        if (this.y < -10) {
            POP.score.escaped += 1; // update score
            this.remove = true;
        } 
    In the main update loop, we increase POP.
    score.hit accordingly:
    // in the update loop 
    if (POP.entities[i].type ===
     'bubble' && checkCollision) { 
        hit = POP.collides(POP.entities[i], 
                            {x: POP.Input.x, y: POP.
    Input.y, r: 7});
        if (hit) { 
            POP.score.hit += 1; 
        } 
    
        POP.entities[i].remove = hit; 
    } 
    In order for the statistics to be accurate,
    we need to record all of the taps
    the user makes:
    // and record all taps 
    if (POP.Input.tapped) { 
        // keep track of taps; needed to 
        // calculate accuracy 
        POP.score.taps += 1; 
    Accuracy is obtained by dividing the number
    of hits by the number of taps,
    multiplied by 100, which gives us a nice
    percentage. Note that ~~(POP.score.accuracy)
    is a quick way (i.e. a hack) to round floats
    down to integers.
    // Add at the end of the update loop 
    // to calculate accuracy 
    POP.score.accuracy =
     (POP.score.hit / POP.score.taps) * 100; 
    POP.score.accuracy = isNaN(POP.score.accuracy) ? 
        0 :
        ~~(POP.score.accuracy); 
     // a handy way to round floats
    Lastly, we use our POP.Draw.text to display
    the scores in the main update function.
    // and finally in the draw function 
    POP.Draw.text
    ('Hit: ' + POP.score.hit, 20, 30, 14, '#fff'); 
    POP.Draw.text
    ('Escaped: ' + POP.score.escaped,
     20, 50, 14, '#fff'); 
    POP.Draw.text
    ('Accuracy: ' + POP.score.accuracy +
     '%', 20, 70, 14, '#fff'); 

    7. Spit And Polish

    There’s a common understanding that a
    playable demo can be made in a couple of hours,
    but a polished game takes days, week,
    months or even years!
    We can do a few things to improve the visual
    appeal of the game.

    Particle Effects

    Most games boast some form of particle
    effects, which are great for explosions.
    What if we made a bubble explode into many
    tiny bubbles when it is popped, rather than
    disappear instantly?
    Take a look at our Particle class:
    POP.Particle = function(x, y,r, col) { 
    
        this.x = x; 
        this.y = y; 
        this.r = r; 
        this.col = col; 
    
        // determines whether particle will 
        // travel to the right of left 
        // 50% chance of either happening 
        this.dir =
     (Math.random() * 2 > 1) ? 1 : -1; 
    
        // random values so particles do not 
        // travel at the same speeds 
        this.vx = ~~(Math.random() * 4) * this.dir; 
        this.vy = ~~(Math.random() * 7); 
    
        this.remove = false; 
    
        this.update = function() { 
    
            // update coordinates 
            this.x += this.vx; 
            this.y += this.vy; 
    
            // increase velocity so particle 
            // accelerates off screen 
            this.vx *= 0.99; 
            this.vy *= 0.99; 
    
            // adding this negative amount to the 
            // y velocity exerts an upward pull on 
            // the particle, as if drawn to the 
            // surface 
            this.vy -= 0.25;
    
            // off screen 
            if (this.y < 0) { 
                this.remove = true; 
            } 
    
        };
    
        this.render = function() { 
            POP.Draw.circle 
    (this.x, this.y, this.r, this.col); 
        }; 
    
    }; 
    It’s fairly obvious what is going on here.
    Using some basic acceleration so that the
    particles speed up as the reach the surface
    is a nice touch. Again, this math and physics
    are beyond the scope of this article, but for
    those interested,
    To create the particle effect, we push several
    particles into our entities array
    whenever a bubble is hit:
    // modify the main update function like so: 
    if (hit) { 
        // spawn an explosion 
        for (var n = 0; n < 5; n +=1 ) { 
            POP.entities.push(new POP.Particle( 
                POP.entities[i].x, 
                POP.entities[i].y, 
                2, 
                // random opacity to 
     spice it up a bit
                'rgba
    (255,255,255,'+Math.random()*1+')'
            )); 
        } 
        POP.score.hit += 1; 
    } 

    Waves

    Given the underwater theme of the game,
    adding a wave effect to the top of the screen would be a nice touch. We can do this by drawing a number of overlapping circles to give the illusion of waves:
    // set up our wave effect; 
    // basically, a series of overlapping circles 
    // across the top of screen 
    POP.wave = { 
        x: -25, // x coordinate of first circle 
        y: -40, // y coordinate of first circle 
        r: 50, // circle radius 
        time: 0, // we'll use this in 
    calculating the sine wave 
        offset: 0 // this will be the
     sine wave offset 
    }; 
    // calculate how many circles we need to 
    // cover the screen's width
    POP.wave.total =
     Math.ceil(POP.WIDTH / POP.wave.r) + 1; 
    Add the code above to the POP.init function.
    POP.wave has a number of values that we’ll
    need to draw the waves.
    Add the following to the main update function.
    It uses a sine wave to adjust the position of
    the waves and give the illusion of movement.
    // update wave offset 
    // feel free to play with these values for 
    // either slower or faster waves 
    POP.wave.time = new Date().getTime() * 0.002; 
    POP.wave.offset =
     Math.sin(POP.wave.time * 0.8) * 5; 
    All that’s left to be done is to draw the waves,
    which goes into the render function.
    // display snazzy wave effect 
    for (i = 0; i < POP.wave.total; i++) { 
    
        POP.Draw.circle(
                    POP.wave.x + POP.wave.
    offset +  (i * POP.wave.r), 
                    POP.wave.y,
                    POP.wave.r, 
                    '#fff'); 
    } 
    Here, we’ve reused our sine wave solution for
    the bubbles to make the waves move gently to
    and fro. Feeling seasick yet?

    Final Thoughts

    Phew! That was fun. Hope you enjoyed this short
    forage into tricks and techniques for making
    an HTML5 game. We’ve managed to create a very
    simple game that works on most smartphones as
    well as modern browsers. Here are some things
    you could consider doing:
    • Store high scores using local storage.
    • Add a splash screen and a “Game over” screen.
    • Enable power-ups.
    • Add audio. Contrary to what I said at the
    • beginning of this article, this isn’t
    • , just a bit of a headache. One technique is
    • to use audio sprites (kind of like CSS image
    • sprites); Remy Sharp breaks it down 6.
    • Let your imagination run wild!
    If you are interested in further exploring the
    possibilities of mobile HTML5 games,
    I recommend test-driving a couple of frameworks
    to see what works for you. Juho Vepsäläinen
    If you’re willing to invest a little cash,
    then Impact is a great starting point, with
    thorough documentation and lively helpful forums.
    And the impressive X-Type demonstrates what is
    possible. Not bad, eh?
    (al) (jc) *

    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&