Ensure js are always loaded with fresh versions

This commit is contained in:
Flatlogic Bot 2025-10-02 06:18:59 +00:00
parent e6f6732eaa
commit 67991b8a3e
8 changed files with 117 additions and 197 deletions

View File

@ -16,3 +16,13 @@ RewriteRule ^(.+?)/?$ $1.php [L]
# 2) Optional: strip trailing slash for non-directories (keeps .php links working) # 2) Optional: strip trailing slash for non-directories (keeps .php links working)
RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ $1 [R=301,L] RewriteRule ^(.+)/$ $1 [R=301,L]
<FilesMatch "\.(js)$">
FileETag None
<IfModule mod_headers.c>
Header unset ETag
Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
Header set Pragma "no-cache"
Header set Expires "Wed, 11 Jan 1984 05:00:00 GMT"
</IfModule>
</FilesMatch>

View File

@ -63,3 +63,47 @@
background-color: #4CAF50; background-color: #4CAF50;
color: white; color: white;
} }
#tutorial-modal {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.7);
display: flex;
justify-content: center;
align-items: center;
color: white;
font-family: sans-serif;
z-index: 100;
}
.modal-content {
text-align: center;
background-color: #333;
padding: 40px;
border-radius: 10px;
}
.modal-content h2 {
font-size: 50px;
margin-bottom: 20px;
}
.modal-content p {
font-size: 20px;
margin-bottom: 15px;
line-height: 1.5;
}
#start-game-btn {
margin-top: 20px;
padding: 15px 30px;
font-size: 20px;
cursor: pointer;
border: none;
border-radius: 5px;
background-color: #4CAF50;
color: white;
}

View File

@ -44,8 +44,7 @@ export class Ball {
const fieldLength = 100; const fieldLength = 100;
const ballRadius = 0.8; const ballRadius = 0.8;
this.mesh.position.x = Math.max(-fieldWidth / 2 + ballRadius, Math.min(fieldWidth / 2 - ballRadius, this.mesh.position.x));
this.mesh.position.z = Math.max(-fieldLength / 2 + ballRadius, Math.min(fieldLength / 2 - ballRadius, this.mesh.position.z));
// --- Force 2D movement on the XZ plane --- // --- Force 2D movement on the XZ plane ---

View File

@ -2,19 +2,23 @@
import * as THREE from 'three'; import * as THREE from 'three';
export class Player { export class Player {
constructor(scene, color, position, team) { constructor(scene, color, position, type, team) {
this.scene = scene; this.scene = scene;
this.color = color; this.color = color;
this.position = position; this.velocity = new THREE.Vector3(0, 0, 0);
this.type = type;
this.team = team; this.team = team;
this.createPlayer(); this.radius = 1.5;
this.hasBall = false;
this.createPlayer(new THREE.Vector3(position.x, position.y, position.z));
} }
createPlayer() { createPlayer(initialPosition) {
const playerGeometry = new THREE.CapsuleGeometry(1, 2, 4, 8); const playerGeometry = new THREE.CapsuleGeometry(1, 2, 4, 8);
const playerMaterial = new THREE.MeshStandardMaterial({ color: this.color }); const playerMaterial = new THREE.MeshStandardMaterial({ color: this.color });
this.mesh = new THREE.Mesh(playerGeometry, playerMaterial); this.mesh = new THREE.Mesh(playerGeometry, playerMaterial);
this.mesh.position.set(this.position.x, this.position.y, this.position.z); this.mesh.position.copy(initialPosition);
this.mesh.initialPosition = initialPosition.clone();
this.mesh.castShadow = true; this.mesh.castShadow = true;
this.mesh.lastVelocity = new THREE.Vector3(); this.mesh.lastVelocity = new THREE.Vector3();
this.mesh.team = this.team; this.mesh.team = this.team;

View File

@ -14,18 +14,16 @@ export class Team {
createTeam() { createTeam() {
for (let i = 0; i < this.numberOfPlayers; i++) { for (let i = 0; i < this.numberOfPlayers; i++) {
const position = this.generatePosition(i); const position = this.generatePosition(i);
const player = new Player(this.scene, this.color, position, this.isPlayerTeam ? 'player' : 'bot'); const player = new Player(this.scene, this.color, position, this.isPlayerTeam ? 'player' : 'bot', this);
this.players.push(player); this.players.push(player);
} }
} }
resetPositions() { resetPositions() {
for (let i = 0; i < this.players.length; i++) { this.players.forEach(player => {
const player = this.players[i]; player.mesh.position.copy(player.mesh.initialPosition);
const position = this.generatePosition(i); player.velocity.set(0, 0, 0);
player.mesh.position.set(position.x, position.y, position.z); });
player.mesh.velocity.set(0, 0, 0);
}
} }
generatePosition(i) { generatePosition(i) {

View File

@ -1,8 +1,8 @@
import * as THREE from 'three'; import * as THREE from 'three';
import { Field } from './Field.js'; import { Field } from 'app/field';
import { Ball } from './Ball.js'; import { Ball } from 'app/ball';
import { Team } from './Team.js'; import { Team } from 'app/team';
class Game { class Game {
constructor() { constructor() {
@ -10,8 +10,6 @@ class Game {
this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
this.renderer = new THREE.WebGLRenderer({ antialias: true }); this.renderer = new THREE.WebGLRenderer({ antialias: true });
this.keyboardState = {}; this.keyboardState = {};
this.init();
} }
init() { init() {
@ -403,4 +401,14 @@ class Game {
} }
} }
new Game(); const game = new Game();
const startGameBtn = document.getElementById('start-game-btn');
const tutorialModal = document.getElementById('tutorial-modal');
function startGame() {
tutorialModal.style.display = 'none';
game.init();
}
startGameBtn.addEventListener('click', startGame);

View File

@ -1,36 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pocket 5 Soccer</title>
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
<style>
body { margin: 0; overflow: hidden; }
canvas { display: block; }
</style>
</head>
<body>
<div id="scoreboard">
<span id="red-score">0</span> - <span id="blue-score">0</span>
</div>
<div id="timer">30</div>
<div id="game-over-modal" style="display: none;">
<div id="game-over-content">
<h2>Game Over</h2>
<p id="final-score"></p>
<p id="winner"></p>
<button id="restart-button">Restart Game</button>
</div>
</div>
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.163.0/build/three.module.js",
"three/addons/": "https://unpkg.com/three@0.163.0/examples/jsm/"
}
}
</script>
<script type="module" src="assets/js/main.js?v=<?php echo time(); ?>"></script>
</body>
</html>

175
index.php
View File

@ -3,151 +3,44 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pocket 5 Soccer - Fast-Paced 5v5 Action</title> <title>Pocket 5 Soccer</title>
<meta name="description" content="Experience Pocket 5 Soccer, a real-time multiplayer 5v5 soccer game designed for quick, engaging matches on mobile and desktop.">
<!-- Bootstrap 5 CDN -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- Google Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@700&family=Roboto:wght@400;500&display=swap" rel="stylesheet">
<!-- Custom CSS -->
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>"> <link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
<style>
<!-- Open Graph Meta Tags --> body { margin: 0; overflow: hidden; }
<meta property="og:title" content="Pocket 5 Soccer - Fast-Paced 5v5 Action"> canvas { display: block; }
<meta property="og:description" content="Real-time 5v5 multiplayer soccer. Quick matches, smart AI, and cross-platform controls."> </style>
<meta property="og:image" content="https://picsum.photos/seed/soccermeta/1200/630">
<meta property="og:url" content="">
<meta property="og:type" content="website">
</head> </head>
<body> <body>
<div id="tutorial-modal">
<!-- Navigation Bar --> <div class="modal-content">
<nav class="navbar navbar-expand-lg navbar-light bg-white fixed-top shadow-sm"> <h2>Pocket 5 Soccer</h2>
<div class="container"> <p>Use Arrow Keys to move. Press S to pass, D to shoot.</p>
<a class="navbar-brand" href="#">Pocket 5 Soccer</a> <button id="start-game-btn">Start Game</button>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link" href="#rules">Game Rules</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#controls">Controls</a>
</li>
<li class="nav-item ms-lg-3">
<a class="btn btn-primary" href="game.php">Play Now</a>
</li>
</ul>
</div>
</div> </div>
</nav> </div>
<div id="scoreboard">
<!-- Hero Section --> <span id="red-score">0</span> - <span id="blue-score">0</span>
<header class="hero"> </div>
<div class="container"> <div id="timer">30</div>
<h1 class="display-3">Fast-Paced 5v5 Action</h1> <div id="game-over-modal" style="display: none;">
<p class="lead">Real-time multiplayer soccer designed for quick, intense matches.</p> <div id="game-over-content">
<a href="game.php" class="btn btn-primary btn-lg">Play Now</a> <h2>Game Over</h2>
<a href="#rules" class="btn btn-secondary btn-lg">Learn More</a> <p id="final-score"></p>
<p id="winner"></p>
<button id="restart-button">Restart Game</button>
</div> </div>
</header> </div>
<script type="importmap">
<main> {
<!-- Game Rules Section --> "imports": {
<section id="rules"> "three": "https://unpkg.com/three@0.163.0/build/three.module.js",
<div class="container"> "three/addons/": "https://unpkg.com/three@0.163.0/examples/jsm/",
<h2 class="section-title">Game Rules & Play Style</h2> "app/field": "./assets/js/Field.js?v=<?php echo time(); ?>",
<div class="row g-4 align-items-center"> "app/ball": "./assets/js/Ball.js?v=<?php echo time(); ?>",
<div class="col-lg-6"> "app/team": "./assets/js/Team.js?v=<?php echo time(); ?>"
<img src="https://picsum.photos/seed/soccerstrategy/800/600" class="img-fluid rounded shadow" alt="A top-down view of a soccer game strategy board."> }
</div> }
<div class="col-lg-6"> </script>
<div class="accordion" id="rulesAccordion"> <script type="module" src="assets/js/main.js?v=<?php echo time(); ?>"></script>
<div class="accordion-item">
<h2 class="accordion-header" id="headingOne">
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
Core Gameplay
</button>
</h2>
<div id="collapseOne" class="accordion-collapse collapse show" aria-labelledby="headingOne" data-bs-parent="#rulesAccordion">
<div class="accordion-body">
<ul class="list-group list-group-flush">
<li class="list-group-item"><strong>Match Specs:</strong> 5v5 teams, 2-minute match duration.</li>
<li class="list-group-item"><strong>Control Model:</strong> Each human controls one player.</li>
<li class="list-group-item"><strong>Orientation:</strong> Vertical screen for mobile.</li>
<li class="list-group-item"><strong>AI Players:</strong> AI fills all positions not controlled by humans.</li>
</ul>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="headingTwo">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
Advanced Mechanics
</button>
</h2>
<div id="collapseTwo" class="accordion-collapse collapse" aria-labelledby="headingTwo" data-bs-parent="#rulesAccordion">
<div class="accordion-body">
<ul class="list-group list-group-flush">
<li class="list-group-item"><strong>Smart Passing:</strong> Auto-targets nearest teammate in a 30-degree arc.</li>
<li class="list-group-item"><strong>Directional Shooting:</strong> Ball trajectory follows player's facing direction.</li>
<li class="list-group-item"><strong>Active Tackle:</strong> High-speed sprint to win the ball. Failure results in a 1-second movement penalty.</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Controls Section -->
<section id="controls" class="bg-white">
<div class="container">
<h2 class="section-title">Dual Platform Controls</h2>
<div class="row g-4 align-items-center">
<div class="col-lg-6 order-lg-2">
<img src="https://picsum.photos/seed/soccercontrols/800/600" class="img-fluid rounded shadow" alt="Close-up on a person's hands using a mobile phone for gaming.">
</div>
<div class="col-lg-6 order-lg-1">
<div class="row">
<div class="col-md-6">
<h4>Mobile</h4>
<div class="control-item"><strong>Movement:</strong> Virtual Joystick</div>
<div class="control-item"><strong>Actions:</strong> On-screen Buttons</div>
</div>
<div class="col-md-6">
<h4>Desktop</h4>
<div class="control-item"><strong>Movement:</strong> Arrow Keys</div>
<div class="control-item"><strong>Pass:</strong> 'S' Key</div>
<div class="control-item"><strong>Shoot:</strong> 'D' Key</div>
<div class="control-item"><strong>Tackle:</strong> Spacebar</div>
</div>
</div>
</div>
</div>
</div>
</section>
</main>
<!-- Footer -->
<footer class="text-center">
<div class="container">
<p class="mb-0">&copy; <?php echo date("Y"); ?> Pocket 5 Soccer. All Rights Reserved.</p>
</div>
</footer>
<!-- Bootstrap 5 JS Bundle -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<!-- Custom JS -->
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
</body> </body>
</html> </html>