Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentes Révision précédente Prochaine révision | Révision précédente | ||
wiki:projets:crowd [2019/05/21 19:57] daphne [Code] |
wiki:projets:crowd [2020/10/05 14:39] (Version actuelle) |
||
---|---|---|---|
Ligne 2: | Ligne 2: | ||
- | **Daphné Chamot-Rooke** (contact : [[daphne.chamot-rooke@etu.upmc.fr|daphne.chamot-rooke@etu.upmc.fr]])\\ | + | |
- | **Himany Seri** (contact : [[himany.seri@etu.upmc.fr|himany.seri@etu.upmc.fr]]) | + | **Himany Seri** (contact : [[himany.seri@etu.upmc.fr|himany.seri@etu.upmc.fr]]) |
Début : Février 2019\\ | Début : Février 2019\\ | ||
Fin : mai 2019 | Fin : mai 2019 | ||
- | **Objectif :** créer un dispositif qui modifie la perception d' | + | |
- | **Matériel :** | + | |
* plusieurs PC avec souris | * plusieurs PC avec souris | ||
* une connexion internet | * une connexion internet | ||
- | * logiciel Processing installé | + | * Javascript, Node.js, P5.js |
+ | * un serveur avec node js | ||
===== Cahier des charges ===== | ===== Cahier des charges ===== | ||
Ligne 25: | Ligne 27: | ||
==== Description et évolution du projet ==== | ==== Description et évolution du projet ==== | ||
- | Nous avions d' | + | Nous avions d' |
+ | |||
+ | La deuxième idée que nous avons eue sur la foule était de créer une application qui nous permettait de cartographier la densité de personnes se trouvant à un endroit. Si dans le lieu ou l’on se trouve la densité de personnes est plus importante à droite alors les feuilles sont plus denses sur la partie droite. Chaque feuille représentait un groupe de quatre personnes, et en fonction des mouvements des gens les feuilles bougeraient. | ||
+ | |||
+ | {{: | ||
+ | |||
+ | |||
+ | Nous avons choisi de créer un programme pour ordinateur car sur smartphone se posait un problème : le joueur joue avec son doigt et de ce fait ne rencontre aucun obstacle. Il peut très bien passer par-dessus un autre joueur pour le devancer. Le professeur Charles Lenay nous a alors fait remarquer qu’il était difficile voire impossible de créer des obstructions alors qu’avec une souris cela était possible. Nous avons alors choisi de créer un programme pour ordinateur, | ||
Notre jeu se compose d'un avatar représentant soi-même à la 3e personne, vu du dessus. Un " | Notre jeu se compose d'un avatar représentant soi-même à la 3e personne, vu du dessus. Un " | ||
Nous voulons faire plusieurs " | Nous voulons faire plusieurs " | ||
+ | |||
+ | {{: | ||
+ | |||
==== Expression fonctionnelle du besoin ==== | ==== Expression fonctionnelle du besoin ==== | ||
Ligne 42: | Ligne 54: | ||
==== Veille des dispositifs ==== | ==== Veille des dispositifs ==== | ||
+ | |||
+ | Il existe de nombreux programmes pour simuler l' | ||
+ | * la cohésion : pour former un groupe, les boids se rapprochent les uns des autres ; | ||
+ | * la séparation : deux boids ne peuvent pas se trouver au même endroit au même moment ; | ||
+ | * l' | ||
+ | |||
+ | {{: | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | Dans le même genre, il y a par exemple la synchronisation des lucioles. | ||
+ | |||
+ | {{: | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | Humanity est un jeu imaginé par le collectif japonais Tha Ltd, il s’agit d’un jeu de réflexion à mi-chemin entre la simulation de foule et l’expérience SF qui met en scène une foule aveugle qui fonce droit devant sans s’arrêter. Chaque niveau comporte des obstacles, des pièges, et autres difficultés. Le but est de sauver le plus d’êtres humains possible à chaque niveau. | ||
+ | Pour le moment, on sait simplement qu’" | ||
+ | |||
+ | {{: | ||
+ | |||
+ | Liens pour voir le jeu : | ||
+ | [[http:// | ||
+ | [[http:// | ||
+ | |||
+ | Crowd city\\ | ||
+ | Le but du jeu est de vous déplacer pour recruter de nouveaux membres et former une foule. Lorsque vous croisez un autre joueur, si vous avez plus de bonhommes que lui, foncez-lui dessus. Sinon, fuyez. | ||
+ | |||
+ | {{: | ||
+ | |||
+ | Source : [[https:// | ||
+ | |||
+ | |||
==== Veille graphique ==== | ==== Veille graphique ==== | ||
Ligne 59: | Ligne 104: | ||
{{: | {{: | ||
+ | ===== Posters ===== | ||
+ | |||
+ | {{: | ||
+ | {{: | ||
+ | {{: | ||
===== Réalisation ===== | ===== Réalisation ===== | ||
+ | ==== Aspects techniques ==== | ||
+ | |||
+ | Nous avons installé [[https:// | ||
+ | On suit ensuite les instructions de [[https:// | ||
+ | Nous avons été confrontées à plusieurs problèmes. En effet, nous avions commencé à coder en Java sur Processing, mais cela ne permet pas de créer un code multijoueur en ligne. Nous devions donc réecrire ce code en javascript en utilisant [[https:// | ||
+ | C'est par les limites de notre savoir informatique que nous avons simplifié au maximum notre jeu mais les bases sont posées pour complexifier le principe. | ||
==== Code ==== | ==== Code ==== | ||
Ligne 68: | Ligne 124: | ||
//this code is based on https:// | //this code is based on https:// | ||
- | var blobs = []; //liste pour stocker les blobs | + | var blobs = []; //liste pour stocker les blobs |
- | function Blob(id, x, y) { //définit l' | + | function Blob(id, x, y, vx, vy) { |
+ | | ||
this.id = id; | this.id = id; | ||
this.x = x; | this.x = x; | ||
this.y = y; | this.y = y; | ||
+ | this.vx = vx; | ||
+ | this.vy = vy; | ||
} | } | ||
- | var monstres = []; //liste pour stocker les monstres | + | var monstres = []; //liste pour stocker les monstres |
- | function Monster (xm, ym) { //définit l' | + | function Monster(xm, ym) { |
- | this.xm = xm; | + | |
- | this.ym = ym; | + | this.xm = xm; |
- | + | this.ym = ym; | |
} | } | ||
// Using express: http:// | // Using express: http:// | ||
- | var express = require('express'); | + | var express = require("express"); |
// Create the app | // Create the app | ||
var app = express(); | var app = express(); | ||
Ligne 97: | Ligne 156: | ||
var host = server.address().address; | var host = server.address().address; | ||
var port = server.address().port; | var port = server.address().port; | ||
- | console.log('Example app listening at http://' | + | console.log("Example app listening at http://" |
} | } | ||
- | app.use(express.static('public')); | + | app.use(express.static("public")); |
// WebSocket Portion | // WebSocket Portion | ||
// WebSockets work with the HTTP server | // WebSockets work with the HTTP server | ||
- | var io = require('socket.io')(server); | + | var io = require("socket.io")(server); |
setInterval(heartbeat, | setInterval(heartbeat, | ||
function heartbeat() { | function heartbeat() { | ||
- | io.sockets.emit('heartbeat_blobs', blobs); | + | |
- | io.sockets.emit('heartbeat_monstre', monstres); | + | io.sockets.emit("heartbeat_monstre", monstres); |
} | } | ||
- | |||
// Register a callback function to run when we have an individual connection | // Register a callback function to run when we have an individual connection | ||
// This is run for each individual user that connects | // This is run for each individual user that connects | ||
- | io.sockets.on('connection', | + | io.sockets.on( |
+ | "connection", | ||
// We are given a websocket object in our function | // We are given a websocket object in our function | ||
function(socket) { | function(socket) { | ||
- | |||
console.log(" | console.log(" | ||
- | socket.on('start_blobs', | + | socket.on("start_blobs", function(data) { |
- | | + | console.log(socket.id + " " + data.x + " " + data.y); |
- | console.log(socket.id + " " + data.x + " " + data.y); | + | socket.broadcast.emit("start_blobs", data); |
- | socket.broadcast.emit('start_blobs', data); | + | var blob = new Blob(socket.id, |
- | var blob = new Blob(socket.id, | + | blobs.push(blob); |
- | blobs.push(blob); | + | }); |
- | } | + | |
- | ); | + | |
- | + | ||
- | socket.on(' | + | |
- | function(datam) { | + | |
- | console.log(datam.xm + " " + datam.ym); | + | |
- | socket.broadcast.emit(' | + | |
- | var monstre = new Monster(datam.xm, | + | |
- | | + | |
- | | + | |
- | ); | + | |
- | socket.on(' | + | socket.on(" |
- | function(data) { | + | |
- | // | + | socket.broadcast.emit(" |
- | for (var i = 0; i < blobs.length; | + | var monstre = new Monster(datam.xm, |
- | if (socket.id == blobs[i].id) { | + | monstres.push(monstre); |
- | // | + | }); |
- | blobs[i].x = data.x; | + | |
- | blobs[i].y = data.y; | + | socket.on(" |
- | } | + | // |
- | } | + | for (var i = 0; i < blobs.length; |
+ | if (socket.id == blobs[i].id) { | ||
+ | // | ||
+ | blobs[i].x = data.x; | ||
+ | blobs[i].y = data.y; | ||
+ | } | ||
} | } | ||
- | ); | + | |
- | + | ||
- | socket.on(' | + | socket.on(" |
- | | + | // |
- | // | + | for (var i = 0; i < blobs.length; i++) { |
- | for (var i = 0; i < monstres.length; i++) { | + | if (socket.id == blobs[i].id) { |
- | monstres[i].xm = datam.xm; | + | // |
- | monstres[i].ym = datam.ym; | + | blobs[i].vx |
- | } | + | blobs[i].vy = data.vy; |
+ | } | ||
} | } | ||
- | ); | + | |
- | + | ||
- | socket.on(' | + | |
- | // remove the eaten blob | + | |
- | // set array of blobs excluding the eaten blob | + | |
- | var eaten = { | + | socket.on(" |
- | id: '' | + | // |
- | }; | + | for (var i = 0; i < monstres.length; i++) { |
- | + | | |
- | var newblob = blobs.filter(function( | + | |
- | | + | |
- | eaten.id = blobs.id; | + | }); |
- | } | + | |
- | return blobs.id !== data.eatenId; | + | socket.on(" |
- | }); | + | // remove the eaten blob |
- | blobs = newblob; | + | // set array of blobs excluding the eaten blob |
- | | + | var eaten = { |
- | }); | + | id: "" |
- | | + | }; |
- | socket.on('disconnect', function() { | + | |
- | console.log(" | + | var newblob = blobs.filter(function(blobs) { |
- | blobs = blobs.filter(function( blobs ) { | + | if (blobs.id === data.eatenId) { |
- | return blobs.id !== socket.id; | + | eaten.id = blobs.id; |
- | }); | + | } |
- | }); | + | |
- | } | + | return blobs.id !== data.eatenId; |
+ | }); | ||
+ | blobs = newblob; | ||
+ | |||
+ | | ||
+ | }); | ||
+ | |||
+ | socket.on("disconnect", function() { | ||
+ | console.log(" | ||
+ | blobs = blobs.filter(function(blobs) { | ||
+ | return blobs.id !== socket.id; | ||
+ | }); | ||
+ | }); | ||
+ | } | ||
); | ); | ||
Ligne 200: | Ligne 260: | ||
// | // | ||
var socket; | var socket; | ||
- | var blob; | + | var blob; // |
- | var blobs = []; //liste de blobs | + | var blobs = []; //liste de blobs |
- | var monstres = []; | + | var monstres = []; //liste de monstres |
- | var monstre; | + | var monstre; //monstre |
- | var timer; //bool pour le timer | + | var timer; //bool pour le timer |
- | var jeu = false; | + | var jeu = false; //bool pour le jeu |
- | var intro = true; | + | var intro = true; //bool pour l' |
- | const radius = 30; | + | const radius = 30; //rayon du monstre |
var alive = true; | var alive = true; | ||
+ | let spring = 0.05; | ||
function setup() { | function setup() { | ||
- | + | | |
- | | + | if (alive) { |
- | if (alive) { | + | socket = io.connect("http:// |
- | socket = io.connect('http:// | + | } |
- | } | + | |
- | + | //nouveaux blob, monstre et timer | |
- | //nouveaux blob, monstre et timer | + | timer = new Timer(); |
- | timer = new Timer(); | + | blob = new Blob(random(width), |
- | blob = new Blob(random(width), | + | monstre = new Monster(random(width), |
- | monstre = new Monster(random(width), | + | |
- | + | //data pour la position du blob | |
- | //data pour la position du blob | + | var data = { |
- | var data = { | + | x: blob.pos.x, |
- | x: blob.pos.x, | + | y: blob.pos.y, |
- | y: blob.pos.y, | + | vx: blob.vel.x, |
- | }; | + | vy: blob.vel.y |
- | + | | |
- | //data pour la position du monstre | + | |
- | var datam = { | + | //data pour la position du monstre |
- | xm: monstre.pos.x, | + | var datam = { |
- | ym: monstre.pos.y, | + | xm: monstre.pos.x, |
- | }; | + | ym: monstre.pos.y |
+ | }; | ||
+ | |||
+ | socket.emit(" | ||
+ | | ||
+ | alive = true; | ||
+ | |||
+ | socket.on(" | ||
+ | var stillAlive = false; | ||
+ | for (var i = 0; i < data.length; | ||
+ | if (socket.id == data[i].id) { | ||
+ | stillAlive = true; | ||
+ | | ||
+ | } | ||
+ | alive = stillAlive; | ||
+ | blobs = data; | ||
+ | }); | ||
- | socket.emit(' | + | |
- | socket.emit(' | + | monstres = datam; |
- | alive = true; | + | }); |
- | + | ||
- | socket.on(' | + | |
- | function(data) { | + | |
- | var stillAlive = false; | + | |
- | for (var i = 0; i < data.length; | + | |
- | if (socket.id == data[i].id) { | + | |
- | stillAlive = true; | + | |
- | // | + | |
- | } | + | |
- | } | + | |
- | // | + | |
- | alive = stillAlive; | + | |
- | blobs = data; | + | |
- | }); | + | |
- | + | ||
- | socket.on(' | + | |
- | function(datam) { | + | |
- | monstres = datam; | + | |
- | }); | + | |
} | } | ||
function draw() { | function draw() { | ||
- | | + | |
- | textSize(30); | + | textSize(30); |
- | fill(255); | + | fill(255); |
- | a=timer.minute(); | + | a = timer.minute(); |
- | b=timer.second(); | + | b = timer.second(); |
- | temps = a + ":" | + | temps = a + ":" |
- | + | ||
- | if (socket.connected && alive && jeu) { | + | if (socket.connected && alive && jeu) { |
- | timer.stop(); | + | timer.stop(); |
- | // if (isNaN(blob.pos.x) || isNaN(blob.pos.y)) { | + | blob.show(); |
- | // alive = false; | + | blob.update(); |
- | // } | + | monstre.deflect(); |
- | blob.show(); | + | monstre.move(); |
- | // | + | score = temps; |
- | // | + | text(temps, width / 2 - 40, 50); //affiche le temps en haut de l' |
- | //} | + | |
- | blob.update(); | + | |
- | monstre.deflect(); | + | |
- | monstre.move(); | + | |
- | for (var i = blobs.length - 1; i >=0; i--) { | + | |
- | if (socket.id !== blobs[i].id) { | + | |
- | fill(255); | + | |
- | circle(blobs[i].x, | + | |
- | } else { | + | |
- | var newblob = new Blob(blobs[i].x, | + | |
- | if (mange(newblob)) { | + | |
- | var data = { | + | |
- | eatenId: | + | |
- | }; | + | |
- | socket.emit(' | + | |
- | } | + | |
- | } | + | |
- | } | + | |
- | + | ||
- | for (var i = monstres.length - 1; i >=0; i--) { | + | |
- | fill(blob.c); | + | |
- | // | + | |
- | circle(monstres[i].xm, | + | |
- | } | + | |
- | + | ||
- | + | ||
- | //jeu = mange(blob); | + | |
- | score = temps; | + | |
- | text(temps, width/2 - 40, 50); //affiche le temps en haut de l' | + | |
- | var data = { | + | |
- | x: blob.pos.x, | + | |
- | y: blob.pos.y, | + | |
- | }; | + | |
- | var datam = { | + | for (var i = blobs.length - 1; i >= 0; i--) { |
- | xm: monstre.pos.x, | + | blob.collide(blobs[i]); |
- | ym: monstre.pos.y, | + | if (socket.id |
- | }; | + | |
- | + | ||
- | socket.emit(' | + | |
- | socket.emit(' | + | |
- | + | ||
- | } if (!jeu) { | + | |
- | timer.start(); | + | |
fill(255); | fill(255); | ||
stroke(255); | stroke(255); | ||
- | | + | |
- | + | } else { | |
- | | + | |
- | //si c'est l' | + | |
- | text(" | + | var data = { |
- | text(" | + | |
- | } else { | + | }; |
- | | + | |
- | | + | |
- | text("Score : " | + | |
- | text(" | + | |
} | } | ||
+ | } | ||
} | } | ||
- | } | ||
- | function reset() { // | + | for (var i = monstres.length - 1; i >= 0; i--) { |
- | console.log(' | + | |
- | | + | |
- | stillAlive=true; | + | |
- | jeu = true; | + | } |
- | | + | |
- | | + | var data = { |
- | timer.stop(); // | + | x: blob.pos.x, |
- | } | + | y: blob.pos.y, |
+ | vx: blob.vel.x, | ||
+ | vy: blob.vel.y | ||
+ | }; | ||
+ | |||
+ | | ||
+ | xm: monstre.pos.x, | ||
+ | ym: monstre.pos.y | ||
+ | }; | ||
+ | |||
+ | socket.emit(" | ||
+ | | ||
+ | socket.emit(" | ||
+ | } | ||
+ | if (!jeu) { | ||
+ | timer.start(); | ||
+ | | ||
+ | stroke(255); | ||
+ | textSize(50); | ||
- | function mousePressed() { | + | if (intro) { |
- | | + | |
- | alive = true; | + | |
- | | + | |
- | reset(); | + | |
+ | //si c'est la fin du jeu : Game Over et le temps final s' | ||
+ | text(" | ||
+ | text("Score : " + score, width / 2 - 150, height / 2); | ||
+ | text(" | ||
} | } | ||
+ | } | ||
} | } | ||
+ | function reset() { | ||
+ | //quand c'est la fin du jeu, permet de redémarrer une partie juste en cliquant | ||
+ | console.log(" | ||
+ | alive = true; | ||
+ | stillAlive = true; | ||
+ | jeu = true; | ||
+ | timer.stop(); | ||
+ | } | ||
+ | function mousePressed() { | ||
+ | //on passe l' | ||
+ | intro = false; | ||
+ | alive = true; | ||
+ | if (jeu == false) { | ||
+ | reset(); | ||
+ | } | ||
+ | } | ||
- | // Classe Blob | + | //Classe Blob |
class Blob { | class Blob { | ||
- | constructor(x, | + | |
- | this.pos = createVector(x, | + | this.pos = createVector(x, |
- | this.vel = createVector(0, | + | this.vel = createVector(0, |
- | this.acc = createVector(0, | + | this.acc = createVector(0, |
- | this.topspeed = 2; | + | this.topspeed = 2; |
- | this.r = 20; | + | this.r = 20; |
- | this.c = color(int (50 + Math.random() * (220 - 50)), int (50 + Math.random() * (220 - 50)), int (50 + Math.random() * (220 - 50))); | + | this.c = color( |
- | | + | |
- | } | + | |
- | | + | |
- | | + | |
- | this.acc.add(this.mouse); | + | //couleur ni trop sombre ni trop claire |
- | this.acc.sub(this.pos); | + | } |
- | this.acc.setMag(0.2); | + | |
- | this.vel.add(this.acc); | + | collide(other) { |
- | this.mouse.sub(this.pos); | + | let dx = other.x - this.pos.x; |
- | this.mouse.setMag(7); | + | let dy = other.y - this.pos.y; |
- | this.pos.add(this.mouse); | + | let distance |
- | this.vel.limit(this.topspeed); | + | |
- | this.pos.add(this.vel); | + | |
- | this.pos.x=Math.min(this.pos.x,width-10); //gestion des coins de la boite | + | |
- | | + | |
- | this.pos.y=Math.min(this.pos.y,height-10); | + | |
- | | + | |
+ | if (distance < this.r / 2) { | ||
+ | let angle = atan2(dy, dx); | ||
+ | let targetX = this.pos.x + (cos(angle) * this.r) / 2; | ||
+ | let targetY = this.pos.y + (sin(angle) * this.r) / 2; | ||
+ | let ax = (targetX - other.x) * spring; | ||
+ | let ay = (targetY - other.y) * spring; | ||
+ | this.vel.x -= ax; | ||
+ | this.vel.y -= ay; | ||
+ | other.vx += ax; | ||
+ | other.vy += ay; | ||
} | } | ||
- | + | | |
- | show () { //dessine le blob | + | |
- | fill(this.c); | + | |
- | stroke(this.c); | + | |
- | circle(this.pos.x, | + | |
- | } | + | |
- | } | + | |
- | // | + | update() { |
+ | this.mouse = createVector(mouseX, | ||
+ | this.acc.add(this.mouse); | ||
+ | this.acc.sub(this.pos); | ||
+ | this.acc.setMag(0.2); | ||
+ | this.vel.add(this.acc); | ||
+ | this.mouse.sub(this.pos); | ||
+ | this.mouse.setMag(7); | ||
+ | this.pos.add(this.mouse); | ||
+ | this.vel.limit(this.topspeed); | ||
+ | this.pos.add(this.vel); | ||
+ | this.pos.x = Math.min(this.pos.x, | ||
+ | this.pos.x = Math.max(this.pos.x, | ||
+ | this.pos.y = Math.min(this.pos.y, | ||
+ | this.pos.y = Math.max(this.pos.y, | ||
+ | } | ||
+ | show() { | ||
+ | //dessine le blob | ||
+ | fill(this.c); | ||
+ | stroke(this.c); | ||
+ | circle(this.pos.x, | ||
+ | } | ||
+ | } | ||
+ | |||
+ | //Classe Monster | ||
class Monster { | class Monster { | ||
- | | + | |
- | this.pos = createVector(x, | + | this.pos = createVector(x, |
- | this.vel = createVector(random(2, | + | this.vel = createVector(random(2, |
- | if (int(random(0, | + | if (int(random(0, |
- | this.vel.x *= -1; | + | this.vel.x *= -1; |
- | } | + | |
- | if (int(random(0, | + | |
- | this.vel.y *= -1; | + | |
- | } | + | |
} | } | ||
- | + | | |
- | + | this.vel.y *= -1; | |
- | + | ||
- | move () { //permet au monstre de bouger (à vitesse constante si epsi=0,0) | + | |
- | this.epsi = createVector(random(-1, | + | |
- | this.vel.add(this.epsi); | + | |
- | this.pos.add(this.vel); | + | |
- | if(b%5==0) { | + | |
- | this.vel = createVector(random(2, | + | |
- | if (int(random(0, | + | |
- | this.vel.x *= -1; | + | |
- | } | + | |
- | if (int(random(0, | + | |
- | this.vel.y *= -1; | + | |
- | } | + | |
- | } | + | |
} | } | ||
+ | } | ||
- | / | + | move() { |
- | | + | |
- | | + | |
- | | + | |
- | | + | this.pos.add(this.vel); |
- | + | | |
- | deflect | + | this.vel = createVector(random(2, 4), random(2, 4)); |
- | if (this.pos.x + radius > width || this.pos.x - radius < 0) { | + | if (int(random(0, 2)) == 1) { |
this.vel.x *= -1; | this.vel.x *= -1; | ||
- | } | + | |
- | if (this.pos.y + radius > height || this.pos.y - radius < 0) { | + | if (int(random(0, |
- | this.vel.y *= -1; | + | this.vel.y *= -1; |
- | } | + | } |
+ | } | ||
+ | } | ||
+ | |||
+ | //permet au monstre de ne pas sortir des bords, il " | ||
+ | deflect() { | ||
+ | if (this.pos.x + radius > width || this.pos.x - radius < 0) { | ||
+ | this.vel.x *= -1; | ||
+ | } | ||
+ | | ||
+ | this.vel.y *= -1; | ||
} | } | ||
- | + | } | |
} | } | ||
- | mange = function(blob) { //le monstre " | + | //le monstre " |
- | if (this.blob.pos.x <= monstre.pos.x + radius && this.blob.pos.x >= monstre.pos.x - radius && this.blob.pos.y <= monstre.pos.y + radius && this.blob.pos.y >= monstre.pos.y - radius) { | + | mange = function(blob) { |
- | jeu = false; | + | if ( |
- | return true; | + | |
- | } | + | |
- | return false; | + | |
- | } | + | |
+ | | ||
+ | jeu = false; | ||
+ | return true; | ||
+ | } | ||
+ | return false; | ||
+ | }; | ||
+ | //Classe Timer | ||
+ | class Timer { | ||
+ | constructor() { | ||
+ | this.startTime = 0; | ||
+ | this.stopTime = 0; | ||
+ | this.running = false; | ||
+ | } | ||
+ | start() { | ||
+ | this.startTime = new Date(); | ||
+ | this.running = true; | ||
+ | } | ||
- | // Classe Timer | + | stop() { |
+ | this.stopTime = new Date(); | ||
+ | this.running = false; | ||
+ | } | ||
- | class Timer { | + | getElapsedTime() |
- | | + | |
- | this.startTime | + | this.elapsed |
- | | + | } else { |
- | this.running | + | |
} | } | ||
- | + | | |
- | | + | } |
- | this.startTime | + | |
- | this.running | + | second() { |
+ | this.sec = int((this.getElapsedTime() / 1000) % 60); | ||
+ | if (this.sec < 10) { | ||
+ | this.sec | ||
+ | } else { | ||
+ | this.sec = "" | ||
} | } | ||
- | | + | return this.sec; |
- | stop () { | + | } |
- | this.stopTime = new Date(); | + | |
- | this.running = false; | + | minute() { |
- | } | + | this.min = int((this.getElapsedTime() / (1000 * 60)) % 60); |
- | + | if (this.min < 10) { | |
- | getElapsedTime () { | + | this.min = " |
- | if (this.running) { | + | } else { |
- | this.elapsed = (new Date() - this.startTime); | + | this.min = "" |
- | } else { | + | |
- | this.elapsed = (this.stopTime - this.startTime); | + | |
- | } | + | |
- | | + | |
- | } | + | |
- | + | ||
- | second () { | + | |
- | | + | |
- | if (this.sec< | + | |
- | this.sec=" | + | |
- | | + | |
- | | + | |
- | } | + | |
- | return this.sec; | + | |
- | } | + | |
- | + | ||
- | | + | |
- | this.min = int ((this.getElapsedTime() / (1000*60)) % 60); | + | |
- | if (this.min< | + | |
- | this.min=" | + | |
- | } else { | + | |
- | this.min="" | + | |
- | } | + | |
- | return | + | |
} | } | ||
+ | return this.min; | ||
+ | } | ||
} | } | ||
+ | |||
</ | </ | ||
Ligne 516: | Ligne 588: | ||
</ | </ | ||
</ | </ | ||
+ | ===== Expérimentation ===== | ||
+ | |||
+ | Nous avons testé notre [[http:// | ||
+ | |||
+ | Nous avons rencontré certains problèmes, l’application buggue sur certains ordinateurs et smartphones et les utilisateurs sont obligés de rafraîchir la page de ce fait ils n’ont pas pu jouer correctement. | ||
+ | |||
+ | Une seconde remarque nous a été faite : le manque d’explications (car ils n’avaient pas les posters devant eux). Pour résoudre ce problème nous avons décidé de rajouter un texte expliquant plus en détails ce que doivent faire les joueurs et pourquoi ils ont perdu. | ||
+ | |||
+ | Certains joueurs se cachent dans les recoins pour éviter de se faire manger par le monstre on a alors l’impression que les chances de survies sont plus importantes aux niveaux des bords. Pour résoudre ce problème on voudrait ajouter des interdictions ou des complications au niveau des coins. | ||
+ | Toutefois le monstre a déjà un mouvement imprévisible et une vitesse qui varie, ce qui rend le jeu plus difficile. | ||
+ | |||
+ | Notre dernier problème et que nous n' | ||
+ | |||
+ | L’idée de rajouter des recoins dans l’aire du jeu nous a été suggérée, néanmoins après ce premier test nous trouvons que notre jeu remplit assez bien nos attentes. | ||
+ | |||
+ | Nous avons filmé une partie : on observe effectivement quelques joueurs dans les recoins, et sinon des mouvements de poursuite et d' | ||
+ | |||
+ | {{ : | ||
+ | |||
+ | === Idées de développement === | ||
+ | |||
+ | Pour améliorer notre projet nous aurions pu rajouter des recoins pour permettre aux joueurs de se cacher. Cependant, cela n’aurait pas permis de voir la foule en mouvement car on aurait observé un amas derrière un mur. De plus, le cercle ayant la possibilité de passer à proximité, les individus ont autant de chances de se faire manger que s’il n’y avait pas d’obstacles. Coder les obstacles est difficile : les faire apparaître est simple mais interdire au monstre de s’en approcher et permettre aux joueurs de se cacher est plus difficile. Combien de joueurs peuvent se cacher derrière ? Il suffit que quelqu’un s'y cache dès le début de la partie et décide de ne pas bouger pour gagner (dans l' | ||
+ | |||
+ | Nous aurions aimé allez plus loin et créer différents univers de salles ou du moins changer quelques paramètres afin de voir si le comportement des gens change en fonction des circonstances. Observons-nous la même chose si le but est de survivre ou si c'est de faire une chorégraphie | ||
+ | |||
+ | Pour voir l’incidence du monstre nous pensons réaliser une partie avec le monstre visible cette fois-ci. | ||
+ | |||
+ | |||
+ | |||
+ | === Problèmes rencontrés === | ||
+ | |||
+ | Il a été compliqué de créer une interface permettant à tous les joueurs de jouer simultanément. De plus la vitesse des joueurs dépend de leur machine et les monstres ne semblent pas totalement synchronisés. Impossible de faire rebondir les blobs entre eux. | ||
+ | |||
===== Mémoire ===== | ===== Mémoire ===== | ||
- | {{ : | + | {{ : |