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

DOC BRB

The document outlines the structure and functionality of a web-based soccer game, including HTML, CSS, and JavaScript components. It features a canvas for rendering the game, controls for player movement and actions, and a scoring system. The game includes mechanics for player movement, ball physics, and user interactions through touch controls.

Uploaded by

oficialffmax27
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

DOC BRB

The document outlines the structure and functionality of a web-based soccer game, including HTML, CSS, and JavaScript components. It features a canvas for rendering the game, controls for player movement and actions, and a scoring system. The game includes mechanics for player movement, ball physics, and user interactions through touch controls.

Uploaded by

oficialffmax27
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 12

<!

DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0,
user-scalable=yes">
<title>Pro Soccer Game</title>
<style>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
user-select: none;
}

body {
overflow: hidden;
position: fixed;
width: 100%;
height: 100%;
background-color: #0e3b1c;
}

canvas {
background: linear-gradient(135deg, #0d3519 0%, #0e3b1c 25%, #0e3b1c 75%, #0d3519
100%);
display: block;
touch-action: none;
width: 100%;
height: 100%;
}

.button-container {
position: fixed;
bottom: 40px;
right: 40px;
display: flex;
gap: 20px;
z-index: 10;
}

.button {
width: 90px;
height: 90px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-family: Arial, sans-serif;
font-weight: bold;
font-size: 16px;
color: white;
text-shadow: 1px 1px 2px rgba(0,0,0,0.5);
transform: scale(1);
transition: transform 0.15s ease;
cursor: pointer;
}

.button:active {
transform: scale(0.92);
}

#buttonA {
background: radial-gradient(circle, #ff3838 0%, #e62020 100%);
box-shadow: 0 4px 15px rgba(255,0,0,0.3);
}

#buttonB {
background: radial-gradient(circle, #2ed573 0%, #26ae60 100%);
box-shadow: 0 4px 15px rgba(46,213,115,0.3);
}

#analog-stick {
position: fixed;
bottom: 40px;
left: 40px;
width: 150px;
height: 150px;
background: rgba(255, 255, 255, 0.1);
border: 2px solid rgba(255, 255, 255, 0.2);
border-radius: 50%;
touch-action: none;
z-index: 10;
}

#analog-knob {
position: absolute;
width: 60px;
height: 60px;
background: radial-gradient(circle, rgba(255,255,255,0.95) 0%, rgba(200,200,200,0.95)
100%);
border-radius: 50%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
box-shadow: 0 2px 8px rgba(0,0,0,0.2);
cursor: grab;
}

#analog-knob:active {
cursor: grabbing;
}

#placar {
position: fixed;
top: 20px;
left: 50%;
transform: translateX(-50%);
color: white;
font-family: Arial, sans-serif;
font-size: 24px;
background: rgba(0,0,0,0.5);
padding: 10px 20px;
border-radius: 10px;
z-index: 10;
}

.timer {
position: fixed;
top: 70px;
left: 50%;
transform: translateX(-50%);
color: white;
font-family: Arial, sans-serif;
font-size: 20px;
background: rgba(0,0,0,0.5);
padding: 5px 15px;
border-radius: 8px;
z-index: 10;
}

.gol-mensagem {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(0);
color: white;
font-family: Arial, sans-serif;
font-size: 48px;
font-weight: bold;
text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
opacity: 0;
transition: transform 0.3s ease, opacity 0.3s ease;
z-index: 20;
}

.gol-mensagem.active {
transform: translate(-50%, -50%) scale(1);
opacity: 1;
}
</style>
</head>
<body>
<canvas id="gameCanvas"></canvas>
<div id="analog-stick">
<div id="analog-knob"></div>
</div>
<div class="button-container">
<div id="buttonB" class="button">PASSE</div>
<div id="buttonA" class="button">CHUTE</div>
</div>
<div id="placar">
<span id="placarTime1">0</span>
:
<span id="placarTime2">0</span>
</div>
<div class="timer">10:00</div>
<div class="gol-mensagem">GOL!</div>
<script>
class Game {
constructor() {
this.canvas = document.getElementById('gameCanvas');
this.ctx = this.canvas.getContext('2d');
this.setupConstants();
this.setupGameState();
this.setupControls();
this.init();

// Adiciona listener para orientação da tela


window.addEventListener('orientationchange', () => {
setTimeout(() => {
this.resizeCanvas();
this.resetPositions();
}, 100);
});
}

setupConstants() {
this.PLAYER_MAX_SPEED = 6.5;
this.PLAYER_ACCELERATION = 0.7;
this.PLAYER_FRICTION = 0.92;
this.PLAYER_RADIUS = 22;
this.BALL_RADIUS = 12;
this.BALL_FRICTION = 0.985; // Ajustado para menor flutuação
this.BALL_BOUNCE = 0.65; // Reduzido para menor quique
this.KICK_POWER = 18;
this.PASS_POWER = 12;
this.BALL_GRAVITY = 0.3; // Adicionado gravidade à bola
}

setupGameState() {
this.score1 = 0;
this.score2 = 0;
this.gameTime = 600; // 10 minutos em segundos
this.resetPositions();
this.analogPosition = { x: 0, y: 0 };
this.isAnalogActive = false;
this.buttonAPressed = false;
this.buttonBPressed = false;
this.lastKickTime = 0;
}

setupControls() {
const analogStick = document.getElementById('analog-stick');
const analogKnob = document.getElementById('analog-knob');
let isDragging = false;
const maxDistance = 45; // Reduzido para melhor controle

const updateAnalogPosition = (clientX, clientY) => {


const rect = analogStick.getBoundingClientRect();
const centerX = rect.width / 2;
const centerY = rect.height / 2;

const x = clientX - rect.left - centerX;


const y = clientY - rect.top - centerY;
const distance = Math.min(Math.hypot(x, y), maxDistance);
const angle = Math.atan2(y, x);

const normalizedX = (distance / maxDistance) * Math.cos(angle);


const normalizedY = (distance / maxDistance) * Math.sin(angle);

const knobX = centerX + (normalizedX * maxDistance);


const knobY = centerY + (normalizedY * maxDistance);

analogKnob.style.transform = `translate(${knobX - 30}px, ${knobY - 30}px)`;

this.analogPosition = {
x: normalizedX,
y: normalizedY
};
this.isAnalogActive = distance > 0;
};

const resetAnalog = () => {


analogKnob.style.transform = 'translate(-50%, -50%)';
this.analogPosition = { x: 0, y: 0 };
this.isAnalogActive = false;
};

analogStick.addEventListener('touchstart', (e) => {


isDragging = true;
updateAnalogPosition(e.touches[0].clientX, e.touches[0].clientY);
});

document.addEventListener('touchmove', (e) => {


if (isDragging) {
e.preventDefault();
updateAnalogPosition(e.touches[0].clientX, e.touches[0].clientY);
}
}, { passive: false });

document.addEventListener('touchend', () => {
isDragging = false;
resetAnalog();
});

// Botões
document.getElementById('buttonA').addEventListener('touchstart', () =>
this.buttonAPressed = true);
document.getElementById('buttonA').addEventListener('touchend', () =>
this.buttonAPressed = false);
document.getElementById('buttonB').addEventListener('touchstart', () =>
this.buttonBPressed = true);
document.getElementById('buttonB').addEventListener('touchend', () =>
this.buttonBPressed = false);
}

init() {
this.resizeCanvas();
window.addEventListener('resize', () => this.resizeCanvas());
this.gameLoop();
}

resizeCanvas() {
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
}
resetPositions() {
const centerX = this.canvas.width / 2;
const centerY = this.canvas.height / 2;

this.player = {
x: centerX - 100,
y: centerY,
vx: 0,
vy: 0,
rotation: 0
};

this.ball = {
x: centerX,
y: centerY,
vx: 0,
vy: 0
};
}

updatePlayer() {
if (this.isAnalogActive) {
const targetVX = this.analogPosition.x * this.PLAYER_MAX_SPEED;
const targetVY = this.analogPosition.y * this.PLAYER_MAX_SPEED;

this.player.vx += (targetVX - this.player.vx) * this.PLAYER_ACCELERATION;


this.player.vy += (targetVY - this.player.vy) * this.PLAYER_ACCELERATION;
this.player.rotation = Math.atan2(this.analogPosition.y, this.analogPosition.x);
} else {
this.player.vx *= this.PLAYER_FRICTION;
this.player.vy *= this.PLAYER_FRICTION;
}

this.player.x += this.player.vx;
this.player.y += this.player.vy;

// Colisão com bordas


this.player.x = Math.max(this.PLAYER_RADIUS, Math.min(this.canvas.width -
this.PLAYER_RADIUS, this.player.x));
this.player.y = Math.max(this.PLAYER_RADIUS, Math.min(this.canvas.height -
this.PLAYER_RADIUS, this.player.y));

// Colisão com a bola


const dx = this.ball.x - this.player.x;
const dy = this.ball.y - this.player.y;
const distance = Math.hypot(dx, dy);
const minDist = this.PLAYER_RADIUS + this.BALL_RADIUS;
if (distance < minDist) {
const angle = Math.atan2(dy, dx);
const pushForce = (minDist - distance) * 0.2;

this.ball.x = this.player.x + Math.cos(angle) * minDist;


this.ball.y = this.player.y + Math.sin(angle) * minDist;

this.ball.vx += Math.cos(angle) * pushForce + this.player.vx * 0.5;


this.ball.vy += Math.sin(angle) * pushForce + this.player.vy * 0.5;
}
}

updateBall() {
// Aplica fricção
this.ball.vx *= this.BALL_FRICTION;
this.ball.vy *= this.BALL_FRICTION;

// Aplica gravidade
this.ball.vy += this.BALL_GRAVITY;

// Atualiza posição
this.ball.x += this.ball.vx;
this.ball.y += this.ball.vy;

// Colisão com bordas


if (this.ball.x < this.BALL_RADIUS || this.ball.x > this.canvas.width -
this.BALL_RADIUS) {
this.ball.vx *= -this.BALL_BOUNCE;
this.ball.x = this.ball.x < this.BALL_RADIUS ? this.BALL_RADIUS : this.canvas.width
- this.BALL_RADIUS;
}

if (this.ball.y < this.BALL_RADIUS || this.ball.y > this.canvas.height -


this.BALL_RADIUS) {
this.ball.vy *= -this.BALL_BOUNCE;
this.ball.y = this.ball.y < this.BALL_RADIUS ? this.BALL_RADIUS :
this.canvas.height - this.BALL_RADIUS;

// Adiciona atrito extra quando a bola toca o chão


if (this.ball.y > this.canvas.height - this.BALL_RADIUS) {
this.ball.vx *= 0.95;
}
}
}

handleButtons() {
const currentTime = Date.now();
const dx = this.ball.x - this.player.x;
const dy = this.ball.y - this.player.y;
const distance = Math.hypot(dx, dy);

if (distance < this.PLAYER_RADIUS * 2) {


if (this.buttonAPressed && currentTime - this.lastKickTime > 500) {
this.kickBall(this.KICK_POWER);
this.lastKickTime = currentTime;
}
if (this.buttonBPressed && currentTime - this.lastKickTime > 500) {
this.kickBall(this.PASS_POWER);
this.lastKickTime = currentTime;
}
}
}

kickBall(power) {
const dx = this.ball.x - this.player.x;
const dy = this.ball.y - this.player.y;
const angle = Math.atan2(dy, dx);

this.ball.vx = Math.cos(angle) * power + this.player.vx * 0.5;


this.ball.vy = Math.sin(angle) * power + this.player.vy * 0.5;
}

draw() {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.drawField();
this.drawPlayer();
this.drawBall();
}

drawField() {
this.ctx.strokeStyle = 'rgba(255, 255, 255, 0.3)';
this.ctx.lineWidth = 2;

// Linha central
this.ctx.beginPath();
this.ctx.moveTo(this.canvas.width / 2, 0);
this.ctx.lineTo(this.canvas.width / 2, this.canvas.height);
this.ctx.stroke();

// Círculo central
this.ctx.beginPath();
this.ctx.arc(this.canvas.width / 2, this.canvas.height / 2, 70, 0, Math.PI * 2);
this.ctx.stroke();

// Gols
const goalWidth = 20;
const goalHeight = 140;
const goalY = (this.canvas.height - goalHeight) / 2;

this.ctx.strokeStyle = 'rgba(255, 255, 255, 0.5)';


this.ctx.lineWidth = 4;

// Gol esquerdo
this.ctx.strokeRect(0, goalY, goalWidth, goalHeight);

// Gol direito
this.ctx.strokeRect(this.canvas.width - goalWidth, goalY, goalWidth, goalHeight);
}

drawPlayer() {
this.ctx.save();
this.ctx.translate(this.player.x, this.player.y);
this.ctx.rotate(this.player.rotation);

// Corpo do jogador
this.ctx.fillStyle = '#1a73e8';
this.ctx.beginPath();
this.ctx.arc(0, 0, this.PLAYER_RADIUS, 0, Math.PI * 2);
this.ctx.fill();

// Indicador de direção
this.ctx.fillStyle = '#fff';
this.ctx.beginPath();
this.ctx.arc(this.PLAYER_RADIUS/2, 0, this.PLAYER_RADIUS/4, 0, Math.PI * 2);
this.ctx.fill();

this.ctx.restore();
}

drawBall() {
const gradient = this.ctx.createRadialGradient(
this.ball.x, this.ball.y, 0,
this.ball.x, this.ball.y, this.BALL_RADIUS
);
gradient.addColorStop(0, '#ffffff');
gradient.addColorStop(1, '#e0e0e0');

this.ctx.beginPath();
this.ctx.fillStyle = gradient;
this.ctx.arc(this.ball.x, this.ball.y, this.BALL_RADIUS, 0, Math.PI * 2);
this.ctx.fill();

this.ctx.strokeStyle = '#000';
this.ctx.lineWidth = 1;
this.ctx.beginPath();
this.ctx.arc(this.ball.x, this.ball.y, this.BALL_RADIUS * 0.7, 0, Math.PI * 2);
this.ctx.stroke();
}

updateTimer() {
if (this.gameTime > 0) {
this.gameTime--;
const minutes = Math.floor(this.gameTime / 60);
const seconds = this.gameTime % 60;
document.querySelector('.timer').textContent =
`${minutes}:${seconds.toString().padStart(2, '0')}`;
}
}

checkGoal() {
const goalHeight = 140;
const goalY = (this.canvas.height - goalHeight) / 2;

if (this.ball.x <= this.BALL_RADIUS &&


this.ball.y > goalY &&
this.ball.y < goalY + goalHeight) {
this.score2++;
this.showGoal();
this.resetPositions();
} else if (this.ball.x >= this.canvas.width - this.BALL_RADIUS &&
this.ball.y > goalY &&
this.ball.y < goalY + goalHeight) {
this.score1++;
this.showGoal();
this.resetPositions();
}

document.getElementById('placarTime1').textContent = this.score1;
document.getElementById('placarTime2').textContent = this.score2;
}

showGoal() {
const golMensagem = document.querySelector('.gol-mensagem');
golMensagem.classList.add('active');
setTimeout(() => golMensagem.classList.remove('active'), 1500);
}

gameLoop() {
this.updatePlayer();
this.updateBall();
this.handleButtons();
this.checkGoal();
this.updateTimer();
this.draw();
requestAnimationFrame(() => this.gameLoop());
}
}

window.onload = () => new Game();


</script>
</body>
</html>

You might also like