private void addBricks(){
for (int i = 0; i < NBRICK_ROWS; i++){
for (int j = 0; j < NBRICKS_PER_ROW; j++){
int y = BRICK_Y_OFFSET + (i * (BRICK_HEIGHT + BRICK_SEP));
int x = (BRICK_X_OFFSET) + (j * (BRICK_WIDTH + BRICK_SEP));
brick = new GRect (x, y, BRICK_WIDTH, BRICK_HEIGHT );
add (brick);
}
}
}
我正在尝试在这里制作突破性游戏,这是一段代码。
我在画布上添加了一组矩形。在我的计划中,我想在球击中它们时将其中的一部分移除。问题是我不知道具体如何引用它们。也就是说,我不知道在remove()
中输入哪些参数,因为它们都是brick
谢谢!
以下整个计划
import acm.graphics.*;
import acm.program.*;
import acm.util.*;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class Breakout extends GraphicsProgram {
/** Width and height of application window in pixels */
public static final int APPLICATION_WIDTH = 440;
public static final int APPLICATION_HEIGHT = 660;
/** Dimensions of game board (usually the same) */
private static final int WIDTH = 400;
private static final int HEIGHT = 600;
/** 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 = 10;
/** 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;
/** Offset of the side bricks from the sides of game window so that the whole set of bricks are in the centre */
private static final int BRICK_X_OFFSET = ((WIDTH - NBRICKS_PER_ROW * (BRICK_WIDTH + BRICK_SEP) + BRICK_SEP) / 2);
/** Number of turns */
private static final int NTURNS = 3;
/** Game speed */
private static final int DELAY = 1;
/* Method: run() */
/** Runs the Breakout program. */
public void run() {
addMouseListeners();
addWorld();
runGame();
}
private void addWorld(){
setSize (APPLICATION_WIDTH, APPLICATION_HEIGHT);
addPlayingBox();
addBricks();
addPaddle();
}
/* lives and number of bricks will be check before game runs
* if there are either no lives of bricks left game is over
* ball and ball physics are only added to the screen after there is a mouse click.
*/
private void runGame(){
while (true){
// add a gameover label
waitForClick();
addBall();
addBallMotion();
}
}
//adds the playing area onto screen
private void addPlayingBox(){
topBounds = new GLine (0, 0, WIDTH, 0);
bottomBounds = new GLine (0, HEIGHT, WIDTH, HEIGHT);
leftBounds = new GLine (0, 0, 0, HEIGHT);
rightBounds = new GLine (WIDTH, 0, WIDTH, HEIGHT);
add (topBounds);
add (bottomBounds);
add (leftBounds);
add (rightBounds);
}
/*bricks are added to the top row and left column 1st and consequently to the its right column
* and to the next row when a row is all filled up
*/
private void addBricks(){
for (int i = 0; i < NBRICK_ROWS; i++){
for (int j = 0; j < NBRICKS_PER_ROW; j++){
int y = BRICK_Y_OFFSET + (i * (BRICK_HEIGHT + BRICK_SEP));
int x = (BRICK_X_OFFSET) + (j * (BRICK_WIDTH + BRICK_SEP));
brick = new GRect (x, y, BRICK_WIDTH, BRICK_HEIGHT );
colorBrick(brick, i);
add (brick);
}
}
}
// every consecutive 2 rows are colored the same
private void colorBrick(GRect brick, int rowNumber){
brick.setFilled (true);
switch (rowNumber + 1) {
case 1: case 2: brick.setColor(Color.red);
break;
case 3: case 4: brick.setColor(Color.orange);
break;
case 5: case 6: brick.setColor(Color.yellow);
break;
case 7: case 8: brick.setColor(Color.green);
break;
case 9: case 10:brick.setColor(Color.cyan);
break;
}
}
//adds paddle to screen
private void addPaddle(){
paddle = new GRect (WIDTH / 2 - PADDLE_WIDTH / 2, HEIGHT - PADDLE_Y_OFFSET, PADDLE_WIDTH, PADDLE_HEIGHT);
paddle.setFilled(true);
paddle.setColor (Color.BLACK);
add (paddle);
}
//creates motion for the paddle according to mouse movement
public void mouseMoved(MouseEvent e){
paddle.setLocation ((e.getX() - PADDLE_WIDTH / 2), (double) (HEIGHT - PADDLE_Y_OFFSET));
/* checks if the paddle within the playing area
* if not, the paddles will stay at the extremities*/
if ( paddle.getX() > (WIDTH - PADDLE_WIDTH)){
paddle.setLocation((double) (WIDTH - PADDLE_WIDTH), (double) (HEIGHT - PADDLE_Y_OFFSET));
}
if ( paddle.getX() < 0){
paddle.setLocation((double) 0, (double) (HEIGHT - PADDLE_Y_OFFSET));
}
}
/* creates the ball
*/
private void addBall(){
double ballInitXPosition = WIDTH / 2 - BALL_RADIUS;
double ballInitYPosition = HEIGHT / 2 - BALL_RADIUS;
ball = new GOval (ballInitXPosition, ballInitYPosition,
BALL_RADIUS * 2, BALL_RADIUS * 2);
ball.setFilled(true);
ball.setColor(Color.BLACK);
add (ball);
}
/* kick start the ball motion with predetermined values
*/
private void addBallMotion(){
// y component of starting velocity; pixels per second
vy = 0.3;
/* x component of starting velocity; pixels per second
* which ranges according to the random generator
* can be negative or positive, ball can go left or right with equal chances
* angle must not be 0 or 180 degrees otherwise the ball will not move anywhere else
*/
vx = rgen.nextDouble(0.0, 0.5);
if (rgen.nextBoolean(0.5)){
vx = -vx;
}
while (true){
ball.move(vx, vy);
checkCollision();
pause(DELAY);
}
}
private void checkCollision(){
checkWallCollision();
checkBrickAndPaddleCollision();
}
//checks for wall collision
private void checkWallCollision(){
if ( (getCollidingObject() == leftBounds) || (getCollidingObject() == rightBounds )){
vx = -vx;
}
//checks for floor and ceiling collision collision
if ( (getCollidingObject() == topBounds) ){
vy = -vy;
}
if ( (getCollidingObject() == bottomBounds)){
remove (ball);
runGame();
}
}
/* check if there is any collision with brick or paddle
*/
private void checkBrickAndPaddleCollision(){
GObject collider = getCollidingObject();
/* brick is removed and y direction of ball is reversed
* bricks counter goes down by 1 and score goes up by 1
*/
if (collider != paddle &&
collider != null &&
collider != topBounds &&
collider != rightBounds &&
collider != bottomBounds &&
collider != leftBounds){
remove(collider);
vy = -vy;
}
/* collide with paddle, y direction is reversed
*/
else if (collider == paddle){
vy = -vy;
}
}
//check for collision at the 4 sides of the ball
//starting with the top and going clockwise
//returns the object nearest to the screen that touches the sides of the ball
private GObject getCollidingObject(){
GObject ballTop = getElementAt ( (ball.getX() + BALL_RADIUS), (ball.getY() - .1) );
GObject ballRight = getElementAt ( (ball.getX() + (BALL_RADIUS * 2) + .1), (ball.getY() + BALL_RADIUS) );
GObject ballBottom = getElementAt ( (ball.getX() + BALL_RADIUS), ball.getY() + (BALL_RADIUS * 2) + .1);
GObject ballLeft= getElementAt ( (ball.getX() - .1), (ball.getY() + BALL_RADIUS) );
if (ballTop != null){
return (ballTop);
}
else if (ballRight != null){
return (ballRight);
}
else if (ballBottom != null){
return (ballBottom);
}
else if (ballLeft != null){
return (ballLeft);
}
return (null);
}
private GRect paddle; // creates a paddle that only moves linearly according to mouses' x coordinate
private GRect brick;
private GOval ball;
private double vx, vy; // x and y components of the ball's velocity
private RandomGenerator rgen = RandomGenerator.getInstance();
// creates a bounding box that is the playing area
private GLine topBounds;
private GLine bottomBounds;
private GLine leftBounds;
private GLine rightBounds;
}
答案 0 :(得分:1)
你必须维护一个单独的砖块存在的映射。我想你也需要这样的东西来进行碰撞检测。我会做类似以下的事情。
public class Game
{
Collection<Brick> bricks;
Ball ball;
public void initLocation()
{
for (int i = 0; i < NBRICK_ROWS; i++)
{
for (int j = 0; j < NBRICKS_PER_ROW; j++)
{
int y = BRICK_Y_OFFSET + (i * (BRICK_HEIGHT + BRICK_SEP));
int x = (BRICK_X_OFFSET) + (j * (BRICK_WIDTH + BRICK_SEP));
bricks.add(new Brick(x, y));
}
}
}
public void drawBricks()
{
for (Brick brick : bricks)
{
brickRect = new GRect(x, y, BRICK_WIDTH, BRICK_HEIGHT);
add(brick);
}
}
}
public class Brick
{
int x;
int y;
public Brick(int x, int y)
{
this.x = x;
this.y = y;
}
}
public class Ball
{
int x;
int y;
}
此代码不完整,但应该让您了解如何保持对砖块的引用。当你检查碰撞时,你可以遍历砖块,找到与球发生碰撞的任何东西,然后在那块砖上调用remove()。
答案 1 :(得分:1)
因此,如果您使用外部库(add()
)中的acm.graphics
,则需要保留自己添加的砖块副本。也许添加一个boolean
值的二维数组或类似@thattolleyguy的结构建议你的类然后添加它们的方法
private void addBrick(int x, int y)
{
brickArray[x][y] = true; //your own copy of brick locations
int yloc = BRICK_Y_OFFSET + (i * (BRICK_HEIGHT + BRICK_SEP));
int xloc = (BRICK_X_OFFSET) + (j * (BRICK_WIDTH + BRICK_SEP));
brick = new GRect (xloc, yloc, BRICK_WIDTH, BRICK_HEIGHT );
add (brick);
}
然后,您可以使用removeBrick
方法从阵列中轻松删除它们(将该位置设置为false)和外部库(或者您可能需要重绘)。
同时强>
对象引用brick
仅在此函数中引用,因此它只需要是本地
private void addBricks()
{
GRect brick;
...
add(brick);
...
}
答案 2 :(得分:0)
如果我是你,我会将所有GRect
存储在List<GRect>
中。此列表应位于您的运营中心。
我认为绘图是由repaint()
方法触发的。可能在sperate线程中,您需要检查球与每个GRect
之间的距离,当您发现与球相交的GRect
时,您可以将GRect
传递给{{1} }}。
一个简单的解决方案是在每个remove()
中保留isVisible
标记,并在GRect
中对其进行修改。顺便说一句,Java对象通过引用传递,您的修改将生效。