homepage/_assets/js/pong.js

248 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();
}
}