【问题标题】:Collision between ball and paddle in pong game on canvas画布乒乓球比赛中球和桨之间的碰撞
【发布时间】:2017-05-06 19:16:21
【问题描述】:

球似乎从桨的一侧反弹,但当它从一侧弹起时,它会通过桨出现故障。我只是找不到背后的方法,这真的让我很困扰。我正在使用一些逻辑门来定义需要反转球的方向

function startGame() {
    GameArea.start();
	Ball1 = new CircleComp('white' , window.innerWidth - 200 , window.innerHeight - 20);
	Ball1.ySpeed = 13.5;
	Ball1.xSpeed = 6;
	Paddle1 = new PaddleComp( 87, 83, 0, window.innerHeight / 2.5, 10, 70);
	Paddle2 = new PaddleComp( 38, 40, window.innerWidth - 10, window.innerHeight / 2.5, 10 , 70);
}
var GameArea = {
	canvas : canvas = document.querySelector("canvas"),
	start : function (){
		this.canvas.width = window.innerWidth;
		this.canvas.height = window.innerHeight;
		this.ctx = this.canvas.getContext('2d');
		this.interval = setInterval(updateGameArea, 20);
        window.addEventListener('keydown', function (e) {
            GameArea.keys = (GameArea.keys || []);
            GameArea.keys[e.keyCode] = true;
        })
        window.addEventListener('keyup', function (e) {
            GameArea.keys[e.keyCode] = false; 
        })
    }, 
	clear : function() {
        this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
    }
}
function CircleComp(color, x , y){
	this.x = x;
	this.y = y;
	this.width = 8;
    this.height = 8;
	var context1 = GameArea.ctx;
	this.update = function(){
		context1.beginPath();
		context1.fillStyle = color;
		context1.fillRect(this.x, this.y, this.width, this.height);
		context1.fill();
		context1.stroke();
		this.updatePosition();
	}
	this.updatePosition = function(){
		this.y += this.ySpeed;	
		this.x += this.xSpeed;
		if(this.x + this.width > GameArea.canvas.width){
			this.xSpeed = -this.xSpeed;
		}
		if(this.y + this.height > GameArea.canvas.height){
			this.ySpeed = -this.ySpeed;;	
		}
		if(this.x - this.width < 0){
			this.xSpeed = -this.xSpeed;
		}	
		if(this.y - this.height < 0){
			this.ySpeed = -this.ySpeed;
		}
		if(this.y + this.height > Paddle2.y && this.y - this.width < (Paddle2.y + 130) && this.x + this.width > Paddle2.x ){
			this.xSpeed = -this.xSpeed;
		}	
		if(this.y + this.height > Paddle1.y && this.y - this.width < (Paddle1.y + 70) && this.x - this.height < Paddle1.x + 10){
			this.xSpeed = -this.xSpeed;
		}
	}
}
function PaddleComp(Upkey, Downkey, x, y, width, height){
	this.x = x;
	this.y = y;
	this.width = width;
	this.height = height;
	this.ySpeed = 0;
	var context2 = GameArea.ctx;
	this.update = function(){
	context2.fillStyle = 'white';
	context2.fillRect(x,this.y,this.width,this.height);	
	this.updatePosition();
	}
	this.updatePosition = function() {
		this.ySpeed = 0;	
		if (GameArea.keys && GameArea.keys[Upkey]) {
			this.ySpeed = -15; //console.log('Up');
		}
		if (GameArea.keys && GameArea.keys[Downkey]) {
			this.ySpeed = 15; //console.log('Down');
		}
		if ((GameArea.keys && GameArea.keys[Downkey]) && this.y + 130 > window.innerHeight){
			this.ySpeed = this.ySpeed -15 ;	
		}
		if ((GameArea.keys && GameArea.keys[Upkey]) && this.y < 0 ){
			this.ySpeed = this.ySpeed +15 ;	
		}
		this.y += this.ySpeed;			
	}
}
function updateGameArea(){
	GameArea.clear();
	Paddle1.update();
	Paddle2.update();
	Ball1.update();
}
<html>
	<head>
		<meta charset='urf-8'>
		<style>
			canvas{
				border: 0px solid black;
				background-color: black;
			}
			body{
				margin: 0;
				overflow: hidden;
			}
		</style>
	</head>
	<body onload='startGame()'>
		<canvas></canvas>
		<script src='Pong.js'></script>
	</body>
</html>

【问题讨论】:

    标签: javascript canvas bounding-box pong


    【解决方案1】:

    无法直接看到您的代码有什么问题,所以我只是用球对象中的球、球棒(桨)测试函数重写了代码,并从玩家对象中调用。球.checkPad(玩家);测试球是否击中了球员的球棒。为了帮助想象正在发生的事情,我放慢了速度,让蝙蝠变成了真正的 phat。当球击中球棒时,球棒会变黄,球棒会变红一秒钟左右。

    你问的部分有很多cmets,

    希望对你有帮助

    从 OP 问题复制的演示。

    const setting = {
        speed : 2, // of ball
        left : 0,
        width : 400,
        height : 200,
        padWidth : 50,
        padHeight : 80,
        padSpeed : 4, // double balls
        hitPauseCount : 30,  // nuber of frames to hold when there is a collisiotn so you
                              // can check all is good
    }
    const keys = {
        ArrowUp : false,
        ArrowDown : false,
        ArrowLeft : false,
        ArrowRight : false,
        keyEvent(e) { // dont use keyCode it has depreciated
            if (keys[e.code] !== undefined) {
                keys[e.code] = e.type === "keydown";
                e.preventDefault();
            }
        }
    }
    var ctx;
    var ball1, paddle1, paddle2;
    var gameArea = {
        start() {
            canvas.width = setting.width;
            canvas.height = setting.height;
            ctx = canvas.getContext('2d');
            requestAnimationFrame(updateGameArea);
        },
        clear() {
            ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
        }
    }
    gameArea.start();
    ball = new CircleComp('white', window.innerWidth - 200, window.innerHeight - 20);
    ball.ySpeed = setting.speed;
    ball.xSpeed = setting.speed;
    paddle1 = new PaddleComp("ArrowUp", "ArrowDown", setting.left, setting.height / 2, setting.padWidth, setting.padHeight);
    paddle2 = new PaddleComp("ArrowLeft", "ArrowRight", setting.width - setting.padWidth, setting.height / 2, setting.padWidth, setting.padHeight);
    window.addEventListener('keydown', keys.keyEvent);
    window.addEventListener('keyup', keys.keyEvent);
    
    
    function CircleComp(color, x, y) {
        this.x = x;
        this.y = y;
        this.width = 8;
        this.height = 8;
        this.xSpeed = setting.speed;
        var hit = 0;
        var restartCount;
        var serveDirection;
    
        this.reset = function(){
            this.x = ctx.canvas.width /2;
            this.y = ctx.canvas.height / 2;
            this.xSpeed = -this.xSpeed
            this.ySpeed = setting.speed * Math.sign(Math.random() - 0.5);
            restartCount = 60;
        }
        this.draw = function () {
            if(hit > 0){ 
                hit -= 1;
                ctx.fillStyle = "yellow";
            }else{
                ctx.fillStyle = color;
            }
            ctx.fillRect(this.x, this.y, this.width, this.height);
        }
        // next funtion is called by the player objects
        this.checkPad = function (player) {
            if (player.x > canvas.width / 2) { // is player on left or right
                if (this.xSpeed > 0) { // player on right only check if ball moving rigth
                    if (this.x + this.width > player.x) { // ball is in paddles zone
                        //if not  bottom of ball above top of bat or top of ball bellow bottom of bat
                        if (!(this.y + this.height <= player.y || this.y >= player.y + player.height)) {
                            // ball and bat in contact
                            // is ball moving down and the balls top edge above the player
                            // then ball has hit the top side of the bat
                            if(this.ySpeed > 0 && this.y <= player.y){ 
                                this.y = player.y - this.width;
                                this.ySpeed =  -setting.speed;
                            }else if(this.ySpeed < 0 && this.y + this.height >= player.y + player.height){ // do bottom check
                                this.y = player.y + player.height;
                                this.ySpeed =  setting.speed;
                            }else{  // ball hit front of bat
                                this.x = player.x - this.width;
                                this.xSpeed =  - setting.speed;
                            }
                            player.hit = setting.hitPauseCount;  // counters to show FX when a hit happens
                            hit = setting.hitPauseCount;
                        }
                    }
                }
    
            } else { // player must be left
                if (this.xSpeed < 0) { // ball must move left
                    if (this.x < player.x + player.width) { // ball is in paddles zone
                        if (!(this.y + this.height <= player.y || this.y >= player.y + player.height)) {
                            // ball and bat in contact
                            // ball and bat in contact
                            // is ball moving down and the balls top edge above the player
                            // then ball has hit the top side of the bat
                            if(this.ySpeed > 0 && this.y <= player.y){ 
                                this.y = player.y - this.width;
                                this.ySpeed =  -setting.speed;
                            }else if(this.ySpeed < 0 && this.y + this.height >= player.y + player.height){ // do bottom check
                                this.y = player.y + player.height;
                                this.ySpeed =  setting.speed;
                            }else{  // ball hit front of bat
                                this.x = player.x + player.width;
                                this.xSpeed = setting.speed;
                            }
                            player.hit = setting.hitPauseCount;  // counters to show FX when a hit happens
                            hit = setting.hitPauseCount;
                        }
                    }
                }
            }
        }
        this.update = function () {
            if(restartCount > 0){ // wait for restart pause
                restartCount -= 1;
            }else{
                if(hit > 0){  // do nothing if paused
                    return;
                }
                this.y += this.ySpeed;
                this.x += this.xSpeed;
                if (this.x + this.width >= canvas.width) {
                    this.reset();  // point
                } else if (this.x < 0) {
                    this.reset(); // point
                }
                if (this.y + this.height >= canvas.height) {
                    this.y = canvas.height - this.height;
                    this.ySpeed = -setting.speed;
                } else if (this.y < 0) {
                    this.y = 0;
                    this.ySpeed = setting.speed;
                }
            }
        }
        this.reset();
    }
    function PaddleComp(upKey, downKey, x, y, width, height) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
        this.hit = 0;
        this.draw = function () {
            if(this.hit > 0){ 
                this.hit -= 1;
                ctx.fillStyle = "red";
            }else{
                ctx.fillStyle = '#9CF';
            }
            ctx.fillRect(this.x, this.y, this.width, this.height);
        }
        this.update = function () {
            if (keys[upKey]) {
                this.y -= setting.padSpeed;
            };
            if (keys[downKey]) {
                this.y += setting.padSpeed;
            };
            if (this.y < 0) {
                this.y = 0;
            }
            if (this.y + this.height >= canvas.height) {
                this.y = canvas.height - this.height;
            }
            ball.checkPad(this);
        }
    }
    function updateGameArea() {
        gameArea.clear();
        paddle1.update();
        paddle2.update();
        ball.update();
        paddle1.draw();
        paddle2.draw();
        ball.draw();
        requestAnimationFrame(updateGameArea);
    }
    &lt;canvas id=canvas style='background:#69C;border:2px blue solid'&gt;&lt;/canvas&gt;

    【讨论】:

    • 谢谢!它真的帮助我理解了碰撞机制。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多