Atelier.

atelier · lecții

Lecția 13 30 min avansat 3 întrebări quiz

PvP între 2 mașini — ESP-NOW + ultrasonic

Cum trimit mașina ta un mesaj la mașina lui Darius când îl lovești. Damage, scut activ, magnet. ESP-NOW peer-to-peer fără router.

Ce înveți

  • Cum trimit 2 ESP32 mesaje direct între ele (ESP-NOW, fără router)
  • Cum măsori distanța cu HC-SR04 ultrasonic
  • Cum sincronizezi 'scut activ' între mașini — efect global, nu doar local
  • Cum desenezi pe pagina de control viața (HP) și power-up-ul activ

ESP-NOW recap (de la VIA)

ESP-NOW = mesaje directe între 2 ESP32. Nu trebuie router, nu trebuie internet. Doar:

  1. Fiecare ESP32 are un MAC (adresa fizică unică, 6 bytes ca C0:49:EF:00:00:01)
  2. Tu îți spui în cod: „vreau să vorbesc cu MAC C0:49:EF:00:00:02
  3. Trimiți esp_now_send(mac, pachet, lungime) → ajunge în 1-2 ms

La CART-K avem 2 mașini care comunică:

  • M1 (Sergiu) — MAC C0:49:EF:00:00:01
  • M2 (Darius) — MAC C0:49:EF:00:00:02

Mesaje pe care le trimitem

struct cart_msg {
  uint8_t tip;          // 1 = lovire, 2 = scut activ, 3 = magnet, 4 = ping
  uint8_t source_id;    // 1 sau 2
  int hp;               // viața mea curentă (0..100)
  int power_up;         // ce power-up am activ (0=niciunul, 1=banana, etc.)
  uint32_t ms_ramas;    // câte ms mai durează power-up-ul meu
};

Detectare lovire cu HC-SR04

const int TRIG = 5;
const int ECHO = 18;

float distanta_cm() {
  digitalWrite(TRIG, LOW); delayMicroseconds(2);
  digitalWrite(TRIG, HIGH); delayMicroseconds(10);
  digitalWrite(TRIG, LOW);
  long durata = pulseIn(ECHO, HIGH, 30000);  // timeout 30ms
  return durata * 0.0343 / 2;   // cm
}

void verifica_lovire() {
  float d = distanta_cm();
  if (d > 0 && d < 10.0) {
    // Posibil mașină inamică
    cart_msg m = { .tip = 1, .source_id = MEU, .hp = hp_curent };
    esp_now_send(mac_inamic, (uint8_t*)&m, sizeof(m));
  }
}

Recepție și reguli PvP

void onESPNowRecv(const uint8_t* mac, const uint8_t* data, int len) {
  cart_msg* m = (cart_msg*)data;
  if (m->tip == 1) {  // m-a lovit
    if (scut_activ) {
      // Reflectez damage înapoi
      cart_msg back = { .tip = 1, .source_id = MEU, .hp = hp_curent };
      esp_now_send(mac_inamic, (uint8_t*)&back, sizeof(back));
    } else {
      hp_curent -= 10;
      flash_led_damage();
      if (hp_curent <= 0) {
        morm_temporar();  // 5s oprit pentru „respawn"
      }
    }
  }
  if (m->tip == 2) {  // inamic a activat scut
    scut_activ_inamic = true;
    sfarsit_scut_inamic = millis() + m->ms_ramas;
  }
}

Magnet — efect global

Când M1 activează magnet (trece peste tile portocaliu):

  1. M1 broadcast: „M1 has magnet, dur 3000ms”
  2. M2 primește mesajul → forțează direcția spre M1 timp de 3s, indiferent de ce trimite joystick-ul lui Darius
  3. M2 trimite înapoi „I’m pulled, can’t escape” → pe pagina de control a lui Darius apare „!! MAGNETIZAT !!”

Cod pe M2:

if (magnetizat && millis() < sfarsit_magnetizare) {
  drive_spre(POSITIE_M1);   // ignoră joystick
} else {
  drive_din_joystick();
}

Pe pagina de control — afișare HP + power-up

<div class="hp-bar">
  <div class="hp-fill" style="width: 80%"></div>
</div>
<div class="powerup">SCUT ACTIV 3.2s</div>

Pagina /sergiu/cart-k/control/ ascultă pe WebSocket de la mașina ta și afișează în plus și starea mașinii inamice (din mesajele ESP-NOW recepționate).

Reguli PvP de pornit

EvenimentEfect
Lovești inamic la <10cm fără scut-10 HP pentru el
Inamic te lovește în timp ce ai scut-10 HP pentru el (reflectat)
Ai magnet activinamicul vine spre tine 3s
Treci peste vârtej (mov)te învârti 1.5s
HP < 0„mort” temporar 5s, apoi revino cu 50 HP
Primul la 3 ture câștigăsau primul care reduce inamicul la 0 HP de 3 ori

Tu decizi regulile. Asta-i partea cea mai distractivă — fără reguli scrise în piatră de altcineva.

Pas următor

Construiește. Curse cu Darius. Schimbă regulile când se plictisesc unul dintre voi.

După lecția asta, poți

  • 2 mașini se vede una pe alta și interactionează în timp real
  • Implementezi reguli PvP simple: scut blochează damage, magnet trage mașina inamică spre tine
  • Faci propriul tău joc multi-player fără internet, doar 2 ESP32