2015-06-02 15 views
11

Liên kết với bút mã của tôi hereLàm thế nào tôi có thể làm cho các chấm canvas HTML của tôi di chuyển tự nhiên hơn?

Tôi muốn có ý kiến ​​về cách tôi có thể làm cho các chấm vải chuyển động theo cách chất lỏng, lỏng hơn.

Tôi đã thử giới hạn hướng cho một số lần hiển thị nhất định (draw()), đã cải thiện nó một chút! Nhưng nó vẫn thiếu tính lưu loát, đi qua như cứng nhắc và 'cứng mã hóa'.

Câu lệnh chuyển đổi này là hướng đi được thiết lập, hoặc đã truyền một số nguyên ngẫu nhiên hoặc hướng trước đó.

switch (direction) { 
        case 1: 
         star.x--; 
         break; 
        case 2: 
         star.x++; 
         break; 
        case 3: 
         star.y--; 
         break; 
        case 4: 
         star.y++; 
         break; 
        case 5: 
         star.y--; 
         star.x--; 
         break; 
        case 6: 
         star.y--; 
         star.x++; 
         break; 
        case 7: 
         star.y++; 
         star.x++; 
         break; 
        case 8: 
         star.y++; 
         star.x--; 
         break; 
} 

Cảm ơn!

+2

Tôi sẽ sử dụng chức năng giảm tốc để giảm tốc/tăng tốc các hạt khi chúng thay đổi hướng. – Eduardo

+0

Tôi nghĩ rằng điều chính khiến nó trông "không tự nhiên" đối với tôi là tất cả chúng đều có những thay đổi hướng lớn về cơ bản cùng một lúc. Tất nhiên, tôi đang tưởng tượng họ như là lỗi như vậy .. –

Trả lời

11

Bạn có thể làm điều này bằng cách:

  • Tạo một spline hồng y dựa trên dòng ngẫu nhiên chỉ
  • Đi bộ dọc theo đường đó và vẽ một ngôi sao trên vị trí hiện tại

Tại sao hồng y spline? Một spline hồng y sẽ tạo ra một đường trơn tru giữa một tập hợp các điểm. Nếu cũng có giá trị độ căng. Bằng cách phóng đại giá trị độ căng (tức là ngoài phạm vi [0,1] bình thường) nó sẽ tạo ra các đường xoăn thay thế.

snapshot

// draw example lines 
var ctx = c.getContext("2d"), p = [0,100, 25,40, 50,70, 75,50, 100,80, 125,32, 150,100, 175,60]; 
ctx.font = "bold 16px sans-serif"; 

render(0); render(0.5); render(-2); 
ctx.setTransform(1,0,0,1,0, 110); 

render(-2, 3, "Segments: 3"); render(-2, 9, "Segments: 9"); render(-2, 25, "Segments: 25"); 

function render(t, seg, txt) { 
    ctx.beginPath(); 
    ctx.moveTo(0, 100); 
    ctx.curve(p, t, seg || 20); 
    ctx.stroke(); 
    ctx.fillText(txt ? txt : (!t ? "Plain poly-line" : "Cardinal, tension: " + t), 0, 20); 
    ctx.translate(200,0); 
} 

Chúng ta có thể tận dụng lợi thế của bất động sản này và vẽ một điểm dọc theo một dòng như vậy để tạo ra một phong trào chất lỏng-ish. Chuyển động có thể được tinh chế bằng cách de/tăng độ phân giải phân đoạn giữa mỗi dòng trong spline mà sẽ ảnh hưởng đến độ mượt cũng như tốc độ.

Các ưu điểm khác là chúng ta không phải tính toán bất kỳ thứ gì trong chính hình động (sẽ có "đỉnh" ban đầu khi thiết lập các điểm (cache)), chúng ta chỉ cập nhật con trỏ mảng và kết xuất. Và sự phân bố sẽ là khá ngay cả khi các điểm là các lực dọc theo các đường phân bố đồng đều (vô hình).

Làm thế nào để thực hiện nó có thể thay đổi tất nhiên - đây là một ví dụ về một cách tiếp cận:

Ví dụ thực hiện

Xác định một đối tượng sao (nó thực sự cần được prototyped nhưng vì lợi ích của bản demo):

function Star(ctx, xseg) { 

    var points = [],    // holds points for cardinal points 
     cPos = 0, oPos = -1,  // positions in line 
     len, 
     w = ctx.canvas.width, 
     x = -10, y = -10; 

    // this iterates and loop the point list    
    this.animate = function() { 
     cPos++; 

     if (cPos > len - 2) { 
      cPos = 0; oPos = -1; 
     } 

     var pos = cPos * 2; 
     x = points[pos]; 
     y = points[pos + 1]; 

     drawStar(); 
    } 

    // render some star 
    function drawStar() { 
     ctx.rect(x, y, 2, 2); 
    } 

    // This generate a set of random points, then converts those into 
    // points for a cardinal spline (linked as script). 
    function generatePath() { 
     var w = ctx.canvas.width, 
      h = ctx.canvas.height, 
      numOfSeg = 20, 
      dh = h/numOfSeg, 
      i= 0, l, x, y; 

     for(; i<= numOfSeg; i++) {   
      x = xseg + w/8 * Math.random(); 
      y = h - (i * dh + ((dh/2) * Math.random() - (dh/4))); 
      points.push(x, y); 
     } 

     points = curve(points, -2, 200 * Math.random() + 100); 
     l = points.length; 

     // adjust for out of edges 
     for(i = 0; i < l; i += 2) if (points[i] > w) points[i] -= w; 
     len = points.length/2; 
     cPos = parseInt(len * Math.random()); 
    } 
    generatePath(); 
} 

Full dụ

function Star(ctx, xseg) { 

    var points = [],    // holds points for cardinal points 
     cPos = 0, oPos = -1,  // positions in line 
     len, 
     w = ctx.canvas.width, 
     x = -10, y = -10; 

    this.animate = function() { 
    cPos++; 
    if (cPos > len - 2) { 
     cPos = 0; oPos = -1; 
    } 

    var pos = cPos * 2; 
    x = points[pos]; 
    y = points[pos + 1]; 

    drawStar(); 
    }; 

    function drawStar() { 
    ctx.moveTo(x + 2, y); 
    ctx.arc(x, y, 2, 0, Math.PI*2); 
    } 

    function generatePath() { 
    var w = ctx.canvas.width, 
     h = ctx.canvas.height, 
     numOfSeg = 20, 
     dh = h/numOfSeg, 
     i= 0, l, x, y; 

    for(; i <= numOfSeg; i++) {   
     x = xseg + w/8 * Math.random(); 
     y = h - (i * dh + ((dh/2) * Math.random() - (dh/4))); 
     points.push(x, y); 
    } 

    points = getCurvePoints(points, -2, (400 * Math.random() + 200)|0); 
    l = points.length; 

    for(i = 0; i < l; i += 2) if (points[i] > w) points[i] -= w; 
    len = points.length/2; 
    cPos = (len * Math.random())|0; 

    } 
    generatePath(); 
} 

// Main code 
var canvas = document.querySelector("canvas"), 
    ctx = canvas.getContext("2d"), 
    stars = [], 
    numOfStars = 100, 
    segs = canvas.width/numOfStars, 
    i = 0, 
    throttle = 0, 
    delay = 2; 

// create stars 
for(; i < numOfStars; i++) stars.push(new Star(ctx, i * segs - segs)); 

ctx.fillStyle = "#fff"; 
ctx.shadowColor ="#fff"; 
ctx.shadowBlur = 7; 

// ANIMATE 
(function animate() {  
    if (!throttle) { 
    ctx.clearRect(0, 0, canvas.width, canvas.height); 
    ctx.beginPath(); 
    for(var i = 0; i < stars.length; i++) stars[i].animate(); 
    ctx.fill(); 
    } 

    throttle++; 
    if (throttle === delay) throttle = 0; 

    requestAnimationFrame(animate); 
})(); 

Xem đồng de để thực hiện spline hồng y trong this answer.

Cách tiếp cận khác là sử dụng các hạt và biến đổi vận tốc bằng cách sử dụng ví dụ như một hàm xoang. Để làm việc này tối ưu, bạn có thể cần một tốc độ lưới để thay đổi ảnh hưởng đến một hạt dựa trên vị trí. Lưới có thể có hướng ngẫu nhiên và vận tốc.

+0

tại sao các dấu chấm dường như "vỗ"? (giống như những con bướm nhỏ) –

+0

@WoodrowBarlow nó thực sự là một trái từ một mã trước đó này được dựa trên. Tôi đã có mà sẽ mô phỏng mảnh vàng vào thời điểm đó. Tôi đang nghĩ đến việc xóa bỏ tính năng đó để đơn giản hóa mã. – K3N

+0

Hiệu ứng ánh sáng lung linh bị xóa, có thể tìm thấy mã trong [history] (http://stackoverflow.com/revisions/30606133/3). – K3N

Các vấn đề liên quan