commit
7cea49d309
15 changed files with 647 additions and 0 deletions
@ -0,0 +1,2 @@ |
||||
.idea |
||||
|
@ -0,0 +1,6 @@ |
||||
{ |
||||
"display_name": "Lissajous curve", |
||||
"info_text": "Live rendering of a graph of a system of parametric equations.", |
||||
"visible": true, |
||||
"tags": ["Simulation", "Maths"] |
||||
} |
After Width: | Height: | Size: 318 B |
@ -0,0 +1,59 @@ |
||||
class Curve{ |
||||
|
||||
constructor(x, y){ |
||||
this.x = size / 2 + (x + 1) * size; |
||||
this.y = size / 2 + (y + 1) * size; |
||||
this.vertices = []; |
||||
this.color = Curve.getColor(x + 1, y + 1); |
||||
this.image = createGraphics(size, size); |
||||
this.image.clear(); |
||||
this.image.strokeWeight(1); |
||||
this.image.stroke(this.color); |
||||
} |
||||
|
||||
static getColor(x, y){ |
||||
let div = x / y; |
||||
if (div > 1) div = y / x; |
||||
colorMode(HSB); |
||||
let c = color(div * 360, 100, 100); |
||||
colorMode(RGB); |
||||
return c; |
||||
} |
||||
|
||||
update(xi, yi){ |
||||
let x = size / 2 + sin(angle * (xi + 1)) * radius; |
||||
let y = size / 2 - cos(angle * (yi + 1)) * radius; |
||||
this.addPoint(x, y); |
||||
} |
||||
|
||||
addPoint(x, y){ |
||||
let v1 = this.vertices[this.vertices.length - 1]; |
||||
let x1 = x; |
||||
let y1 = y; |
||||
if (v1){ |
||||
x1 = v1.x; |
||||
y1 = v1.y; |
||||
} |
||||
this.vertices.push({x: x, y: y}); |
||||
|
||||
this.image.line(x1, y1, x, y); |
||||
} |
||||
|
||||
reset(){ |
||||
this.vertices = []; |
||||
this.image.clear(); |
||||
} |
||||
|
||||
show(){ |
||||
image(this.image, this.x, this.y); |
||||
|
||||
translate(this.x, this.y); |
||||
stroke(200); |
||||
strokeWeight(10); |
||||
let v = this.vertices[this.vertices.length - 1]; |
||||
if (v) |
||||
point(v.x - size / 2, v.y - size / 2); |
||||
translate(-this.x, -this.y); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,25 @@ |
||||
'use strict';
|
||||
|
||||
function keyPressed(){
|
||||
|
||||
} |
||||
|
||||
function keyReleased(){ |
||||
|
||||
} |
||||
|
||||
function mouseMoved(){ |
||||
|
||||
} |
||||
|
||||
function mouseDragged(){ |
||||
|
||||
} |
||||
|
||||
function mousePressed(){ |
||||
|
||||
} |
||||
|
||||
function mouseReleased(){ |
||||
|
||||
} |
@ -0,0 +1,212 @@ |
||||
'use strict'; |
||||
|
||||
let projectName = "lissajous_curve"; |
||||
|
||||
let debug = false, |
||||
viewPort = {x: 0, y: 0}, |
||||
font, |
||||
settings, |
||||
loader; |
||||
|
||||
//Only for online games
|
||||
let socket; |
||||
|
||||
let rows, |
||||
cols, |
||||
angle = 0, |
||||
vel, |
||||
size, |
||||
radius, |
||||
curves; |
||||
|
||||
function preload(){ |
||||
loadJSON('data/settings/libraries.json', json => loadScripts(json)); |
||||
loadJSON('data/settings/settings.json', json => settings = json); |
||||
loadFont('data/styles/font.ttf', f => font = f); |
||||
} |
||||
|
||||
function setup(){ |
||||
interfaceSetup(); |
||||
canvasSetup(); |
||||
updateValues(); |
||||
updateInterface(); |
||||
} |
||||
|
||||
function draw(){ |
||||
|
||||
background(10); |
||||
|
||||
updateLissajous(); |
||||
showLissajous(); |
||||
|
||||
if (loader){ |
||||
loader.update(); |
||||
loader.display(); |
||||
} |
||||
|
||||
if (debug) debugInformation(); |
||||
} |
||||
|
||||
function updateLissajous(){ |
||||
angle += vel; |
||||
if (angle > TWO_PI){ |
||||
angle = 0; |
||||
for (let cr of curves){ |
||||
for (let cc of cr){ |
||||
cc.reset(); |
||||
} |
||||
} |
||||
} |
||||
for (let x = 0; x < cols; x++){ |
||||
for (let y = 0; y < rows; y++){ |
||||
curves[x][y].update(x, y); |
||||
} |
||||
} |
||||
} |
||||
|
||||
function showLissajous(){ |
||||
showGrid(); |
||||
showCircles(); |
||||
showPoints(); |
||||
showMovingGrid(); |
||||
showCurves(); |
||||
} |
||||
|
||||
function showGrid(){ |
||||
stroke('rgba(255, 255, 255, 0.1)'); |
||||
strokeWeight(1); |
||||
for (let i = 1; i <= cols + 1; i++){ |
||||
line(i * size, 0, i * size, size * (rows + 1));
|
||||
} |
||||
for (let i = 1; i <= rows + 1; i++){ |
||||
line(0, i * size, size * (cols + 1), i * size); |
||||
} |
||||
} |
||||
|
||||
function showCircles(){ |
||||
noFill(); |
||||
stroke(200); |
||||
strokeWeight(2); |
||||
for (let x = 3 * size / 2; x < size * (cols + 1); x += size){ |
||||
let y = size / 2; |
||||
ellipse(x, y, radius * 2); |
||||
} |
||||
for (let y = 3 * size / 2; y < size * (rows + 1); y += size){ |
||||
let x = size / 2; |
||||
ellipse(x, y, radius * 2); |
||||
} |
||||
} |
||||
|
||||
function showPoints(){ |
||||
stroke(200); |
||||
strokeWeight(10); |
||||
for (let i = 1; i <= cols; i++){ |
||||
let x = size * (i + 0.5) + sin(angle * i) * radius; |
||||
let y = size / 2 - cos(angle * i) * radius; |
||||
point(x, y); |
||||
} |
||||
for (let i = 1; i <= rows; i++){ |
||||
let x = size / 2 + sin(angle * i) * radius; |
||||
let y = size * (i + 0.5) - cos(angle * i) * radius; |
||||
point(x, y); |
||||
} |
||||
} |
||||
|
||||
function showMovingGrid(){ |
||||
stroke('rgba(255, 255, 255, 0.2)'); |
||||
strokeWeight(1); |
||||
for (let i = 1; i <= cols; i++){ |
||||
let x = size * (i + 0.5) + sin(angle * i) * radius; |
||||
line(x, 0, x, size * (rows + 1)); |
||||
} |
||||
for (let i = 1; i <= rows; i++){ |
||||
let y = size * (i + 0.5) - cos(angle * i) * radius; |
||||
line(0, y, size * (cols + 1), y); |
||||
} |
||||
} |
||||
|
||||
function showCurves(){ |
||||
strokeWeight(1); |
||||
for (let x = 0; x < cols; x++){ |
||||
for (let y = 0; y < rows; y++){ |
||||
curves[x][y].show(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
function updateValues(){ |
||||
removeCurves(); |
||||
|
||||
cols = int($('#cols').val()), |
||||
rows = int($('#rows').val()); |
||||
|
||||
angle = 0; |
||||
|
||||
|
||||
if (width / height > (cols + 1) / (rows + 1)){ |
||||
size = height / (rows + 1); |
||||
} else { |
||||
size = width / (cols + 1); |
||||
} |
||||
radius = size * 0.45; |
||||
|
||||
|
||||
createCurves(); |
||||
} |
||||
|
||||
function updateInterface(){ |
||||
let c = $('#cols').val(), |
||||
r = $('#rows').val(), |
||||
v = $('#vel').val(); |
||||
|
||||
$('span[name="cols"]').html(c); |
||||
$('span[name="rows"]').html(r); |
||||
$('span[name="vel"]').html(v); |
||||
|
||||
vel = float(v); |
||||
} |
||||
|
||||
function removeCurves(){ |
||||
if (!curves) |
||||
return; |
||||
for (let x = 0; x < cols; x++){ |
||||
for (let y = 0; y < rows; y++){ |
||||
curves[x][y].image.remove(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
function createCurves(){ |
||||
curves = []; |
||||
for (let x = 0; x < cols; x++){ |
||||
curves[x] = []; |
||||
for (let y = 0; y < rows; y++){ |
||||
curves[x][y] = new Curve(x, y); |
||||
} |
||||
} |
||||
} |
||||
|
||||
function canvasSetup(){ |
||||
setFrameRate(60); |
||||
let w = $('#canvas-holder').width(), |
||||
h = $('#canvas-holder').height(); |
||||
let canvas = createCanvas(w, h); |
||||
canvas.parent('canvas-holder'); |
||||
textFont(font); |
||||
imageMode(CENTER); |
||||
} |
||||
|
||||
function interfaceSetup(){ |
||||
|
||||
} |
||||
|
||||
function loadScripts(libs){ |
||||
for (let script in libs){ |
||||
if (libs[script]){ |
||||
let url = location.protocol + '//' + location.host + '/lib/benjocraeft/' + script + '.js'; |
||||
console.log(url); |
||||
$.getScript(url); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,48 @@ |
||||
'use strict'; |
||||
|
||||
function socketConnect(){ |
||||
socket = io("https://" + window.location.hostname + "?game=" + projectName); |
||||
} |
||||
|
||||
function createLobby(dom){ |
||||
if (inputIsValid('create')){ |
||||
onlineRequestFrontend(dom); |
||||
//TODO
|
||||
} |
||||
} |
||||
|
||||
function joinLobby(dom){ |
||||
if (inputIsValid('join')){ |
||||
onlineRequestFrontend(dom); |
||||
//TODO
|
||||
} |
||||
} |
||||
|
||||
function onlineRequestFrontend(dom){ |
||||
$(dom).blur(); |
||||
$(dom).attr('disabled', 'disabled'); |
||||
if (loader) loader.destroy(); |
||||
loader = new Loader($('#loader').get(0)); |
||||
} |
||||
|
||||
function inputIsValid(type){ |
||||
let valid = true; |
||||
$('.error-label').html(''); |
||||
if (type === 'create'){ |
||||
if ($('#player-name > input').val() === ''){ |
||||
valid = false; |
||||
$('#player-name > .error-label').html('Please enter a name!'); |
||||
} |
||||
} |
||||
if (type === 'join'){ |
||||
if ($('#player-name > input').val() === ''){ |
||||
valid = false; |
||||
$('#player-name > .error-label').html('Please enter a name!'); |
||||
} |
||||
if ($('#lobby-code > input').val() === ''){ |
||||
valid = false; |
||||
$('#lobby-code > .error-label').html('Please enter your code!'); |
||||
} |
||||
} |
||||
return valid; |
||||
} |
@ -0,0 +1,8 @@ |
||||
{ |
||||
"collision": false, |
||||
"colorPicker": false, |
||||
"cookie": true, |
||||
"loader": true, |
||||
"prototypes": true, |
||||
"technical": true |
||||
} |
@ -0,0 +1,3 @@ |
||||
{ |
||||
|
||||
} |
@ -0,0 +1,88 @@ |
||||
#color_picker{ |
||||
width: 300px; |
||||
height: 25%; |
||||
margin: 20px; |
||||
margin-top: 50px; |
||||
border: 5px solid #000; |
||||
background-color: #000; |
||||
-webkit-user-select: none; |
||||
-moz-user-select: none; |
||||
-ms-user-select: none; |
||||
user-select: none; |
||||
position: relative; |
||||
} |
||||
#color_picker_numeric{ |
||||
width: 80%; |
||||
padding: 5%; |
||||
margin: 5%; |
||||
background-color: #888; |
||||
border-radius: 10px; |
||||
overflow: hidden; |
||||
} |
||||
.color_picker_rgb{ |
||||
float: left; |
||||
width: 22%; |
||||
height: 35px; |
||||
font-size: 25px; |
||||
color: #000; |
||||
} |
||||
.color_picker_rgb:nth-child(1){ |
||||
margin-right: 10%; |
||||
margin-left: 3%; |
||||
background-color: #F00; |
||||
|
||||
} |
||||
.color_picker_rgb:nth-child(2){ |
||||
background-color: #0F0; |
||||
} |
||||
.color_picker_rgb:nth-child(3){ |
||||
margin-left: 10%; |
||||
background-color: #00F; |
||||
color: #FFF; |
||||
} |
||||
#color_picker_hex{ |
||||
width: 50%; |
||||
height: 30px; |
||||
font-size: 25px; |
||||
margin: 10% 25% 0 25%; |
||||
} |
||||
#saturation{ |
||||
position: relative; |
||||
width: calc(100% - 33px); |
||||
height: 100%; |
||||
background: linear-gradient(to right, #FFF 0%, #F00 100%); |
||||
float: left; |
||||
margin-right: 6px; |
||||
} |
||||
#value { |
||||
width: 100%; |
||||
height: 100%; |
||||
background: linear-gradient(to top, #000 0%, rgba(255,255,255,0) 100%); |
||||
} |
||||
#sb_picker{ |
||||
border: 2px solid; |
||||
border-color: #FFF; |
||||
position: absolute; |
||||
width: 14px; |
||||
height: 14px; |
||||
border-radius: 10px; |
||||
bottom: 50px; |
||||
left: 50px; |
||||
box-sizing: border-box; |
||||
z-index: 10; |
||||
} |
||||
#hue { |
||||
width: 27px; |
||||
height: 100%; |
||||
position: relative; |
||||
float: left; |
||||
background: linear-gradient(to bottom, #F00 0%, #F0F 17%, #00F 34%, #0FF 50%, #0F0 67%, #FF0 84%, #F00 100%); |
||||
} |
||||
#hue_picker { |
||||
position: absolute; |
||||
background: #000; |
||||
border-bottom: 1px solid #000; |
||||
top: 0; |
||||
width: 27px; |
||||
height: 2px; |
||||
} |
Binary file not shown.
@ -0,0 +1,88 @@ |
||||
input[type=range] { |
||||
-webkit-appearance: none; |
||||
margin: 18px 0; |
||||
width: 100%; |
||||
} |
||||
input[type=range]:focus { |
||||
outline: none; |
||||
} |
||||
input[type=range]::-webkit-slider-runnable-track { |
||||
width: 100%; |
||||
height: 8.4px; |
||||
cursor: pointer; |
||||
animate: 0.2s; |
||||
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; |
||||
background: #3071a9; |
||||
border-radius: 1.3px; |
||||
border: 0.2px solid #010101; |
||||
} |
||||
input[type=range]::-webkit-slider-thumb { |
||||
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; |
||||
border: 1px solid #000000; |
||||
height: 36px; |
||||
width: 16px; |
||||
border-radius: 3px; |
||||
background: #ffffff; |
||||
cursor: pointer; |
||||
-webkit-appearance: none; |
||||
margin-top: -14px; |
||||
} |
||||
input[type=range]:focus::-webkit-slider-runnable-track { |
||||
background: #367ebd; |
||||
} |
||||
input[type=range]::-moz-range-track { |
||||
width: 100%; |
||||
height: 8.4px; |
||||
cursor: pointer; |
||||
animate: 0.2s; |
||||
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; |
||||
background: #3071a9; |
||||
border-radius: 1.3px; |
||||
border: 0.2px solid #010101; |
||||
} |
||||
input[type=range]::-moz-range-thumb { |
||||
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; |
||||
border: 1px solid #000000; |
||||
height: 36px; |
||||
width: 16px; |
||||
border-radius: 3px; |
||||
background: #52b923; |
||||
cursor: pointer; |
||||
} |
||||
input[type=range]::-ms-track { |
||||
width: 100%; |
||||
height: 8.4px; |
||||
cursor: pointer; |
||||
animate: 0.2s; |
||||
background: transparent; |
||||
border-color: transparent; |
||||
border-width: 16px 0; |
||||
color: transparent; |
||||
} |
||||
input[type=range]::-ms-fill-lower { |
||||
background: #2a6495; |
||||
border: 0.2px solid #010101; |
||||
border-radius: 2.6px; |
||||
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; |
||||
} |
||||
input[type=range]::-ms-fill-upper { |
||||
background: #3071a9; |
||||
border: 0.2px solid #010101; |
||||
border-radius: 2.6px; |
||||
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; |
||||
} |
||||
input[type=range]::-ms-thumb { |
||||
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; |
||||
border: 1px solid #000000; |
||||
height: 36px; |
||||
width: 16px; |
||||
border-radius: 3px; |
||||
background: #ffffff; |
||||
cursor: pointer; |
||||
} |
||||
input[type=range]:focus::-ms-fill-lower { |
||||
background: #3071a9; |
||||
} |
||||
input[type=range]:focus::-ms-fill-upper { |
||||
background: #367ebd; |
||||
} |
@ -0,0 +1,33 @@ |
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
<head> |
||||
<meta charset="utf-8"> |
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.6.0/p5.min.js" type="text/javascript"></script> |
||||
<script src="https://code.jquery.com/jquery-3.6.4.min.js" type="text/javascript"></script> |
||||
<script src="data/scripts/init.js" type="text/javascript"></script> |
||||
<script src="data/scripts/events.js" type="text/javascript"></script> |
||||
<script src="data/scripts/online.js" type="text/javascript"></script> |
||||
<script src="data/scripts/curve.js" type="text/javascript"></script> |
||||
<link href="styles.css" rel="stylesheet"> |
||||
<link href="data/styles/color_picker.css" rel="stylesheet"> |
||||
<link href="data/styles/range_input.css" rel="stylesheet"> |
||||
<link href="data/images/favicon.ico" rel="icon" type="image/x-icon"> |
||||
<title>Lissajous curve</title> |
||||
</head> |
||||
<body> |
||||
<div id="p5_loading"></div> |
||||
<div id="content"> |
||||
<div id="canvas-holder"></div> |
||||
<div id="interface"> |
||||
<h1>Lissajous Curve</h1> |
||||
<span>Columns: </span><span name="cols"></span> |
||||
<input id="cols" max="20" min="1" oninput="updateInterface();" step="1" type="range" value="5"> |
||||
<span>Rows: </span><span name="rows"></span> |
||||
<input id="rows" max="20" min="1" oninput="updateInterface();" step="1" type="range" value="5"> |
||||
<span>Velocity: </span><span name="vel"></span> |
||||
<input id="vel" max="0.1" min="0" oninput="updateInterface();" step="0.005" type="range" value="0.02"> |
||||
<button onclick="updateValues();">OK</button> |
||||
</div> |
||||
</div> |
||||
</body> |
||||
</html> |
@ -0,0 +1,75 @@ |
||||
a:link, a:hover, a:active, a:visited{color: #000;} |
||||
|
||||
html, body{margin: 0; padding: 0; height: 100%; width: 100%;} |
||||
|
||||
canvas{margin: 0; padding: 0; border: none; display: block;} |
||||
|
||||
button:hover{cursor: pointer;} |
||||
|
||||
@font-face{ |
||||
font-family: "Rametto"; |
||||
src: url("data/styles/font.ttf"); |
||||
} |
||||
|
||||
*{ |
||||
font-family: "Rametto"; |
||||
color: #000; |
||||
font-size: 17px; |
||||
} |
||||
|
||||
:root{ |
||||
--interface-width: 200px; |
||||
--width: calc(100vw - var(--interface-width) - 20px); |
||||
--height: 100vh; |
||||
--interface-color: rgb(36, 56, 145); |
||||
} |
||||
|
||||
/** |
||||
* Standard styles |
||||
*/ |
||||
|
||||
#canvas-holder{ |
||||
position: relative; |
||||
width: var(--width); |
||||
height: var(--height); |
||||
} |
||||
#canvas-holder canvas{ |
||||
position: absolute; |
||||
top: 0; |
||||
left: 0; |
||||
right: 0; |
||||
bottom: 0; |
||||
border-radius: inherit; |
||||
} |
||||
#p5_loading{ |
||||
display: none; |
||||
} |
||||
|
||||
|
||||
|
||||
#interface{ |
||||
position: absolute; |
||||
right: 0; |
||||
top: 0; |
||||
width: var(--interface-width); |
||||
height: calc(100% - 20px); |
||||
background-color: var(--interface-color); |
||||
border-left: 2px solid rgb(122, 105, 216); |
||||
padding: 10px; |
||||
text-align-last: center; |
||||
} |
||||
|
||||
h1{ |
||||
text-decoration: underline; |
||||
} |
||||
|
||||
input{ |
||||
background-color: var(--interface-color); |
||||
} |
||||
|
||||
button{ |
||||
background-color: rgb(71, 177, 22); |
||||
border-radius: 3px; |
||||
box-shadow: 2px 2px 5px #000; |
||||
border: 2px solid rgb(36, 94, 10); |
||||
} |
After Width: | Height: | Size: 425 KiB |
Loading…
Reference in new issue