I'm trying to initialize the breakout game so that the game starts with the paddle added to the canvas at a specified location then have the same paddle move with the mouse.
So, 1. create paddle and add on canvas
2. move paddle as it tracks the mouse's position.
PROBLEM: Paddle added to canvas stays where it is but another paddle NOT ADDED to canvas moves according to event listener. One paddle stays stationary and another tracks the mouse.
I have moved the add(paddle) statement to the mouse
ENV: Mac OSX 10.8.4 , JVM 1.6 (installed with OSX)
Is there some kind of setting in java that needs to be set to refresh the paddle upon mouse event? or is it an environmental issue?
/*
* File: Breakout.java
* -------------------
* Name:
* Section Leader:
*
* 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.*;
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
* Should not be used directly (use getWidth()/getHeight() instead).
* * */
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 = 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;
/** Number of turns */
private static final int NTURNS = 3;
/** ADDED KNM Private Instance Variables */
private GRect paddle;
/* Method: run() */
/** Runs the Breakout program. */
public void run() {
/* You fill this in, along with any subsidiary methods */
init();
}
public void init(){
addMouseListeners();
setSize(APPLICATION_WIDTH,APPLICATION_HEIGHT);
prepTiles();
prepPaddle();
}
private void prepTiles(){
for (int i = 1; i <= NBRICK_ROWS; i++){
int x_pos_start = 0;//(CANVAS_MIDDLE - BRICK_WIDTH/2) - (NBRICKS_PER_ROW/2 - 2)*BRICK_WIDTH;
int y_pos = BRICK_Y_OFFSET + (i-1)*(BRICK_HEIGHT+BRICK_SEP);
Color BRICK_COLOR = getBRICK_COLOR(i);
//case for color fills
for(int y = 1; y <= NBRICKS_PER_ROW; y++ ){
//adjust to beginning of row then add bricks
int x_pos = x_pos_start + ((y-1)*(BRICK_WIDTH+BRICK_SEP));
G3DRect grect = new G3DRect(x_pos, y_pos, BRICK_WIDTH, BRICK_HEIGHT);
grect.setFilled(true);
grect.setColor(BRICK_COLOR);
add(grect);
}
}
}
public void prepPaddle(){
double x_pos = APPLICATION_WIDTH/2 - PADDLE_WIDTH/2;
double y_pos = APPLICATION_HEIGHT - PADDLE_HEIGHT - PADDLE_Y_OFFSET;
paddle = new GRect(x_pos, y_pos, PADDLE_WIDTH, PADDLE_HEIGHT);
paddle.setFilled(true);
paddle.setColor(Color.DARK_GRAY);
add(paddle); // want to keep this.
}
public void mouseMoved(MouseEvent e){
// add(paddle); // I tried moveing the statement here but, that doesn't create the paddle until the mouse hovers above the application canvas.
paddle.setLocation(e.getX() - PADDLE_WIDTH/2, paddle.getY());
if (paddle.getX() <= 0) paddle.setLocation(0, paddle.getY());
if (paddle.getX() + PADDLE_WIDTH >= getWidth()) paddle.setLocation(getWidth() - PADDLE_WIDTH, paddle.getY());
}
private Color getBRICK_COLOR(int i_row){
switch (i_row){
case 1 :
case 2 : return Color.RED;
case 3 :
case 4 : return Color.ORANGE;
case 5 :
case 6 : return Color.yellow;
case 7 :
case 8 : return Color.green;
case 9 :
case 10: return Color.cyan;
default: return Color.black;
}
}
}
You probably just need to call repaint() after moving the paddle.
turns out i was calling init() procedure for the wrong reasons. I renamed the called caused the problem. i changed the function to something else and it all worked out fine. trying to figure out what happened ther
Related
I have limited Java experience and am using the program below to teach a high school level student introductory Java. Most programs from the class should work as is before extending it, like the program below. I am able to get the program running in Eclipse and drawing a Blue ball like it states in the code. BUT, I can not get the ball to move up, down, left, or right. Was something left out of this 'starter' code that draws the ball, but does not respond to the arrow keys? It's as if all my keyPressed() code is ignored. Any insights are much appreciated.
.
import java.awt.*;
import java.awt.event.*; // #1
import javax.swing.*;
/******************************************************************************
*
* KeyListenerDemo.java
* Demonstrates getting keyboard input using the KeyListener interface.
*
* Program 18: Extend this program by adding a few more keystroke commands:
* z (VK_Z) - Cause the ball to jump to a random new location.
* s (VK_S) - Make the ball smaller - multiply its diameter 1/2.
* b (VK_B) - Make the ball bigger - multiply its diameter by 2.
* c (VK_C) - Change the color (in any way you'd like).
*
* In addition, modify the program to ensure the following:
* - The ball goes all the way to the edge of the screen but stays
* completely on the screen.
* - If a doubled diameter doesn't fit, make it as large as possible.
* - Be sure the ball never completely disappears.
*
*****************************************************************************/
public class KeyListenerDemo extends JFrame
implements KeyListener // #2
{
// Class Scope Finals
private static final int SCREEN_WIDTH = 1000;
private static final int SCREEN_HEIGHT = 800;
private static final int START_RADIUS = 25;
private static final int START_X = 100;
private static final int START_Y = 100;
private static final int STEP_SIZE = 10;
// Class Scope Variables
private static int x = START_X; // x at center of the ball
private static int y = START_Y; // y at center of the ball
private static int radius = START_RADIUS; // radius of the ball
// Methods
/**
* Create the window and register this as a KeyListener
*
* #param args
*/
public static void main (String[] args)
{
// Set up the JFrame window.
KeyListenerDemo gp = new KeyListenerDemo();
gp.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
gp.setVisible(true);
gp.addKeyListener(gp); // #3
// If this class had a constructor and you moved this line into
// that constructor it could not refer to gp since that variable
// is local to this method. Instead you would write::
// addKeyListener(this);
}
/**
* Called when a key is first pressed
* Required for any KeyListener
*
* #param e Contains info about the key pressed
*/
public void keyPressed(KeyEvent e) // #4A
{
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_LEFT)
{
x = x - STEP_SIZE;
}
else if (keyCode == KeyEvent.VK_RIGHT)
{
x = x + STEP_SIZE;
}
else if (keyCode == KeyEvent.VK_UP)
{
y = y - STEP_SIZE;
}
else if (keyCode == KeyEvent.VK_DOWN)
{
y = y + STEP_SIZE;
}
repaint();
}
/**
* Called when typing of a key is completed
* Required for any KeyListener
*
* #param e Contains info about the key typed
*/
public void keyTyped(KeyEvent e) // #4B
{
}
/**
* Called when a key is released
* Required for any KeyListener
*
* #param e Contains info about the key released
*/
public void keyReleased(KeyEvent e) // #4C
{
}
/**
* paint - draw the figure
*
* #param g Graphics object to draw in
*/
public void paint(Graphics g)
{
g.setColor(Color.white);
g.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
g.setColor(Color.blue);
g.fillOval(x - radius, y - radius, 2 * radius, 2 * radius);
}
}
I'm trying to build a pyramid in Java using GRect. I use getWidth() to position the pyramid in the center of the canvas but it tends to trip the left part of pyramid.
I'm learning programming through CS106A and using Java 1.6 so tried to get some other peoples code and they too showed the same bug. I tried to draw a simple rect and it works fine.
Is it some issue with Java applet as it tends to ignore getWidth() value at all. I used println(); to get getWidth() value and it works.
import acm.graphics.GRect;
import acm.program.GraphicsProgram;
public class Pyramid extends GraphicsProgram {
/**
* eclipse generated SVUID
*/
private static final long serialVersionUID = 5703830460071233096L;
/** Width of each brick in pixels */
private static final int BRICK_WIDTH = 30;
/** Width of each brick in pixels */
private static final int BRICK_HEIGHT = 12;
/** Number of bricks in the base of the pyramid */
private static final int BRICKS_IN_BASE = 14;
public void run() {
//centering the pyramid
int _canvasWidth = getWidth(); //canvas width
//println(_canvasWidth); //to check if getWidth returns a value
int _brickSpace = BRICKS_IN_BASE * BRICK_WIDTH; //space consumed by the base row
int _freeSpace = _canvasWidth - _brickSpace; //empty base level space
int _xOffset = _freeSpace / 2; //x for left most brick of base row
for(int row=0; row<BRICKS_IN_BASE; row++){ //the row number
int _rowTab = (BRICK_WIDTH/2) * row; //indentaion for each row
int _brickInRow = BRICKS_IN_BASE - row; //bricks as per row
for(int _brickNumber=0; _brickNumber<_brickInRow; _brickNumber++){ //placing bricks till _brickInRow
int x = (_xOffset + _rowTab) + (_brickNumber * BRICK_WIDTH);
int y = (BRICK_HEIGHT * (BRICKS_IN_BASE - row)); //y as per row num
GRect _brick = new GRect(x, y, BRICK_WIDTH, BRICK_HEIGHT); //creating brick instance
add(_brick);
}
}
}
}
I tried your code and it draws the pyramid at the centre at first, but the problem comes up when I resize the viewer window.
The point is Java applets have an inherited method called public void paint(Graphics g) that is called whenever the applet has to be painted. Resizing the viewer window is one of the cases that makes the paint method called.
So, to fix this you need to override the paint method, ie. add such a method:
public void paint(Graphics g) {
this.run();
super.paint(g);
}
This method will be called every time the window is resized. But remember you don't need multiple pyramids so add following line to your run method to remove all the previous bricks before adding the new ones.
removeAll();
I don't know if I'm properly calling a GOval method. My goal is to create the Target corporation logo but with 5 circles. I'm supposed to have the Target symbol centered in the window and have the number of the circles and dimensions controlled by the named constants.
I'm starting with GOval bigCircle and that is my most outer filled circle in color red. Am I properly incorporating the createFilledCircle method?
I only have three circles so far because we're building off a previous assignment and that assignment only had three circles. Also how does N_CIRCLE fit into the picture?
import acm.program.*;
import acm.graphics.*;
import java.awt.*;
public class TargetSymbol extends GraphicsProgram {
public void run(){
double x = getWidth() / 2;
double y = getHeight() / 2;
GOval bigCircle = createFilledCircle(x - OUTER_RADIUS, y - OUTER_RADIUS, 2 * OUTER_RADIUS, 2 * OUTER_RADIUS);
createFilledCircle.setFilled(true);
createFilledCircle.setColor(Color.RED);
add(createFilledCircle);
GOval middleCircle = new GOval(100, 100, 200, 200);
middleCircle.setFilled(true);
middleCircle.setColor(Color.WHITE);
add(middleCircle);
GOval innerCircle = new GOval(155, 150, 100, 100);
innerCircle.setFilled(true);
innerCircle.setColor(Color.RED);
add(innerCircle);
}
private GOval createFilledCircle(double x, double y, double r, Color color){
GOval circle = new GOval( x-r, x-y, 2 * r, 2 * r);
circle.setColor(color);
circle.setFilled(true);
return circle;
}
private static final int N_CIRCLE = 5;
private static final double OUTER_RADUS = 75;
private static final double INNER_RADIUS = 10;
I would say you have the right idea.
GOval bigCircle = createFilledCircle(x - OUTER_RADIUS, y - OUTER_RADIUS, 2 * OUTER_RADIUS, 2 * OUTER_RADIUS);
createFilledCircle.setFilled(true);
createFilledCircle.setColor(Color.RED);
There is no variable called createFilledCircle, so you can't set it to be filled, or set it's color. We could change it to bigCircle, but that would be redundan, as you're already setting those values in the createFilledCircle() method.
I would just recommend you get rid of those 2 parts altogether, leaving you with:
GOval bigCircle = createFilledCircle(x - OUTER_RADIUS, y - OUTER_RADIUS, 2 * OUTER_RADIUS, 2 * OUTER_RADIUS);
N_CIRCLE, I can only assume represents the number of circles there are. For example, if N_CIRCLE is 5, there's the red outer circle, the white circle inside that, a red circle inside that white circle, etc.
Thus you want to use a loop that creates the circles relative to the amount of circles you have (N_CIRCLE).
e.g.
for(int a = 0; a < N_CIRCLE; a++)
{
Create a circle that is smaller than the outer one
Set it's color/fill etc.
}
I did this same assignment and I successfully completed it using this code. I apologize for it being sloppy and in bad form; I wrote it when I was first learning how to write in Java.
/*
* File: Target.java
* Name:
* Section Leader:
* -----------------
* This file is the starter file for the Target problem.
*/
import acm.graphics.*;
import acm.program.*;
import java.awt.*;
public class Target extends GraphicsProgram {
public void run() {
/* You fill this in. */
double moveX = getWidth()/2 - 36;
double moveY = getHeight()/2 - 36;
GOval outerRed = new GOval(72, 72);
outerRed.setFilled(true);
outerRed.setColor(Color.RED);
outerRed.setFillColor(Color.RED);
outerRed.move(moveX, moveY);
GOval middleWhite = new GOval(12.6, 12.6, 46.8, 46.8);
middleWhite.setFilled(true);
middleWhite.setColor(Color.WHITE);
middleWhite.setFillColor(Color.WHITE);
middleWhite.move(moveX, moveY);
GOval innerRed = new GOval(25.2, 25.2, 21.6, 21.6);
innerRed.setFilled(true);
innerRed.setColor(Color.RED);
innerRed.setFillColor(Color.RED);
innerRed.move(moveX, moveY);
add(outerRed);
add(middleWhite);
add(innerRed);
}
}
Here is my solution to this using constants:
/*
* File: Target.java
* Name:
* Section Leader:
* -----------------
* This file is the starter file for the Target problem.
*/
import acm.graphics.*;
import acm.program.*;
import java.awt.*;
public class Target extends GraphicsProgram {
private static final int RADIUS_OUTER_CIRCLE = 72;
private static final int RADIUS_MID_CIRCLE = 54;
private static final int RADIUS_INNER_CIRCLE = 32;
public void run() {
GOval outerCircle = new GOval(getWidth()/2 - RADIUS_OUTER_CIRCLE/2 , getHeight()/2 - RADIUS_OUTER_CIRCLE/2, RADIUS_OUTER_CIRCLE, RADIUS_OUTER_CIRCLE);
outerCircle.setFilled(true);
outerCircle.setFillColor(Color.RED);
add(outerCircle);
GOval midCircle = new GOval(getWidth()/2 - RADIUS_MID_CIRCLE/2 , getHeight()/2 - RADIUS_MID_CIRCLE/2, RADIUS_MID_CIRCLE, RADIUS_MID_CIRCLE);
midCircle.setFilled(true);
midCircle.setFillColor(Color.WHITE);
add(midCircle);
GOval innerCircle = new GOval(getWidth()/2 - RADIUS_INNER_CIRCLE/2 , getHeight()/2 - RADIUS_INNER_CIRCLE/2, RADIUS_INNER_CIRCLE, RADIUS_INNER_CIRCLE);
innerCircle.setFilled(true);
innerCircle.setFillColor(Color.RED);
add(innerCircle);
}
}
This is not a homework problem. I am only going over a freely available course from Stanford. I am using Ubuntu Linux with Eclipse.
Problem and Question:
I am drawing rectangles by calling add() on a acm.program.GraphicsProgram object. I am drawing certain number of rectangles which have a certain fixed width. However I am seeing that my rectangles are flowing off the visible area. I have tried setting a big enough width and height for both the GraphicsProgram object and the GCanvas object but still my rectangles are falling off the visible area. I always get the same height for GraphicsProgram object no matter what height I set. Any pointers as to what am I doing wrong?
import acm.graphics.*;
import acm.program.*;
import java.awt.*;
public class Pyramid extends GraphicsProgram {
/** Width of each brick in pixels */
private static final int BRICK_WIDTH = 30;
/** Width of each brick in pixels */
private static final int BRICK_HEIGHT = 12;
/** Number of bricks in the base of the pyramid */
private static final int BRICKS_IN_BASE = 14;
public void run() {
setWindowSize();
this.createPyramid();
}
private void createPyramid()
{
int centerX = findCenter();
int startingX = centerX - (BRICKS_IN_BASE / 2) * BRICK_WIDTH;
int startingY = BRICK_HEIGHT;
for(int numBricks = BRICKS_IN_BASE; numBricks>= 1; numBricks--)
{
this.layBricks(startingX,startingY , numBricks);
startingX = startingX + BRICK_WIDTH / 2;
startingY = (BRICKS_IN_BASE - numBricks + 2) * BRICK_HEIGHT;
}
}
private void layBricks(int x, int y, int numOfBricks)
{
for(int i = 0; i < numOfBricks; i++)
{
add(new GRect(x,y,this.BRICK_WIDTH, this.BRICK_HEIGHT));
x+=this.BRICK_WIDTH;
}
}
private void setWindowSize()
{
int width = BRICK_WIDTH * BRICKS_IN_BASE * 2;
int height = BRICKS_IN_BASE * BRICK_HEIGHT * 2;
this.setSize(width, height);
//this.setForeground(Color.GREEN);
//this.setBackground(Color.BLUE);
//this.getGCanvas().setBounds(0, 0, width, height);
//this.getGCanvas().add(new GRect(0,0,300,30));
//this.getGCanvas().setBackground(Color.WHITE);
System.out.println(this.getHeight());
System.out.println(this.getWidth());
System.out.println(this.getGCanvas().getHeight());
System.out.println(this.getGCanvas().getWidth());
}
private int findCenter()
{
return this.getWidth() / 2;
}
}
I'm working through the same Stanford course online and ran into the same problem. The setSize method would resize the display but not the values returned by getWidth and getHeight.
You can change the width and height by going to Project > Properties > Run/Debug Settings > Edit > Parameters tab.
I assume there is something more direct or code-based, but this is an easy solution.
Start by not hard coding the brick sizes like this
int brick_width = (getWidth() / BRICKS_IN_BASE) - (getWidth() / 50);
int brick_height = (brick_width / 3);
That way your pyramid will always be drawn within whatever the screen size happens to be.
It should also be centered, once your brick sizes are relative to window size, guaranteeing that the bricks will always be centered becomes easier. The only wrench I have found are weird
window sizes such as 50 x 500, but that doesn't happen too often.
Here is a look at my solution
import acm.graphics.*;
import acm.program.*;
import java.awt.*;
public class Pyramid1 extends GraphicsProgram {
public void run(){
int brick_width = (getWidth() / BRICKS_IN_BASE) - (getWidth() / 50);
int brick_height = (brick_width / 3);
for(int n = 0; n < BRICKS_IN_BASE; n++ ){
//make a row at level n of bricks that is BRICKS_IN_BASE - n bricks wide.
int bricks_in_level = BRICKS_IN_BASE - n;
int x = ((getWidth() / 2) - ((bricks_in_level * brick_width) / 2)); //find the center then offset to farthest left.
int y = (((getHeight() / 2) + ((BRICKS_IN_BASE / 2) * brick_height )) - ((n + 1) * brick_height)); //start at the 1/2 and move down half max stack height and move up a brick each round.
GRect brick = new GRect(x, y, brick_width, brick_height);
brick.setFilled(true);
brick.setFillColor(Color.RED);
add(brick);
if(bricks_in_level > 1){ //If there are 2 or more bricks needed in this level
for(int needed_bricks = bricks_in_level - 1; needed_bricks > 0; needed_bricks -= 1){
x += brick_width;
GRect needed_brick = new GRect(x, y, brick_width, brick_height);
needed_brick.setFilled(true);
needed_brick.setFillColor(Color.RED);
add(needed_brick);
}
}
}
}
private static final int BRICKS_IN_BASE = 12;
}
The main problem was that I was using open-java-jdk and not sun-java-jdk. After changing the jre my Applet is behaving in a more predictable way.
This is my first post on SO!
I've on my own been working a few weeks through Stanford's "Programming Methodology" class which is an intro to programming with java. I've been doing all the programs so far with little difficulty, researching what I needed with minimal difficulty.
Right now, all I have are a set of bricks, and a ball that I was able to get to bounce off the walls. Currently the ball doesn't do anything but bounce around in the canvas and just passes through the bricks.
There are lots of steps involved, the other ones I am pretty sure I can take care of. The ones I am having a hard time with are...
1) Get the ball to bounce off the bricks.
2) Get the bricks to disappear when the ball bounces off them.
some resources I've been using -
Using the ACM Graphics Package
Stanford PDF with the assignment guidelines
I guess my question is. What do I need to understand in order to be able to solve the problems I listed above. In one of the lectures, the professor talks about using "getElementAt()" But I don't really understand how that method works or how I can use it to get my ball to bounce off the bricks and then after, make them disappear.
Code I wrote so far -
/*
* File: Breakout.java
* -------------------
* Name: Sandi
* Section Leader: I'm learning this online
*
* 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.*;
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 = 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;
/** Number of turns */
private static final int NTURNS = 3;
/* Method: run() */
/** Runs the Breakout program. */
public void run() {
addBricks();
addBall();
//velocity of the ball's x and y
ballVX = 1;
ballVY = 2;
while (true) {
moveBall();
pause(10);
}
}
private void addBricks() {
int startY = BRICK_Y_OFFSET;
GRect brick;
for (int i = 0; i < NBRICK_ROWS; i++) {
int startX = BRICK_SEP;
for (int j = 0; j < NBRICKS_PER_ROW; j++) {
brick = new GRect(startX, startY, BRICK_WIDTH, BRICK_HEIGHT);
add(brick);
colorBricks(brick, Color.RED, 0, 1);
colorBricks(brick, Color.ORANGE, 2, 3);
colorBricks(brick, Color.YELLOW, 4, 5);
colorBricks(brick, Color.GREEN, 6, 7);
colorBricks(brick, Color.CYAN, 8, 9);
startX += BRICK_WIDTH + BRICK_SEP;
}
startY += BRICK_HEIGHT + BRICK_SEP;
}
}
private void colorBricks(GRect brick, Color color, int fromRowNumber,
int toRowNumber) {
//this will make it so that if the bricks are between two y coordinates
//then the method will set it to a certain color and color it.
if (brick.getY() >= BRICK_Y_OFFSET + fromRowNumber
* (BRICK_HEIGHT + BRICK_SEP)
&& brick.getY() <= BRICK_Y_OFFSET + toRowNumber
* (BRICK_HEIGHT + BRICK_SEP)) {
brick.setColor(color);
brick.setFilled(true);
}
}
private void addBall() {
ball = new GOval(getWidth() / 2, getHeight() / 2, BALL_RADIUS,
BALL_RADIUS);
ball.setFilled(true);
add(ball);
}
private void moveBall() {
double borderX = ball.getX();
double borderY = ball.getY();
if (borderX == 0 || borderX == getWidth() - BALL_RADIUS) {
ballVX = -ballVX;
}
if (borderY == 0 || borderY == getHeight() - BALL_RADIUS) {
ballVY = -ballVY;
}
ball.move(ballVX, ballVY);
}
private GOval ball;
private double ballVX;
private double ballVY;
}
Thanks guys!
There are of course many things that could be done to enhance your program. But to solve your next problem I think you have to understand a little bit of the "magic" of the classes you are depend on.
I havn't studied your API in depth, but it looks like your call add(brick); adds your brick to an array/collection internally stored in GraphicsProgram (if you can get the source code of the classes you depend on it might be helpfull to read and understand the code). You can access the objects you have added later on with getElementAt. So if you add a brick at the location (10,20) and later call getElementAt(10,20) it should return this brick.
You should modify your moveBall method to check if the new position of the ball would contain a brick and, if so, act accordingly. Something like this:
private void moveBall() {
double borderX = ball.getX();
double borderY = ball.getY();
GRect brick = getElementAt(borderX, borderY);
if (brick != null) {
doSomethingWithBall();
} else {
if (borderX == 0 || borderX == getWidth() - BALL_RADIUS) {
ballVX = -ballVX;
}
if (borderY == 0 || borderY == getHeight() - BALL_RADIUS) {
ballVY = -ballVY;
}
}
ball.move(ballVX, ballVY);
}
You might have to fiddle a little bit with the values you pass into getElementAt and what exactly you do when you find a brick. You have to take into account that the bricks are not points but have a height and a width, the ball is moving and not a point, too ...
Edit: Your ball is added to the collection, too. So it might be possible that the ball is returned instead of a brick. You should not pass the actual position of your ball to the getElementAt method but an value where the ball is after it moves half the ball radius when there is no brick in the way.
private GObject getCollidingObject() {
double x = ball.getX(), y = ball.getY();
if (getElementAt(x, y) != null) { return getElementAt(x, y); }
else if (getElementAt(x, y + BALL_RADIUS * 2) != null) {
return getElementAt(x, y + BALL_RADIUS * 2); }
else if (getElementAt(x + BALL_RADIUS * 2, y + BALL_RADIUS * 2) != null) {
return getElementAt(x + BALL_RADIUS * 2, y + BALL_RADIUS * 2); }
else if (getElementAt(x + BALL_RADIUS * 2, y) != null) {
return getElementAt(x + BALL_RADIUS * 2, y); }
else { return null; }
}
... these two methods works perfectly together ...
private void elementsCollisions() {
GObject collider = getCollidingObject();
if (collider == paddle) {
vy = -vy;
}
else if (collider != null) {
remove(collider);
vy = -vy;
}
getElementAt(x, y) - returns object at the specified point. Decompose problem as much as possible if you can't solve fast.
Index the bricks in a way that you can easily check if a brick exists at a certain coordinate.
When you create a brick, you add it to the container, and then you lose it. You don't have a reference to it going forward that you can use to compare to the current ball location.
Based on your design, I believe you should do this through a 2-dimensional array. When you create the bricks, also put the GRect object in a 2-dimensional array. One dimension should be the row, and the other the column. Then you will be able to access these bricks by x and y coordinate using this array. (This is what you will need to do to detect a bounce.)
When the ball moves, the same way that you detect it bouncing off walls, check if the ball's position makes it border a spot where a brick could be. If it does, from any direction, then check if the brick is actually there by looking at your array. If there is a brick there, bounce the ball and remove the brick. Also be sure to set that location in the array to be null to indicate that the brick is gone.
Then you also have your victory condition... when all of the elements of the array have been set to null.