我正试图通过在线学习cs106a课程来学习java。目前,我已经达到突破的极限,我遇到了一些错误
我还没有完全完成,但我想先解决这些问题,然后再进一步。
问题1:
当球与砖块碰撞时,它们似乎并不总是从画布上移开。有时砖块会在第二次碰撞时被移走。但有一排(黄砖(对球的碰撞根本没有反应。
问题2:
拖动鼠标可以移动我的球拍。唯一的问题是,砖块也可以像划桨一样移动。
我知道这与的这段代码有关
gobj = getElementAt(lastX, lastY);
如果我把它全部移走,砖块就不能再移动了。这很好。但我还是无论我在哪里点击和拖动,都可以移动球拍。
有人能给我一个提示,让我改正错误吗?
下面是我的代码。感谢
/*
* File: Breakout.java
* -------------------
* This file will eventually implement the game of Breakout.
*/
import acm.graphics.*;
import acm.program.*;
import acm.util.*;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import org.omg.CORBA.PUBLIC_MEMBER;
public class breakout extends GraphicsProgram {
/** Width and height of application window in pixels */
public static final int APPLICATION_WIDTH = 400;
public static final int APPLICATION_HEIGHT = 600;
/** Dimensions of game board (usually the same) */
private static final int WIDTH = APPLICATION_WIDTH;
private static final int HEIGHT = APPLICATION_HEIGHT;
/** Dimensions of the paddle */
private static final int PADDLE_WIDTH = 60;
private static final int PADDLE_HEIGHT = 10;
/** Offset of the paddle up from the bottom */
private static final int PADDLE_Y_OFFSET = 30;
/** Number of bricks per row */
private static final int NBRICKS_PER_ROW = 10;
/** Number of rows of bricks */
private static final int NBRICK_ROWS = 8;
/** Separation between bricks */
private static final int BRICK_SEP = 4;
/** Width of a brick */
private static final int BRICK_WIDTH = (WIDTH - (NBRICKS_PER_ROW - 1)* BRICK_SEP)/ NBRICKS_PER_ROW;
/** Height of a brick */
private static final int BRICK_HEIGHT = 8;
/** Radius of the ball in pixels */
private static final int BALL_RADIUS = 10;
/** Offset of the top brick row from the top */
private static final int BRICK_Y_OFFSET = 70;
/** Number of turns */
private static final int NTURNS = 3;
private static final int DELAY = 50;
private static final double X_START = WIDTH / 2;
private static final double Y_START = 450;
public void run() {
world();
play();
}
private void ball() {
ball = new GOval(X_START, Y_START, BALL_RADIUS, BALL_RADIUS);
ball.setFillColor(Color.BLACK);
ball.setFilled(true);
add(ball);
}
private void paddle() {
paddle = new GRect(100, 500, PADDLE_WIDTH, PADDLE_HEIGHT);
paddle.setColor(Color.BLACK);
paddle.setFilled(true);
add(paddle);
}
private void brick(int x, int y, Color c) {
GRect brick = new GRect(x, y, BRICK_WIDTH, BRICK_HEIGHT);
brick.setColor(getBackground());
brick.setFillColor(c);
brick.setFilled(true);
add(brick);
}
private void brickRow(int x, int y, Color c) {
x = BRICK_SEP / 2;
y += BRICK_Y_OFFSET;
for (int i = 0; i < NBRICKS_PER_ROW; i++) {
brick(x, y, c);
x += BRICK_WIDTH + BRICK_SEP;
}
}
private void world() {
//initialize x and y position for the rows of bricks
int x = 0;
int y = 0;
// set starting color for first row
Color c = Color.red;
paddle();
//create 2 rows of bricks and switch colors
for (int i = 0; i < NBRICK_ROWS; i++) {
if (i <= 1) {
c = Color.ORANGE;
} else if (i > 1 && i <= 3) {
c = Color.YELLOW;
} else if (i > 3 && i <= 5) {
c = Color.GREEN;
} else if (i > 5 && i <= 7) {
c = Color.CYAN;
}
brickRow(x, y, c);
y += BRICK_HEIGHT + BRICK_SEP;
}
}
private void moveBall() {
ball.move(xVel, yVel);
}
public void mousePressed(MouseEvent e) {
lastX = e.getX();
lastY = e.getY();
gobj = getElementAt(lastX, lastY);
}
public void mouseDragged(MouseEvent e) {
if (paddle != null) {
paddle.move(e.getX() - lastX, getY());
lastX = e.getX();
lastY = e.getY();
}
//constrain paddle movement
if (paddle.getX() < 0){
paddle.setLocation(0, 500);
}else if (paddle.getX()+BRICK_WIDTH > WIDTH ){
paddle.setLocation(WIDTH-BRICK_WIDTH, 500);
}
}
private void checkForCollision() {
// ball collission with walls
if (ball.getY() > getHeight() - BALL_RADIUS
|| ball.getY() < 0 + BALL_RADIUS) {
yVel = -yVel;
} else if (ball.getX() > getWidth() - BALL_RADIUS
|| ball.getX() < 1 + BALL_RADIUS) {
xVel = -xVel;
// ball collission with paddle
} else if (getElementAt(ball.getX() + BALL_RADIUS, ball.getY()
+ BALL_RADIUS) == paddle) {
yVel = -yVel;
// check for collision with bricks to remove them but ignore collision with paddle
} else if (getElementAt(ball.getX(), ball.getY()) != null
&& getElementAt(ball.getX(), ball.getY()) != paddle) {
remove(getCollidingObject(ball.getX(), ball.getY()));
yVel = -yVel;
} else if (getElementAt(ball.getX() + BALL_RADIUS, ball.getY()
+ BALL_RADIUS) != null
&& getElementAt(ball.getX() + BALL_RADIUS, ball.getY()
+ BALL_RADIUS) != paddle) {
remove(getCollidingObject(ball.getX() + BALL_RADIUS, ball.getY()
+ BALL_RADIUS));
yVel = -yVel;
} else if (getElementAt(ball.getX() + BALL_RADIUS, ball.getY()
+ BALL_RADIUS) != null
&& getElementAt(ball.getX() + BALL_RADIUS, ball.getY()
+ BALL_RADIUS) != paddle) {
remove(getCollidingObject(ball.getX() + BALL_RADIUS, ball.getY()
+ BALL_RADIUS));
yVel = -yVel;
} else if (getElementAt(ball.getX(), ball.getY() + BALL_RADIUS) != null
&& getElementAt(ball.getX(), ball.getY() + BALL_RADIUS) != paddle) {
remove(getCollidingObject(ball.getX(), ball.getY() + BALL_RADIUS));
yVel = -yVel;
}
}
private void play() {
addMouseListeners();
ball();
while (true) {
checkForCollision();
moveBall();
pause(DELAY);
}
}
private GObject getCollidingObject(double x, double y) {
return getElementAt(x, y);
}
private double lastX;
private double lastY;
private double xVel = 5;
private double yVel = 15;
private GOval ball;
private GRect paddle;
private GObject gobj;
}
为什么不使用讲义19:中的建议方法
private GObject getCollidingObject()
同时使用对撞机:
GObject collider = getCollidingObject();
首先,用墙碰撞和(用砖划桨(游戏元素碰撞将你的条件分离为两种不同的方法,从而简化else if
级联(分解我想你知道它的意思(。您只有两个对象——您应该担心paddle
和bricks
,所以您只需要比较(collider == paddle)
和collider != null
。此外,在比较中只使用半径,但应使用直径(2*radius(。玩得开心:(
你是y步,因为球的每一个移动在15时都太大了。由于每块砖的高度只有8,因此在评估该位置是否包含对象之前,有时会绕过砖。例如,假设你是最后一个剩下的评估——你是一个Y位置为20的球,而最近的砖块只有2的长度。您的下一次评估将不包括此砖块,因为您移动了15,砖块的高度为8,这意味着y值的范围为22到30。在你的下一次评估中,你将离开这块砖5分。我知道考虑到砖块的位置,这些值应该颠倒,但你明白了。。。
对于y值中较小的步长,将更定期地检查碰撞,如果您使步长足够小,则可以消除此问题。