2011年4月28日 星期四

以HTML5畫CropCircle--save() & restore() & clip()

Your browser does not support the canvas element. 這個麥田圈不是很容易"反向工程",不過也剛好可以讓Jimmy's papa可以練習下列幾個重要的canvas函數,但是不知道製作麥田圈的"地外文明"人士是如何辦到的,Jimmy's papa試過很多方式微調參數,想讓中間剪裁出來的圓圈裡頭的黑白條紋,可以很精準的對應到兩旁同心圓的白黑條紋,可惜都會有些許的空隙出現,Jimmy's papa在想是否因為採用2d的作圖方式才會產生如此落差呢?
context.save()       //目前設定狀態存入堆疊
context.restore()    //回存設定狀態取自堆疊
context.translate()  //位移矩陣
context.rotate()     //旋轉矩陣
context.clip()       //剪裁遮罩
<canvas id="myCropCircle0426" width="600" height="300" style="border:1px solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>

<script type="text/javascript">
<!--

function drawTwinCircles(context,centerX,centerY,radius,d)
{
    context.save();
    context.translate(450,-150);
    context.rotate(Math.PI*2/4);
    //-----------
    context.fillStyle="black";
    context.beginPath();        
    context.arc(centerX+radius/6+d,centerY,radius/6,0, 2*Math.PI,false);
    context.fill();
    context.beginPath();        
    context.arc(centerX+radius*2-radius/6-d,centerY,radius/6,0, 2*Math.PI,false);
    context.fill();
    //-----------
    context.beginPath();
    context.arc(300,150,125-15,0,Math.PI*2,true);
    context.fill();
    context.lineWidth=10;
    context.strokeStyle="white"; 
    context.stroke();    


    context.restore();
}


function drawTwinConcentricCircles(context,centerX,centerY,radius,d)
{
    context.save();
    for (var i=6;i>0;i--)
    {
        if((i%2)==0)
            context.fillStyle="black";
        else
            context.fillStyle="white";
        context.beginPath();        
        context.arc(centerX+radius/6+d,centerY,radius/6*i,0, 2*Math.PI,false);
        context.fill();
        context.beginPath();        
        context.arc(centerX+radius*2-radius/6-d,centerY,radius/6*i,0, 2*Math.PI,false);
        context.fill();

    }


    context.restore();
}


function drawFloatTwinConcentricCircles(context,centerX,centerY,radius,d)
{
    context.save();
    context.translate(450,-150);
    context.rotate(Math.PI*2/4);

    // Create a circular clipping path        
    context.beginPath();
    context.arc(300,150,125-15,0,Math.PI*2,true);
    context.clip();

    context.beginPath();
    context.arc(300,150,125-15,0,Math.PI*2,true);
    context.fill();

    for (var i=6;i>0;i--)
    {
        if((i%2)==0)
            context.fillStyle="white";
        else
            context.fillStyle="black";
        context.beginPath();        
        context.arc(centerX+radius/6+d,centerY,radius/6*i,0, 2*Math.PI,false);
        context.fill();
        context.beginPath();        
        context.arc(centerX+radius*2-radius/6-d,centerY,radius/6*i,0, 2*Math.PI,false);
        context.fill();
    
    }


    context.restore();
}



    var canvas=document.getElementById("myCropCircle0426");
    var context=canvas.getContext("2d");

    var d = 3;

    var draw1=setTimeout("drawTwinCircles(context,150,150,150,d)",1000);
    var draw2=setTimeout("drawTwinConcentricCircles(context,150,150,150,d)",2000);
    var draw3=setTimeout("drawFloatTwinConcentricCircles(context,150,150,150,d)",3000);


-->
</script>

2011年4月23日 星期六

Joule Thief--焦耳神偷 吸" 電 "大法

Jimmy's papa最近在看很新奇的漩渦數學(不是火影忍者的漩渦鳴人喔!)時,不小心看到有人介紹Joule Thief這個簡單的電路,很好奇看完YouTube一堆影片後,Jimmy's papa在想如果線圈做得夠大的話,吸到的電不知道夠不夠啟動冰箱冷氣啊?

這段影片介紹如何以便宜的電子元件製作Joule Thief電路的LED照明,讓廢電池起死回生

Jimmy's papa還沒時間仔細研究這段影片,不過似乎是在實驗說12伏特的蓄電池可以用來驅動9瓦的省電燈泡

2011年4月20日 星期三

開始教Jimmy用BricxCC寫NXC程式

今天晚上教Jimmy在Ubuntu上用BricxCC寫NXC程式,就是很那種簡單的PlayTone程式,編譯完後,再以JNXT/Scratch將.rxe檔案Push到NXT機器人上,最後是執行程式,然後是回頭再次修改參數,當然我知道寫code對Jimmy來說太難了,但是我初步只想讓他對整個流程有個粗淺的印象

以HTML5畫CropCircle---外星切派法

這個麥田圈像不像切好的派或披薩,原本Jimmy's papa以為不過就是畫個派而已,哪知道怎麼試就是畫不出來,原本以為只將黑派白派跟圈圈作互斥或(xor)合成運算,就會黑的變白的,白的變黑的,但結果不管黑白統統被蓋掉是變成了白圈圈,幸好Jimmy's papa冰雪聰明找到了解決的方法,不過過程有點複雜,很難解釋給Jimmy小朋友他爸爸是怎麼做到的,或許就說這是外星人切派法吧!!
對了,要看到完整的麥田圈需要直接點入這篇文章才可
Your browser does not support the canvas element.
<script type="text/javascript">
<!--


function drawPie(context,centerX,centerY,radius,startingAngle, 
    endingAngle, antiClockwise,fillStyle,globalCompositeOperation)
{
    context.globalCompositeOperation = globalCompositeOperation;
        context.beginPath();
    context.arc(centerX,centerY,radius,startingAngle, endingAngle,antiClockwise);
        context.lineTo(centerX, centerY);
    context.closePath();
 
    context.lineWidth=1;
    context.fillStyle=fillStyle;
    context.fill();
}

function drawBlackPie(context,centerX,centerY,radius,startingAngle, 
    endingAngle, antiClockwise,fillStyle,globalCompositeOperation)
{

    drawPie(context,centerX,centerY,radius,startingAngle, 
    endingAngle, antiClockwise,fillStyle,globalCompositeOperation);
    drawPie(context,centerX,centerY,radius,startingAngle, 
    endingAngle, antiClockwise,fillStyle,globalCompositeOperation);
    drawPie(context,centerX,centerY,radius*0.95,startingAngle, 
    endingAngle, antiClockwise,fillStyle,globalCompositeOperation);
}

function drawWhitePie(context,centerX,centerY,radius,startingAngle, 
    endingAngle, antiClockwise,fillStyle,globalCompositeOperation)
{

    drawPie(context,centerX,centerY,radius,startingAngle, 
    endingAngle, antiClockwise,fillStyle,globalCompositeOperation);
    drawPie(context,centerX,centerY,radius*0.95,startingAngle, 
    endingAngle, antiClockwise,fillStyle,globalCompositeOperation);
    
}

    var canvas=document.getElementById("myCropCircle0420");
    var context=canvas.getContext("2d");
 
    var centerX = 150;
    var centerY = 150;
    var radius = 150;
    //var lineWidth = 1;
 
    


    context.beginPath();        
    context.arc(centerX,centerY,radius,0, 2*Math.PI,false);
 
    context.fillStyle="white";
    context.fill();
    context.lineWidth=2;
    context.strokeStyle="black"; 
    context.stroke();



    var i=0;
    while (i<18)
    {
      drawBlackPie(context,centerX,centerY,radius,Math.PI*(1.5+i/9),Math.PI*(1.5+(++i)/9),false,'black','xor');
      drawWhitePie(context,centerX,centerY,radius,Math.PI*(1.5+i/9), Math.PI*(1.5+(++i)/9),false,'black','xor');
    }


    var dbb=setTimeout("drawPie(context,centerX,centerY*3/8,radius/3.2,0, Math.PI*2,false,'black','xor')",1000);
    var dbb=setTimeout("drawPie(context,centerX,centerY*4/3,radius/1.7,0, Math.PI*2,false,'black','xor')",1500);
    var llb=setTimeout("drawPie(context,centerX*3/7,centerY*2/3,radius/8,0, Math.PI*2,false,'black','xor')",2000);
    var rlb=setTimeout("drawPie(context,centerX*11/7,centerY*2/3,radius/8,0, Math.PI*2,false,'black','xor')",2500);
</script>

2011年4月14日 星期四

以Canvas globalCompositeOperation屬性製作CropCircle

Jimmy's papa很喜歡麥田圈的美麗又兼具高度對稱性,早就想讓Jimmy試著用Scratch畫畫看,可惜目前Scratch的畫圖功能有點陽春,無法作到兩個圖形的各種合成操作,幸好HTML canvas提供globalCompositeOperation屬性,可以很輕鬆的寫出javascript程式碼畫出簡單的麥田圈,嗯!晚上再一圈一圈的畫給Jimmy看,讓他看看爸爸也可以畫出外星人的麥田圈,呵呵!!!

如果你看的左邊大圖(程式線上畫出來的)與右邊小圖是不一樣的話,你的瀏覽器有可能是IE or Opera
Your browser does not support the canvas element.
畫麥田圈的javascript程式碼如下
var c=document.getElementById("JimmyScratchLab_myCropCircle0413");
var context=c.getContext("2d");
  context.fillStyle   = '#000000';
  context.strokeStyle = '#f00';
  context.lineWidth   = 4;

  context.beginPath();
  context.arc(150, 150, 150, 0, 360, false);
  context.closePath();
  context.fill();

context.globalCompositeOperation = "xor";

  context.beginPath();  
  context.arc(150, 90, 60, 0, 360, false);  
  context.closePath();
  context.fill();

context.globalCompositeOperation = "xor";

  context.beginPath();  
  context.arc(100, 120, 60, 0, 360, false);  
  context.closePath();
  context.fill();

context.globalCompositeOperation = "xor";

  context.beginPath();  
  context.arc(100, 180, 60, 0, 360, false);  
  context.closePath();
  context.fill();

context.globalCompositeOperation = "xor";

  context.beginPath();  
  context.arc(150, 210, 60, 0, 360, false);  
  context.closePath();
  context.fill();

context.globalCompositeOperation = "xor";

  context.beginPath();  
  context.arc(205, 180, 60, 0, 360, false);  
  context.closePath();
  context.fill();

context.globalCompositeOperation = "xor";

  context.beginPath();  
  context.arc(205, 120, 60, 0, 360, false);  
  context.closePath();
  context.fill();
//-----------------
context.globalCompositeOperation = "xor";

  context.beginPath();  
  context.arc(100, 60, 30, 0, 360, false);  
  context.closePath();
  context.fill();

context.globalCompositeOperation = "xor";

  context.beginPath();  
  context.arc(50, 150, 30, 0, 360, false);  
  context.closePath();
  context.fill();

context.globalCompositeOperation = "xor";

  context.beginPath();  
  context.arc(100, 240, 30, 0, 360, false);  
  context.closePath();
  context.fill();

context.globalCompositeOperation = "xor";

  context.beginPath();  
  context.arc(200, 240, 30, 0, 360, false);  
  context.closePath();
  context.fill();

context.globalCompositeOperation = "xor";

  context.beginPath();  
  context.arc(250, 150, 30, 0, 360, false);  
  context.closePath();
  context.fill();

context.globalCompositeOperation = "xor";

  context.beginPath();  
  context.arc(200, 60, 30, 0, 360, false);  
  context.closePath();
  context.fill();
//--------------------------
context.globalCompositeOperation = "destination-out";

  context.beginPath();  
  context.arc(150, 150, 60, 0, 360, false);  
  context.closePath();
  context.fill();

//--------------------------
context.globalCompositeOperation = "copy";

  context.beginPath();  
  context.arc(150, 150, 20, 0, 360, false);  
  context.closePath();
  context.fill();

2011年4月13日 星期三

遊戲--Interlocked(3D拆積木)

通常Jimmy睡前半小時,我都會安排他"玩玩"子由數學Scratch小喵咪程式,今天剛好找到一個叫做Interlocked的3d解謎遊戲,風格跟Blockorz遊戲蠻類似的,遊戲的操控也很簡單,左下角有個小眼睛,點選它可以將鼠標切換成Glance tool(3df全方位瀏覽)或Pull tool(拉積木),晚上先讓他玩到第五關看看

2011年4月7日 星期四

測試HTML 3D Game

Jimmy's papa寫過一陣子flash 3d程式,覺得那是對程式設計者及使用者很糟糕的經驗,不僅套用的網頁不斷的使瀏覽器狂當,而且拖慢了電腦整體的效率(自從部落格放上flash廣告後,發現我的筆電的散熱風扇運動量也增加不少),為此還K了一陣子Adobe Alchemy技術,順便涉獵一下何謂LLVM,不過還是無助於解決問題,但是Jimmy's papa最近在研究的HTML5似乎可寫出效率不錯的3D網頁小遊戲,國外有人寫出輕薄短小的"3D Walker"有興趣的網友可以測試看看,現在Jimmy除了玩Scratch外,我也開始利用www.w3schools.com提供的小範例教Jimmy寫簡單的網頁,雖然他覺得爸爸教他的東西很難,不過當他自己做出一個簡單的海綿寶寶網頁,臉上也露出開心的笑容 目前Jimmy's papa在部落格上擺上測試用的3D Game Banner,還在想辦法加上一些特效
待續......