XY Panel and Numbers

Change orientation to be a thumb controlled joystick
Feedback by providing number to user and on conductor
parent 9f4faf86
......@@ -12,7 +12,7 @@ defmodule Grains do
supervisor(Grains.Endpoint, []),
# Start your own worker by calling: Grains.Worker.start_link(arg1, arg2, arg3)
# worker(Grains.Worker, [arg1, arg2, arg3]),
worker(Grains.Concounter, [0]),
worker(Grains.CounterAgent, []),
worker(Grains.StatefulMap, []),
worker(Grains.Beat, [60]),
supervisor(Grains.Presence, []),
......
defmodule Grains.Concounter do
use GenServer
def inc(pid), do: GenServer.cast(pid, :inc)
def dec(pid), do: GenServer.cast(pid, :dec)
def val(pid) do
GenServer.call(pid, :val)
end
def start_link(initial_val) do
GenServer.start_link(__MODULE__, initial_val)
end
def init(initial_val) do
{:ok, initial_val}
end
def handle_cast(:inc, val) do
{:noreply, val + 1}
end
def handle_cast(:dec, val) do
{:noreply, val - 1}
end
def handle_call(:val, _from, val) do
{:reply, val, val}
end
end
defmodule Grains.Type do
alias Grains.{StatefulMap, CounterAgent}
@nr_types 2
@nr_colors 255
@nr_saturations 50
......@@ -8,6 +10,20 @@ defmodule Grains.Type do
Integer.mod(parse(uuid), @nr_types)
end
def select_count(uuid) do
nr = StatefulMap.get(uuid)
nr = if nr == nil do
nr = CounterAgent.click()
StatefulMap.put(uuid, nr)
nr
else
nr
end
nr
end
# returns a tuple for hue / saturation
def select_color(uuid) do
i = parse(uuid)
......
......@@ -3,7 +3,7 @@ defmodule Grains.Mixfile do
def project do
[app: :grains,
version: "0.0.87",
version: "0.0.88",
elixir: "~> 1.2",
elixirc_paths: elixirc_paths(Mix.env),
compilers: [:phoenix, :gettext] ++ Mix.compilers,
......
......@@ -6,7 +6,7 @@
"watch": "brunch watch --stdin"
},
"dependencies": {
"interface": "git://github.com/charlieroberts/interface.js.git",
"interface": "git://github.com/jcfischer/interface.js.git",
"jquery": ">= 2.1",
"osc-js": "^1.0.2",
"p5": "^0.5.8",
......
......@@ -81,8 +81,9 @@ defmodule Grains.Presence do
def fetch(_topic, entries) do
for {key, %{metas: metas}} <- entries, into: %{} do
{hue, saturation} = Type.select_color(key)
name = Type.select_count(key)
{key, %{metas: metas, type: Type.select_type(key),
hue: hue, saturation: saturation}}
hue: hue, saturation: saturation, name: name}}
end
end
......
defmodule Grains.PresenceChannel do
use Grains.Web, :channel
alias Grains.Presence
alias Grains.{Presence, CounterAgent, StatefulMap}
def join("presence:lobby", _, socket) do
send self(), :after_join
......@@ -9,15 +9,17 @@ defmodule Grains.PresenceChannel do
end
def handle_info(:after_join, socket) do
IO.puts("handle_join: #{socket.assigns.user_uuid}")
Grengine.PerformanceSupervisor.start_performance(socket.assigns.user_uuid)
user_uuid = socket.assigns.user_uuid
IO.puts("handle_join: #{user_uuid}")
Grengine.PerformanceSupervisor.start_performance(user_uuid)
Grains.Endpoint.broadcast("osc", "presence", %{user: socket.assigns.user_uuid,
Grains.Endpoint.broadcast("osc", "presence", %{user: user_uuid,
joins: true})
Presence.track(socket, socket.assigns.user_uuid, %{
online_at: :os.system_time(:milli_seconds)
Presence.track(socket, user_uuid, %{
online_at: :os.system_time(:milli_seconds),
})
push socket, "presence_state", Presence.list(socket)
{:noreply, socket}
......@@ -25,4 +27,5 @@ defmodule Grains.PresenceChannel do
end
end
......@@ -5,6 +5,7 @@ defmodule Grains.UserSocket do
## Channels
channel "slider:*", Grains.SliderChannel
channel "xy:*", Grains.XyChannel
channel "orientation:*", Grains.OrientationChannel
channel "acceleration:*", Grains.AccelerationChannel
......
......@@ -13,16 +13,18 @@ defmodule Grains.Token do
token = Phoenix.Token.sign(conn, "user socket", uuid )
type = Type.select_type(uuid)
{hue, saturation} = Type.select_color(uuid)
IO.puts "User Type: #{type}"
nr = Type.select_count(uuid)
IO.puts "User Type: #{type}, Nr: #{nr}"
conn
|> assign(:user_token, token)
|> assign(:user_type, type)
|> assign(:user_hue, hue)
|> assign(:user_name, nr)
|> assign(:user_saturation, saturation)
|> put_session(:user_uuid, uuid)
|> configure_session(renew: true)
end
end
/* This file is for your main application css. */
.interfacePanel {
display: none;
height: 300px;
display: block;
height: 450px;
width: 450px;
border: 1px solid blue;
}
.bpmPanel {
......
......@@ -8,8 +8,9 @@ import {Socket, Presence} from "phoenix";
// Boid class
// Methods for Separation, Cohesion, Alignment added
function Boid(p, x, y, type, hue, saturation) {
function Boid(p, x, y, type, hue, saturation, name) {
this.p = p;
this.name = name;
this.acceleration = this.p.createVector(0, 0);
this.velocity = p5.Vector.random2D();
this.position = this.p.createVector(x, y);
......@@ -17,7 +18,7 @@ function Boid(p, x, y, type, hue, saturation) {
this.norm_radius = 24;
this.radius = 24;
this.r_rand = 1.0;
this.maxspeed = 3; // Maximum speed
this.maxspeed = 3.2; // Maximum speed
this.maxforce = 0.05; // Maximum steering force
this.type = type;
this.separation_f = 2.0;
......@@ -33,7 +34,7 @@ function Boid(p, x, y, type, hue, saturation) {
Boid.prototype.set_velocity = function(dx, dy) {
// this.velocity = this.p.createVector(dx, dy);
let acc = this.p.createVector(dx, dy);
let acc = this.p.createVector(dy, dx);
this.applyForce(acc);
};
......@@ -96,19 +97,6 @@ Boid.prototype.seek = function(target) {
return steer;
};
// Draw boid as a circle
Boid.prototype.render = function() {
this.p.fill((this.radius * 8) - 1);
this.p.stroke(200);
this.p.push();
this.p.translate(this.position.x, this.position.y);
let factor = 1 + Math.random(0.1) - 0.1;
this.p.rotate((this.p.frameCount / -175.0 )* factor);
this.p.arc(0, 0, this.radius * factor, this.radius * factor, 0, this.p.PI + this.p.QUARTER_PI,
this.p.OPEN);
this.p.pop();
if (this.radius > this.norm_radius) { this.radius = this.radius - 1; }
};
// Wraparound
Boid.prototype.borders = function() {
......@@ -272,6 +260,7 @@ function Master(p, x, y, type) {
this.master = true;
this.radius = 48;
this.type = type;
this.maxspeed = 2.5;
this.cohesion_f = 2;
this.separation_f = 1;
this.alignment_f = 2;
......@@ -371,8 +360,14 @@ Boid.prototype.render = function(list) {
case 'star': this.render_star();
break;
default: this.render_circle();
break;
}
if (this.name) {
this.p.rotate(-this.p.frameCount / this.spin);
this.p.textSize(19).textStyle(this.p.BOLD).strokeWeight(2).stroke(200).fill(0);
this.p.text(this.name, 0, 0);
}
this.p.pop();
this.adjust_radius();
......@@ -395,7 +390,11 @@ let PresenceSketch = {
types: {0: 'circle', 1: 'square', 2: 'triangle', 3: 'star'},
set_velocity(name, dx, dy) {
PresenceSketch.boids[name].set_velocity(dx, dy);
console.log("set velocity: ", dx, dy);
let boid = PresenceSketch.boids[name];
if (boid) {
boid.set_velocity(dx, dy);
}
},
set_acceleration(name, z) {
......@@ -407,11 +406,12 @@ let PresenceSketch = {
_.each(joins, function(val, name) {
if (name) {
console.log(val);
PresenceSketch.boids[name] = new Boid(PresenceSketch.p5,
Math.random() * PresenceSketch.width,
Math.random() * PresenceSketch.height,
PresenceSketch.types[val.type],
val.hue, val.saturation);
val.hue, val.saturation, val.name);
}
});
},
......@@ -435,7 +435,7 @@ let PresenceSketch = {
Math.random() * PresenceSketch.width,
Math.random() * PresenceSketch.height,
PresenceSketch.types[p.type],
val.hue, val.saturation);
val.hue, val.saturation, val.name);
}
}
});
......
......@@ -4,31 +4,19 @@ import socket from "../socket";
import SliderPanel from "../slider";
import OrientationPanel from "../orientation";
import AccelerationPanel from "../acceleration";
import XyPanel from "../xypanel";
export default class View extends MainView {
mount() {
super.mount();
OrientationPanel.init(socket, "orientationPanel");
XyPanel.init(socket, "xyPanel");
// OrientationPanel.init(socket, "orientationPanel");
AccelerationPanel.init(socket, "accelerationPanel");
// ugly ugly, but quick and dirty and it seems to work...
setTimeout(function() {
let msg = document.getElementById('calibration');
if (msg) { msg.classList.add('end'); };
setTimeout(function() {
let msg = document.getElementById('calibration');
msg.style.display = 'none';
}, 1000);
}, 5000);
let shape = document.getElementById("shape");
let hue = window.userHue;
let saturation = window.userSaturation;
shape.setAttribute('fill', "hsl(" + hue + ', ' + saturation + '%, 80%)');
console.log("PlayerView mounted");
}
......
import Interface from "interface.js";
import _ from "underscore";
let XyPanel = {
xyChannel : null,
old_x: 0,
old_y: 0,
dot_id: 'na',
init(socket, domId) {
if (!document.getElementById(domId)) {
return;
}
let that = this;
socket.connect();
this.xyChannel = socket.channel("xy:" + domId);
this.xyChannel.join()
.receive("ok", resp => {
console.log("join xy: ", resp.dot_id);
that.dot_id = resp.dot_id;
var a = new Interface.Panel({ background:"#000", container:document.getElementById(domId) });
var xy = new Interface.XY({
childWidth: 45,
numChildren: 1,
childIds: [that.dot_id],
background:"#111",
fill: "rgba(127,127,127,.2)",
bounds:[0,0,1,1],
onvaluechange: function() {
// just send the first array entry as we only have one dot to control
that.send_value(this.values[0]);
}
});
a.background = 'black';
a.add(xy); console.log("adding xy");
// resp.values.forEach( (element) => {
// this.setSliderValue(element);
// } );
})
.receive("error", reason => console.log("join failed", reason));
console.log("adding xy");
},
send_value(values) {
let d = new Date();
if (d.getTime() % 5 == 0) {
let x = Math.round(200 * (values.x - 0.5) * 3.14) / 100;
let y = Math.round(200 * (values.y - 0.5) * 3.14) / 100;
// console.log(scaled);
let payload = {x: x,
y: y
};
console.log(payload);
this.xyChannel.push("xy", payload)
.receive("error", e => console.log(e));
}
},
};
export default XyPanel;
<h1><a href="/play/play">Play</a></h1>
<div id="calibration">
<h2>Calibrating</h2>
<p>Please move your phone left/right and forward/backward to
calibrate sensors</p>
</div>
<div id="xyPanel" class="interfacePanel"></div>
<div id="svg-container">
<%= if assigns[:user_type] == 0 do %>
<svg xmlns="http://www.w3.org/2000/svg"
version="1.1"
x="0" y="0"
viewBox="0 0 120 120"
enable-background="new 0 0 120 120"
xml:space="preserve"
>
<circle cx="0" cy="0" r="18"
transform="translate(50, 50)"
id="shape"/>
</svg>
<% end %>
<%= if assigns[:user_type] == 1 do %>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
x="0" y="0"
viewBox="0 0 120 120"
enable-background="new 0 0 120 120"
xml:space="preserve"
>
<rect x="0" y="0" width="24" height="20"
transform="translate(50, 50)"
id="shape"/>
</svg>
<% end %>
<%= if assigns[:user_type] == 2 do %>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
x="10px" y="0px"
viewBox="0 0 120 120"
enable-background="new 0 0 120 120"
xml:space="preserve"
>
<polygon x="0" y="0"
points="0,0 20,0 10,20"
transform="translate(50, 50)"
id="shape"/>
</svg>
<% end %>
<%= if assigns[:user_type] == 3 do %>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
x="0px" y="0px"
viewBox="0 0 120 120"
enable-background="new 0 0 120 120"
xml:space="preserve"
>
<polygon points="15,1.5 6,29.7 28.5,11.7 1.5,11.7 24,29.7"
transform="translate(50, 50)"
id="shape"/>
</svg>
<% end %>
</div>
<div id="orientationPanel" class="interfacePanel"></div>
<div id="accelerationPanel" class="interfacePanel"></div>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment