Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/background.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
createReplayIsConfirmedOnBackgroundMessage,
createStartMessage,
isMessageContentIsReadyMessage,
isMessageRequestReplayToBackgroundMessage
} from "~message"
Expand All @@ -26,7 +27,7 @@ chrome.runtime.onMessage.addListener((message, sender) => {
) {
chrome.tabs.sendMessage(
_senderTabId,
message.message
createStartMessage(message.options)
)
}
chrome.runtime.onMessage.removeListener(startReplay)
Expand Down
31 changes: 7 additions & 24 deletions src/content.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import { dragAndMoveBall, visualizeBlocks } from "~game/debug"
import { replay } from "~game/end/gameOver"
import { main } from "~game/main"
import { getBlocks } from "~game/object/blocks"
import {
createContentIsReadyMessage,
isMessageStartMessage,
isMessageTestMessage
} from "~message"

export {}
Expand All @@ -25,29 +22,13 @@ chrome.runtime.sendMessage(createContentIsReadyMessage())
let started = false // prevent multiple execution
chrome.runtime.onMessage.addListener(function(message) {

let mainOrDebug: () => void;
if (isMessageStartMessage(message)) {
mainOrDebug = () => main(message)
} else if (isMessageTestMessage(message)) {
mainOrDebug = () => {
const blocks = getBlocks()
visualizeBlocks(blocks)
main({
type: "test",
options: {
...message.options,
withScoreboard: false
}
})
dragAndMoveBall(blocks)
}
} else {
if (!isMessageStartMessage(message)) {
return
}

// Check and mark as started only when the message is "start" or "test".
// Check and mark as started only when the message is "start".
if (started) {
replay(message)
replay(message.options)
return
}
started = true
Expand All @@ -56,8 +37,10 @@ chrome.runtime.onMessage.addListener(function(message) {
// because document.body is required for exec `preventScroll()`,
// and block calculation should be executed after iframes have been loaded.
if (window.document.readyState === "complete") {
mainOrDebug()
main(message.options)
} else {
window.addEventListener("load", mainOrDebug)
window.addEventListener("load", () => {
main(message.options)
})
}
})
17 changes: 2 additions & 15 deletions src/game/animation/startBallAnimation.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
import {
ballSetting,
getInitialBallSpeed,
initialBallDirection,
type StartOptions
} from "../configuration/settings"
import type { Ball } from "../object/ball"
import { getBallCenterPosition } from "../object/ball"
import type { Bar } from "../object/bar"
import type { Block } from "../object/blocks"
import type { Vector } from "../utils/vector"
import { getVectorMultipliedWithScalar } from "../utils/vector"
import { getUpdatedBallDirection, getUpdatedBallSpeed } from "./updateBall"
import { getUpdatedBallDirection, getUpdatedBallSpeed, updateBallPositionBy } from "./updateBall"

export function startBallAnimation(
ball: Ball,
Expand All @@ -31,7 +29,7 @@ export function startBallAnimation(
})
function updateBall(ball: Ball): void {
updateBallVelocity(ball)
updateBallPosition(ball)
updateBallPositionBy(ball, currentBallVelocity)
id = requestAnimationFrame(() => updateBall(ball))
}

Expand All @@ -41,17 +39,6 @@ export function startBallAnimation(
}
return stopBallAnimation

function updateBallPosition(ball: Ball): void {
const currentBallPosition = getBallCenterPosition(ball)
Object.assign(ball.style, {
transform:
`translate(` +
`${currentBallPosition.x - ballSetting.radius + currentBallVelocity.x}px, ` +
`${-(currentBallPosition.y - ballSetting.radius + currentBallVelocity.y)}px` +
`)`
})
}

function updateBallVelocity(ball: Ball): void {
// acceleration
currentBallSpeed = getUpdatedBallSpeed(currentBallSpeed)
Expand Down
16 changes: 15 additions & 1 deletion src/game/animation/updateBall.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
ballAcceleration,
ballSetting,
barSetting,
maximumLimitOfBallSpeed,
redundancyOfCollisionWithBar,
Expand All @@ -19,7 +20,9 @@ import {
type Vector
} from "../utils/vector"

export function getUpdatedBallSpeed(currentBallSpeed: number) {
export { updateObjectPositionTo as updateBallPositionTo } from "./updateObject"

export function getUpdatedBallSpeed(currentBallSpeed: number): number {
return Math.min(currentBallSpeed + ballAcceleration, maximumLimitOfBallSpeed)
}

Expand Down Expand Up @@ -221,3 +224,14 @@ export function updateBallDirectionByCollisionWithBlocks(
}
return { x: currentBallDirection.x, y: currentBallDirection.y }
}

export function updateBallPositionBy(ball: Ball, velocity: Vector): void {
const currentBallPosition = getBallCenterPosition(ball)
Object.assign(ball.style, {
transform:
`translate(` +
`${currentBallPosition.x - ballSetting.radius + velocity.x}px, ` +
`${-(currentBallPosition.y - ballSetting.radius + velocity.y)}px` +
`)`
})
}
1 change: 1 addition & 0 deletions src/game/animation/updateBar.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { updateObjectPositionTo as updateBarPositionTo } from "./updateObject"
9 changes: 9 additions & 0 deletions src/game/animation/updateObject.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export function updateObjectPositionTo(obj: HTMLDivElement, position: { x: number, y: number }): void {
Object.assign(obj.style, {
transform:
`translate(` +
`${position.x}px, ` +
`${position.y}px` +
`)`
})
}
4 changes: 3 additions & 1 deletion src/game/configuration/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ export const collisionPointOnBallClass = "bba-collision-point-on-ball"
export type StartOptions = {
withScoreboard: boolean
initialBallSpeed: "low" | "middle" | "high" | "superHigh"
sound: boolean
sound: boolean,
visualizeBlocks: boolean,
controlMode: "normal" | "mouse"
}

type BarSetting = {
Expand Down
45 changes: 21 additions & 24 deletions src/game/debug.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { updateBallDirectionByCollisionWithBlocks } from "./animation/updateBall"
import { updateBallDirectionByCollisionWithBlocks, updateBallPositionTo } from "./animation/updateBall"
import { startBlockAndScoreUpdate } from "./animation/updateBlocks"
import {
ballId,
ballSetting,
ballZIndex,
collisionPointOnBallClass,
initialBottom,
numberOfCollisionPoints
} from "./configuration/settings"
import {
Expand Down Expand Up @@ -71,37 +73,32 @@ export function updateVisualizedCollisionPointsOnBall(
}
}

export function dragAndMoveBall(blocks: Block[]) {
export function controlBallByMouse(blocks: Block[]): () => void {
const ball = document.getElementById(ballId)
assert(ball !== null, "ball element must be found")

startBlockAndScoreUpdate(blocks, null)

// drag and move ball
let isDragging = false
let offsetX = 0
let offsetY = 0
ball.addEventListener("mousedown", (e) => {
isDragging = true
offsetX = e.clientX - ball.getBoundingClientRect().left
offsetY = e.clientY - ball.getBoundingClientRect().top
})
ball.addEventListener("mouseup", () => {
isDragging = false
})
ball.addEventListener("mousemove", (e) => {
if (isDragging) {
ball.style.left = `${e.clientX - offsetX}px`
ball.style.top = `${e.clientY - offsetY}px`
function onMousemove(e: MouseEvent){
const mousePosition = {
x: e.clientX - ballSetting.radius,
y: -(window.innerHeight - e.clientY - initialBottom + ballSetting.radius)
}
updateBallPositionTo(ball as Ball, mousePosition)

const mouseDirection = { x: e.movementX, y: e.movementY }
updateBallDirectionByCollisionWithBlocks(
getCurrentCollisionPointsOnBall(getBallCenterPosition(ball as Ball), {
x: e.movementX,
y: e.movementY
}),
getCurrentCollisionPointsOnBall(
getBallCenterPosition(ball as Ball),
mouseDirection
),
blocks,
{ x: e.movementX, y: e.movementY }
mouseDirection
)
})
}
document.documentElement.addEventListener("mousemove", onMousemove)

return function removeControlBallByMouse() {
document.documentElement.removeEventListener("mousemove", onMousemove)
}
}
18 changes: 9 additions & 9 deletions src/game/end/gameOver.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import {
createRequestReplayToBackgroundMessage,
isMessageReplayIsConfirmedOnBackgroundMessage,
type AnyStartMessage,
isMessageReplayIsConfirmedOnBackgroundMessage
} from "~message"

import {
ballSetting,
veilZIndex,
type StartOptions
} from "../configuration/settings"
import { getBallCenterPosition, type Ball } from "../object/ball"
import type { Block } from "../object/blocks"

export function startCheckIsGameOver(
ball: Ball,
blocks: Block[],
message: AnyStartMessage,
options: StartOptions,
stopAnimationFuncs: (() => void)[]
) {
requestAnimationFrame(checkIsGameOver)
Expand All @@ -23,21 +23,21 @@ export function startCheckIsGameOver(
const isBallTouchBottom =
getBallCenterPosition(ball).y - ballSetting.radius <= 0
if (isBallTouchBottom) {
gameOver(blocks, message)
gameOver(blocks, options)
stopAnimationFuncs.forEach((f) => f())
return
}
const isAllBlocksDestroyed = !blocks.some((b) => b.remain)
if (isAllBlocksDestroyed) {
gameOver(blocks, message)
gameOver(blocks, options)
stopAnimationFuncs.forEach((f) => f())
return
}
requestAnimationFrame(checkIsGameOver)
}
}

function gameOver(blocks: Block[], message: AnyStartMessage) {
function gameOver(blocks: Block[], options: StartOptions) {
const countOfBrokenBlocks = blocks.filter((b) => !b.remain).length

const gameOverMessage = document.createElement("div")
Expand Down Expand Up @@ -77,17 +77,17 @@ function gameOver(blocks: Block[], message: AnyStartMessage) {
})
replayButton.textContent = "Replay"
replayButton.onclick = () => {
replay(message)
replay(options)
}
gameOverMessage.appendChild(replayButton)
}

export function replay(message: AnyStartMessage) {
export function replay(options: StartOptions) {
chrome.runtime.onMessage.addListener((message) => {
if (isMessageReplayIsConfirmedOnBackgroundMessage(message)) {
location.reload()
}
})

chrome.runtime.sendMessage(createRequestReplayToBackgroundMessage(message))
chrome.runtime.sendMessage(createRequestReplayToBackgroundMessage(options))
}
14 changes: 10 additions & 4 deletions src/game/main.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
import type { AnyStartMessage } from "~message"
import { visualizeBlocks } from "~game/debug"
import { displayMessageInConsole } from "./configuration/easterEggs"
import type { StartOptions } from "./configuration/settings"
import { freezePage } from "./start/freezePage"
import { initializeObjects } from "./start/initializeObjects"
import { standby } from "./start/standby"

export function main(message: AnyStartMessage) {
export function main(options: StartOptions) {
displayMessageInConsole()

try {
freezePage()
const { ball, bar, blocks, scoreboard } = initializeObjects(message.options)
standby(ball, bar, blocks, scoreboard, message)
const { ball, bar, blocks, scoreboard } = initializeObjects(options)

if (options.visualizeBlocks) {
visualizeBlocks(blocks)
}

standby(ball, bar, blocks, scoreboard, options)
} catch (e) {
console.log(e)
}
Expand Down
Loading