Os Sistemas Web e os Jogos Digitais
- #JavaScript
Sumário
1. Introdução
2. O que é um sistema web?
3. Criando um sistema web básico
4. Sistema web para um jogo multiplayer
5. Considerações finais
6. Referências
1 – Introdução
No início da programação, os sistemas eram baseados em mainframes, rodavam localmente e os programadores não tinham acesso direto ao hardware. Depois vieram os PCs e as coisas ficaram mais coloridas e divertidas, mas ainda rodavam localmente. Depois vieram as redes e a arquitetura cliente-servidor.
Com a chegada da Internet, vieram os sistemas web, com websites coloridos, dinâmicos e a interação real começou a acontecer blogs etc.
Atualmente, é muito comum ver sistemas simples ou complexos, como os financeiros rodando como sistemas web. E os jogos, divertidos, emocionantes e viciantes!
Este artigo apresenta o histórico dos sistemas de computador, até os sistemas web, e mostra exemplos de códigos de sistemas web simples.
2 – O que é um sistema web?
Um sistema web é um software projetado para rodar em servidores web, sendo acessado pelos usuários através de navegadores (browsers), usando a Internet.
Suas características principais são:
- Acesso via navegador - não exige instalação no computador do usuário;
- Multiplataforma - funciona em diferentes sistemas operacionais (Windows, Linux, Android etc);
- Atualização centralizada - basta atualizar o servidor, sem necessidade de atualizar manualmente cada dispositivo;
- Arquitetura cliente-servidor: o navegador (cliente) solicita informações, e o servidor processa e responde;
- Escalabilidade - atende qualquer quantidade de usuários, de 1 até milhões;
- Integração - com bancos de dados, APIs, serviços externos e outros sistemas corporativos.
Histórico
Eu aprendi a programar em 1980 e acompanhei a evolução dos sistemas de computação até hoje. Acreditem, nem sempre foi assim. 😊
No início dos anos 80, na universidade, a gente programava perfurando cartões, para mainframes, recebendo o resultado em listagens impressas, sem nenhum contato com os equipamentos. Depois, vieram os terminais burros, onde a gente digitava o programa e ele era executado no mainframe, com o resultado da execução chegando na tela textual monocromática. O processamento era centralizado, com poucos usuários simultâneos e o processamento era, principalmente, em lote (batch).
No início dos anos 90, com a chegada no Brasil dos primeiros PCs, os sistemas passaram a rodar localmente, instalados no computador. Isso trouxe mais facilidade de uso, mas resultou na dificuldade de manutenção, pois cada máquina precisava de atualização manual e local.
Logo depois vieram as redes locais e os programas passaram, a ser instalados em um computador separado e dedicado, o servidor, e os usuários podiam executá-los nos seus computadores clientes. Era a arquitetura cliente-servidor, que permitiu sistemas corporativos maiores e mais complexos. Além disso, a atualização do software só precisava ser feita no servidor, não em cada máquina cliente. No cliente ficava a interface com o usuário e no servidor o processamento dos dados e o acesso ao banco de dados.
O próximo passo, a partir de 1995, foi o surgimento da Internet, especialmente do serviço www (ou a web). As aplicações passaram a rodar em navegadores (browsers), com o acesso passando a ser global. Os programas não precisavam ser instalados em nenhuma máquina do cliente, criando o modelo de 3 camadas (navegador, servidor e bando de dados). Inicialmente, os sistemas eram escritos em HTML, CSS e Javascript. Depois vieram as linguagens de backend.
Os passos seguintes foram o lançamento e popularização dos smartphones e seus aplicativos mobile (apps), armazenamento em nuvem, ferramentas de IA, e contando...
3 – Criando um sistema web básico
Como foi dito, um sistema web é construído sobre a arquitetura cliente-servidor e é composta do frontend e do backend:
· Cliente (Front-end): navegador (ou app) do usuário, responsável pela apresentação na interface do usuário;
· Servidor (Back-end): responsável pelo processamento de dados, fluxos e regras de negócio, ou seja, a lógica do negócio.
· Banco de Dados: armazena as informações de forma persistente, permitindo consultas em SQL;
No frontend, temos as linguagens:
· HTML – responsável pelo layout dos elementos da página;
· CSS – cuida da formatação dos elementos do jogo, configurando cores, alinhamento, fontes etc.;
· Javascript – é quem dá a dinâmica da página, inserindo ações para eventos da interface com o usuário, definindo temporizações, e mensagens para o usuário;
· Também são usados frameworks como React, Angular ou Vue.js.
Já o Backend é composto de:
· Linguagens como Python (Django/Flask), Java (Spring), PHP (Laravel), JavaScript (Node.js), .NET, Go etc.
· Banco de dados – Pode ser um banco de dados relacional (como MySQL, PostgreSQL, SQL Server) ou não-relacional (MongoDB, Redis, Cassandra). No caso de elementos geográficos, para georreferenciamento, é preciso usar um banco que ofereça esta característica, como o PostgreSQL;
- Servidor Web: cuida da comunicação dos dados entre o backend e o frontend dos usuários. Exemplos são Apache, Nginx ou serviços em nuvem;
Um típico exemplo de fluxo de um sistema web é:
Usuário → navegador envia requisição HTTP → servidor processa → consulta banco de dados → retorna resposta → servidor web envia resposta HTTP → navegador exibe.
Exemplo de sistema web bem simples
A seguir, segue a codificação para um sistema web de cadastro de usuários, usando frontend com HTML e backend com Python e Flask), com integração a um banco SQLite.
O seu funcionamento é o seguinte:
- O usuário acessa http://localhost:5000.
- O navegador exibe o formulário HTML.
- Quando ele envia os dados, o Flask recebe pela rota /cadastro.
- Os dados são salvos no banco usuarios.db.
- O servidor responde com uma mensagem de sucesso ou erro.
Front-end (formulário HTML)
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="UTF-8">
<title>Cadastro de Usuário</title>
</head>
<body>
<h2>Cadastro de Usuário</h2>
<form action="/cadastro" method="post">
Nome: <input type="text" name="nome" required><br><br>
Email: <input type="email" name="email" required><br><br>
Senha: <input type="password" name="senha" required><br><br>
<button type="submit">Cadastrar</button>
</form>
</body>
</html>
A seguinte tela será gerada
Back-end (Python + Flask)
from flask import Flask, request, render_template_string
import sqlite3
app = Flask(__name__)
# Cria o banco de dados (se não existir)
def init_db():
conn = sqlite3.connect("usuarios.db")
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS usuarios (
id INTEGER PRIMARY KEY AUTOINCREMENT,
nome TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
senha TEXT NOT NULL
)
""")
conn.commit()
conn.close()
init_db()
# Página inicial (formulário HTML)
@app.route("/")
def index():
html = open("index.html", "r", encoding="utf-8").read()
return render_template_string(html)
# Rota de cadastro
@app.route("/cadastro", methods=["POST"])
def cadastro():
nome = request.form["nome"]
email = request.form["email"]
senha = request.form["senha"]
try:
conn = sqlite3.connect("usuarios.db")
cursor = conn.cursor()
cursor.execute("INSERT INTO usuarios (nome, email, senha) VALUES (?, ?, ?)",
(nome, email, senha))
conn.commit()
conn.close()
return f"Usuário {nome} cadastrado com sucesso!"
except sqlite3.IntegrityError:
return "Erro: este email já está cadastrado!"
if __name__ == "__main__":
app.run(debug=True)
3 – Um sistema web para jogos multiplayer
Uma das principais (e mais divertidas e empolgantes!) aplicações para um servidor web são os jogos digitais (os famosos games).
Seguindo a arquitetura cliente servidor vista na seção anterior, um jogo digital pode ser estruturado da seguinte forma:
Front-end (lado do cliente) - É a parte do jogo que o jogador vê e interage. É responsável pela renderização dos gráficos, captura de entradas do jogador (teclado, mouse, toque) e comunicação em tempo real com o servidor.
As linguagens usadas comumente são HTML5, para a estrutura do jogo, CSS3, para os estilos e o design e JavaScript, para a lógica e interatividade.
Também costumam ser usados frameworks e bibliotecas como Phaser.js e PixiJS (para jogos 2D), Three.js e Babylon.js (para gráficos 3D no navegador) e WebGL, para renderização gráfica acelerada pela GPU);
Back-end (lado do servidor) - Responsável por processar regras que precisam ser centralizadas. As responsabilidades do backend são autenticação de jogadores (login, sessão), armazenamento de dados (pontuações, inventário, progresso), gerenciamento de partidas multiplayer e comunicação para sincronizar estados do jogo (via WebSocket).
As linguagens e frameworks mais usados são Node.js (com Socket.IO para tempo real), Python (Flask/Django + websockets), Java (Spring), mas também são usadas Go e .NET Core.
Banco de dados – Os principais bancos de dados utilizados são os relacionais MySQL e PostgreSQL (para as contas de usuários e rankings de pontuação) ou os não-relacionais MongoDB e Redis (para armazenar os estados de jogo e cache de sessão).
O fluxo de comunicação durante o jogo é:
- O jogador acessa o navegador, que carrega os arquivos HTML/CSS/JS do jogo;
- O frontend processa a lógica gráfica e envia eventos (movimento, ações) ao backend;
- O backend valida as regras globais (pontos, colisões em multiplayer, ranking etc.);
- O banco de dados guarda informações persistentes;
- A comunicação entre o frontend e o backend pode ser feita por HTTP/REST, para requisições ocasionais (como salvar a pontuação) ou por meio de WebSockets, para comunicação contínua e em tempo real (ex.: jogos multiplayer).
Como exemplo de implementação de um sistema web para um jogo, vamos criar o código básico para um jogo 2D multiplayer simples.
O jogo escolhido é bem simples: cada jogador controla um quadradinho colorido em um mapa; o servidor sincroniza posições e salva contas e pontuações.
Foram escolhidas as stacks HTML5 Canvas + JS, no frontend, e Flask + Flask-SocketIO + SQLite no back-end.
Estrutura de pastas:
webgame/
├─ app.py
├─ requirements.txt
├─ templates/
│ └─ index.html
└─ static/
└─ game.js
Arquivo requirements.txt é:
flask==3.0.3
flask-socketio==5.3.6
eventlet==0.36.1
SQLAlchemy==2.0.31
Werkzeug==3.0.3
flask-cors==4.0.1
O código para o frontend ficaria assim (templates/index.html (HTML + Canvas + UI simples):
<!doctype html>
<html lang="pt-br">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Web Arena</title>
<style>
body{font-family:system-ui,Segoe UI,Arial,sans-serif;margin:0;background:#0b1020;color:#e9f0ff}
header{padding:10px 16px;background:#0f1630;display:flex;gap:12px;align-items:center}
#status{margin-left:auto;font-size:.9rem;opacity:.8}
main{display:grid;grid-template-columns:1fr 320px;gap:0}
#gameWrap{display:flex;justify-content:center;align-items:center;padding:8px;background:#0b1020}
canvas{background:#0d1328;border:1px solid #1f2b54;border-radius:12px;box-shadow:0 8px 24px rgba(0,0,0,.35)}
aside{background:#0f1630;border-left:1px solid #22305f;padding:12px 12px 80px}
h3{margin:.2rem 0 .6rem}
.card{background:#0d1533;border:1px solid #213269;border-radius:12px;padding:12px;margin:8px 0}
input,button{padding:10px 12px;border-radius:10px;border:1px solid #2b3f7c;background:#0b1330;color:#e9f0ff}
button{cursor:pointer}
table{width:100%;border-collapse:collapse}
th,td{padding:6px 8px;border-bottom:1px solid #24346b;font-size:.95rem}
#auth{display:flex;gap:6px;flex-wrap:wrap}
small{opacity:.75}
</style>
</head>
<body>
<header>
<strong>🕹️ Web Arena</strong>
<div id="auth">
<input id="user" placeholder="usuário">
<input id="pass" placeholder="senha" type="password">
<button id="btnReg">Registrar</button>
<button id="btnLogin">Login</button>
</div>
<div id="status">Desconectado</div>
</header>
<main>
<div id="gameWrap">
<canvas id="game" width="900" height="600"></canvas>
</div>
<aside>
<div class="card">
<h3>Perfil</h3>
<div id="profile"><small>faça login para jogar</small></div>
</div>
<div class="card">
<h3>Ranking (Top 10)</h3>
<table id="rank"><thead><tr><th>Jogador</th><th>Pontos</th></tr></thead><tbody></tbody></table>
<button id="refreshRank">Atualizar ranking</button>
</div>
<div class="card">
<h3>Ajuda</h3>
<small>Use WASD ou setas para mover. A cada segundo em movimento: +1 ponto. Clique “Salvar Pontos”.</small><br><br>
<button id="saveScore" disabled>Salvar Pontos</button>
</div>
</aside>
</main>
<script src="https://cdn.socket.io/4.7.5/socket.io.min.js" integrity="sha384-FtM6k4r5J6c0vUo5CwH5pVxQx+0d9y8v8s9n7N9rXQz0mN0l5tF9Ew7zQ3A0y7yQ" crossorigin="anonymous"></script>
<script src="/static/game.js"></script>
</body>
</html>
O código para a lógica do cliente (static/game.js), com WebSocket:
// --------------------------- Config & State ---------------------------
const API = "";
let AUTH = { token: null, username: null };
let socket = null;
const cv = document.getElementById("game");
const ctx = cv.getContext("2d");
let world = { w: cv.width, h: cv.height, players: {} };
let my = { x: 100, y: 100, vx: 0, vy: 0, points: 0, alive: false, t0: null };
// --------------------------- UI Helpers ---------------------------
const $ = (sel) => document.querySelector(sel);
const statusEl = $("#status");
const profileEl = $("#profile");
const rankBody = $("#rank tbody");
function setStatus(s){ statusEl.textContent = s; }
function setProfile(){
if (!AUTH.token) { profileEl.innerHTML = "<small>faça login para jogar</small>"; return; }
profileEl.innerHTML =<b>${AUTH.username}</b><br><small>token: ${AUTH.token.slice(0,12)}…</small>`;
}
// --------------------------- Auth (HTTP) ---------------------------
async function json(url, method, body, auth=false){
const r = await fetch(url, {
method,
headers: {
"Content-Type": "application/json",
...(auth && AUTH.token ? { "Authorization": `Bearer ${AUTH.token}` } : {})
},
body: body ? JSON.stringify(body) : undefined
});
const data = await r.json().catch(()=>({}));
if (!r.ok) throw new Error(data.error || r.statusText);
return data;
}
async function registerUser(u,p){
const res = await json("/api/register", "POST", {username:u, password:p});
AUTH = { token: res.token, username: res.username };
localStorage.setItem("auth", JSON.stringify(AUTH));
setProfile();
}
async function loginUser(u,p){
const res = await json("/api/login", "POST", {username:u, password:p});
AUTH = { token: res.token, username: res.username };
localStorage.setItem("auth", JSON.stringify(AUTH));
setProfile();
}
async function loadRank(){
const rows = await json("/api/highscores", "GET");
rankBody.innerHTML = rows.map(r => `<tr><td>${r.username}</td><td>${r.points}</td></tr>`).join("");
}
// --------------------------- Game / Socket ---------------------------
function connectSocket(){
if (!AUTH.token) return;
socket = io("/game", { transports: ["websocket"] });
socket.on("connect", () => {
setStatus("Conectado");
socket.emit("join", { token: AUTH.token });
$("#saveScore").disabled = false;
my.alive = true; my.points = 0; my.t0 = performance.now();
});
socket.on("disconnect", () => setStatus("Desconectado"));
socket.on("world", (data) => { world = data; draw(); });
socket.on("state", (data) => { world.players = data.players; draw(); });
socket.on("player_joined", () => {/* opcional: mostrar mensagem */});
socket.on("player_left", () => {/* opcional */});
socket.on("score_saved", () => { loadRank(); });
socket.on("error", (e) => alert(e.message || "Erro"));
}
// input
const keys = {};
window.addEventListener("keydown", e => { keys[e.key.toLowerCase()] = true; });
window.addEventListener("keyup", e => { keys[e.key.toLowerCase()] = false; });
function step(){
if (!my.alive || !socket) return;
const up = keys["w"] || keys["arrowup"];
const down = keys["s"] || keys["arrowdown"];
const left = keys["a"] || keys["arrowleft"];
const right = keys["d"] || keys["arrowright"];
let dx = 0, dy = 0;
if (up) dy -= 1; if (down) dy += 1; if (left) dx -= 1; if (right) dx += 1;
if (dx || dy) {
socket.emit("move", { token: AUTH.token, dx, dy });
// pontuação simples: +1 por segundo em movimento
const dt = (performance.now() - my.t0)/1000;
if (dt >= 1){ my.points += Math.floor(dt); my.t0 = performance.now(); }
}
requestAnimationFrame(step);
}
function draw(){
ctx.clearRect(0,0,cv.width,cv.height);
// grade leve
ctx.globalAlpha = 0.15;
for(let x=0; x<cv.width; x+=50){ ctx.fillRect(x,0,1,cv.height); }
for(let y=0; y<cv.height; y+=50){ ctx.fillRect(0,y,cv.width,1); }
ctx.globalAlpha = 1;
// desenha jogadores
for (const [token, p] of Object.entries(world.players)){
const me = (AUTH.token && token === AUTH.token);
ctx.beginPath();
ctx.fillStyle = me ? "#5cf27b" : "#7aa8ff";
ctx.strokeStyle = "#0b0";
ctx.rect(p.x-8, p.y-8, 16, 16);
ctx.fill();
// nome
ctx.font = "12px system-ui";
ctx.fillStyle = "#e9f0ff";
ctx.fillText(p.username, p.x - ctx.measureText(p.username).width/2, p.y - 12);
}
// HUD com pontos
ctx.font = "14px system-ui";
ctx.fillStyle = "#e9f0ff";
ctx.fillText(`Pontos: ${my.points}`, 10, 20);
}
// --------------------------- UI wiring ---------------------------
$("#btnReg").onclick = async () => {
const u = $("#user").value.trim(); const p = $("#pass").value;
if (!u || !p) return alert("Informe usuário e senha");
try { await registerUser(u,p); connectSocket(); await loadRank(); requestAnimationFrame(step); }
catch(e){ alert(e.message); }
};
$("#btnLogin").onclick = async () => {
const u = $("#user").value.trim(); const p = $("#pass").value;
if (!u || !p) return alert("Informe usuário e senha");
try { await loginUser(u,p); connectSocket(); await loadRank(); requestAnimationFrame(step); }
catch(e){ alert(e.message); }
};
$("#refreshRank").onclick = loadRank;
$("#saveScore").onclick = async () => {
if (!socket || !AUTH.token) return;
socket.emit("submit_score", { token: AUTH.token, points: my.points, duration_sec: 0 });
};
// restaura sessão
const saved = localStorage.getItem("auth");
if (saved){
try { AUTH = JSON.parse(saved); setProfile(); connectSocket(); loadRank(); requestAnimationFrame(step); }
catch{}
}
setProfile();
O código do backend é muito longo e, como aqui eu quero focar no frontend, não será mostrado.
O backend (servidor) gerencia a posição de todos e garante que os movimentos sejam sincronizados. O banco de dados guarda a conta do jogador (usuário, senha, ranking), a pontuação total acumulada e o histórico de partidas.
A tela do jogo é mostrada abaixo:
O tabuleiro é uma arena em grade (grid). O jogador controla um quadrado colorido (verde ou azul na figura) no tabuleiro.
O jogo funciona da seguinte maneira:
É um jogo multiplayer, em que os jogadores competem para coletar itens e pontuar. O objetivo é coletar pontos e evitar ser atingido por outros jogadores ou obstáculos. Ganha quem acumular mais pontos antes do fim do tempo ou quem atingir primeiro uma pontuação máxima.
O jogador pode ganhar pontos - Cada vez que o jogador se move até uma célula especial (um item ou power-up que aparece aleatoriamente), ele ganha pontos. O Power-up dá pontos e uma vantagem temporária, como mais velocidade.
Ele também pode perder pontos - Se colidir com outro jogador, perde pontos ou fica temporariamente congelado. Se ficar muito tempo sem coletar nada, pode perder pontos por inatividade. Se houver armadilhas na arena, o jogador perde pontos ao cair nelas.
Os quadrados com números são as pontuações de 4 jogadores, os quadradinhos coloridos são os jogadores, as outras figuras são os itens de pontuação.
5 – Considerações finais
Uma das formas modernas de criação de sistemas e aplicativos segue a arquitetura cliente-servidor.
Ela é baseada no uso de navegadores web para renderizar a tela do usuário (frontend), bancos de dados remotos para armazenar os dados persistentes do programa, controlados por regras de negócio armazenadas em servidores (backend), e servidores web, para comunicação com o frontend;
A base para o frontend é composta das linguagens HTML, CSS e Javascript, enquanto no backend são usados Python, Node.js, Java e outras.
Os sistemas web são usados para aplicações simples, sistemas robustos de comércio eletrônico, além de sistemas financeiros, e sistemas divertidos como os jogos digitais.
Este artigo apresentou as características de sistemas web comuns e os conceitos técnicos por trás deles.
Além disso, foram mostrados códigos de exemplo para sistemas web básicos e para o frontend de um jogo digital simples.
Eu gosto de jogar jogos digitais simples. Atualmente, jogo Sudoku, Xadrez, gamão e Rummikub – este último eu jogo todo dia! Inclusive comprei o jogo de tabuleiro dele. Recomendo!!!
6 – Referências
[1] DevMedia. Como funcionam as aplicações web. Disponível em: <https://www.devmedia.com.br/como-funcionam-as-aplicacoes-web/25888>. Acesso em: 21/08/2025.
[2] Kelvin SUNG et all. Build Your Own 2D Game Engine and Create Great Web Games : Using HTML5, JavaScript, and WebGL2. Apress, 2021.
[3] ChatGPT - Jogo criado pelo ChatGPT, Disponível em: <chatgpt.com>. Acesso em: 22/08/2025.