BangleApps_old/apps/bbreaker/app.js

293 lines
8.0 KiB
JavaScript

(function () {
var BALL_RADIUS = 3;
var PADDLE_WIDTH = 26;
var PADDLE_HEIGHT = 6;
var BRICK_ROWS = 2;
var BRICK_HEIGHT = 8;
var BRICK_PADDING = 4;
var BRICK_OFFSET_TOP = 60;
var BRICK_OFFSET_LEFT = 2;
var SPEED_MULTIPLIER = 1.1;
var PADDLE_SPEED = 12;
var ball, paddle, interval;
var bricks = [];
var BRICK_WIDTH, BRICK_COLS;
var score = 0;
var level = 1;
var highScore = 0;
var paused = false;
var gameOver = false;
var lives = 3;
var paddleMove = 0;
var storage = require("Storage");
function loadHighScore() {
var saved = storage.readJSON("breakout_highscore.json", 1);
highScore = saved && saved.highScore ? saved.highScore : 0;
}
function saveHighScore() {
if (score > highScore) {
highScore = score;
storage.writeJSON("breakout_highscore.json", { highScore });
}
}
function initBricks() {
bricks = [];
for (var i = 0; i < BRICK_ROWS * BRICK_COLS; i++) {
bricks.push(1);
}
}
function initGame() {
var screenWidth = g.getWidth();
BRICK_COLS = Math.min(5, Math.floor((screenWidth - BRICK_OFFSET_LEFT + BRICK_PADDING) / (15 + BRICK_PADDING)));
BRICK_WIDTH = Math.floor((screenWidth - BRICK_OFFSET_LEFT - (BRICK_COLS - 1) * BRICK_PADDING) / BRICK_COLS);
ball = {
x: screenWidth / 2,
y: g.getHeight() - 40,
dx: (Math.random() > 0.5 ? 1 : -1) * 3,
dy: -3,
radius: BALL_RADIUS,
prevPos: null
};
paddle = {
x: screenWidth / 2 - PADDLE_WIDTH / 2,
y: g.getHeight() - 20,
width: PADDLE_WIDTH,
height: PADDLE_HEIGHT,
prevPos: null
};
lives = 3;
score = 0;
level = 1;
gameOver = false;
paused = false;
loadHighScore();
initBricks();
}
function drawLives() {
var heartSize = 6;
var spacing = 2;
var startX = g.getWidth() - (lives * (heartSize + spacing)) - 2;
var y = 32;
g.setColor(1, 0, 0);
for (var i = 0; i < lives; i++) {
var x = startX + i * (heartSize + spacing);
g.fillPoly([x + 3, y, x + 6, y + 3, x + 3, y + 6, x, y + 3], true);
}
}
function drawBricks() {
g.setColor(0, 1, 0);
for (var i = 0; i < bricks.length; i++) {
if (bricks[i]) {
var c = i % BRICK_COLS;
var r = Math.floor(i / BRICK_COLS);
var brickX = BRICK_OFFSET_LEFT + c * (BRICK_WIDTH + BRICK_PADDING);
var brickY = BRICK_OFFSET_TOP + r * (BRICK_HEIGHT + BRICK_PADDING);
g.fillRect(brickX, brickY, brickX + BRICK_WIDTH - 1, brickY + BRICK_HEIGHT - 1);
}
}
}
function drawBall() {
g.setColor(1, 1, 1);
g.fillCircle(ball.x, ball.y, ball.radius);
g.setColor(0.7, 0.7, 0.7);
g.fillCircle(ball.x - 0.5, ball.y - 0.5, ball.radius - 1);
}
function drawPaddle() {
g.setColor(0, 1, 1);
g.fillRect(paddle.x, paddle.y, paddle.x + paddle.width - 1, paddle.y + paddle.height - 1);
}
function drawHUD() {
g.setColor(0, 0, 0).fillRect(0, 0, g.getWidth(), BRICK_OFFSET_TOP - 1);
g.setColor(1, 1, 1);
g.setFont("6x8", 1);
g.setFontAlign(-1, -1);
g.drawString("Score: " + score, 2, 22);
g.setFontAlign(0, -1);
g.drawString("High: " + highScore, g.getWidth() / 2, 22);
g.setFontAlign(1, -1);
g.drawString("Lvl: " + level, g.getWidth() - 2, 22);
drawLives();
if (paused) {
g.setFontAlign(0, 0);
g.drawString("PAUSED", g.getWidth() / 2, g.getHeight() / 2);
}
}
function draw() {
if (paddle.prevPos) {
g.setColor(0, 0, 0).fillRect(paddle.prevPos.x - 1, paddle.prevPos.y - 1, paddle.prevPos.x + paddle.width + 1, paddle.prevPos.y + paddle.height + 1);
}
if (ball.prevPos) {
g.setColor(0, 0, 0).fillCircle(ball.prevPos.x, ball.prevPos.y, ball.radius + 1);
}
drawHUD();
drawBall();
drawPaddle();
g.flip();
ball.prevPos = { x: ball.x, y: ball.y };
paddle.prevPos = { x: paddle.x, y: paddle.y, width: paddle.width, height: paddle.height };
}
function showGameOver() {
g.clear();
g.setFont("6x8", 2);
g.setFontAlign(0, 0);
g.setColor(1, 0, 0);
g.drawString("GAME OVER", g.getWidth() / 2, g.getHeight() / 2 - 20);
g.setFont("6x8", 1);
g.setColor(1, 1, 1);
g.drawString("Score: " + score, g.getWidth() / 2, g.getHeight() / 2);
g.drawString("High: " + highScore, g.getWidth() / 2, g.getHeight() / 2 + 12);
g.drawString("BTN2 = Restart", g.getWidth() / 2, g.getHeight() / 2 + 28);
g.flip();
}
function collisionDetection() {
for (var i = 0; i < bricks.length; i++) {
if (bricks[i]) {
var c = i % BRICK_COLS;
var r = Math.floor(i / BRICK_COLS);
var brickX = BRICK_OFFSET_LEFT + c * (BRICK_WIDTH + BRICK_PADDING);
var brickY = BRICK_OFFSET_TOP + r * (BRICK_HEIGHT + BRICK_PADDING);
if (ball.x + ball.radius > brickX && ball.x - ball.radius < brickX + BRICK_WIDTH && ball.y + ball.radius > brickY && ball.y - ball.radius < brickY + BRICK_HEIGHT) {
ball.dy = -ball.dy;
bricks[i] = 0;
score += 10;
g.setColor(0, 0, 0).fillRect(brickX, brickY, brickX + BRICK_WIDTH - 1, brickY + BRICK_HEIGHT - 1);
break;
}
}
}
}
function allBricksCleared() {
for (var i = 0; i < bricks.length; i++) {
if (bricks[i]) return false;
}
return true;
}
function resetAfterLifeLost() {
clearInterval(interval);
interval = undefined;
ball.x = g.getWidth() / 2;
ball.y = g.getHeight() - 40;
ball.dx = (Math.random() > 0.5 ? 1 : -1) * 3;
ball.dy = -3;
paddle.x = g.getWidth() / 2 - PADDLE_WIDTH / 2;
ball.prevPos = null;
paddle.prevPos = null;
g.clear();
drawBricks();
draw();
setTimeout(() => { interval = setInterval(update, 50); }, 1000);
}
function update() {
if (paused || gameOver) return;
if (paddleMove) {
paddle.x += paddleMove * PADDLE_SPEED;
if (paddle.x < 0) paddle.x = 0;
if (paddle.x + paddle.width > g.getWidth()) {
paddle.x = g.getWidth() - paddle.width;
}
}
ball.x += ball.dx;
ball.y += ball.dy;
if (ball.x + ball.radius > g.getWidth() || ball.x - ball.radius < 0) {
ball.dx = -ball.dx;
}
if (ball.y - ball.radius < 0) {
ball.dy = -ball.dy;
}
if (ball.y + ball.radius >= paddle.y && ball.x >= paddle.x && ball.x <= paddle.x + paddle.width) {
ball.dy = -ball.dy;
ball.y = paddle.y - ball.radius;
}
if (ball.y + ball.radius > g.getHeight()) {
lives--;
if (lives > 0) {
resetAfterLifeLost();
return;
} else {
clearInterval(interval);
interval = undefined;
saveHighScore();
gameOver = true;
setTimeout(showGameOver, 50);
return;
}
}
collisionDetection();
if (allBricksCleared()) {
level++;
ball.dx = (Math.random() > 0.5 ? 1 : -1) * Math.abs(ball.dx) * SPEED_MULTIPLIER;
ball.dy *= SPEED_MULTIPLIER;
initBricks();
ball.prevPos = null;
paddle.prevPos = null;
g.clear();
drawBricks();
}
draw();
}
function showGetReady(callback) {
g.clear();
g.setFont("6x8", 2);
g.setFontAlign(0, 0);
g.setColor(1, 1, 0);
g.drawString("GET READY!", g.getWidth() / 2, g.getHeight() / 2);
g.flip();
setTimeout(() => {
g.clear();
drawBricks();
draw();
callback();
}, 1500);
}
function startGame() {
initGame();
showGetReady(() => {
interval = setInterval(update, 50);
});
}
setWatch(() => {
if (gameOver) {
startGame();
return;
}
paused = !paused;
if (paused) {
drawHUD();
g.flip();
} else {
g.clear();
drawBricks();
draw();
}
}, BTN2, { repeat: true, edge: "rising" });
setWatch(() => { paddleMove = -1; }, BTN1, { repeat: true, edge: "rising" });
setWatch(() => { paddleMove = 0; }, BTN1, { repeat: true, edge: "falling" });
setWatch(() => { paddleMove = 1; }, BTN3, { repeat: true, edge: "rising" });
setWatch(() => { paddleMove = 0; }, BTN3, { repeat: true, edge: "falling" });
startGame();
})();