Create: Computing AgesDoc Brass
Programmes intégrés

pong

pong en réseau à deux

Tourne sur Mini+ Mini-ordinateur et suivants · 142 lignes
Tapez ceci à l'invite d'un ordinateur pour le copier sur le support :
Terminal
> examples pong
> edit pong

Le programme

pong
-- PONG à deux joueurs sur deux ordinateurs reliés par câble, radio ou
-- Wi-Fi. Premier ordinateur : pong host   Second : pong join
-- Flèches haut/bas (ou Z/S) pour la raquette. Le premier à 5 gagne.
-- Ctrl+T quitte. L'hôte déplace la balle et envoie tout l'état 10 fois
-- par seconde ; l'autre ordinateur n'envoie que sa raquette.
local mode = arg[1]
if mode ~= "host" and mode ~= "join" then
  print("Usage : pong host   ou   pong join")
  return
end
local W, H, PAD, WIN = 40, 15, 4, 5  -- terrain, hauteur des raquettes, score gagnant
local me = {y = 6}
local other = {y = 6}
local left, right = me, other  -- l'hôte joue à gauche
if mode == "join" then left, right = other, me end
local ball = {x = 20, y = 8, dx = 1, dy = 1, wait = 10}
local score = {left = 0, right = 0}
local peer = nil
local running = true

-- 1. Trouver l'autre joueur
if mode == "host" then
  print("J'attends un joueur (pong join)...")
  while peer == nil do
    local m = net.receive()
    if m.channel == "pong" and m.data == "join" then
      peer = m.sender
      net.send(peer, "hello", "pong")
    end
  end
else
  print("Je cherche une partie (pong host)...")
  while peer == nil do
    net.broadcast("join", "pong")
    local m = net.receive(1)  -- nil après 1 seconde sans message
    if m and m.channel == "pong" and m.data == "hello" then peer = m.sender end
  end
end

-- 2. La balle : seul l'hôte la déplace
function serve(dir)
  ball.x = W // 2
  ball.y = H // 2
  ball.dx = dir
  if math.random(2) == 1 then ball.dy = 1 else ball.dy = -1 end
  ball.wait = 10  -- une seconde avant le service
end

function hit(paddle, y)
  return y >= paddle.y and y < paddle.y + PAD
end

function step()
  if ball.wait > 0 then
    ball.wait = ball.wait - 1
    return
  end
  local nx = ball.x + ball.dx
  local ny = ball.y + ball.dy
  if ny < 1 or ny > H then  -- rebond sur les murs
    ball.dy = -ball.dy
    ny = ball.y + ball.dy
  end
  if nx == 1 and hit(left, ny) then
    ball.dx = 1
    nx = ball.x + 1
  elseif nx == W and hit(right, ny) then
    ball.dx = -1
    nx = ball.x - 1
  elseif nx < 1 then
    score.right = score.right + 1
    serve(1)
    return
  elseif nx > W then
    score.left = score.left + 1
    serve(-1)
    return
  end
  ball.x = nx
  ball.y = ny
end

-- 3. L'affichage, sur les deux ordinateurs
function draw()
  term.clear()
  term.set_fg(term.colors.yellow)
  term.set_cursor(W // 2 - 2, 1)
  term.write(score.left .. " - " .. score.right)
  term.set_fg(term.colors.white)
  term.set_cursor(1, 2)
  term.write(string.rep("=", W + 2))
  term.set_cursor(1, H + 3)
  term.write(string.rep("=", W + 2))
  for i = 0, PAD - 1 do
    term.set_cursor(2, left.y + 2 + i)
    term.write("#")
    term.set_cursor(W + 1, right.y + 2 + i)
    term.write("#")
  end
  term.set_fg(term.colors.orange)
  term.set_cursor(ball.x + 1, ball.y + 2)
  term.write("O")
  term.set_fg(term.colors.white)
end

-- 4. La boucle de jeu : touches, messages, et un minuteur toutes les 0,1 s
local timer = os.start_timer(0.1)
while running do
  local e = os.pull_event()  -- n'importe quel évènement
  if e.name == "key" or e.name == "char" then
    local k = e.key or e.char
    if (k == "up" or k == "w" or k == "z") and me.y > 1 then me.y = me.y - 1 end
    if (k == "down" or k == "s") and me.y < H - PAD + 1 then me.y = me.y + 1 end
    if mode == "join" then net.send(peer, {y = me.y}, "pong") end
  elseif e.name == "message" and e.sender == peer and type(e.data) == "table" then
    local d = e.data
    other.y = d.y
    if mode == "join" then  -- l'hôte envoie tout l'état
      ball.x = d.bx
      ball.y = d.by
      score.left = d.sl
      score.right = d.sr
    end
  elseif e.name == "timer" and e.id == timer then
    timer = os.start_timer(0.1)
    if mode == "host" then
      step()
      net.send(peer, {y = me.y, bx = ball.x, by = ball.y, sl = score.left, sr = score.right}, "pong")
    end
    draw()
    if score.left >= WIN or score.right >= WIN then running = false end
  end
end

term.set_cursor(1, H + 4)
local mine = score.left
if mode == "join" then mine = score.right end
if mine >= WIN then
  print("Gagné !")
else
  print("Perdu !")
end