0% found this document useful (0 votes)
3 views

teste2

The document is an HTML code for a 3D stacking game called 'Stackerful 3D'. It includes styles for the game's layout, score display, and game states, as well as JavaScript code that manages game logic, including block placement and scoring. The game utilizes the Three.js library for rendering 3D graphics and allows users to interact by clicking or pressing the spacebar to stack blocks.
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views

teste2

The document is an HTML code for a 3D stacking game called 'Stackerful 3D'. It includes styles for the game's layout, score display, and game states, as well as JavaScript code that manages game logic, including block placement and scoring. The game utilizes the Three.js library for rendering 3D graphics and allows users to interact by clicking or pressing the spacebar to stack blocks.
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 8

<!

DOCTYPE html>
<html lang="en">

<head>
<meta name="viewport" content="width=device-width,user-scalable=no">
<meta charset="UTF-8">
<meta name="referrer" content="no-referrer-when-downgrade">
<title>Stackerful 3D</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Comfortaa">
<style>
body {
margin: 0;
overflow: hidden;
height: 100vh;
font-family: 'Comfortaa', cursive;
background: linear-gradient(135deg, #D0CBC7 0%, #9B8E8A 100%);
display: flex;
justify-content: center;
align-items: center;
}

#container {
width: 100%;
height: 100%;
position: relative;
}

#score {
position: absolute;
top: 20px;
width: 100%;
text-align: center;
font-size: 10vh;
color: #333344;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
display: none;
animation: pulse 2s infinite;
}

@keyframes pulse {
0% {
transform: scale(1);
}

50% {
transform: scale(1.05);
}

100% {
transform: scale(1);
}
}

#game {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}

.game-over,
.game-ready {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.5s ease;
z-index: 10;
background-color: rgba(255, 255, 255, 0.9);
padding: 40px;
border-radius: 20px;
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);
}

.game-over.active,
.game-ready.active {
opacity: 1;
}

#start-button,
#restart-button {
border: none;
padding: 15px 30px;
background-color: #4CAF50;
color: white;
font-size: 24px;
cursor: pointer;
margin-top: 20px;
border-radius: 50px;
transition: all 0.3s ease;
font-family: 'Comfortaa', cursive;
}

#start-button:hover,
#restart-button:hover {
background-color: #45a049;
transform: scale(1.05);
}

#instructions {
position: absolute;
width: 100%;
top: 16vh;
left: 0;
text-align: center;
transition: opacity 0.5s ease;
display: none;
color: #333344;
font-size: 2.5vh;
text-shadow: 1px 1px 2px rgba(255, 255, 255, 0.5);
}
#highscore {
position: absolute;
top: 20px;
right: 20px;
font-size: 24px;
color: #333344;
}
</style>
</head>

<body>
<div id="container">
<div id="game"></div>
<div id="score">0</div>
<div id="instructions">Click or press spacebar to place the block</div>
<div id="highscore">High Score: 0</div>
<div class="game-over">
<h2>Game Over</h2>
<p>You did great, you're the best!</p>
<p>Your score: <span id="final-score"></span></p>
<p>Click the button to start again</p>
<div id="restart-button">Start Again</div>
</div>
<div class="game-ready active">
<h2>Welcome to Stackerful 3D</h2>
<p>Stack blocks as high as you can!</p>
<div id="start-button">Start</div>
</div>
</div>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
(function() {
let GG_ALL_GAME_CONFIG = {
blockColors: [0x000000, 0x00BFFF, 0x32CD32, 0xFFD700, 0xFF8C00, 0xFF4500],
blockWidth: 15,
blockHeight: 2,
blockDepth: 15,
blockSpeed: 0.1,
cameraDistance: 50,
gameOverThreshold: 0.01,
cameraRotationSpeed: 0,
fallingSpeed: 0.2, // Reduced for smoother falling animation
fallingRotationSpeed: 0.05, // Reduced for smoother rotation
fallingAnimationDuration: 2000 // Duration of falling animation in
milliseconds
};
(function() {
class Stage {
constructor() {
this.container = document.getElementById('game');
this.renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
this.renderer.setSize(window.innerWidth, window.innerHeight);
this.container.appendChild(this.renderer.domElement);
this.scene = new THREE.Scene();
let aspect = window.innerWidth / window.innerHeight;
let d = GG_ALL_GAME_CONFIG.cameraDistance;
this.camera = new THREE.PerspectiveCamera(45, aspect, 1, 1000);
this.camera.position.set(d, d, d);
this.camera.lookAt(new THREE.Vector3(0, 0, 0));
this.light = new THREE.DirectionalLight(0xffffff, 0.8);
this.light.position.set(d, d, d);
this.scene.add(this.light);
this.softLight = new THREE.AmbientLight(0xffffff, 0.5);
this.scene.add(this.softLight);
window.addEventListener('resize', () => this.onResize());
this.onResize();
}
moveCamera(y) {
this.camera.position.y = y + GG_ALL_GAME_CONFIG.cameraDistance;
this.camera.lookAt(new THREE.Vector3(0, y, 0));
}
onResize() {
this.renderer.setSize(window.innerWidth, window.innerHeight);
this.camera.aspect = window.innerWidth / window.innerHeight;
this.camera.updateProjectionMatrix();
}
render() {
this.renderer.render(this.scene, this.camera);
}
add(elem) {
this.scene.add(elem);
}
remove(elem) {
this.scene.remove(elem);
}
}
class Block {
constructor(yPosition, index, previousBlockWidth) {
this.width = previousBlockWidth || GG_ALL_GAME_CONFIG.blockWidth;
this.height = GG_ALL_GAME_CONFIG.blockHeight;
this.depth = GG_ALL_GAME_CONFIG.blockDepth;
this.position = {
x: this.getRandomStartPosition(),
y: yPosition,
z: 0
};
this.speed = GG_ALL_GAME_CONFIG.blockSpeed;
this.direction = this.position.x > 0 ? -1 : 1;
this.state = 'active';
this.geometry = new THREE.BoxGeometry(this.width, this.height,
this.depth);
this.material = this.createMaterial(index);
this.mesh = new THREE.Mesh(this.geometry, this.material);
this.mesh.position.set(this.position.x, this.position.y,
this.position.z);
this.mesh.scale.set(1, 1, 1);
this.fallingPart = null;
}
getRandomStartPosition() {
const side = Math.random() > 0.5 ? 1 : -1;
return side * (GG_ALL_GAME_CONFIG.blockWidth + Math.random() * 7); //
Increased range for larger blocks
}
createMaterial(index) {
const colors = GG_ALL_GAME_CONFIG.blockColors;
return new THREE.MeshPhongMaterial({
color: colors[index % colors.length],
flatShading: true,
shininess: 100
});
}
tick() {
if (this.state === 'active') {
this.position.x += this.direction * this.speed;
if (Math.abs(this.position.x) > GG_ALL_GAME_CONFIG.blockWidth + 7)
{ // Increased range for larger blocks
this.direction *= -1;
}
this.mesh.position.x = this.position.x;
}
}
place(previousBlock) {
this.state = 'placed';
this.mesh.position.y = this.position.y;
if (previousBlock) {
let overlap = this.calculateOverlap(previousBlock);
if (overlap < this.width) {
this.cutBlock(overlap, previousBlock);
}
}
}
calculateOverlap(previousBlock) {
let previousBlockRight = previousBlock.mesh.position.x +
previousBlock.width / 2;
let previousBlockLeft = previousBlock.mesh.position.x -
previousBlock.width / 2;
let currentBlockRight = this.mesh.position.x + this.width / 2;
let currentBlockLeft = this.mesh.position.x - this.width / 2;
if (currentBlockLeft > previousBlockRight || currentBlockRight <
previousBlockLeft) {
return 0;
}
return Math.min(previousBlockRight, currentBlockRight) -
Math.max(previousBlockLeft, currentBlockLeft);
}
cutBlock(overlap, previousBlock) {
let newWidth = overlap;
let cutWidth = this.width - newWidth;
// Adjust the size and position of the main block
this.width = newWidth;
this.mesh.scale.x = newWidth / GG_ALL_GAME_CONFIG.blockWidth;
this.mesh.position.x = previousBlock.mesh.position.x;
// Create the falling part
let fallingGeometry = new THREE.BoxGeometry(cutWidth, this.height,
this.depth);
let fallingMaterial = this.material.clone();
this.fallingPart = new THREE.Mesh(fallingGeometry, fallingMaterial);
// Set the position of the falling part
let fallingPartX = this.mesh.position.x + (this.direction * (newWidth +
cutWidth) / 2);
this.fallingPart.position.set(fallingPartX, this.mesh.position.y,
this.mesh.position.z);
// Add the falling part to the scene
game.stage.add(this.fallingPart);
// Start the falling animation
this.animateFallingPart();
}
animateFallingPart() {
if (this.fallingPart) {
const startTime = Date.now();
const startY = this.fallingPart.position.y;
const startRotation = this.fallingPart.rotation.z;
const animate = () => {
const elapsedTime = Date.now() - startTime;
const progress = Math.min(elapsedTime /
GG_ALL_GAME_CONFIG.fallingAnimationDuration, 1);
// Use easing function for smoother animation
const easeProgress = this.easeOutQuad(progress);
this.fallingPart.position.y = startY - easeProgress * 60; // Fall
60 units
this.fallingPart.rotation.z = startRotation + easeProgress *
Math.PI * 2; // Rotate 360 degrees
if (progress < 1) {
requestAnimationFrame(animate);
} else {
game.stage.remove(this.fallingPart);
this.fallingPart = null;
}
};
animate();
}
}
easeOutQuad(t) {
return t * (2 - t);
}
}
class Game {
constructor() {
this.state = 'loading';
this.blocks = [];
this.score = 0;
this.highScore = 0;
this.stage = new Stage();
this.scoreContainer = document.getElementById('score');
this.startButton = document.getElementById('start-button');
this.restartButton = document.getElementById('restart-button');
this.gameOverScreen = document.querySelector('.game-over');
this.startButton.addEventListener('click', () => this.startGame());
this.restartButton.addEventListener('click', () => this.startGame());
document.addEventListener('keydown', e => {
if (e.key === ' ' && this.state === 'playing') this.placeBlock();
});
document.addEventListener('click', (e) => {
if (this.state === 'playing' && e.target !== this.restartButton)
this.placeBlock();
});
this.loadHighScore();
this.tick();
this.updateState('ready');
this.canPlaceBlock = false;
}
addInitialBlock() {
let initialBlock = new Block(0, 0);
initialBlock.position.x = 0;
initialBlock.mesh.position.x = 0;
initialBlock.state = 'placed';
initialBlock.width = GG_ALL_GAME_CONFIG.blockWidth;
this.stage.add(initialBlock.mesh);
this.blocks.push(initialBlock);
}
updateState(newState) {
this.state = newState;
document.querySelector('.game-ready').classList.toggle('active',
newState === 'ready');
this.gameOverScreen.classList.toggle('active', newState === 'ended');
this.scoreContainer.style.display = newState === 'playing' ? 'block' :
'none';
document.getElementById('instructions').style.display = newState ===
'playing' ? 'block' : 'none';
}
startGame() {
this.blocks.forEach(block => this.stage.remove(block.mesh));
this.blocks = [];
this.score = 0;
this.scoreContainer.innerHTML = this.score;
this.updateState('playing');
this.addInitialBlock();
this.addBlock();
this.stage.camera.position.set(GG_ALL_GAME_CONFIG.cameraDistance,
GG_ALL_GAME_CONFIG.cameraDistance, GG_ALL_GAME_CONFIG.cameraDistance);
this.stage.camera.lookAt(new THREE.Vector3(0, 0, 0));
// Add a small delay before allowing block placement
setTimeout(() => {
this.canPlaceBlock = true;
}, 500);
}
endGame() {
this.updateState('ended');
document.getElementById('final-score').textContent = this.score;
if (this.score > this.highScore) {
this.highScore = this.score;
this.saveHighScore();
}
document.getElementById('highscore').textContent = `High Score: $
{this.highScore}`;
this.canPlaceBlock = false;
}
placeBlock() {
if (this.state !== 'playing' || !this.canPlaceBlock) return;
let currentBlock = this.blocks[this.blocks.length - 1];
if (currentBlock.state === 'active') {
let prevBlock = this.blocks.length > 1 ?
this.blocks[this.blocks.length - 2] : null;
currentBlock.place(prevBlock);
if (currentBlock.width <= GG_ALL_GAME_CONFIG.blockWidth *
GG_ALL_GAME_CONFIG.gameOverThreshold) {
this.endGame();
return;
}
this.score++;
this.scoreContainer.innerHTML = this.score;
this.addBlock();
}
}
addBlock() {
let newIndex = this.blocks.length %
GG_ALL_GAME_CONFIG.blockColors.length;
let previousBlock = this.blocks[this.blocks.length - 1];
let newBlock = new Block(
previousBlock.position.y + GG_ALL_GAME_CONFIG.blockHeight,
newIndex,
previousBlock.width
);
this.stage.add(newBlock.mesh);
this.blocks.push(newBlock);
newBlock.state = 'active';
}
tick() {
if (this.state === 'playing') {
this.blocks.forEach(block => {
block.tick();
if (block.fallingPart) {
block.animateFallingPart();
}
});
if (this.blocks.length > 0) {
const topBlockY = this.blocks[this.blocks.length - 1].position.y;
this.stage.moveCamera(topBlockY / 2);
}
}
this.stage.render();
requestAnimationFrame(() => this.tick());
}
loadHighScore() {
const savedHighScore = localStorage.getItem('stackerful3DHighScore');
if (savedHighScore) {
this.highScore = parseInt(savedHighScore);
document.getElementById('highscore').textContent = `High Score: $
{this.highScore}`;
}
}
saveHighScore() {
localStorage.setItem('stackerful3DHighScore',
this.highScore.toString());
}
}
const game = new Game();
})();
})();
</script>

</body>

</html>

You might also like