Skip to content

Commit

Permalink
clarify tanks example
Browse files Browse the repository at this point in the history
  • Loading branch information
jbakse committed Jan 12, 2022
1 parent 70b5760 commit 8d82445
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 42 deletions.
34 changes: 34 additions & 0 deletions public/examples/tanks/README.md
Expand Up @@ -4,3 +4,37 @@
- **space** to fire

> Open this example in two browser windows at once!
# A Common Problem

When two players try to write to the same shared object at the same time a conflict occurs. Some data is lost and its possible for things to get into a bad state. A conflict occurs even if the changes are limited to different properties of the shared object.

One common time a conflict like this happens is when the host is trying to animate some data in a shared object (like moving a bullet every frame) and another player tires to change _anything_ in the same shared object.

# More Generally

This kind of problem comes up when 1) multiple clients write to the same record and 2) the writing is frequent (typically every frame).

If only one client is writing to the shared there is no potential for conficts.

If writing is infrequent (typically event based rather than every frame), the potential for a conflict is there, but its less likely to happen and much less likely to happen repeatedly leading to a bad state.

# A Partial Solution

On way to partially work around this by having players create new bullets in their own shared object. The host then moves them over into the main shared.

This way the players don't write to shared at all, only the host does.

This partially works but...

The player writes new bullets to its own participant share + the host removes bullets from that share so they are both writing to the same share. If nothing else is going on, this is fine. The host writes to the participant shared _in response_ to the participant writing to it, so they won't write at the same time.

But, if the participant is writing something else to the shared object, and writing it frequently (like the player is turning while shooting, so lots of updates to the tank angle) we end up with the same kind of problem.

# A Little Better

This example goes a step further and uses second shared object to communicate new bullets to the host. All particpants write new bullets there, the host will remove them and add them to the main shared. Now we have multiple players and the host writing to the same record, but not rapidly. So we can still get a conflict, but its much less likely.

This is starting to look a lot like a message sending or event scheme. A real messaging system could prevent conflicts in this case.

See tanks_emit for an example that uses messages to solve this problem.
27 changes: 11 additions & 16 deletions public/examples/tanks/index.js
@@ -1,5 +1,4 @@
/* global uuidv4 */
/* global partyEmit partySubscribe*/

class Rect {
constructor(l = 0, t = 0, w = 0, h = 0) {
Expand All @@ -23,12 +22,12 @@ function pointInRect(p, r) {

const bounds = new Rect(0, 0, 400, 400);

let shared, send, me, participants;
let shared, new_bullets, me, participants;

function preload() {
partyConnect("wss://deepstream-server-1.herokuapp.com", "tanks", "main");
shared = partyLoadShared("shared");
send = partyLoadShared("send");
new_bullets = partyLoadShared("send");
me = partyLoadMyShared();
participants = partyLoadParticipantShareds();
}
Expand All @@ -40,28 +39,23 @@ function setup() {

if (partyIsHost()) {
shared.bullets = [];
send.bullets = [];
new_bullets.bullets = [];
}
me.tank = { x: 100, y: 100, a: 0 };

partySubscribe("createBullet", (d) => {
if (partyIsHost()) {
console.log("partySubscribe", d);
}
});
me.tank = { x: 100, y: 100, a: 0 };
}

function draw() {
checkKeys();
showData();
if (partyIsHost()) stepGame();
drawScene();
showData();
}

function stepGame() {
// copy sent bullets to main bullet array
while (send.bullets.length) {
shared.bullets.push(send.bullets.shift());
// move sent bullets to main bullet array
while (new_bullets.bullets.length) {
shared.bullets.push(new_bullets.bullets.shift());
}

// step bullets
Expand All @@ -75,6 +69,7 @@ function showData() {
"\t"
);
}

function drawScene() {
background("#cc6666");
shared.bullets.forEach(drawBullet);
Expand Down Expand Up @@ -110,17 +105,17 @@ function drawBullet(b) {

function keyPressed() {
if (key === " ") {
send.bullets.push({
new_bullets.bullets.push({
x: me.tank.x,
y: me.tank.y,
dX: sin(me.tank.a) * 6,
dY: -cos(me.tank.a) * 6,
});
partyEmit("createBullet", "hell yeah");
}

return false;
}

function checkKeys() {
// forward
if (keyIsDown(87) /*w*/) {
Expand Down
26 changes: 0 additions & 26 deletions public/examples/tanks/notes.md

This file was deleted.

0 comments on commit 8d82445

Please sign in to comment.