我正在为我的Java课程设计一个台球游戏。我遇到了撞球碰撞的问题。球碰到了对方,偶尔相互滑动,卡住了。我似乎无法确定此错误的原因。我希望有人能帮助我找到问题的原因。我的代码如下。谢谢。
float cueX = 200;
float cueY = 225;
float cueDeltaX;
float cueDeltaY;
float ballWidth = 25;
float score = 0;
Billiards[] billiards = new Billiards[3];
void setup()
{
size (850, 450);
background(0);
fill(#29B748);
rect(0, 0, 599, 599);
billiards[0] = new Billiards(600, 225, 0, 0, false, "", 0);
billiards[1] = new Billiards(625, 211, 0, 0, false, "", 1);
billiards[2] = new Billiards(625, 239, 0, 0, false, "", 2);
//billiards[3] = new Billiards(625, 250, 0, 0, false, "", 2);
}
void draw()
{
background(0);
fill(#FFFFFF);
stroke(#A6A7A6);
text("DeltaX: " + cueDeltaX + " Delta Y: " + cueDeltaY, 20, 20);
text(score, 500, 20);
fill(#29B748);
rect(25, 25, 799, 399);
poolCueLines();
drawCue();
moveCue();
cueBounce();
cueFriction();
drawBilliards();
billiards[0].collision();
billiards[0].moveBall();
billiards[0].billiardBounce();
billiards[0].billiardFriction();
billiards[1].collision();
billiards[1].moveBall();
billiards[1].billiardBounce();
billiards[1].billiardFriction();
billiards[2].collision();
billiards[2].moveBall();
billiards[2].billiardBounce();
billiards[2].billiardFriction();
}
void poolCueLines() {
if (mousePressed)
{
stroke(#FFFFFF);
line(cueX, cueY, mouseX, mouseY);
}
}
void mouseReleased()
{
cueDeltaX = (cueX - mouseX)/50;
cueDeltaY = (cueY - mouseY)/50;
}
void drawCue() {
noStroke();
fill(0);
fill(#FFFFFF);
stroke(#A6A7A6);
ellipse(cueX, cueY, ballWidth, ballWidth);
noFill();
}
void moveCue() {
cueX += cueDeltaX;
cueY += cueDeltaY;
}
void cueBounce() {
if (cueX > width-25-ballWidth/2 || cueX < 25 + ballWidth/ 2) {
cueDeltaX = -cueDeltaX;
cueDeltaX = cueDeltaX * 0.6;
if (cueX < 25+ ballWidth/2) {
cueX = 26 + ballWidth/2;
} else {
cueX = width-26-ballWidth/2;
}
}
if (cueY > height-25-ballWidth/2 || cueY < 25 + ballWidth/ 2) {
cueDeltaY = -cueDeltaY;
cueDeltaY = cueDeltaY * 0.6;
if (cueY < 25+ ballWidth/2) {
cueY = 26 + ballWidth/2;
} else {
cueY = height-26-ballWidth/2;
}
}
}
void drawBilliards() {
//Yellow Ball 1
fill(#ffff00);
stroke(#A6A7A6);
ellipse(billiards[0].ballXpos, billiards[0].ballYpos, ballWidth, ballWidth);
//Blue 2
fill(#000099);
stroke(#A6A7A6);
ellipse(billiards[1].ballXpos, billiards[1].ballYpos, ballWidth, ballWidth);
//Red 3
fill(#ff0000);
stroke(#A6A7A6);
ellipse(billiards[2].ballXpos, billiards[2].ballYpos, ballWidth, ballWidth);
}
void cueFriction() {
cueDeltaX = cueDeltaX * 0.995;
cueDeltaY = cueDeltaY * 0.995;
}
class Billiards
{
float ballXpos;
float ballYpos;
float deltaXball;
float deltaYball;
int billiardsNum;
Billiards(float tempXpos, float tempYpos, float deltaXbill, float deltaYbill, boolean stripe, String stripeColor, int billiardNum) {
ballXpos = tempXpos;
ballYpos = tempYpos;
deltaXball = deltaXbill;
deltaYball = deltaYbill;
billiardsNum = billiardNum;
}
void collision() {
if (cueX > ballXpos-ballWidth && cueX < ballXpos+ballWidth) {
if (cueY < ballYpos+ballWidth && cueY > ballYpos-ballWidth) {
cueDeltaX = -cueDeltaX * 0.8;
deltaXball = -cueDeltaX * 0.6;
cueDeltaY = -cueDeltaY * 0.8;
deltaYball = -cueDeltaY * 0.6;
}
}
int ballNum = 0;
for (int i=0; i < 3; i++) {
if (billiards[ballNum].ballXpos > ballXpos-ballWidth && billiards[ballNum].ballXpos < ballXpos+ballWidth) {
if (billiards[ballNum].ballYpos < ballYpos+ballWidth && billiards[ballNum].ballYpos > ballYpos-ballWidth) {
if (billiardsNum == ballNum) {
} else {
//if (billiards[ballNum].deltaXball < 0.2 || billiards[ballNum].deltaYball < 0.2) {
if (deltaXball > 0){
billiards[ballNum].ballXpos += -3;
}else if (deltaXball < 0){
billiards[ballNum].ballXpos += 3;
}
if (deltaYball > 0){
billiards[ballNum].ballXpos += -3;
}else if (deltaYball < 0){
billiards[ballNum].ballXpos += 3;
}
billiards[ballNum].deltaXball = -billiards[ballNum].deltaXball * 0.8;
deltaXball = -billiards[ballNum].deltaXball * 0.6;
billiards[ballNum].deltaYball = -billiards[ballNum].deltaYball * 0.8;
deltaYball = -billiards[ballNum].deltaYball * 0.6;
//}
//} else {
// billiards[ballNum].deltaXball = -billiards[ballNum].deltaXball * 0.8;
// deltaXball = -billiards[ballNum].deltaXball * 0.6;
// billiards[ballNum].deltaYball = -billiards[ballNum].deltaYball * 0.8;
// deltaYball = -billiards[ballNum].deltaYball * 0.6;
//}
}
}
}
ballNum += 1;
}
}
void moveBall() {
ballXpos += deltaXball;
ballYpos += deltaYball;
}
void billiardBounce() {
if (ballXpos > width-25-ballWidth/2 || ballXpos < 25 + ballWidth/ 2) {
deltaXball = -deltaXball;
deltaXball = deltaXball * 0.6;
if (ballXpos < 25+ ballWidth/2) {
ballXpos = 26 + ballWidth/2;
} else {
ballXpos = width-26-ballWidth/2;
}
}
if (ballYpos > height-25-ballWidth/2 || ballYpos < 25 + ballWidth/ 2) {
deltaYball = -deltaYball;
deltaYball = deltaYball * 0.6;
if (ballYpos < 25+ ballWidth/2) {
ballYpos = 26 + ballWidth/2;
} else {
ballYpos = height-26-ballWidth/2;
}
}
}
void billiardFriction() {
deltaXball = deltaXball * 0.995;
deltaYball = deltaYball * 0.995;
}
}
答案 0 :(得分:1)
嗯,问题在于你的碰撞代码。你在那里有很多神奇的硬编码数字,零评论描述了它们的用途。这将使调试变得非常困难,这很难帮助你。
但有一件事让我感到惊讶的是,你正在与运动分开处理碰撞。这可能没问题,但是你如何做到这一点,你可以让自己陷入这种境地:
您可能希望仔细阅读并添加注释,直到您完全了解代码的作用。但老实说,这不是一个简单的问题。你可能最好从一个空白的草图开始,并从更简单的东西开始。尝试将问题缩小到MCVE。不要发布整个草图,只需将其缩小到特定情况,两个圆圈使用硬编码值而不是用户输入进行冲突。
您还可以查看Processing编辑器附带的CircleCollision示例。只需转到文件 - &gt;示例 - &gt;主题 - &gt;动作 - &gt; CircleCollision,您将看到一个草图,其中显示了处理圆碰撞的示例。
以下是该示例的碰撞代码:
void checkCollision(Ball other) {
// get distances between the balls components
PVector bVect = PVector.sub(other.position, position);
// calculate magnitude of the vector separating the balls
float bVectMag = bVect.mag();
if (bVectMag < r + other.r) {
// get angle of bVect
float theta = bVect.heading();
// precalculate trig values
float sine = sin(theta);
float cosine = cos(theta);
/* bTemp will hold rotated ball positions. You
just need to worry about bTemp[1] position*/
PVector[] bTemp = {
new PVector(), new PVector()
};
/* this ball's position is relative to the other
so you can use the vector between them (bVect) as the
reference point in the rotation expressions.
bTemp[0].position.x and bTemp[0].position.y will initialize
automatically to 0.0, which is what you want
since b[1] will rotate around b[0] */
bTemp[1].x = cosine * bVect.x + sine * bVect.y;
bTemp[1].y = cosine * bVect.y - sine * bVect.x;
// rotate Temporary velocities
PVector[] vTemp = {
new PVector(), new PVector()
};
vTemp[0].x = cosine * velocity.x + sine * velocity.y;
vTemp[0].y = cosine * velocity.y - sine * velocity.x;
vTemp[1].x = cosine * other.velocity.x + sine * other.velocity.y;
vTemp[1].y = cosine * other.velocity.y - sine * other.velocity.x;
/* Now that velocities are rotated, you can use 1D
conservation of momentum equations to calculate
the final velocity along the x-axis. */
PVector[] vFinal = {
new PVector(), new PVector()
};
// final rotated velocity for b[0]
vFinal[0].x = ((m - other.m) * vTemp[0].x + 2 * other.m * vTemp[1].x) / (m + other.m);
vFinal[0].y = vTemp[0].y;
// final rotated velocity for b[0]
vFinal[1].x = ((other.m - m) * vTemp[1].x + 2 * m * vTemp[0].x) / (m + other.m);
vFinal[1].y = vTemp[1].y;
// hack to avoid clumping
bTemp[0].x += vFinal[0].x;
bTemp[1].x += vFinal[1].x;
/* Rotate ball positions and velocities back
Reverse signs in trig expressions to rotate
in the opposite direction */
// rotate balls
PVector[] bFinal = {
new PVector(), new PVector()
};
bFinal[0].x = cosine * bTemp[0].x - sine * bTemp[0].y;
bFinal[0].y = cosine * bTemp[0].y + sine * bTemp[0].x;
bFinal[1].x = cosine * bTemp[1].x - sine * bTemp[1].y;
bFinal[1].y = cosine * bTemp[1].y + sine * bTemp[1].x;
// update balls to screen position
other.position.x = position.x + bFinal[1].x;
other.position.y = position.y + bFinal[1].y;
position.add(bFinal[0]);
// update velocities
velocity.x = cosine * vFinal[0].x - sine * vFinal[0].y;
velocity.y = cosine * vFinal[0].y + sine * vFinal[0].x;
other.velocity.x = cosine * vFinal[1].x - sine * vFinal[1].y;
other.velocity.y = cosine * vFinal[1].y + sine * vFinal[1].x;
}
}
您还可以查看上述示例的基于网络的版本: