balldrop

This example shows a simple physics simulation. It uses partyIsHost() to make sure only one client runs the simulation at a time. The last click is stored in the shared record named shared. The position of the bouncing ball is stored in a second shared record named host. Having only one client—the host—write to the frequently updated shared record prevents write conflicts.

p5.party is better suited to slower paced games and apps, but this app shows what is possible if you push it a bit.

Try this example in two browser windows at once!

index.js

let host;
let shared;

function preload() {
  partyConnect("wss://demoserver.p5party.org", "ball_drop");
  shared = partyLoadShared("shared");
  host = partyLoadShared("host");
}

function setup() {
  createCanvas(400, 400);
  noStroke();

  // set initial values
  if (partyIsHost()) {
    host.ball = {
      x: width * 0.5,
      y: 0,
      dX: 0,
      dY: 0,
    };
    shared.click = {
      x: width * 0.51,
      y: height * 0.5,
    };
  }
}

function draw() {
  background("#660066");
  noStroke();

  if (partyIsHost()) {
    fill(255);
    textSize(20);
    textFont("Courier New");
    text("Hosting!", 10, 30);
  }

  // read shared data
  if (partyIsHost()) {
    // apply momentum
    host.ball.x += host.ball.dX;
    host.ball.y += host.ball.dY;

    // apply gravity
    host.ball.dY += 0.6;

    // respawn
    if (host.ball.y > height + 50) {
      host.ball = {
        x: width * 0.5,
        y: -50,
        dX: 0,
        dY: 0,
      };
    }

    // handle collisions
    if (dist(host.ball.x, host.ball.y, shared.click.x, shared.click.y) < 40) {
      // move out of penetration
      const collision_vector = createVector(
        host.ball.x - shared.click.x,
        host.ball.y - shared.click.y
      );
      collision_vector.normalize();
      host.ball.x = shared.click.x + collision_vector.x * 40;
      host.ball.y = shared.click.y + collision_vector.y * 40;

      // bounce
      const velocityVector = createVector(host.ball.dX, host.ball.dY);
      velocityVector.reflect(collision_vector);
      velocityVector.mult(0.5);
      host.ball.dX = velocityVector.x;
      host.ball.dY = velocityVector.y;
    }
  }

  // draw
  fill("white");
  ellipse(host.ball.x, host.ball.y, 40, 40);

  fill("#66ff66");
  ellipse(shared.click.x, shared.click.y, 40, 40);
}

function mousePressed(e) {
  // write shared data
  shared.click.x = mouseX;
  shared.click.y = mouseY;
}

index.html

<!DOCTYPE html>
<html>
  <head> </head>
  <body>
    <main></main>

    <div id="readme"></div>

    <h2>index.js</h2>
    <div id="source-javascript"></div>

    <h2>index.html</h2>
    <div id="source-html"></div>

    <script src="https://cdn.jsdelivr.net/npm/p5@1.4.1/lib/p5.js"></script>
    <script src="/dist/p5.party.js"></script>
    <script src="index.js"></script>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.0.3/highlight.min.js"></script>
    <link rel="stylesheet" href="/examples.css" />
    <script src="/examples.js" type="module"></script>
  </body>
</html>