弹跳球 [英] Bouncing draggable ball

查看:97
本文介绍了弹跳球的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当您拖动并释放鼠标时,我有这个可拖动的球,它的方向相反。我该如何从墙壁弹起?另外,如果应该移动600像素,并在200像素后撞到墙,则应该再移动400像素。
http://jsfiddle.net/bepcmsgo/5/

I have this draggable ball when you drag and release, it is going the oposite way. How can I make this bounce from the walls? Also if it is supposed to travel 600px and it hit a wall after 200px, it should go for 400px more. 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

I forked your JSFiddle and added a simple bouncing mechanic: 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

我稍微改变了球的运动逻辑,以下是一些说明我的方法的指针:

I changed the ball movement logic slightly, here are some pointers that explain my approach:


  • 对于简单的动作,使用CSS动画是完全可以的,但最好是动态和复杂的东西

  • 在此示例中,所有移动都在JS中逐帧处理,角度为&。在渲染每一帧之前进行摩擦计算,而不是计算最终位置并为那里的路径设置动画。每个刻度都将计算下一个即时位置(如有必要,会跳动),然后显示给用户。刻度之间的延迟为 16ms 以使其达到〜62.5FPS。

  • 我将位置变量移至了<$ c中的命名属性$ c> circle 类比具有 pos1 pos2 使其更易于阅读, pos3 ...都作为全局变量。

  • 该数学运算十分可用于谷歌搜索,我使用pythag来获取与鼠标指针的距离并触发以获取与指针&的角度移动圆圈。弹跳角假定入射角等于反射角。弹跳还假定了完全弹性的碰撞,尽管您可以根据需要降低弹跳的速度。

  • 我在发布前更改了轻微的移动,以使用CSS转换而不是实际移动元素。

  • 最后一点,我建议您查看HTML5 < canvas> ,如果您想做更多图形工作,它是为这样的东西。

  • Using CSS animations is perfectly fine for simple movements, but anything more dynamic and complex is best left to JS to save yourself a lot of CSS code.
  • In this example, all movements are handled frame-by-frame in JS, with angle & friction calculations occurring before each frame is rendered, instead of calculating the final position and animating the path there. Each tick calculates the immediate next position (bouncing if necessary) and then displays to the user. The delay between ticks is 16ms to make it ~62.5FPS.
  • I moved your position variables to named properties in the circle class to make it easier to read than having pos1, pos2, pos3... all as global variables.
  • The math is quite googleable, I used pythag to get the distance to the mouse pointer and trig to get the angle to the pointer & move the circle. The bounce angle assumes that the angle of incidence equals angle of reflection. The bounce also assumes perfectly elastic collision, although you could decrease velocity on a bounce if you wanted.
  • I changed the slight movement before release to use CSS translation instead of actually moving the element.
  • One final note, I would suggest looking into HTML5 <canvas> if you want to do more graphical stuff, it was built for stuff like this.

这篇关于弹跳球的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆