Please find attached some of the source code for a game of snake I'm trying to create:
package Snake;
import java.awt.*;
import Snake.GameBoard.*;
public enum TileType {
SNAKE(Color.GREEN),
FRUIT(Color.RED),
EMPTY(null),
private Color tileColor;
private TileType(Color color) {
this.tileColor = color;
}
// # return
public Color getColor() {
return tileColor;
}
private TileType[] tiles;
public void GameBoard() {
tiles = new TileType[MAP_SIZE * MAP_SIZE];
resetBoard();
}
// Reset all of the tiles to EMPTY.
public void resetBoard() {
for(int i = 0; i < tiles.length; i++) {
tiles[i] = TileType.EMPTY;
}
}
// # param x The x coordinate of the tile.
// # param y The y coordinate of the tile.
// # return The type of tile.
public TileType getTile(int x, int y) {
return tiles[y * MAP_SIZE + x];
}
/**
* Draws the game board.
* #param g The graphics object to draw to.
*/
public void draw(Graphics2D g) {
//Set the color of the tile to the snake color.
g.setColor(TileType.SNAKE.getColor());
//Loop through all of the tiles.
for(int i = 0; i < MAP_SIZE * MAP_SIZE; i++) {
//Calculate the x and y coordinates of the tile.
int x = i % MAP_SIZE;
int y = i / MAP_SIZE;
//If the tile is empty, so there is no need to render it.
if(tiles[i].equals(TileType.EMPTY)) {
continue;
}
//If the tile is fruit, we set the color to red before rendering it.
if(tiles[i].equals(TileType.FRUIT)) {
g.setColor(TileType.FRUIT.getColor());
g.fillOval(x * TILE_SIZE + 4, y * TILE_SIZE + 4, TILE_SIZE - 8, TILE_SIZE - 8);
g.setColor(TileType.SNAKE.getColor());
} else {
g.fillRect(x * TILE_SIZE + 1, y * TILE_SIZE + 1, TILE_SIZE - 2, TILE_SIZE - 2);
}
}
}
}
A lot of this works fine. However, where it says 'private Color tileColor;', I'm getting 'I'm getting 'Syntax error on token tileColor', please delete token' but when I delete this it causes even more reds on my IDE (I'm using Eclipse).
Also, whenever MAP_SIZE and TILE_SIZE appear, it says they cannot be resolved to a variable, despite the fact they are present in the following class:
package Snake;
public class GameBoard {
public static final int TILE_SIZE = 25;
public static final int MAP_SIZE = 20;
}
within the same package, and should therefore be easy for the compiler to find.
You need a semi-colon here:
SNAKE(Color.GREEN),
FRUIT(Color.RED),
EMPTY(null); <--
This is required for enums that contain more than simply the constant definitions. From the docs
when there are fields and methods, the list of enum constants must end with a semicolon.
MAP_SIZE and TILE_SIZE cannot be resolved as they exist in a different class, GameBoard. Here are 2 options:
Use the qualified names, i.e. GameBoard.MAP_SIZE & GameBoard.TILE_SIZE
or
As enums can implement interfaces: Make GameBoard an interface and implement the interface. The variables will then become member variables.
Related
public class Hexagon extends JPanel {
// Team that controls the hexagon
public int controller; // 0 neutral // 1 is team 1 // 2 is team 2
// Color of the hexagon
// /* All attributes of the board, used for size an boarder etc... */ Board board
// /* Determines where the hexagon sits on the game board */ int position
public static void main(String args[])
{
JFrame j = new JFrame();
j.setSize(350, 250);
for(int i = 0; i < 121; i++)
{
Hexagon hex = new Hexagon();
j.add(hex);
}
j.setVisible(true);
}
#Override
public void paintComponent(Graphics shape)
{
super.paintComponent(shape);
Polygon hexagon = new Polygon();
// x, y coordinate centers, r is radius from center
Double x, y;
// Define sides of polygon for hexagon
for(int i = 0; i < 6; i++)
{
x = 25 + 22 * Math.cos(i * 2 * Math.PI / 6);
y = 25 + 22 * Math.sin(i * 2 * Math.PI / 6);
hexagon.addPoint(x.intValue(), y.intValue());
}
// Automatic translate
hexagon.translate(10, 10);
// How do I manually control translate?
shape.drawPolygon(hexagon);
}
}
How do I manually translate a polygon? I need to do it to create a game board. So far I've only accomplished automatic translation of polygons which is definitely what I don't need.
I mean like parameterize it so that it's not always 10.
Then you need parameters for your class:
Create a method in your class like `setTranslation(int x, int y) and save the x/y values to instance variables.
In the paintComponent() method you reference these instance variables
Then when you create the Hexagon you can manually set the translation.
Something like:
public void setTranslation(int translationX, int translationY)
{
this.translationX = translationX;
this.translationY = translationY;
}
...
//hexagon.translate(10, 10);
hexagon.translate(translateX, translateY);
...
Hexagon hex = new Hexagon();
hex.setTranslation(10, 10);
Or, you can just pass the translation values as parameters to the constructor of your Hexagon class. The point is you need to have custom properties in your Hexagon class if you want each Hexagon to have a different translation.
Please excuse the possible simiplicity of this question. I'm revisiting Java to teach it to younger kids and also never had much experience with Graphics in the past. I also don't have an IDE available to run this code or debug at the moment, so I'm wondering if someone could help me understand conceptually what is the correct code I should write to extend the program.
There is a sample program below which should run fine. I just need to extend it by adding a few more keystroke capabilities(like stated in the program instructions/comments) as well as make sure the ball goes to the edge of the screen but is still completely visible.
Please let me know if I'm adding the extra keystroke capabilities correctly or how close or far I am. I was thinking of adding the following lines of code in the keyPressed(KeyEvent e) method.
...
else if(keyCode == KeyEvent.VK_Z)
{
g.fillOval(x + radius, y + radius, 2 * radius, 2 * radius);
}
else if(keyCode == KeyEvent.VK_S)
{
g.fillOval(x - radius, y - radius, radius, radius);
}
else if(keyCode == KeyEvent.VK_B)
{
g.fillOval(x - radius, y - radius, 4 * radius, 4 * radius);
}
else if(keyCode == KeyEvent.VK_C)
{
g.setColor(Color.green);
}
.
I'm not completely sure how the code within the if-else blocks (above and below) should be in order to update the characteristics of the ball. Part of the reason is because I may not have a firm understanding of repaint() and paint(Graphics g). Any insights or tips 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);
}
}
That seems correct at a glance (though I also do not work with graphics frequently).
Note that if you were to release the key your ovals may disappear from the screen at the next redraw.
You can create a simple Oval wrapper class to store details like the x, y, width, and height, and put those Ovals into a list that is an instance variable of your KeyListenerDemo.
Your if-blocks would be something akin to:
else if(keyCode == KeyEvent.VK_Z)
{
Oval o = new Oval(x + radius, y + radius, 2 * radius, 2 * radius);
ovals.add(o); // where ovals is an ArrayList<Oval> or LinkedList<Oval>
g.fillOval(o.x, o.y, o.width, o.height);
}
At the public void paint(Graphics g) method you'd loop through the list and (re)draw those ovals.
Edit: I'd implement the oval class like:
public class Oval {
int x;
int y;
int width;
int height;
public Oval(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
}
The list is simply declared as protected List<Oval> ovals = new LinkedList<>();, right above your main method. To loop over it (in your paint method, where g is available, you can use:
for(Oval o : ovals){
g.fillOval(o.x, o.y, o.width, o.height);
}
Hopefully this helps!
im trying to put restrictions on movement if my chicken reaches the corner here is my code for my move method
public void move1(){
if(((x<=350) && (y>=350)) || ((x>=450) && (y>=350))){
if(dy<0){
dy=0;
}
}
if(((x>=350) && (y<=350)) || ((x<=450) && (y<=350))){
if(dx<0 || dx>0){
dx=0;
}
}
if(((y<=250) && (x<=350)) || ((y<=250) && (x>=450))){
if(dy>0){
dy=0;
}
}
if (x >= 750){
x = 750;
}
if (y >= 575){
y = 575;
}
x += dx;y += dy;
}
i used a key adapter for the movement of my chicken but its from a different class
public void keyPressed(KeyEvent e) {
chick.keyPressed(e);
}
the animation is perfectly fine but my chicken wont respond the keyevent
I would strongly recommend you to have a look at KeyBindings, they are more accustomed to such situations, which are more concerned about focus related issues. This post regarding Motion Using the Keyboard, might will surely interest you, on the topic concern :-)
EDIT :
Here a small program from help :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class KeyBindingExample
{
private DrawingBoard contentPane;
/*
* There variables will simply
* decide how much the square
* will move with click key press,
* in this case I have set this to
* 1 (inside the constructor).
* brakes will simply tell whether
* the square will move or not in
* a given direction.
*/
private int speed;
private int brakes;
public KeyBindingExample() {
speed = 5;
brakes = 0;
}
private void displayGUI()
{
JFrame frame = new JFrame("Swing Worker Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
contentPane = new DrawingBoard(10, 10, Color.BLUE.darker());
addBindingsToBoard();
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private void addBindingsToBoard() {
/*
* Since, when UP Arrow is pressed, that means, the square
* can move vertically upwards, hence, the square will move
* along Y-Axis that too in the negative direction of the
* same, though along X-Axis the square will move nowhere,
* hence, we passing 0 and -1, since we want to add the
* current location (say square is at present at 50, 50),
* now after UP Arrow key event, square will be at (50, 49);
*/
putBindingsFor(contentPane, KeyStroke.getKeyStroke("UP"),
"UP Arrow Key", brakes, -speed);
/*
* When RIGHT Arrow is pressed, the square is suppose to
* move horizontally, along the X-Axis, in the positive
* direction towards the RIGHT. Hence +1 change along X-Axis
* and no change along Y-Axis, i.e. from (50, 49), the square
* will now move to (51, 49), that's why we passing (+1, 0)
*/
putBindingsFor(contentPane, KeyStroke.getKeyStroke("RIGHT"),
"RIGHT Arrow Key", speed, brakes);
/*
* When DOWN Arrow is pressed, the square is suppose to
* move vertically, along the Y-Axis, in the positive
* direction towards the BOTTOM. Hence no change along X-Axis
* and +1 change along Y-Axis, i.e. from (51, 49), the square
* will now move to (51, 50), that's why we passing (0, +1)
*/
putBindingsFor(contentPane, KeyStroke.getKeyStroke("DOWN"),
"DOWN Arrow Key", brakes, +speed);
/*
* When LEFT Arrow is pressed, the square is suppose to
* move horizontally, along the X-Axis, in the negative
* direction towards the LEFT side. Hence -1 change along X-Axis
* and no change along Y-Axis, i.e. from (51, 50), the square
* will now move to (50, 50), that's why we passing (-1, 0).
* The square will atlast come to it's initial position.
*/
putBindingsFor(contentPane, KeyStroke.getKeyStroke("LEFT"),
"LEFT Arrow Key", -speed, brakes);
}
private void putBindingsFor(JComponent comp,
KeyStroke keyStroke, String value, final int moveX, final int moveY) {
comp.getInputMap().put(keyStroke, value);
comp.getActionMap().put(value, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent ae) {
contentPane.setValues(moveX, moveY);
}
});
}
public static void main(String[] args)
{
Runnable runnable = new Runnable()
{
#Override
public void run()
{
new KeyBindingExample().displayGUI();
}
};
EventQueue.invokeLater(runnable);
}
}
class DrawingBoard extends JPanel {
private int x;
private int y;
private int width;
private int height;
private Color rectColor;
public DrawingBoard(int x, int y, Color rColor) {
setOpaque(true);
this.x = x;
this.y = y;
rectColor = rColor;
width = height = 10;
}
public void setValues(int deltaX, int deltaY) {
System.out.format("Firstly X : %d\tY : %d%n", x, y);
repaint(x, y, width, height);
/*
* Whatever values are passed from above, i.e.
* say on Left ARROW, we passing (-1, 0),
* therefore deltaX will be -1 and deltaY will
* be 0. Now whatever the current value of X is
* we are simply adding deltaX to that value
* and the same goes for deltaY as well.
* Now since the value for x and y is updated
* after these two statements below, we checking
* that whether these two updated values lies
* within the bounds of our board or not.
* If they are, then we simply calling repaint,
* to draw the square at this new location, else
* we simply bring back the previous values of
* x and y to their previous state.
*/
x += deltaX;
y += deltaY;
if ((x + width) <= getWidth() && (y + height) <= getHeight()
&& x >= 0 && y >= 0) {
System.out.format("Later X : %d\tY : %d%n", x, y);
repaint(x, y, width, height);
}
else {
x -= deltaX;
y -= deltaY;
System.out.format("Later X : %d\tY : %d%n", x, y);
repaint(x, y, width, height);
}
}
/*
* Make this a customary habbit of overridding
* this method whenever you have to override
* any JComponent, instead of calling
* setPreferredSize(...).
*/
#Override
public Dimension getPreferredSize() {
return (new Dimension(100, 100));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(rectColor);
g.fillRect(x, y, width, height);
}
}
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();
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.