我想做一个小游戏,用户可以点击页面上的某个地方,圆圈就会跟着到指针的位置,从那里开始,用户可以拖动鼠标,让圆圈像弹弓一样移动。我希望圆圈能够在墙壁上反弹。
然而,当圆圈与墙壁碰撞时,圆圈似乎会 "粘 "在墙上,而不是直接弹开。我想这可能是因为圆圈改变方向的速度太快,导致圆圈出现了圆角误差?另外,顶墙的碰撞还没有实现,因为我认为我没有正确声明顶墙的div对象。
let windowHeight = window.innerHeight;
let windowWidth = window.innerWidth;
//console.log(`Window height: ${windowHeight}, Window width: ${windowWidth}`);
var $ = document.querySelector.bind(document);
var $on = document.addEventListener.bind(document);
var mouseX, mouseY;
$on('mousedown', function (e){
mouseX = e.clientX || e.pageX;
mouseY = e.clientY || e.pageY;
initialX = mouseX;
initialY = mouseY;
//console.log('mousedown');
});
$on('mouseup', function (e){
//var d = Math.hypot(e.clientX - mouseX, e.clientY - mouseY);
var movebyX = (Math.abs(e.clientX - mouseX));
var movebyY = (Math.abs(e.clientY - mouseY));
// Move puck in opposite direction
if (e.clientX > mouseX){
mouseX -= movebyX;
}
else if(e.clientX < mouseX){
mouseX += movebyX;
}
if (e.clientY > mouseY){
mouseY -= movebyY;
}
else if(e.clientY < mouseY){
mouseY += movebyY;
}
//console.log('mouseup');
});
var circle = $('#circle');
var top = $('#top');
var bottom = $('#bottom');
var left = $('#left');
var right = $('#right');
var top = $('#top');
var x = void 0,
y = void 0,
dx = void 0;
dy = void 0;
v0x = void 0;
v0y = void 0;
accelScalar = 0.3;
key = -1;
velocityScalar = 0.05;
teleport = 0.1;
isCollide = false;
swap = false;
initialX = void 0;
initialY = void 0;
var followMouse = function followMouse(){
key = requestAnimationFrame(followMouse);
//tester();
if(!x || !y){
x = mouseX;
y = mouseY;
}
else {
makeMove(findVelocity().dx,findVelocity().dy);
}
};
function tester() {
console.log(top.getBoundingClientRect());
}
function findVelocity(){
v0x = (mouseX - x) * velocityScalar
v0y = (mouseY - y) * velocityScalar
return {
dx: v0x * accelScalar,
dy: v0y * accelScalar,
};
}
function makeMove(vx,vy){
//console.log(`x: ${x}, mouseX: ${mouseX}, vx: ${vx}`);
// teleport, avoid asymptote
if(Math.abs(vx) + Math.abs(vy) < teleport) {
x = mouseX;
y = mouseY;
vx = 0;
vy = 0;
}
// update position if collision
if (x-41 < (left.getBoundingClientRect().x)){
vx = -vx
vy = -vy
}
if (x+41 > (right.getBoundingClientRect().x)){
vx = -vx
vy = -vy
}
if (y+41 > (bottom.getBoundingClientRect().y)){
vx = -vx
vy = -vy
}
x += vx;
y += vy;
// show circle position
circle.style.left = (x-20) + 'px';
circle.style.top = (y-20) + 'px';
}
followMouse();
html, body {
margin: 0;
height: 100%;
background: #161616;
}
.wrap {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
overflow: hidden;
}
@keyframes animation {
0% {
transform: scale(0.9)
}
25% {
transform: scale(1.1)
}
50% {
transform: scale(0.9)
}
75% {
transform: scale(1.1)
}
100% {
transform: scale(0.9)
}
}
#circle {
width: 50px;
height: 50px;
background: none;
border: 5px solid aqua;
border-radius: 50%;
position: absolute;
left: 50%;
top: 50%;
margin: -10px 0 0 -10px;
pointer-events: none;
/*animation: animation 5s infinite
*/
}
#top, #bottom, #left, #right {
background: #a5ebff;
position: fixed;
}
#left, #right {
top: 0; bottom: 0;
width: 10px;
}
#left { left: 0; }
#right { right: 0; }
#top, #bottom {
left: 0; right: 0;
height: 10px;
}
#top { top: 0; }
#bottom { bottom: 0; }
<!DOCTYPE html>
<html>
<head>
<title> Test Project </title>
<link rel = "stylesheet" href = "main.css">
</head>
<body>
<div class = "wrap">
<div id = "circle"></div>
</div>
<div id="left"></div>
<div id="right"></div>
<div id="top"></div>
<div id="bottom"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script type = "text/javascript" src = "./main.js"> </script>
</body>
</html>
两个问题。
顶部 是顶层框架的保留变量。 与试图访问带有id的元素相冲突。top
(您应该避免依赖它,使用getElementById代替)
仅仅反转速度是行不通的,因为你每一帧的速度都是用鼠标最后点击的位置来计算的(这也是你在接近鼠标XY时速度衰减的工作方式)。最简单的方法是使用鼠标点击边界外的距离来设置一个新的鼠标点击位置,在边界内按距离偏移。 基本上与以边框为轴反转位置的效果相同。 在这种情况下,它也会在这个反转轴上加进一半的圆圈宽度。 使用硬编码的数字,但如果想要改进,也可以从实际尺寸计算。)
let windowHeight = window.innerHeight;
let windowWidth = window.innerWidth;
//console.log(`Window height: ${windowHeight}, Window width: ${windowWidth}`);
var $ = document.querySelector.bind(document);
var $on = document.addEventListener.bind(document);
var mouseX, mouseY;
$on('mousedown', function (e){
mouseX = e.clientX || e.pageX;
mouseY = e.clientY || e.pageY;
initialX = mouseX;
initialY = mouseY;
//console.log('mousedown');
});
$on('mouseup', function (e){
//var d = Math.hypot(e.clientX - mouseX, e.clientY - mouseY);
var movebyX = (Math.abs(e.clientX - mouseX));
var movebyY = (Math.abs(e.clientY - mouseY));
// Move puck in opposite direction
if (e.clientX > mouseX){
mouseX -= movebyX;
}
else if(e.clientX < mouseX){
mouseX += movebyX;
}
if (e.clientY > mouseY){
mouseY -= movebyY;
}
else if(e.clientY < mouseY){
mouseY += movebyY;
}
//console.log('mouseup');
});
var circle = $('#circle');
var top = $('#top');
var bottom = $('#bottom');
var left = $('#left');
var right = $('#right');
var top = $('#top');
var x = void 0,
y = void 0,
dx = void 0;
dy = void 0;
v0x = void 0;
v0y = void 0;
accelScalar = 0.3;
key = -1;
velocityScalar = 0.05;
teleport = 0.1;
isCollide = false;
swap = false;
initialX = void 0;
initialY = void 0;
var followMouse = function followMouse(){
key = requestAnimationFrame(followMouse);
//tester();
if(!x || !y){
x = mouseX;
y = mouseY;
}
else {
makeMove(findVelocity().dx,findVelocity().dy);
}
};
function tester() {
console.log(top.getBoundingClientRect());
}
function findVelocity(){
v0x = (mouseX - x) * velocityScalar
v0y = (mouseY - y) * velocityScalar
return {
dx: v0x * accelScalar,
dy: v0y * accelScalar,
};
}
function makeMove(vx,vy){
//console.log(`x: ${x}, mouseX: ${mouseX}, vx: ${vx}`);
// teleport, avoid asymptote
if(Math.abs(vx) + Math.abs(vy) < teleport) {
x = mouseX;
y = mouseY;
vx = 0;
vy = 0;
}
// update position if collision
if (x-41 < (left.getBoundingClientRect().x)){
mouseX = Math.abs(mouseX - x) + 41
}
if (x+31 > (right.getBoundingClientRect().x)){
mouseX = right.getBoundingClientRect().x - Math.abs(mouseX - x) - 31
}
var top = document.getElementById('top')
if (y-41 < (top.getBoundingClientRect().y)){
mouseY = Math.abs(mouseY - y) + 41
}
if (y+31 > (bottom.getBoundingClientRect().y)){
mouseY = bottom.getBoundingClientRect().y - Math.abs(mouseY - y) - 31
}
x += vx;
y += vy;
// show circle position
circle.style.left = (x-20) + 'px';
circle.style.top = (y-20) + 'px';
}
followMouse();
html, body {
margin: 0;
height: 100%;
background: #161616;
}
.wrap {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
overflow: hidden;
}
@keyframes animation {
0% {
transform: scale(0.9)
}
25% {
transform: scale(1.1)
}
50% {
transform: scale(0.9)
}
75% {
transform: scale(1.1)
}
100% {
transform: scale(0.9)
}
}
#circle {
width: 50px;
height: 50px;
background: none;
border: 5px solid aqua;
border-radius: 50%;
position: absolute;
left: 50%;
top: 50%;
margin: -10px 0 0 -10px;
pointer-events: none;
/*animation: animation 5s infinite
*/
}
#top, #bottom, #left, #right {
background: #a5ebff;
position: fixed;
}
#left, #right {
top: 0; bottom: 0;
width: 10px;
}
#left { left: 0; }
#right { right: 0; }
#top, #bottom {
left: 0; right: 0;
height: 10px;
}
#top { top: 0; }
#bottom { bottom: 0; }
<!DOCTYPE html>
<html>
<head>
<title> Test Project </title>
<link rel = "stylesheet" href = "main.css">
</head>
<body>
<div class = "wrap">
<div id = "circle"></div>
</div>
<div id="left"></div>
<div id="right"></div>
<div id="top"></div>
<div id="bottom"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script type = "text/javascript" src = "./main.js"> </script>
</body>
</html>