Jump to content

  • Log In with Google      Sign In   
  • Create Account


Critique/tips on first breakout attempt?


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
9 replies to this topic

#1 stein102   Members   -  Reputation: 475

Like
2Likes
Like

Posted 20 March 2013 - 10:30 PM

I have followed the advice given by Alpha_ProgDes and made a pong game, followed by a breakout game. I made the game in Java with Slick as my game library. It's pretty basic and has a few errors, but I'm fairly happy with the overall result. There is still work to be done, the errors I need to fix right now are:

 

1) When ball collides with the paddle on the side it still changes the balls dy, not the dx. I feel like it would be easy enough to make another shape and add it onto the ends of the paddle for the ball to collide with.

2) Sometimes when the ball collides with the bricks, instead of bouncing off and destroying the brick, it continues through that brick and destroys another. I'm not sure what causes this but I feel like it has something to do with the order I've set up the collision in.

 

Possibly features to add:

1) Music and sound - This should be easy enough, it's just a matter of finding some sounds to use

2) A menu

3) Actual game levels - Read from a text file, instead of 5 solid lines of brick

4) A level editor - Probably something I'd come back to after gaining more experience

5) Player lives - After #3

6) A score - After #3

 

What do you guys think? Any suggestions of things I can do differently?

 

After typing this all out, I got an error with the uploader, it reads "Upload Skipped(Error503)". Any idea what this means? I'd like to get some input on this project.



Sponsor:

#2 stein102   Members   -  Reputation: 475

Like
1Likes
Like

Posted 20 March 2013 - 11:27 PM

The proper attachment

 

Attached File  Breakout.rar   3.02MB   42 downloads


Edited by Gaiiden, 21 March 2013 - 03:55 AM.
double-post from thread merge


#3 Krohm   Crossbones+   -  Reputation: 3020

Like
2Likes
Like

Posted 21 March 2013 - 01:51 AM

I'd consider (2) unacceptable. I'm not sure about (1) either.

I strongly suggest to use sweeping collision checking.

I also suggest to do (5) and (6) before (3) as I expect those to be easier. Do easy things first.

 

As a side note, I don't suggest to use text files. Their inability to be "natively set up in columns" makes them hard to deal with in my opinion.

Consider .csv instead: this way, you can edit them in (say) openoffice calc, export it (it's basically a txt anyway) but you gain the explicit aligned cells of a spreadsheet.

In the past, I've experimented with this for a maze-oriented game. The fact each cell can contain nearly arbitrary data without messing up the layout (at least in calc) was a serious bonus for me.

 

No idea about the upload error. I'm fairly sure other people have uploaded executables in the past.



#4 Alpha_ProgDes   Crossbones+   -  Reputation: 4688

Like
0Likes
Like

Posted 21 March 2013 - 03:16 AM

After typing this all out, I got an error with the uploader, it reads "Upload Skipped(Error503)". Any idea what this means? I'd like to get some input on this project.

Just post the code here. It'll be easier on everyone.
Beginner in Game Development? Read here.
 
Super Mario Bros clone tutorial written in XNA 4.0 [MonoGame, ANX, and MonoXNA] by Scott Haley
 
If you have found any of the posts helpful, please show your appreciation by clicking the up arrow on those posts Posted Image
 
Spoiler

#5 stein102   Members   -  Reputation: 475

Like
2Likes
Like

Posted 21 March 2013 - 04:06 PM

After typing this all out, I got an error with the uploader, it reads "Upload Skipped(Error503)". Any idea what this means? I'd like to get some input on this project.

Just post the code here. It'll be easier on everyone.

 

Main Class:

import java.util.Random;
import org.lwjgl.input.Mouse;
import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.BasicGame;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;

public class BreakoutMain extends BasicGame {

	static AppGameContainer app;
	Brick[] bricks;
	Paddle paddle;
	Ball ball;
	boolean gameOver = false;
	Item item;

	public BreakoutMain() {
		super("Breakout");

	}

	public void init(GameContainer container) throws SlickException {
		paddle = new Paddle(Mouse.getX());
		bricks = new Brick[60];
		ball = new Ball(Mouse.getX());
		item = new Item(1000, 0);
		int brickx = 5;
		int bricky = 5;

		for (int c = 0; c < 5; c++) {
			for (int i = 0; i < 12; i++) {
				bricks[(c * 12) + i] = new Brick(brickx, bricky);
				brickx += 65;
			}
			bricky += 35;
			brickx = 5;
		}
	}

	public void update(GameContainer container, int delta)
			throws SlickException {
		if (!gameOver) {
			Input input = app.getInput();

			if (input.isMousePressed(0) && !ball.isFree()) {
				ball.setFree(true);
			}

			paddle.update(Mouse.getX());
			ball.update(Mouse.getX());
			item.update();

			collision();
		} else {
			if (Mouse.isButtonDown(0)) {
				System.exit(0);
			}
		}
	}

	public void render(GameContainer container, Graphics g)
			throws SlickException {
		if (!gameOver) {
			paddle.paint(g);
			ball.paint(g);
			item.paint(g);

			for (Brick b : bricks) {
				b.paint(g);
			}
		} else {
			g.drawString("Game Over", 350, 280);
		}
	}

	public static void main(String[] args) throws SlickException {
		app = new AppGameContainer(new BreakoutMain());

		app.setDisplayMode(785, 600, false);
		app.start();
	}

	public void collision() {
		// Ball-Brick
		for (Brick currentBrick : bricks) {
			if (ball.ballCircle.intersects(currentBrick.brickRect)) {
				ball.setDy(-ball.getDy());

				Random rand = new Random();
				// 10% chance to drop item on broken brick
				switch (rand.nextInt(49)) {
				case 0:
					item = new ItemBigPaddle(
							currentBrick.brickRect.getCenterX(),
							currentBrick.brickRect.getCenterY());
					break;
				case 1:
					item = new ItemSmallPaddle(
							currentBrick.brickRect.getCenterX(),
							currentBrick.brickRect.getCenterY());
					break;
				case 2:
					item = new ItemFastBall(
							currentBrick.brickRect.getCenterX(),
							currentBrick.brickRect.getCenterY());
					break;
				case 3:
					item = new ItemSlowBall(
							currentBrick.brickRect.getCenterX(),
							currentBrick.brickRect.getCenterY());
					break;
				}

				currentBrick.brickRect.setX(1000);
			}
		}

		// Ball-Right Wall
		if (ball.ballCircle.getMaxX() >= 785) {
			ball.setDx(-ball.getDx());
		}

		// Ball-Left Wall
		if (ball.ballCircle.getMinX() <= 0) {
			ball.setDx(-ball.getDx());
		}

		// Ball-Top Wall
		if (ball.ballCircle.getMinY() <= 0) {
			ball.setDy(-ball.getDy());
		}

		// Ball-Bottom Wall
		if (ball.ballCircle.getMaxY() >= 600) {
			gameOver = true;
		}

		// Ball-paddle
		if (ball.ballCircle.intersects(paddle.paddleRect)) {
			ball.setDy(-ball.getDy());
		}

		// Paddle-Item
		if (paddle.paddleRect.intersects(item.itemCircle)) {
			item.performAction(ball, paddle);
			item.itemCircle.setCenterX(1000);
		}

	}

}

Ball Class:

import org.newdawn.slick.Color;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.geom.Circle;

public class Ball {

	private float dx = .2f;
	private float dy = .2f;
	private boolean isFree = false;
	Circle ballCircle;

	public Ball(int mouseX) {
		ballCircle = new Circle(mouseX, 550, 10);
	}

	public void update(int mouseX) {
		if (!isFree) {
			ballCircle.setCenterX(mouseX);
		} else {
			ballCircle.setCenterX(ballCircle.getCenterX() + dx);
			ballCircle.setCenterY(ballCircle.getCenterY() - dy);
		}
	}

	public void paint(Graphics g) {
		g.setColor(Color.white);
		g.fillOval(ballCircle.getX(), ballCircle.getY(),
				ballCircle.getHeight(), ballCircle.getWidth());

	}

	// Getters and setters

	public boolean isFree() {
		return isFree;
	}

	public void setFree(boolean isFree) {
		this.isFree = isFree;
	}

	public float getDx() {
		return dx;
	}

	public void setDx(float dx) {
		this.dx = dx;
	}

	public float getDy() {
		return dy;
	}

	public void setDy(float dy) {
		this.dy = dy;
	}

}

Paddle Class:

import org.newdawn.slick.Color;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.geom.Rectangle;

public class Paddle {

	Rectangle paddleRect;

	public Paddle(float MouseX) {
		paddleRect = new Rectangle(MouseX, 560, 60, 15);
	}

	public void paint(Graphics g) {
		g.setColor(Color.white);
		g.fillRect(paddleRect.getX(), paddleRect.getY(), paddleRect.getWidth(),
				paddleRect.getHeight());
	}

	public void update(int mouseX) {
		paddleRect.setCenterX(mouseX);
		if (paddleRect.getMaxX() >= 785)
			paddleRect.setX(785 - paddleRect.getWidth());

		if (paddleRect.getX() <= 0)
			paddleRect.setX(0);
	}

}

Brick Class:

import org.newdawn.slick.Color;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.geom.Rectangle;

public class Brick {

	private boolean destroyed = false;
	Rectangle brickRect;

	public Brick(float x, float y) {

		brickRect = new Rectangle(x, y, 60, 30);
	}

	public void paint(Graphics g) {
		g.setColor(Color.white);
		g.fillRect(brickRect.getX(), brickRect.getY(), brickRect.getWidth(),
				brickRect.getHeight());
	}
}

Item Class:

import org.newdawn.slick.Color;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.geom.Circle;

public class Item {

	Circle itemCircle;
	float dy = .15f;
	Color color;

	public Item(float x, float y) {
		itemCircle = new Circle(x, y, 7);
	}

	public void update() {
		if (itemCircle.getCenterX() != 1000) {
			itemCircle.setCenterY(itemCircle.getCenterY() + dy);
		}
	}

	public void performAction(Ball ball, Paddle paddle) {}

	public void paint(Graphics g) {
		g.setColor(color);
		g.fillOval(itemCircle.getCenterX(), itemCircle.getCenterY(),
				itemCircle.getWidth(), itemCircle.getHeight());
	}

}

 


There are other classes for the various items I've made, they're pretty basic though. Only thing different in them is that I change color and add stuff into the action performed method. The only items I've made are Speed up, Speed down, Bigger paddle and Smaller paddle.



#6 jellyfishchris   Members   -  Reputation: 300

Like
2Likes
Like

Posted 21 March 2013 - 05:35 PM

Have you looked at what happens if you try to hit a block from on top of it?
If you look at

 

ball.setDy(-ball.getDy()); 

 

 

You should consider using vectors to represent the balls velocity.



#7 stein102   Members   -  Reputation: 475

Like
0Likes
Like

Posted 21 March 2013 - 05:46 PM

How would I represent a vector in Java? What would I use to store say V = 20m/s[N45E]? Or would I just use the components and have like Vx and Vy?



#8 stein102   Members   -  Reputation: 475

Like
0Likes
Like

Posted 21 March 2013 - 07:34 PM

Also, fixed the problem where the ball continues through multiple bricks. Just added a break after

currentBrick.brickRect.setX(1000);

 In the Collision method



#9 Chad Smith   Members   -  Reputation: 1082

Like
0Likes
Like

Posted 22 March 2013 - 10:43 AM

How would I represent a vector in Java? What would I use to store say V = 20m/s[N45E]? Or would I just use the components and have like Vx and Vy?

I think Slick already has a Vector class that you can use.

 

http://slick.cokeandcode.com/javadoc/org/newdawn/slick/geom/Vector2f.html



#10 stein102   Members   -  Reputation: 475

Like
0Likes
Like

Posted 22 March 2013 - 10:53 PM

So how would I use a vector to represent the balls velocity? When the ball hits a stationary object, it's velocity just reverses, so that's simple. When the object hits the paddle though, would I reverse the velocity of the ball and add on the velocity of the paddle?






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS