An arcade game built in Processing. The player moves a paddle at the bottom of the screen to bounce a ball into rows of bricks, and must clear every brick in each level without letting the ball fall. Each level gets harder with a faster ball and stronger bricks, broken bricks can drop power-up items, and collisions between the ball, paddle, bricks and screen edges are calculated with basic physics.
View source code (Final_Brick_Breaker.pde)
Paddle paddle;
ArrayList<Ball> balls;
ArrayList<Brick> bricks;
ArrayList<Item> items = new ArrayList<Item>();
int score = 0;
int itemTimer = 0;
int expandEndTime = 0;
int fireballEndTime = 0;
int slowEndTime = 0;
boolean gameOver = false;
boolean gameWon = false;
int currentLevel = 0;
int totalLevels = 3;
boolean gameStarted = false;
boolean fireBallMode = false;
boolean isSlowed = false;
void setup() {
size(800, 600);
textAlign(CENTER, CENTER);
textFont(createFont("Arial", 24));
resetGame();
}
void resetGame() {
paddle = new Paddle();
balls = new ArrayList<Ball>();
balls.add(new Ball(currentLevel));
items.clear(); // เคลียร์ไอเท็มเดิม
loadLevel(currentLevel);
gameStarted = false;
}
void draw() {
background(30, 30, 50);
if (!gameOver && !gameWon) {
paddle.update();
paddle.display();
// ตรวจสอบเวลาไอเท็มหมด
if (expandEndTime > 0 && millis() > expandEndTime) {
paddle.w /= 1.5;
expandEndTime = 0;
}
if (fireballEndTime > 0 && millis() > fireballEndTime) {
fireBallMode = false;
fireballEndTime = 0;
}
if (slowEndTime > 0 && millis() > slowEndTime) {
for (Ball b : balls) {
b.speedX /= 0.7;
b.speedY /= 0.7;
}
slowEndTime = 0;
isSlowed = false;
}
for (Brick b : bricks) {
b.display();
}
if (!gameStarted) {
balls.get(0).display();
fill(255);
text("Press SPACE to Start", width / 2, height / 2);
return;
}
for (int i = bricks.size() - 1; i >= 0; i--) {
if (bricks.get(i).isBroken()) {
bricks.remove(i);
}
}
for (int i = balls.size() - 1; i >= 0; i--) {
Ball b = balls.get(i);
b.update();
b.checkCollision(paddle, bricks);
b.display();
if (b.y > height) {
balls.remove(i);
}
}
for (int i = items.size() - 1; i >= 0; i--) {
Item item = items.get(i);
item.update();
item.display();
if (item.isCaught(paddle)) {
item.collected = true;
activateItem(item.type);
items.remove(i);
} else if (item.y > height) {
items.remove(i); // หล่นทะลุพื้น
}
}
if (balls.isEmpty()) {
gameOver = true;
}
fill(255);
text("Score: " + score, width / 2, 20);
text("Level: " + (currentLevel + 1), width - 100, 20);
if (bricks.size() == 0) {
currentLevel++;
if (currentLevel < totalLevels) {
delay(500);
resetGame();
} else {
gameWon = true;
}
}
} else if (gameOver) {
fill(255, 0, 0);
text("Game Over", width / 2, height / 2 - 20);
text("Final Score: " + score, width / 2, height / 2);
text("Click to Restart", width / 2, height / 2 + 30);
} else if (gameWon) {
fill(0, 255, 0);
text("YOU WIN THE GAME!", width / 2, height / 2 - 20);
text("Total Score: " + score, width / 2, height / 2);
text("Click to Play Again", width / 2, height / 2 + 30);
}
}
void mousePressed() {
if (gameOver || gameWon) {
currentLevel = 0;
score = 0;
gameOver = false;
gameWon = false;
resetGame();
}
}
void keyPressed() {
if (!gameStarted && key == ' ') {
gameStarted = true;
}
}
// ------------------ Paddle ------------------
class Paddle {
float x, y, w, h;
Paddle() {
w = 120;
h = 20;
y = height - 40;
}
void update() {
x = constrain(mouseX - w / 2, 0, width - w);
}
void display() {
fill(255);
rect(x, y, w, h, 10);
}
}
// ------------------ Ball ------------------
class Ball {
float x, y;
float r = 15;
float speedX;
float speedY;
Ball(int level) {
x = width / 2;
y = height / 2;
float speedBase = 4 + level * 1.5;
speedX = random(1) < 0.5 ? speedBase : -speedBase;
speedY = -speedBase;
}
void update() {
x += speedX;
y += speedY;
if (x < 0 || x > width) speedX *= -1;
if (y < 0) speedY *= -1;
}
void display() {
fill(0, 255, 255);
ellipse(x, y, r * 2, r * 2);
}
void checkCollision(Paddle p, ArrayList<Brick> bricks) {
if (y + r >= p.y && y + r <= p.y + p.h && x >= p.x && x <= p.x + p.w) {
speedY *= -1;
y = p.y - r;
}
for (Brick b : bricks) {
if (!b.isBroken() && x > b.x && x < b.x + b.w && y - r < b.y + b.h && y + r > b.y) {
speedY *= -1;
b.hit();
score += 10; // เพิ่มคะแนนเมื่อโดนอิฐ
if (b.isBroken()) {
// สุ่มปล่อยไอเท็ม (โอกาส 30%)
if (random(1) < 0.3) {
String[] possibleItems = {"expand", "fireball", "multiball", "slow", "score"};
String itemType = possibleItems[(int)random(possibleItems.length)];
items.add(new Item(b.x + b.w/2 - 15, b.y + b.h/2 - 15, itemType));
}
}
break;
}
}
}
}
class Item {
float x, y, w = 30, h = 30;
String type;
boolean collected = false;
Item(float x, float y, String type) {
this.x = x;
this.y = y;
this.type = type;
}
void update() {
y += 3;
}
void display() {
if (!collected) {
if (type.equals("expand")) fill(0, 200, 255);
else if (type.equals("fireball")) fill(255, 100, 0);
else if (type.equals("multiball")) fill(0, 255, 100);
else if (type.equals("slow")) fill(255, 255, 0);
else if (type.equals("score")) fill(255);
rect(x, y, w, h, 10);
}
}
boolean isCaught(Paddle p) {
return !collected && y + h > p.y && y < p.y + p.h && x + w > p.x && x < p.x + p.w;
}
}
// ------------------ Brick ------------------
class Brick {
float x, y, w, h;
int hitsLeft;
Brick(float x, float y, float w, float h, int strength) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.hitsLeft = strength;
}
void hit() {
hitsLeft--;
}
boolean isBroken() {
return hitsLeft <= 0;
}
void display() {
if (!isBroken()) {
if (hitsLeft == 1) {
fill(255, 100, 100); // อ่อน
} else {
fill(100, 100, 255); // แข็ง
}
rect(x, y, w, h, 5);
}
}
}
// ------------------ Level Loader ------------------
void loadLevel(int levelNum) {
bricks = new ArrayList<Brick>();
int cols = 10;
int rows = 3 + levelNum * 2; // เพิ่มจำนวนแถวตามเลเวล
float brickW = width / cols;
float brickH = 30;
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
if (random(1) < 0.85) {
int strength;
if (levelNum >= 1 && random(1) < 0.25) {
strength = 2; // บางก้อนแข็งขึ้นในเลเวลสูง
} else {
strength = 1;
}
bricks.add(new Brick(c * brickW, r * brickH + 50, brickW - 5, brickH - 5, strength));
}
}
}
}
void activateItem(String type) {
if (type.equals("expand")) {
paddle.w *= 1.5;
expandEndTime = millis() + 8000; // อยู่ได้ 8 วินาที
} else if (type.equals("fireball")) {
fireBallMode = true;
fireballEndTime = millis() + 8000;
} else if (type.equals("multiball")) {
ArrayList<Ball> newBalls = new ArrayList<Ball>();
for (Ball b : balls) {
Ball extra = new Ball(currentLevel);
extra.x = b.x;
extra.y = b.y;
extra.speedX = -b.speedX;
extra.speedY = b.speedY;
newBalls.add(extra);
}
balls.addAll(newBalls);
} else if (type.equals("slow")) {
if (!isSlowed) {
for (Ball b : balls) {
b.speedX *= 0.7;
b.speedY *= 0.7;
}
isSlowed = true;
}
slowEndTime = millis() + 8000;
} else if (type.equals("score")) {
score += 100;
}
}