2013-05-10 63 views
0

我爲必須使用任何物理形式的項目創建了此動畫。 我是一個總的初學者,太:)無論如何,這是我的項目現在:畫布中的球運動路徑以及其他想法?

Bouncing Balls

你可以設置重力和力量,然後點擊播放,並且只需拖放拍攝球。您可以更改這些值並點擊更新以查看效果。

我的問題是,我怎麼能創建一個效果,當我按比例按鈕(例如)我可以看到球的路徑?它是否複雜?正如我所說我是初學者,所以沒有複雜的代碼:)

另外,你有什麼想法讓項目更好嗎?任何額外的「物理」效果?或者,也許你知道一個網站,顯示HTML5/js中的明喻(請)效果的教程,所以我可以添加額外的效果到我的項目。

+0

您可以在球之間添加碰撞,也可以添加另一個滑塊,在其中更改復原(每次反彈時的能量損失量)或用可調粘度滑塊拖動空氣。 – fibonatic 2013-05-14 00:07:44

回答

1

一種可能性(因爲您每幀清除畫布)將會將球路徑繪製到輔助畫布上,而不會在每一幀清除。然後,當您清除第一幀時,在清除之後和渲染球之前渲染第二幀。

第二個畫布當然必須與第一個畫布的尺寸相同,以便所有球點正確排列。第二個畫布也應該有一個低於第一個的z-index,所以只有當你特別地將它渲染到第一個畫布時(即,當單選按鈕被選中時)才顯示它。

爲了減少收音機未檢查時的延遲,您可以跳過將球路徑畫到第二個畫布,儘管我不認爲您會看到任何性能的顯着提高。

對於每個幀更新,您將在第二個畫布上用像素或線(從前一個位置到當前位置)標記每個球的位置。

看你的代碼,你似乎很能幹,所以我跳過寫一個例子,因爲我認爲這將是你不錯的體驗:)

修改「的script.js」來源證明的解決方案

window.onload = function(){ 
    $("#canvas").hide(); 

    var howManyPaths = 0; 
    var showPath=false; 

    // SLIDERS 
    var gravitySlider = document.getElementById('gravitySlider'); 
    var gravityVal = document.getElementById('gravityValue'); 

    gravitySlider.onchange = function(){ 
     gravityVal.value = gravitySlider.value; 
    } 

    gravityVal.onkeyup = function(){ 
      gravitySlider.value = gravityVal.value;  
    } 

    var forceSlider = document.getElementById('forceSlider'); 
    var forceValue = document.getElementById('forceValue'); 

    forceSlider.onchange = function(){ 
     forceValue.value = forceSlider.value; 
    } 

    forceValue.onkeyup = function(){ 
      forceSlider.value = forceValue.value;  
    } 

    // GLOBAL VARIABLES 
    var test = false; 
    var gravityCount = $("#gravity").val(); 
    var forceCount = $("#rectangles").val();  

    // CSS : 
    var playCSS = document.getElementById("play"); 
    var restartCSS = document.getElementById("restart"); 
    var clickableCSS = document.getElementById("setup"); 
    var clickableBG = document.getElementById("img"); 

    //restartCSS.style.visibility="hidden"; 

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

    var canvas2 = document.getElementById("canvas2"); 
    var ctx2 = canvas2.getContext("2d"); 


    //var ctx; 
    var gravity = 9.86; 
    var forceFactor = 0.5; 
    var mouseDown = false; 
    var balls = new Array(); 
    var mousePos = new Array(); 

    // EVENT HANDLER 
    function onMouseDown(evt){ 
     mouseDown = true; 
     mousePos['downX'] = evt.pageX; 
     mousePos['downY'] = evt.pageY; 
    } 

    function onMouseUp(evt){ 
     mouseDown = false; 


     setup.style.visibility="visible"; 


     if(test == true && !(mousePos['downX'] < 200 && mousePos['downY'] < 150)){ 

     restartCSS.style.visibility="visible"; 

     forceFactor = forceCount; 



     balls.push(new ball(mousePos["downX"], 
          mousePos["downY"], 
          (evt.pageX - mousePos["downX"]) * forceFactor, 
          (evt.pageY - mousePos["downY"]) * forceFactor, 
          10 + (Math.random() * 10), 
          0.8, 
          randomColor() 
        )); 
     } 
     ctx2.clearRect(0, 0, canvas2.width, canvas2.height); 
    } 

    function onMouseMove(evt){ 
     mousePos['currentX'] = evt.pageX; 
     mousePos['currentY'] = evt.pageY; 
    } 

    function resizeWindow(evt){ 
     //canvas.height = 960; 
     //canvas.width = 720; 
     canvas.height = $(window).height()-6; 
     canvas.width = $(window).width(); 

     canvas2.height = $(window).height()-6; 
     canvas2.width = $(window).width(); 
    } 

    $(document).mousedown(onMouseDown); 
    $(document).mouseup(onMouseUp); 
    $(document).mousemove(onMouseMove); 

    $(window).bind("resize", resizeWindow); 

    // GRAPHICS CODE 
     function circle(x, y, r, col){ 
      ctx.beginPath(); 
      ctx.arc(x, y, r, 0, Math.PI*2, true); 
      ctx.closePath; 

      // fill   
      ctx.fillStyle = col; 
      ctx.fill(); 

      // stroke 
      ctx.lineWidth = r * 0.1; 
      ctx.strokeStyle = "#000000"; 
      ctx.stroke(); 
} 




function circlePath(x, y) 
{ 
    ctx2.clearRect(0, 0, canvas2.width, canvas2.height); 
    ctx2.fillStyle = '#3f4043'; 
    ctx2.fillRect(x, y, 5, 5); 
    ctx2.strokeStyle = "black"; 
    ctx2.strokeRect(x, y, 5, 5); 
} 





     function randomColor(){ 
      var letter = "ABCDEF".split(""); 
      var color = "#"; 

      for(var i=0; i<6; i++){ 
       color += letter[Math.round(Math.random()*15)]; 
      } 

      return color; 
      } 

     function arrow(fromX, fromY, toX, toY, color){ 
      // path 
      ctx.beginPath(); 
      var headLen = 10; 
      var angle = Math.atan2(toY - fromY, toX - fromX); 
      ctx.moveTo(fromX, fromY); 
      ctx.lineTo(toX, toY); 

      ctx.lineTo(toX - headLen * Math.cos(angle - Math.PI/6), toY - headLen * Math.sin(angle - Math.PI/6)); 
      ctx.moveTo(toX, toY); 
      ctx.lineTo(toX - headLen * Math.cos(angle + Math.PI/6), toY - headLen * Math.sin(angle + Math.PI/6)); 

      // style 
      ctx.lineWith = 1; 
      ctx.strokeStyle = color; 
      ctx.lineCap = "butt"; 
      ctx.stroke(); 
     } 


     function drawBall(){ 

      // Gravity 
      gravity = gravityCount; 

      this.speedY += gravity * 0.5; // v = a * t 
      this.x += this.speedX * 0.05; // s = v * t 
      this.y += this.speedY * 0.05; 

      // prawa ściana 
      if(this.x + this.r > canvas.width){ 
       this.x = canvas.width - this.r; 
       this.speedX *= -1 * this.bounce;  
      } 

      // lewa ściana 
      if(this.x - this.r < 0){ 
       this.x = this.r; 
       this.speedX *= -1 * this.bounce;  
      } 

      // dolna ściana 
      if(this.y + this.r > canvas.height){ 
       this.y = canvas.height - this.r; 
       this.speedY *= -1 * this.bounce; 

      } 

      // górna ściana 
      if(this.y - this.r < 0){ 
       this.y = this.r; 
       this.speedY *= -1 * this.bounce; 
      } 

         // zwalnianie na ziemi 
      if (this.speedX > 0.25){ 
       this.speedX -= 0.25; 
        if (this.speedY > 0.25) 
         this.speedY -= 0.25; 
      } 

      if (this.speedX < -0.25){ 
       this.speedX += 0.25; 
        //if (this.speedY < -0.25) 
        // this.speedY += 0.25; 
      } 

      circle(this.x, this.y, this.r, this.col);; 

     } 

    // OBJECTS 
     function ball(positionX, positionY, sX, sY, radius, b, color){ 
      this.x = positionX; 
      this.y = positionY; 
      this.speedX = sX; 
      this.speedY = sY; 
      this.r = radius; 
      this.bounce = b;  
      this.col = color; 

      this.draw = drawBall; 
     } 

    //GAME LOOP 
     function gameLoop(){ 
      ctx.clearRect(0, 0, canvas.width, canvas.height); 
      //grab the context from your destination canvas 

      //if path drawing is enabled, first draw the path canvas to the display canvas 
      if (showPath) ctx.drawImage(canvas2,0,0); 

      if(mouseDown == true){ 
       // ctx.clearRect(0, 0, canvas.width, canvas.height); /* !important !!!!!!!!!!!!!!! */ 
       arrow(mousePos['downX'], mousePos['downY'], mousePos['currentX'], mousePos['currentY'], "red"); 
      } 

      for(var i=0; i<balls.length; i++){ 
       balls[i].draw(); 
       if (i==balls.length-1) { 
        //draw path 
        ctx2.fillStyle = '#3f4043'; 
        ctx2.fillRect(balls[i].x, balls[i].y, 5, 5); 
        ctx2.strokeStyle = "black"; 
        ctx2.strokeRect(balls[i].x, balls[i].y, 5, 5);  
       } 
      } 

      ctx.fillStyle = "#000000"; 
      ctx.font = "15px Arial"; 
      ctx.fillText("Balls: " + balls.length + " " + gravityCount + " " + forceCount + " " + howManyPaths, 10, canvas.height -10); 

     } 
    // START THE GAME 
    function init(){ 
     //$("#setup").hide(); 
     $("#canvas").show(); 
     $("#canvas2").hide(); 
     ctx = $('canvas')[0].getContext("2d");  
     canvas.height = $(window).height()-6; 
     canvas.width = $(window).width(); 
     //canvas.width = 960; 
     //canvas.height = 720; 
     canvas2.height = $(window).height()-6; 
     canvas2.width = $(window).width(); 
     return setInterval(gameLoop, 10); 
    } 

    $("#play").click(function() { 
     test = true; 
     playCSS.style.visibility="hidden"; 
     gravityCount = $("#gravitySlider").val(); 
     forceCount = $("#forceSlider").val(); 
     init(); 

    }); 

    $("#restart").click(function() {  
     window.location.href="index.html"; 
    }); 

    $("#refresh").click(function() {  
     gravityCount = $("#gravitySlider").val(); 
     forceCount = $("#forceSlider").val(); 
    }); 

    $("#showPath").click(function() { 
     showPath=true; 
    }); 

    $("#hidePath").click(function() { 
     showPath=false; 
    }); 
} 
+0

http://www.ii.uj.edu.pl/~kadluczs/MiSK-fresh/ 我已經設法創建了一個路徑(2秒鐘,我將添加一個選項來選擇路徑的長度)但它只創建第一個球的路徑.. 我已經嘗試了網絡上的每個重置/清除畫布方法,並沒有運氣..我怎樣才能完全清除畫布,而不是隱藏它,並能夠繪製我創建的最後一個球的路徑(鼠標點擊意味着新球)。代碼將不勝感激:) – Fengson 2013-05-10 12:39:23

+0

好吧,你幾乎在那裏。如果一個布爾值(假設名爲'showPath')爲真,則不要顯示/隱藏第二個畫布,而要在第一個畫布上繪製第二個畫布。我已經用修改後的'script.js'來源更新了我的答案。記下對繪製循環的更改,並對showPath和hidePath按鈕單擊綁定。 – Seidr 2013-05-14 14:01:58

+0

嗯,它對於動畫效果很好,但它仍然繪製多條路徑,而不是1條。我猜這是不可能的,或者難以實現在拍攝新球時完全清除畫布。不清楚一次,然後讓其他球被顯示。 我的意思是:總是隻顯示一條路徑(最後一條球的路徑)無論什麼東西:) – Fengson 2013-05-14 15:56:49