2011-06-30 50 views
0

我想通过在线学习cs106a课程学习java。 目前我已经到达了突破exersize,并且遇到了一些问题斯坦福大学cs106a - 突破exersize

我还没有完全完成它,但我想先解决这些问题,然后再继续。

问题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; 

} 
+1

这里的一个问题是你有一个巨大的[神级](http://en.wikipedia.org/wiki/God_object),使你的代码很难分析或调试。你有没有想过重构并将问题分解成单独的类? –

+1

@Ramin我通常不会对这类问题发表评论,但我对我在这里工作的最后一天感到无聊。您的代码假设在碰撞期间永远不会有重叠,并且球总是整齐地撞击左上角(或右下角)的砖块。您应该重新评估您的碰撞检测代码。这是一个已经解决了100万次的问题 - 快速搜索“碰撞检测”会告诉你所有你需要知道的事情。 – SRM

+0

@Hovercraft Full Of Eels我认为你的意思是我的 “私人无效checkForCollision(){”方法是复杂和杂乱的方式?你可能在那里有一个好点。我会看看我能否更好地构建这一点。 – Ramin

回答

1

你为什么不使用建议的方法在讲义19:

private GObject getCollidingObject() 

的使用也对撞机:

GObject collider = getCollidingObject(); 

首先分离与墙壁碰撞和你的条件(用砖块划分)游戏元素碰撞成两种单独的方法,可以简化else if级联(分解我认为你知道它的含义)。你只有两个物体,你应该担心paddlebricks,所以你只需要比较(collider == paddle)collider != null。你也只使用半径比较,但应使用直径(2 *半径)。玩得开心:)

0

对于球的每一个移动来说,你都是15步。因为每个砖的高度只有8,因此有时你在评估该位置是否包含对象之前绕过砖或不。例如。让我们假设你是最后的评估,你的球位置是20的Y位置,最近的砖块只有2的距离。你接下来的评估将不会包括这个砖,因为你移动了15,砖的高度是8,这意味着y值的范围是22到30.在下次评估中,你将离开这块砖5块。我知道值应该倒转考虑砖的位置,但你明白了...

随着y值中较小的步骤会更频繁地检查碰撞,并提供足够小的步骤,解决此问题。

相关问题