碰撞时改变方向

时间:2016-03-10 13:59:40

标签: javascript collision-detection

我必须在碰撞时创建具有反向路径的坠落物体。所以有 x 球的数量随机下降,当它在他的路径上遇到另一个球时,它必须改变方向。他们无法强加自己。我已经创建了该代码:



var flakePositions = [[]];
		var temp = 0;
		var move = 1;
		// snowflake proto
		function Snowflake() {
			this.pos = new Physics();
			// snowflake guid
			this.id = '';
			this.collisionCount = 0;
			// inits
			this.MAX_X_START_POS = 250;
			this.X_START_OFFSET = 200;
			this.MAX_Y_START_POS = 50;
			this.Y_START_OFFSET = 50;
			this.MAX_X_SPEED = 4;
			this.MAX_Y_SPEED = 1.2;

			// use to get sin && cos
			this.animationStepsCounter = 0
			this.fallFactor = 10;
			// snowflake html
			this.getId = function () {
				if (this.id == '') {
					this.id = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,
						function (c) {
							var r = crypto.getRandomValues(new Uint8Array(1))[0] % 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
							return v.toString(16);
						});
				}
				return this.id;
			}
			this.initalize = function () {
				temp++;
				//var size = 5 + Math.random() * 20;
				var size = 20;
				this.flakeDOM.innerHTML = temp;
				this.flakeDOM.style.width = size + "px";
				this.flakeDOM.style.height = size + "px";
				this.flakeDOM.style.opacity = Math.random();
				this.pos.x = (Math.random() * this.MAX_X_START_POS);
				this.pos.y = this.Y_START_OFFSET + (Math.random() * this.MAX_Y_START_POS);
				this.pos.xSpeed = Math.random() * this.MAX_X_SPEED * Math.sign(-0.5 + Math.random());
				this.pos.ySpeed = Math.random() * this.MAX_Y_SPEED;

				//create array
				this.serial = temp;
				flakePositions[temp] = [];
				flakePositions[temp]['id'] = this.id;
				flakePositions[temp]['x'] = this.flakeDOM.style.top;
				flakePositions[temp]['y'] = this.flakeDOM.style.left;
				flakePositions[temp]['radius'] = this.flakeDOM.style.width;
				flakePositions[temp]['xspeed'] = this.pos.xSpeed;
				flakePositions[temp]['yspeed'] = this.pos.ySpeed
			}
			this.move = function () {
				this.flakeDOM.style.top = (this.pos.y += this.pos.ySpeed) + "px";
				this.flakeDOM.style.left = (this.pos.x += Math.sin(this.animationStepsCounter / this.fallFactor) * this.pos.xSpeed) + "px";
				this.animationStepsCounter += this.pos.ySpeed;

				//update array
				flakePositions[this.serial]['x'] = this.flakeDOM.style.top;
				flakePositions[this.serial]['y'] = this.flakeDOM.style.left;


				//check position with rest
                var rect1 = flakePositions[this.serial];
                var rect1d = rect1['id'];

                var firstBall_radius = parseInt(rect1['radius']) / 2;
                var firstBall_x = parseInt(rect1['x']) + firstBall_radius;
                var firstBall_y = parseInt(rect1['y']) + firstBall_radius;
                
                var firstBall_Ax = firstBall_x + firstBall_radius;
                var firstBall_Ay = firstBall_y + firstBall_radius;

                for (var j = 1, len = flakePositions.length; j < len; j++) {
                    if (rect1 !== flakePositions[j]) {
                        var rect2 = flakePositions[j];
                        var rect2d = rect2['id'];
                        var sflake = document.getElementById(rect2d);

                        var secondBall_radius = parseInt(rect2['radius']) / 2;
                        var secondBall_x = parseInt(rect2['x']) + secondBall_radius;
                        var secondBall_y = parseInt(rect2['y']) + secondBall_radius;
                        
                        var secondBall_Ax = secondBall_x + secondBall_radius;
                        var secondBall_Ay = secondBall_y + secondBall_radius;

                        if (firstBall_x + firstBall_radius + secondBall_radius > secondBall_x
                        && firstBall_x < secondBall_x + firstBall_radius + secondBall_radius
                        && firstBall_y + firstBall_radius + secondBall_radius > secondBall_y
                        && firstBall_y < secondBall_y + firstBall_radius + secondBall_radius) {
                            distance = Math.sqrt(
                                ((firstBall_x - secondBall_x) * (firstBall_x - secondBall_x))
                                + ((firstBall_y - secondBall_y) * (firstBall_y - secondBall_y))
                            );
                
                            if (distance < firstBall_radius + secondBall_radius) {
                                console.log('%c balls have collided', 'color: #0000FF');
                                sflake.style.left *= -1;
                            }
                        } 
                    }
                }
			}
		}




		function Physics() {
			// pos
			this.x = 0;
			this.y = 0;
			this.z = 0;
			// speed
			this.xSpeed = 0;
			this.ySpeed = 0;
			this.zSpeed = 0;
			// acceleration
			this.xAccel = 1;
			this.yAccel = 1;
			this.zAccel = 1;
		}

		snowflakes = new Array();
		var interval = 0;

		function makeThisBoom() {
			// snowflakes container
			snowfield = document.getElementById('snow');
			// snowflakes count
			snoflakesCount = 4;
			for (var i = 0; i < snoflakesCount; i++) {
				snowflakes[i] = new Snowflake();
				var flake = document.createElement('div');
				snowflakes[i].flakeDOM = flake;
				flake.id = snowflakes[i].getId();
				flake.classList.add('sf');
				snow.appendChild(flake);
				snowflakes[i].initalize();
				snowflakes[i].move();
			}
			interval = setInterval(anime, 50);
		}

		function anime() {
			for (var flake of snowflakes) {
				flake.move();
			}
		}

		function setInterface() {
			document.getElementById('startstop').onclick = function () {
				if (interval != 0) {
					clearInterval(interval);
					interval = 0;
				} else interval = setInterval(anime, 50);
			}
		}
		document.addEventListener("DOMContentLoaded", makeThisBoom);
		document.addEventListener("DOMContentLoaded", setInterface);
&#13;
.sf{
  position:absolute;
  z-index:9999999;
  display:block;
  width:20px; height:20px;
  /* FOR DEV ONLY */
  background:#FFF;
  opacity:1!important;
  border-radius: 50%;
}
body{
  background:#222;
  overflow:hidden;
}
#snow {
    position: absolute;
    width: 100%;
    height: 100%;
    overflow: hidden;
}
#startstop{
  width:100px;
  height:30px;
  border:0;
  background:rgb(61, 95, 123);
  color:#FFF;
  outline:none;
}
&#13;
<button id="startstop">Start/stop</button>
	<div id="snow">	</div>
&#13;
&#13;
&#13;

它检测到碰撞,但我已经准备好不知道如何在碰撞时反弹。我试图反转它(* -1)但没有。有人有什么想法吗?感谢所有答案

2 个答案:

答案 0 :(得分:0)

你建议的解决方案只是改变碰撞时的方向,只是在碰撞时将速度乘以-1。

请参阅https://jsfiddle.net/f1z9ak6c/

this.pos.xSpeed *= -1;

然而,如果球在彼此的顶部会遇到问题,它们将永远地一起移动,但是只要它们不能在彼此的顶部开始,它就会起作用。你需要编写额外的代码来阻止这种行为,最简单的方法就是确保它们不会在彼此之上产生。

答案 1 :(得分:0)

似乎是台球物理学的一个例子。 我查了一下,页面上有一些有趣的方程式 real world physics problems

我还发现了另一个问题: Ball to Ball Collision - Detection and Handling