簡體   English   中英

彈跳球

[英]Bouncing draggable ball

當您拖動和釋放時,我有一個可拖動的球,它的方向相反。 我該如何從牆壁彈起? 另外,如果應該移動600像素,並在200像素后撞牆,則應該再移動400像素。 http://jsfiddle.net/bepcmsgo/5/

let circle = document.getElementById("circle");
let pos1 = 0;
let pos2 = 0;
let pos3 = 0;
let pos4 = 0;
let mouseDown = false;
let currentCircleTop = 0;
let currentCircleLeft = 0;

circle.addEventListener("mousedown", function(e){
  mouseDown = true;
  pos3 = e.pageX;
  pos4 = e.pageY;
  currentCircleTop = circle.offsetTop;
  currentCircleLeft = circle.offsetLeft;
  this.style.transition = "0.3s all";
})

document.addEventListener("mousemove", function(e){
    if(mouseDown){
        pos1 = pos3 - e.pageX;
        pos2 = pos4 - e.pageY;
        pos3 = e.pageX;
        pos4 = e.pageY;
        circle.style.top = circle.offsetTop - pos2 + "px";
        circle.style.left = circle.offsetLeft - pos1 + "px";
  }
})
document.addEventListener("mouseup", function(){
    if(mouseDown){
        mouseDown = false;
        circle.style.transition = "0.8s all";  
        circle.style.top = currentCircleTop + ((currentCircleTop - circle.offsetTop) * 20) + "px";
        circle.style.left = currentCircleLeft + ((currentCircleLeft - circle.offsetLeft) * 20) + "px";
    }
})

我分叉了您的JSFiddle,並添加了一個簡單的彈跳機制: jsfiddle.net/SydLambert/hnkL392x/2

let circle = document.getElementById("circle");
circle.x=300;
circle.y=150;
circle.direction=0; //in radians
circle.velocity=0;
circle.friction=0.05; //0 to 1

let container=document.getElementById("circleContainer");
container.width=parseInt(container.style.width.slice(0,-2)); //Gets width and height as usable integers
container.height=parseInt(container.style.height.slice(0,-2));

let mouse={
    x:0,
    y:0,
    down:false,
};

let dragDisplayMultiplier=0.2; //How much the circle moves while a drag is in progress.
let velocityDampener=5; //How much the velocity is reduced immediately after the circle is released


function displayCircle(){ //Sets the position of the circle
    circle.style.top=circle.y+"px";
    circle.style.left=circle.x+"px"
}

function step(){ //Uses trig to work out the next positon of the circle
    return {
        x:circle.x+circle.velocity*Math.cos(circle.direction),
        y:circle.y+circle.velocity*Math.sin(circle.direction),
    }
}

function tick(){ //Physics function
    circle.velocity*=1-circle.friction; //Decrease the circle's velocity with friction

    let newLocation=step(); //Determine the next location after the circle has travelled

    //If the next location of the circle is outside the container, the direction is changed.
    //Angle of incidence equals angle of reflection.
    if(newLocation.x<0 || newLocation.x+20>container.width)
        circle.direction=Math.PI-(circle.direction);
    if(newLocation.y<0 || newLocation.y+20>container.height)
        circle.direction*=-1;

    //The next location is now inside the container, so the circle's position can be updated
    newLocation=step();
    circle.x=newLocation.x;
    circle.y=newLocation.y;

    //Displays the circle's new position to the user
    displayCircle();

    //If the circle still has reasonable velocity, the simulation is continued after waiting 16ms
    if(circle.velocity>1){
        setTimeout(tick,16);
    }
}

circle.addEventListener("mousedown", function(e){
    mouse.down=true;
});

document.addEventListener("mousemove", function(e){
    mouse.x=e.pageX;
    mouse.y=e.pageY;
    if(mouse.down) //Offsets the ball whilst the drag is in progress using CSS translation
        circle.style.transform=`translate(${((circle.x+mouse.x)/2-circle.x)*dragDisplayMultiplier}px, ${((circle.y+mouse.y)/2-circle.y)*dragDisplayMultiplier}px)`;
});

document.addEventListener("mouseup", function(){
    if(mouse.down){
        mouse.down = false;
        circle.style.transform="translate(0px, 0px)"; //Resets the CSS translation from the "mousemove" event
        circle.velocity=Math.sqrt((circle.x-mouse.x+10)**2 + (circle.y-mouse.y+10)**2); //Sets the velocity to the distance bewteen the circle and mouse pointer
        circle.velocity/=velocityDampener; //Reduces the velocity slightly for ease of use
        circle.direction=Math.atan2((circle.y-mouse.y+10),(circle.x-mouse.x+10)); //Uses atan2 to find the angle between the circle and the mouse pointer
        setTimeout(tick,16); //Starts the physics simulation
    }
});

displayCircle(); //Sets the initial circle top and left to match x and y

我稍微改變了球的運動邏輯,以下是一些說明我的方法的指針:

  • 使用CSS動畫非常適合簡單的動作,但是最好將JS處理的動態和復雜性留給JS,以節省大量CSS代碼。
  • 在此示例中,所有運動都在JS中逐幀處理,在渲染每一幀之前進行角度和摩擦計算,而不是計算最終位置並在那里動畫路徑。 每個刻度線都會計算出下一個即時位置(必要時會跳動),然后顯示給用戶。 滴答之間的延遲為16ms ,使其約為62.5FPS。
  • 我將您的位置變量移至circle類中的命名屬性,以使其比將pos1pos2pos3 ...全部用作全局變量更容易閱讀。
  • 數學是相當可谷歌的,我用pythag來獲取到鼠標指針的距離,並使用trig來獲取與指針的角度並移動圓。 彈跳角假定入射角等於反射角。 彈跳還假定為完全彈性碰撞,盡管您可以根據需要降低彈跳的速度。
  • 我在發布前更改了輕微的移動,以使用CSS轉換而不是實際移動元素。
  • 最后一點,我建議您研究HTML5 <canvas>如果您想做更多的圖形化工作,它就是為這樣的事情而構建的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM