249 lines
6 KiB
JavaScript
249 lines
6 KiB
JavaScript
|
const PADDING = 50;
|
||
|
|
||
|
const PADDLE_SIZE = {
|
||
|
width: 500,
|
||
|
height: 30,
|
||
|
}
|
||
|
const BALL_SIZE = {
|
||
|
width: 50,
|
||
|
height: 30
|
||
|
}
|
||
|
|
||
|
const PADDLE_POSITION = {
|
||
|
x: (window.screen.availWidth / 2) - (PADDLE_SIZE.width/2),
|
||
|
y: window.screen.availHeight - PADDLE_SIZE.height - PADDING
|
||
|
}
|
||
|
|
||
|
const TARGET_SIZE = {
|
||
|
width: 300,
|
||
|
height: 100
|
||
|
}
|
||
|
|
||
|
const TARGET_GRID = {
|
||
|
x: 4,
|
||
|
y: 3
|
||
|
}
|
||
|
|
||
|
|
||
|
const PADDLE_MOVE = 30;
|
||
|
|
||
|
|
||
|
function shuffleArray(array) {
|
||
|
return array.map(value => ({ value, sort: Math.random() }))
|
||
|
.sort((a, b) => a.sort - b.sort)
|
||
|
.map(({ value }) => value)
|
||
|
}
|
||
|
|
||
|
|
||
|
function plan_grid(){
|
||
|
let n_targets = TARGET_GRID.x * TARGET_GRID.y;
|
||
|
let pages, page_objects;
|
||
|
// get pages that are real pages
|
||
|
pages = document.querySelectorAll('.page-metadata');
|
||
|
page_objects = Array.from(pages).map((page) => {
|
||
|
return {
|
||
|
url: page.getAttribute('url')
|
||
|
}
|
||
|
})
|
||
|
// pad end with blanks
|
||
|
page_objects = Object.assign(new Array(n_targets).fill({url:'blank.html'}), page_objects);
|
||
|
// shuffle array order
|
||
|
page_objects = shuffleArray(page_objects)
|
||
|
|
||
|
// arrange on a grid!
|
||
|
page_objects = page_objects.map((page, idx) => {
|
||
|
let col = idx % TARGET_GRID.x;
|
||
|
let row = Math.floor(idx / TARGET_GRID.x);
|
||
|
let col_grid_width = (window.screen.availWidth-(PADDING*2)) / TARGET_GRID.x
|
||
|
|
||
|
return {
|
||
|
...page,
|
||
|
x: (col_grid_width * col) + PADDING,
|
||
|
y: (PADDING*2 + TARGET_SIZE.height) * row
|
||
|
}
|
||
|
})
|
||
|
|
||
|
return page_objects
|
||
|
}
|
||
|
|
||
|
function popupPosition(popup){
|
||
|
let pos = {
|
||
|
left: popup.screenLeft,
|
||
|
right: popup.screenLeft + popup.outerWidth,
|
||
|
top: popup.screenTop,
|
||
|
bottom: popup.screenTop + popup.outerHeight
|
||
|
}
|
||
|
pos.centerX = (pos.left + pos.right) / 2
|
||
|
pos.centerY = (pos.top + pos.bottom) / 2
|
||
|
return pos
|
||
|
}
|
||
|
|
||
|
function checkIntersect(a, b){
|
||
|
let pos_a = popupPosition(a);
|
||
|
let pos_b = popupPosition(b);
|
||
|
// console.log(pos_a,pos_b)
|
||
|
// check if intersect
|
||
|
let overlap = !(
|
||
|
pos_a.right < pos_b.left ||
|
||
|
pos_a.left > pos_b.right ||
|
||
|
pos_a.bottom < pos_b.top ||
|
||
|
pos_a.top > pos_b.bottom
|
||
|
)
|
||
|
|
||
|
if (overlap === false){
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
// if overlap, check what side we are on
|
||
|
if (Math.abs(pos_a.centerX-pos_b.centerX) > Math.abs(pos_a.centerY-pos_b.centerY)){
|
||
|
// more X difference than y difference, we are left or right
|
||
|
if (pos_a.centerX > pos_b.centerX){
|
||
|
// a is to the right of b
|
||
|
return('right')
|
||
|
} else {
|
||
|
return('left')
|
||
|
}
|
||
|
} else {
|
||
|
if (pos_a.centerY > pos_b.centerY){
|
||
|
// a is below b
|
||
|
return('bottom')
|
||
|
} else {
|
||
|
return('top')
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function endGame(popups, ball, paddle){
|
||
|
for (let popup of popups){
|
||
|
popup.popup.close()
|
||
|
}
|
||
|
ball.popup.close();
|
||
|
paddle.close();
|
||
|
}
|
||
|
|
||
|
function handleIntersect(popup, popups){
|
||
|
if (popup.url === "blank.html"){
|
||
|
popup.popup.close()
|
||
|
let index = popups.indexOf(popup);
|
||
|
if (index > -1){
|
||
|
popups.splice(index, 1);
|
||
|
}
|
||
|
console.log('closing popup')
|
||
|
return false
|
||
|
} else {
|
||
|
window.location = popup.url
|
||
|
console.log('going to new page!')
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function updateBall(ball, popups, paddle){
|
||
|
let end_game = false;
|
||
|
ball.position = popupPosition(ball.popup)
|
||
|
// console.log(ball.position, popups.popup)
|
||
|
// check bounce
|
||
|
if (ball.position.right === window.screen.availWidth || ball.position.left === 0){
|
||
|
ball.velocity.x *= -1
|
||
|
}
|
||
|
if (ball.position.top === screen.availTop){
|
||
|
ball.velocity.y *= -1
|
||
|
}
|
||
|
|
||
|
// check intersections with other windows
|
||
|
for (let popup of popups){
|
||
|
// console.log(popup.popup)
|
||
|
let intersected = checkIntersect(ball.popup, popup.popup)
|
||
|
if (intersected === 'top' || intersected === 'bottom'){
|
||
|
ball.velocity.y *= -1;
|
||
|
} else if (intersected === 'left' || intersected === 'right'){
|
||
|
ball.velocity.x *= -1;
|
||
|
}
|
||
|
if (intersected){
|
||
|
console.log(intersected);
|
||
|
end_game = handleIntersect(popup, popups);
|
||
|
break
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
if (checkIntersect(ball.popup, paddle) && ball.velocity.y < 0){
|
||
|
ball.velocity.y *= -1;
|
||
|
}
|
||
|
|
||
|
if (ball.position.bottom === window.screen.availHeight && ball.velocity.y < 0){
|
||
|
// ball died :(
|
||
|
// end_game = true;
|
||
|
ball.popup.close();
|
||
|
ball = init_ball();
|
||
|
}
|
||
|
|
||
|
if (end_game){
|
||
|
endGame(popups, ball, paddle)
|
||
|
} else {
|
||
|
ball.popup.moveBy(ball.velocity.x, -ball.velocity.y)
|
||
|
window.setTimeout(() => {updateBall(ball, popups, paddle)}, 100)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function init_ball(){
|
||
|
let ball_popup = window.open('ball.html', 'ball', `popup=true,width=${BALL_SIZE.width},height=${BALL_SIZE.height},screenX=${PADDLE_POSITION.x},screenY=${PADDLE_POSITION.y-BALL_SIZE.height}`)
|
||
|
ball_popup.moveTo(PADDLE_POSITION.x,PADDLE_POSITION.y)
|
||
|
|
||
|
let ball = {
|
||
|
popup: ball_popup,
|
||
|
velocity: {x: 20, y: 20}
|
||
|
};
|
||
|
return ball
|
||
|
}
|
||
|
|
||
|
|
||
|
function init_controller(){
|
||
|
let grid = plan_grid();
|
||
|
console.log(grid);
|
||
|
let popups = grid.map((page, idx) => {
|
||
|
return{ ...page,
|
||
|
popup: window.open(page.url, `target-${idx}`, `popup=true,width=${TARGET_SIZE.width},height=${TARGET_SIZE.height},left=${page.x},top=${page.y}`)
|
||
|
}
|
||
|
})
|
||
|
let paddle = window.open('paddle.html', 'paddle', `popup=true,width=${PADDLE_SIZE.width},height=${PADDLE_SIZE.height},screenX=${PADDLE_POSITION.x},screenY=${PADDLE_POSITION.y}`)
|
||
|
|
||
|
let ball = init_ball();
|
||
|
updateBall(ball, popups, paddle);
|
||
|
}
|
||
|
|
||
|
function init_paddle(){
|
||
|
window.resizeTo(PADDLE_SIZE.width, PADDLE_SIZE.height);
|
||
|
window.moveTo(
|
||
|
PADDLE_POSITION.x,
|
||
|
PADDLE_POSITION.y
|
||
|
)
|
||
|
|
||
|
document.addEventListener('keydown', (event) => {
|
||
|
if (event.key == "ArrowLeft"){
|
||
|
if (window.screenX > PADDLE_MOVE) {
|
||
|
window.moveBy(-PADDLE_MOVE, 0)
|
||
|
} else {
|
||
|
window.moveBy(-window.screenX, 0);
|
||
|
}
|
||
|
} else if (event.key == "ArrowRight"){
|
||
|
let right_edge = window.screenX + window.outerWidth;
|
||
|
if (right_edge < window.screen.availWidth - PADDLE_MOVE){
|
||
|
window.moveBy(PADDLE_MOVE, 0)
|
||
|
} else {
|
||
|
window.moveBy(window.screen.availWidth - right_edge, 0)
|
||
|
}
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
export function init(){
|
||
|
let page_type = document.querySelector('main').getAttribute('page');
|
||
|
if (page_type === 'pong'){
|
||
|
init_controller();
|
||
|
} else if (page_type === "paddle"){
|
||
|
init_paddle();
|
||
|
}
|
||
|
}
|