breakout

0

java

목록 보기
11/11
post-thumbnail

/*

  • 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 java.util.*;

import java.util.ArrayList;

public class Breakout extends GraphicsProgram {

// game setting
/* 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;

// paddle information
/* 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;

// bricks information
/* Number of bricks per row /
private static final int NBRICKS_PER_ROW = 10; // 하나의 행에서 brick 갯수

/* 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;

// ball information
/* 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;

/*Ball velocity/
private double vx, vy;

/*Random number generator for vx/
private RandomGenerator rgen = new RandomGenerator();

/* Animation delay or pause time between ball moves /
private static final double DELAY = 10;

/* 벽돌이랑 충돌 횟수 /
private int BRICKCOUNT = NBRICKS_PER_ROWNBRICK_ROWS ; // 벽돌의 갯수(열행)

/* 게임 점수 /
private int game_Score = 0;

/ Method: run() /
/* Runs the Breakout program. /

  public void run() {
	  for (int tries=0 ; tries < NTURNS; tries++) {
		  setUpGame();
		  playGame();
		  if ( BRICKCOUNT == 0 ) {
			  ball.setVisible(false);
			  messageWinner();
			  break;
		  }
	  }
	  if( BRICKCOUNT > 0) {
		  messageGameOver();
	  	}
  }

private void setUpGame() {
	setUpBricks();
	createPaddle();
    createBall();
    drawScoreBox();
}
  

private void setUpBricks() {

	ArrayList<Color> colors = new ArrayList<>(Arrays.asList(Color.RED,Color.ORANGE,Color.YELLOW,Color.GREEN,Color.CYAN));
	
	for (int i=0; i < NBRICK_ROWS;i++) {
	
		double rowStartX = 0;
		double rowStartY = BRICK_Y_OFFSET + BRICK_SEP*i + BRICK_HEIGHT*i;
		// 몫을 통해 colorNumber를 설정
		int colorNumber = i / 2;
		
		// 행표시
		for (int j=0; j < NBRICKS_PER_ROW;j++) {
			
			// rowStartX를 벽돌의 개수의 개수만큼 옆으로 이동 
			double x = rowStartX + BRICK_WIDTH*j + BRICK_SEP*j;
			GRect rect = new GRect(x,rowStartY,BRICK_WIDTH,BRICK_HEIGHT);
			rect.setFilled(true);
			rect.setColor(colors.get(colorNumber));
			add(rect);

		}
	}
}

private GRect paddle;

private void createPaddle() {
    double x = getWidth()/2 - PADDLE_WIDTH/2; // paddle이 화면 중앙에 위치하도록 한다.
    double y = getHeight() - PADDLE_Y_OFFSET - PADDLE_HEIGHT; // 
    paddle = new GRect (x, y, PADDLE_WIDTH, PADDLE_HEIGHT);
    paddle.setFilled(true);
    add (paddle);
    addMouseListeners();
}

public void mouseMoved(MouseEvent e) {
    if ((e.getX() < getWidth() - PADDLE_WIDTH/2) && (e.getX() > PADDLE_WIDTH/2)) {  // 마우스의 위치가 화면 내에 있는 경우
        paddle.setLocation(e.getX() - PADDLE_WIDTH/2, getHeight() - PADDLE_Y_OFFSET - PADDLE_HEIGHT ); // paddle은 마우스의 x좌표를 따라가고, y좌표는 유지된다.
    }
}
 
/** 공만들기  */  
  
private GOval ball;

private void createBall() {
    double x = getWidth()/2 - BALL_RADIUS;
    double y = getHeight()/2 - BALL_RADIUS;
    ball = new GOval(x, y, BALL_RADIUS, BALL_RADIUS);
    ball.setFilled(true);
    add(ball);
}

private void playGame(){
    waitForClick();
    getBallVelocity();
    while (true){
        moveBall();
        if (ball.getY() >= getHeight() - BALL_RADIUS*2) {
        	messageDead();
            waitForClick();
        	removeAll();
        	game_Score = 0;
        	break;
        }
        if (BRICKCOUNT == 0) {
        	break;
        }
    }        
}

private void getBallVelocity(){
    vx = rgen.nextDouble(1.0, 3.0);
    if(rgen. nextBoolean(0.5)) {
    	vx = -vx;
    }
    vy = 3.0;  // 임의의 위치에서 공이 떨어지도록 하였다.
}

AudioClip bounceClip = MediaTools.loadAudioClip("bounce.au"); 

private void moveBall() {
	ball.move(vx, vy);
    if (ball.getX() <= 0 || ball.getX() >=  (getWidth() -  BALL_RADIUS*2)) { // 공이 왼쪽 벽에 닿거나 오른쪽 벽에 닿으면 속도가 반대가 된다.
    	vx = -vx;
    }
    if (ball.getY() <= 0 || ball.getY() >=  (getHeight() -  BALL_RADIUS*2)) { //공이 천장에 닿으면 y의 속도가 반대가 된다.
        vy = -vy;
    }
    
    GObject collider = getCollidingObject();
    
    if (collider == paddle) { // paddle 이랑 충돌하면
    	 if(ball.getY() >= getHeight() - PADDLE_Y_OFFSET - PADDLE_HEIGHT - BALL_RADIUS*2 && ball.getY() < getHeight() - PADDLE_Y_OFFSET - PADDLE_HEIGHT - BALL_RADIUS*2 + 3) { //paddle 에 공이 닿으면 y의 속도가 반대가 된다.
             vy = -1.2*vy;   // 속도가 조금씩 빨라지도록 설정한다.
             vx = 1.2*vx;
         }
    } else if (collider != null) { // 충돌하면
    	remove(collider);  // 충돌한 brick를 제거한다.
    	bounceClip.play();  // 충돌하면 소리가 난다.
    	BRICKCOUNT--;
    	game_Score++;
    	removeScore();
    	vy = - vy;  // 그리고 나서 y의 속도를 바꾼다.
    }
    pause(DELAY);
}

private GObject getCollidingObject() {
    if((getElementAt(ball.getX(), ball.getY())) != null) {  // 왼쪽상단에 충돌이 일어나면 
        return getElementAt(ball.getX(), ball.getY());  // 왼쪽상단 좌표 값을 반환한다. 
     }
   else if (getElementAt( (ball.getX() + BALL_RADIUS*2), ball.getY() ) != null ){  // 왼쪽하단에 충돌이 일어나면
        return getElementAt(ball.getX() + BALL_RADIUS*2, ball.getY());  // 왼쪽하단 좌표 값을 반환한다.
     }
   else if(getElementAt(ball.getX(), (ball.getY() + BALL_RADIUS*2)) != null ){  // 오른쪽상단에 충돌이 일어나면
        return getElementAt(ball.getX(), ball.getY() + BALL_RADIUS*2);  // 오른쪽상단 좌표 값을 반환한다.
     }
   else if(getElementAt((ball.getX() + BALL_RADIUS*2), (ball.getY() + BALL_RADIUS*2)) != null ){  // 오른쪽하단에 충돌이 일어나면
        return getElementAt(ball.getX() + BALL_RADIUS*2, ball.getY() + BALL_RADIUS*2);  // 오른쪽하단 좌표 값을 반환한다.
     }
   else{
        return null;  // 충돌이 없으면 null을 반환한다.
     }
}

private void messageGameOver() {
	GLabel gameOver = new GLabel("Game Over", getWidth()/2, getHeight()/2);
    gameOver.move(-gameOver.getWidth()/2, -gameOver.getHeight());
    gameOver.setColor(Color.RED);
    add (gameOver);
}

private void messageWinner() {
    GLabel Winner = new GLabel (" Winner!!  ^_____^ ", getWidth()/2, getHeight()/2);
    Winner.move(-Winner.getWidth()/2, -Winner.getHeight());
    Winner.setColor(Color.RED);
    add (Winner);
}

private void messageDead() {
    GLabel Dead = new GLabel ("Dead!! ㅡ_ㅡ;; Try Again", getWidth()/2, getHeight()/2);
    Dead.move(-Dead.getWidth()/2, -Dead.getHeight());
    Dead.setColor(Color.RED);
    add (Dead);
}

// 점수 상자의 크기 지정하기
private static final int Width = 80;
private static final int Height = 20;

private void drawScoreBox() {  // 점수 상자 그리기
    int x = getWidth() - 100;  // 상자의 x위치는 정중앙에서 상자의 너비의 반만큼 왼쪽으로 간 곳에서 시작한다.
    int y = getHeight() - PADDLE_Y_OFFSET - PADDLE_HEIGHT +13  ; // 상자의 y위치는 정중앙에서 상자의 높이의 반만큼 위로 간 곳에서 시작한다.
    GLabel score = new GLabel("SCORE : " + game_Score, x, y);
    add(score); 
    double boxCenterX = Width/2;
    double boxCenterY = Height/2;
    double halfScoreBoxWidth = score.getWidth()/2;  
    double halfScoreBoxHeight = score.getAscent()/2; //finds the center of the height for "program"
    score.move( (boxCenterX - halfScoreBoxWidth) , (boxCenterY + halfScoreBoxHeight) ); 
}

}

profile
초보 데이터분석가의 기록 공간입니다 😁

0개의 댓글