原來以為象坦克大戰(zhàn)、超級瑪麗之類的小游戲,開始畫面里面的磚塊字是靜態(tài)圖片,現(xiàn)在才知道原來都是動態(tài)貼圖貼出來的,下面用 HTML5 的繪圖功能,咱也太做一個坦克大決戰(zhàn)的開始畫面,順便研究一下點陣字。
一、點陣字
貼圖實際上和點陣字沒有多大區(qū)別,唯一的區(qū)別就是把點用小圖片代替了而已,下面是一個點陣字的小程序,你可以輸入漢字或者英文字母,然后程序就會分析并生成文字的點陣,然后把它顯示出來。至于怎么分析并生成點陣,思路如下:
1、將文字用 ctx.fillText 方法畫到一塊內(nèi)存畫布上,前景色為黑,背景色為白
2、讀取畫布的每一個像素,并用相應的符號代替,組成字符串
這里有一個問題,內(nèi)存畫布應該多大?我的解決辦法是,盡可能大,保證無論什么字體都不會出界。
在分析完像素的過程中,同時可以記錄下文字的寬度和高度,等分析完成以后,再一次生成一塊新的畫布,這一次可以和文字大小更好相等。
還有一個問題就是文字太小的時候,字體就有點失真,這應該就是一個分辨率的問題,小字體人的肉眼看不清的,程序一樣也分析不清楚。
所以小尺寸的字體需要經(jīng)過專門的設計,像坦克大戰(zhàn)上的字體那樣。
二、磚塊字
知道了點陣子的原理,實現(xiàn)磚塊字就很簡單了,這里是一副資源圖片,磚塊就是從里面截取的:
磚塊很小,在圖片的中間靠右下方,我們玩的坦克大戰(zhàn)游戲里面每一關的地圖就是由這么簡單一個圖片生成的,真是沒想到啊。
下面是磚塊字的點陣數(shù)據(jù),這里只有一部分,剛好組成游戲開機畫面里面的:BATTLE CITY 和游戲結(jié)束畫面里面的
三、代碼
因為時間比較緊張,代碼寫的比較丑,代碼里面用到了一個 jsgame.js,這是我自己對 HTML5 2D 功能進行了一個簡單的包裝,模仿了 pygame 的部分接口樣式。
經(jīng)過封裝以后,可以看出來,繪圖相關的代碼就非常簡單了,其他主要都是運算邏輯代碼。
代碼 Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title></title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <script type="text/javascript" language="javascript" src="jsgame.js"></script> </head> <body> <canvas id="html5_08_1" width="180" height="180" style=" background-color: black"> 你的瀏覽器不支持 Canvas 標簽,請使用 Chrome 瀏覽器 或者 FireFox 瀏覽器 </canvas> 文本:<input type="text" id="text" value="博客園" /> 字號:<input type="text" id="size" value="16" size="2" /> 字體:<select id="fontName"> <option>宋體</option> <option>楷體_GB2312</option> <option>隸書</option> <option>Kristen ITC</option> <option>Harrington</option> </select> <input type="checkbox" id="ckBold" />黑體 <input type="checkbox" id="ckitalic" />斜體 <input type="button" id="btnStart" disabled value="處理" onclick="draw_pixel_text()" /> <br/><textarea wrap="off" rows="20" cols="120" id="txtResult" ></textarea> <p/> <img alt="坦克大戰(zhàn)的資源圖片" src="http://images.cnblogs.com/cnblogs_com/myqiao/sprites.gif"/><br/> <canvas id="html5_08_2" width="480" height="200" style=" background-color: black"> 你的瀏覽器不支持 Canvas 標簽,請使用 Chrome 瀏覽器 或者 FireFox 瀏覽器 </canvas><br/> <input type="button" id="btn_draw" value="繪制磚塊字" onclick="draw_brick_text()" /> <script type="text/javascript"> draw_pixel_text(); function draw_pixel_text(){ var display= Display.attach(document.getElementById("html5_08_1")); document.getElementById("btnStart").setAttribute("disabled","true"); document.getElementById("txtResult").value=""; display.clear(); var text=document.getElementById("text").value var size=document.getElementById("size").value var font=new Font(); font.bold=document.getElementById("ckBold").checked; font.italic=document.getElementById("ckitalic").checked; font.name=document.getElementById("fontName").value; var sur=font.render(text,size); display.draw(sur,10,10); var str=''; for(var y=0;y<sur.height;y++){ for(var x=0;x<sur.width;x++){ if((sur.get_pixel(x,y)[0]<255)) str=str+'龍'; else str=str+' '; } str=str+'n'; } document.getElementById("txtResult").value=str; document.getElementById("btnStart").removeAttribute("disabled"); } ///====================================================================== ///下面的代碼是繪制磚塊字 //截斷字符,每 7 個一組 function chunk(str,len){ var count=0; var list=[]; var temp=[]; var times=0; for(var i=0;i<str.length;i++){ if(count<len){ temp.push(str[i]) count++; }else{ count=0; list[times]=temp; temp=[]; temp.push(str[i]) count++; times++; } } list[times]=temp; return list; } //字母和對應的點陣數(shù)據(jù) var keys="abcegilmortvy"; var values=["0011100011011011000111100011111111111000111100011", "1111110110001111000111111110110001111000111111110", "0011110011001111000001100000110000001100110011110", "1111110110000011000001111100110000011000001111110", "0011111011000011000001100111110001101100110011111", "1111110001100000110000011000001100000110001111110", "1100000110000011000001100000110000011000001111110", "1100011111011111111111111111110101111000111100011", "0111110110001111000111100011110001111000110111110", "1111110110001111000111100111111110011011101100111", "1111110001100000110000011000001100000110000011000", "1100011110001111000111110111011111000111000001000", "1100110110011011001100111100001100000110000011000"]; var game2=new JsGame(); //載入圖片 var img=new Image(); img.src="data:image/gif;base64,......";//省略四個字節(jié) var bricks=[]; img.onload=function(){ //圖片載入后,將磚塊的部分從中間截取出來,并分為四小部分 var temp= new Surface(img).subsurface(56,64,8,8) bricks[0]=temp.subsurface(0,0,4,4) bricks[1]=temp.subsurface(4,0,4,4) bricks[2]=temp.subsurface(0,4,4,4) bricks[3]=temp.subsurface(4,4,4,4) } //檢測資源是否裝載完畢 game2.is_ready(function(){ return img.complete }); //開始繪制 function draw_brick_text(){ //如果正在繪制,則停止 game2.stop() //綁定畫布 var display= new Display.attach(document.getElementById("html5_08_2")); //清空畫布 display.clear(); //要繪制的字符串 var text='BATTLECITY'.toLowerCase(); //將每個字符的點陣數(shù)據(jù)截成 7 段,即每個字符都是 7*7 的點陣,方便繪制 var alph_bits=[]; for(var i=0;i<text.length;i++) for(var index=0;index<keys.length;index++) if(keys[index]==text[i]) alph_bits.push(chunk(values[index],7)); var which=0; var p_row=0; var p_col=0; var surface= new Surface(28,28); game2.loop(function(){ if(alph_bits[which][p_row][p_col]==1){ var temp=null; if((p_row%2)==0){ if((p_col%2)==0) temp=bricks[0]; else temp=bricks[1]; } else{ if((p_col%2)==0) temp=bricks[2]; else temp=bricks[3]; } surface.draw(temp,p_col*4,p_row*4) display.save() display.scale(2,2) if(which<6) display.draw(temp,which*32+p_col*4+20,p_row*4+20); else display.draw(temp,(which-5)*32+p_col*4+20,p_row*4+56); display.restore() } p_col++ if((p_col%7)==0){ p_col=0 p_row++ if((p_row%7)==0){ p_row=0; p_col=0; which++; if(which==text.length) game2.stop() } } }) } </script> </body> </html>