Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Playable Community Game On HomePage #1623

Closed
wants to merge 8 commits into from
Closed
72 changes: 64 additions & 8 deletions src/pages/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ import '../global.css'
import '../legacy/homepage.scss'
import { firestore, getSession } from '../lib/game-saving/account'
import { getConsolesRemaining } from '../lib/remaining-consoles'
import fs from "fs";
import path from "path";
import { dirname } from "path";
import { fileURLToPath } from "url";
import { homepageExampleCode } from '../lib/examples'

const remainingConsoles = await getConsolesRemaining()

Expand All @@ -28,6 +33,40 @@ if (session && session.session.full) {
.get()
gameCount = res.data().count
}

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

async function getGameSourceCode() {
let gameList = [];
try {
const response = await fetch("http://sprig.hackclub.com/api/gallery?new");
gameList = await response.json();
} catch (error) {
console.error("Failed to fetch or parse game list:", error);
return homepageExampleCode;
}

if (gameList.length === 0) {
console.log("No games available in the gallery.");
return homepageExampleCode;
}

const randomIndex = Math.floor(Math.random() * gameList.length);
const selectedGame = gameList[randomIndex];
let gameTitle = selectedGame.filename.replace(/\s/g, "");
const gameContentPath = path.resolve(__dirname, `../../games/${gameTitle}.js`);

try {
console.log("Loading game from:", gameContentPath);
return fs.readFileSync(gameContentPath, "utf-8");
} catch (fileError) {
console.error("Failed to read game file:", fileError);
return homepageExampleCode;
}
}

const gamesource = await getGameSourceCode();
---

<html lang='en'>
Expand Down Expand Up @@ -294,15 +333,14 @@ if (session && session.session.full) {
})
}
</script>

<div id='gamesource-data' data-gamesource={gamesource} style={{ displa: "none", visibility: "hidden"}}></div>
<!-- 3D interactive device: -->
<script>
import * as THREE from 'three'
import { Scene, WebGLRenderer, sRGBEncoding, PerspectiveCamera, AmbientLight, DirectionalLight, HemisphereLight, Raycaster, Vector2, Object3D, Mesh, Texture, BufferGeometry, Material } from 'three'
import { OrbitControls } from '../lib/orbit-controls'
import { type InputKey, VALID_INPUTS } from 'sprig'
import { imageDataEngine } from 'sprig/image-data'
import { homepageExampleCode } from '../lib/examples'

// @ts-ignore
import { RoomEnvironment } from 'three/examples/jsm/environments/RoomEnvironment'
Expand Down Expand Up @@ -390,8 +428,9 @@ if (session && session.session.full) {

const screen = gltf.scene.getObjectByName('Screen')
glass = screen.children.find(({ material }: any) => material?.name === 'Glow Glass')

const fn = new Function(...Object.keys(game.api), homepageExampleCode)
const gameSourceContainer = document.getElementById("gamesource-data");
const gamesource = gameSourceContainer?.dataset.gamesource || '';
const fn = new Function(...Object.keys(game.api), gamesource);
fn(...Object.values(game.api))

glass.material = new THREE.MeshBasicMaterial({ map: new THREE.Texture(game.render()) })
Expand All @@ -408,9 +447,25 @@ if (session && session.session.full) {

const raycast = () => {
raycaster.setFromCamera(mouse, camera)
const object = raycaster.intersectObjects(scene.children)[0]?.object
raycasted.device = object || null
raycasted.hoveredButton = object && buttonNames.includes(object.name) ? object : null
const intersects = raycaster.intersectObjects(scene.children, true);
raycasted.device = null;
raycasted.hoveredButton = null;

for (const intersect of intersects) {
const intersectObject = intersect.object;

if (!raycasted.device) {
raycasted.device = intersectObject;
}

if (buttonNames.includes(intersectObject.name) && !raycasted.hoveredButton) {
raycasted.hoveredButton = intersectObject;
}

if (intersectObject.name === 'Screen') {
// future work on redirecting to game link for clicking on the screen
}
}

document.documentElement.style.cursor =
raycasted.hoveredButton || raycasted.pressedButton
Expand All @@ -420,8 +475,9 @@ if (session && session.session.full) {
: raycasted.device
? 'grab'
: 'unset'

document.documentElement.style.touchAction =
raycasted.pressedButton || controls.isDragging || raycasted.device ? 'none' : 'unset'
raycasted.pressedButton || controls.isDragging || raycasted.device ? 'none' : 'unset';
}

const mousePageCoords = { x: Infinity, y: Infinity }
Expand Down