2014-03-13 74 views
4

你好,你是一羣美妙的天才!將勾選的圖案添加到動態繪製的3人棋牌棋盤

我似乎已經達到了我在這裏的知識高峯,並希望有人能指出我在正確的方向。

我正在嘗試使用JavaScript和HTML 5畫布動態繪製一個3人棋牌/跳棋板。

到目前爲止,我已經想出了這個;

var canvas = document.getElementById('canvas') 
var length = canvas.height/2; 
var center = canvas.width/2; 

var rotation = ToRadians(60); 

var angle = ToRadians(30); 
var height = length * Math.cos(angle); 
var width = length * Math.sin(angle); 
while (rotation < Math.PI * 2) { 
    a = [center, length]; 
    b = [a[0] - height * Math.sin(rotation), a[1] + height * Math.cos(rotation)]; 
    c = [b[0] + width * Math.cos(rotation), b[1] + width * Math.sin(rotation)]; 
    d = [c[0] + width * Math.sin(angle + rotation), c[1] - width * Math.cos(angle + rotation)]; 

    //Drawing Main Frame and 6 segments 
    var c2 = canvas.getContext('2d'); 
    c2.fillStyle = '#f00'; 
    c2.strokeStyle = "#0f0"; 
    c2.beginPath(); 
    c2.moveTo(a[0], a[1]); 
    c2.lineTo(b[0], b[1]); 
    c2.lineTo(c[0], c[1]); 
    c2.lineTo(d[0], d[1]); 
    c2.closePath(); 
    c2.stroke(); 

    //Drawing first set of divides 
    ab1=[((a[0]+b[0])/2),((a[1]+b[1])/2)] 
    cd1=[((c[0]+d[0])/2),((c[1]+d[1])/2)] 
    ab2=[((a[0]+ab1[0])/2),((a[1]+ab1[1])/2)] 
    cd2=[((d[0]+cd1[0])/2),((d[1]+cd1[1])/2)] 
    ab3=[((b[0]+ab1[0])/2),((b[1]+ab1[1])/2)] 
    cd3=[((c[0]+cd1[0])/2),((c[1]+cd1[1])/2)] 

    c2.beginPath(); 
    c2.moveTo(ab1[0], ab1[1]); 
    c2.lineTo(cd1[0], cd1[1]);   
    c2.moveTo(ab2[0], ab2[1]); 
    c2.lineTo(cd2[0], cd2[1]);  
    c2.moveTo(ab3[0], ab3[1]); 
    c2.lineTo(cd3[0], cd3[1]); 
    c2.stroke(); 

    //Drawing second set of divides 
    bc1=[((c[0]+b[0])/2),((c[1]+b[1])/2)] 
    ad1=[((a[0]+d[0])/2),((a[1]+d[1])/2)] 
    bc2=[((c[0]+bc1[0])/2),((c[1]+bc1[1])/2)] 
    ad2=[((d[0]+ad1[0])/2),((d[1]+ad1[1])/2)] 
    bc3=[((b[0]+bc1[0])/2),((b[1]+bc1[1])/2)] 
    ad3=[((a[0]+ad1[0])/2),((a[1]+ad1[1])/2)] 

    c2.beginPath(); 
    c2.moveTo(bc1[0], bc1[1]); 
    c2.lineTo(ad1[0], ad1[1]);   
    c2.moveTo(bc2[0], bc2[1]); 
    c2.lineTo(ad2[0], ad2[1]);  
    c2.moveTo(bc3[0], bc3[1]); 
    c2.lineTo(ad3[0], ad3[1]); 
    c2.stroke(); 

    rotation += ToRadians(60); 
} 
function ToRadians(degrees) { 
    return degrees/(180/Math.PI); 
} 

小提琴:http://jsfiddle.net/yd7Wv/6529/

我對目前的代碼相當請,但我來點,當我需要添加的檢查模式,我徹底難倒。我幾乎不知道如何去做這件事,所以想知道是否有人可以指引我走向正確的方向。 我知道在這裏有一個普遍的共識,人們應該展示自己嘗試去做,但我根本不能! 任何指針,將不勝感激。

乾杯

+0

請在jsfiddle中重現此操作。 –

+0

小提琴鏈接添加 – Spitfire2k6

+0

酷板理念,如果我不在工作中,我很想有一個裂縫:P – alex

回答

5

你在看什麼與四邊形變換密切相關。

您可以將一個段(「三角形」)看作是剛剛扭曲的象限。

Fiddle demo

將會產生這樣的結果:

Board

讓我們從定義一些變量,我們需要計算和循環開始。

var w = canvas.width,    // width 
    h = canvas.height,    // height 
    cx = w * 0.5,     // center of board 
    cy = h * 0.5, 
    r = cx * 0.9,     // radius of board 
    pi2 = Math.PI * 2,    // cache 
    segments = 6,     // a hexagon based shape so 6 
    segment = pi2/segments,  // angle of each segment 
    hSegment = segment * 0.5,  // half segment for center line 
    ul, ur, bl, br,     // quad. corners 
    check = 0.25,     // interpolation interval (one check) 
    yc = 0, xc = 0,     // interpolation counters 
    toggle = false,     // for color 
    x, y = 0, i = 0;     // counters... 

允許通過定義它的外邊界的角部限定一個單一的四邊形正方形:

首先角將是板的中心上,使得一個很簡單:

var ul = { 
    x: cx, 
    y: cy} 

第二角將是右上:

ur = { 
    x: cx + r * Math.cos(hSegment) * 0.865, 
    y: cy + r * Math.sin(hSegment) * 0.865 
}; 

第三個右下角:

br = { 
    x: cx + r * Math.cos(segment), 
    y: cy + r * Math.sin(segment) 
}; 

而在去年,左下:

bl = { 
    x: cx + r * Math.cos(hSegment + segment) * 0.865, 
    y: cy + r * Math.sin(hSegment + segment) * 0.865 
}; 

如果我們繪製出這種形狀,我們會得到這樣的:

Quadrilateral outline

現在我們有了角落我們根本插每個在檢查間隔(0.25)的「方塊」中行,這將總共給我們5行。我們只會計數4,但我們也會使用下一個行與當前值。

爲了內插的兩個點,我們用一個簡單的函數,它有兩個點,一個標準值[0.0,1.0]:

function getInt(p1, p2, t) { 
    return { 
     x: p1.x + (p2.x - p1.x) * t, 
     y: p1.y + (p2.y - p1.y) * t, 
    } 
} 

我們創建一個循環,通過Y和X點進行迭代,所以我們可以做到這一點以系統的方式:

for(y = 0, yc = 0; y < 4; y++) { 
    for(x = 0, xc = 0; x < 4; x++) { 

     // for upper lines (ul-ur), get first row: 
     var l1a = getInt(ul, bl, yc), 
      l1b = getInt(ur, br, yc), 
      l2a = getInt(ul, bl, yc + check), 
      l2b = getInt(ur, br, yc + check), 

      c1 = getInt(l1a, l1b, xc), 
      c2 = getInt(l1a, l1b, xc + check), 
      c3 = getInt(l2a, l2b, xc + check), 
      c4 = getInt(l2a, l2b, xc); 

     ... draw shape ... 

     xc += check; 
    } 
    yc += check;   
} 

本節:

var l1a = getInt(ul, bl, yc),   // current line [0, 3] 
    l1b = getInt(ur, br, yc), 
    l2a = getInt(ul, bl, yc + check), // next line [1, 4] 
    l2b = getInt(ur, br, yc + check), 

計算外部垂直線上的插值點。這給了我們兩個新點,我們再使用來計算水平線上的點,使我們能夠計算出每個角點的「檢查」:

c1 = getInt(l1a, l1b, xc),   // corner 1 UL 
c2 = getInt(l1a, l1b, xc + check), // corner 2 UR (next line) 
c3 = getInt(l2a, l2b, xc + check), // corner 3 BR (next line) 
c4 = getInt(l2a, l2b, xc);   // corner 4 BL 

現在我們簡單地畫的角落,並填寫之間的多邊形:

ctx.beginPath(); 
ctx.moveTo(c1.x, c1.y); 
ctx.lineTo(c2.x, c2.y); 
ctx.lineTo(c3.x, c3.y); 
ctx.lineTo(c4.x, c4.y); 

ctx.fillStyle = toggle ? '#000' : '#fff'; 

要改變顏色,我們使用切換開關。

這種單一的部分將是這樣的:

Single segment

下一步是繪製所有領域。我們重新使用上面的代碼,並且每次只將畫布旋轉一段,然後再做一次切換。

當所有的代碼放在一起,我們得到這樣的:

for(; i < segments; i++) { // loop six segments 
    toggle = !toggle;   // alter color each segment 
    // loop quadrilateral grid 4x4 cells (5x5 lines exclusive) 
    for(y = 0, yc = 0; y < 4; y++) { 
     for(x = 0, xc = 0; x < 4; x++) { 

      // for upper lines (ul-ur), get first row: 
      var l1a = getInt(ul, bl, yc), 
       l1b = getInt(ur, br, yc), 
       l2a = getInt(ul, bl, yc + check), 
       l2b = getInt(ur, br, yc + check), 
       c1 = getInt(l1a, l1b, xc), 
       c2 = getInt(l1a, l1b, xc + check), 
       c3 = getInt(l2a, l2b, xc + check), 
       c4 = getInt(l2a, l2b, xc); 

      ctx.beginPath(); 
      ctx.moveTo(c1.x, c1.y); 
      ctx.lineTo(c2.x, c2.y); 
      ctx.lineTo(c3.x, c3.y); 
      ctx.lineTo(c4.x, c4.y); 
      ctx.fillStyle = toggle ? '#000' : '#fff'; 
      ctx.fill(); 
      toggle = !toggle; 
      xc += check; 
     } 
     yc += check;   // next segment line 
     toggle = !toggle;  // toggle per line as well 
    } 
    ctx.translate(cx, cy); // translate to center 
    ctx.rotate(segment);  // rotate one segment 
    ctx.translate(-cx, -cy); // translate back 
} 

現在,如果你願意等,你可以簡單地畫一個輪廓。

+1

+1做得好!你的解決方案還有創建Spitfire2k6可以用來放置他的棋子的多邊形邊界的附加好處。曾幾何時,我非常喜歡下象棋。 – markE

+1

@markE好點。我忘了它,但是,將每個段作爲一個多邊形存儲在一個數組中可以很容易地檢查邊界。我從來沒有進入國際象棋,但我確實感到生活本身就像一場國際象棋比賽:) – K3N

+0

+10!血腥的地獄男人,你是一個巫師!非常感謝你! – Spitfire2k6