Larry stuff

other animations now work.
carrots added.
Added header control type.
callbacks for input changes.
Screen resizing.
speed controls fixed/changed.
This commit is contained in:
Sam 2024-08-07 21:30:46 +12:00
parent ea9134bfdc
commit a03f8b1e4b
13 changed files with 285 additions and 61 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

View File

@ -1,3 +1,7 @@
:root {
color-scheme: dark;
}
body { body {
-webkit-box-sizing: border-box; -webkit-box-sizing: border-box;
/* Safari/Chrome, other WebKit */ /* Safari/Chrome, other WebKit */
@ -25,7 +29,8 @@ canvas {
padding: 0px 20px 0px 20px; padding: 0px 20px 0px 20px;
width: 500px; width: 500px;
height: 100vh; height: 100vh;
background-color: rgb(189, 189, 189); background-color: rgba(32, 32, 32, 0.616);
overflow-y: scroll;
} }
#custom { #custom {
@ -34,10 +39,25 @@ canvas {
height: 100%; height: 100%;
/* position: absolute; */ /* position: absolute; */
padding: 0px 20px 0px 20px; padding: 20px 0px 0px 0px;
/* width: 500px; */ /* width: 500px; */
/* height: 100vh; */ /* height: 100vh; */
background-color: rgb(189, 189, 189); /* background-color: rgba(100, 100, 100, 0.5); */
}
#custom p{
color: #e0e0e0;
font-family: Roboto, system-ui;
}
#toolbar p{
color: #e0e0e0;
font-family: Roboto, system-ui;
}
.header {
text-align: center;
font-weight: bold;
padding: 12px 0px 0px 2px;
} }
.button { .button {

View File

@ -12,17 +12,16 @@
<div id="toolbar"> <div id="toolbar">
<br> <br>
<select id="shape-selector"> <select id="shape-selector">
<option value="TestParent">Test Parent</option>
<option value="PolyTwistColourWidth">PolyTwistColourWidth</option>
<option value="Larry">Larry</option> <option value="Larry">Larry</option>
<option value="Larry">Snails</option>
<option value="Larry">Background</option>
</select> </select>
<div id="custom"></div> <div id="custom">
</div>
<br> <br>
<p>Controls:</p>
<p>
Press "Space" to pause and start the animation
</p>
<p>
Press "P" to show/hide the control panel
</p>
<br> <br>
<p>Speed</p> <p>Speed</p>
<input type="text" id="inputDegPerSec" value="10" onchange="ChangeDegPerSec(this.value)"> <input type="text" id="inputDegPerSec" value="10" onchange="ChangeDegPerSec(this.value)">
@ -30,8 +29,8 @@
<p>Controls</p> <p>Controls</p>
<div class="controls"> <div class="controls">
<button class="controlFrameButton button-8" onclick="BackwardFrame()"><</button> <button class="controlFrameButton button-8" onclick="BackwardFrame()"><</button>
<button class="controlPauseButton button-8" id="pauseButton" onclick="TogglePause()">Play</button> <button class="controlPauseButton button-8" id="pauseButton" onclick="TogglePause()">Pause</button>
<button class="controlFrameButton button-8" onclick="ForwardFrame()">></button> <button class="controlFrameButton button-8" onclick="ForwardFrame(event)">></button>
</div> </div>
<button class="buttonReset button-8" id="resetButton" onclick="Reset()">Reset Rotation</button> <button class="buttonReset button-8" id="resetButton" onclick="Reset()">Reset Rotation</button>
</div> </div>

View File

@ -5,12 +5,15 @@ async function fetchConfig(className) {
{ {
type: "range", type: "range",
min: 1, min: 1,
max: 5, max: 10,
defaultValue: 1, defaultValue: 5,
property: "magnitude", property: "magnitude",
callback: (instance, newValue) => instance.setMagnitude(newValue) callback: (instance, newValue) => instance.setMagnitude(newValue)
}, },
// Dropdown control to select food {
type: "header",
text: "---Food---"
},
{ {
type: "dropdown", type: "dropdown",
property: "selectedFood", property: "selectedFood",
@ -24,8 +27,8 @@ async function fetchConfig(className) {
{ {
type: "range", type: "range",
min: 0, min: 0,
max: 100, max: 200,
defaultValue: 50, defaultValue: 100,
property: "eatSpeed" property: "eatSpeed"
}, },
{ {
@ -41,6 +44,41 @@ async function fetchConfig(className) {
label: "Start Eating", label: "Start Eating",
method: "startEating", method: "startEating",
}, },
{
type: "header",
text: "---Movement---"
},
// Movement controls
{
type: "range",
min: -360,
max: 360,
defaultValue: 90,
property: "moveDirection"
},
{
type: "range",
min: 1,
max: 100,
defaultValue: 10,
property: "moveDistance"
},
{
type: "range",
min: 1,
max: 10,
defaultValue: 5,
property: "moveSpeed"
},
{
type: "button",
label: "Wander",
method: "wander"
},
{
type: "header",
text: "---Appearance---"
},
// Dropdown control to select hat // Dropdown control to select hat
{ {
type: "dropdown", type: "dropdown",
@ -60,34 +98,6 @@ async function fetchConfig(className) {
label: "Apply Hat", label: "Apply Hat",
method: "applyHat" method: "applyHat"
}, },
// Movement controls
{
type: "range",
min: 0,
max: 360,
defaultValue: 0,
property: "moveDirection"
},
{
type: "range",
min: 1,
max: 100,
defaultValue: 10,
property: "moveDistance"
},
{
type: "range",
min: 1,
max: 10,
defaultValue: 5,
property: "moveSpeed"
},
{
type: "button",
label: "Wander",
method: "wander"
},
// Appearance controls // Appearance controls
{ {
type: "dropdown", type: "dropdown",
@ -122,6 +132,32 @@ async function fetchConfig(className) {
method: "applyBackground" method: "applyBackground"
} }
], ],
PolyTwistColourWidth: [
{ type: "range", min: 1, max: 10, defaultValue: 5, property: "sides" },
{ type: "range", min: -180, max: 2000, defaultValue: 300, property: "width" },
{ type: "range", min: 2, max: 5, defaultValue: 5, property: "line_width" },
{ type: "range", min: 1, max: 100, defaultValue: 50, property: "depth" },
{ type: "range", min: -180, max: 180, defaultValue: -20, property: "rotation"},
{ type: "color", defaultValue: "#4287f5", property: "colour1" },
{ type: "color", defaultValue: "#42f57b", property: "colour2" },
],
TestParent: [
{
type: "button",
label: "Add Child",
method: "addChild"
},
{
type: "dropdown",
property: "selectedChild",
callback: (instance, newValue) => instance.setSelectedChild(newValue),
defaultValue: "",
options: [
{ value: "", label: "None" },
{ value: "0", label: "None" },
]
},
],
// Add other shape configurations here // Add other shape configurations here
}; };
return config[className]; return config[className];
@ -136,6 +172,7 @@ const hatConfig = {
const foodConfig = { const foodConfig = {
apple: { sizeMult: 0.25, n: 4 }, apple: { sizeMult: 0.25, n: 4 },
carrot: { sizeMult: 0.25, n: 6 },
nothing: { sizeMult: 2, n: 5 }, nothing: { sizeMult: 2, n: 5 },
}; };
@ -183,13 +220,38 @@ function addControl(item, instance) {
const newValue = event.target.value; const newValue = event.target.value;
instance[item.property] = newValue; instance[item.property] = newValue;
title.innerText = item.property + ": " + newValue; title.innerText = item.property + ": " + newValue;
if (item.callback) {
item.callback(instance, newValue);
}
}); });
} else if (item.type === "header") {
control = document.createElement("p");
control.innerText = item.text;
control.className = "header";
control.id = "elHeader" + item.text.replace(/\s+/g, '');
}
else if (item.type === "color") {
control = document.createElement("input");
control.type = item.type;
control.value = item.defaultValue;
control.id = "el" + item.property;
control.addEventListener("input", (event) => {
const newValue = event.target.value;
instance[item.property] = newValue;
title.innerText = item.property + ": " + newValue;
})
} }
if (item.type != "header") {
control.className = "control"; control.className = "control";
control.id = "el" + item.property; control.id = "el" + item.property;
}
if (item.type != "button" && item.type != "header") {
parentDiv.appendChild(title); parentDiv.appendChild(title);
}
parentDiv.appendChild(control); parentDiv.appendChild(control);
return { element: control }; return { element: control };
@ -301,6 +363,7 @@ function drawEyelidAccident(x1, y1) {
} }
function DrawPolygon(sides, width, rotation, colour, line_width) { function DrawPolygon(sides, width, rotation, colour, line_width) {
console.log("drawing polygon")
ctx.beginPath(); ctx.beginPath();
ctx.moveTo( ctx.moveTo(
centerX + width * Math.cos((rotation * Math.PI) / 180), centerX + width * Math.cos((rotation * Math.PI) / 180),
@ -318,6 +381,29 @@ function DrawPolygon(sides, width, rotation, colour, line_width) {
} }
ctx.strokeStyle = colour; ctx.strokeStyle = colour;
ctx.lineWidth = line_width; ctx.lineWidth = line_width;
ctx.stroke();
}
function DrawPolygonPosition(sides, width, rotation,x,y, colour, line_width) {
console.log("drawing polygon")
ctx.beginPath();
ctx.moveTo(
x + width * Math.cos((rotation * Math.PI) / 180),
y + width * Math.sin((rotation * Math.PI) / 180)
);
for (var i = 1; i <= sides; i += 1) {
ctx.lineTo(
x +
width *
Math.cos((i * 2 * Math.PI) / sides + (rotation * Math.PI) / 180),
y +
width * Math.sin((i * 2 * Math.PI) / sides + (rotation * Math.PI) / 180)
);
}
ctx.strokeStyle = colour;
ctx.lineWidth = line_width;
ctx.stroke(); ctx.stroke();
} }

View File

@ -22,6 +22,9 @@ let drawObj = null;
function createInstance(className, args) { function createInstance(className, args) {
const classMap = { const classMap = {
Larry: Larry, Larry: Larry,
PolyTwistColourWidth: PolyTwistColourWidth,
TestParent: TestParent,
TestChild: TestChild,
// Add more class constructors here as needed // Add more class constructors here as needed
}; };
@ -34,7 +37,7 @@ function createInstance(className, args) {
} }
//recreate this for child objects?
async function updateDrawObj() { async function updateDrawObj() {
const shapeSelector = document.getElementById("shape-selector"); const shapeSelector = document.getElementById("shape-selector");
const selectedShape = shapeSelector.value; const selectedShape = shapeSelector.value;
@ -51,10 +54,16 @@ async function updateDrawObj() {
// Update instance properties based on control values // Update instance properties based on control values
config.forEach(item => { config.forEach(item => {
if (item.type === "range" || item.type === "dropdown") { if (item.type === "range" || item.type === "dropdown" || item.type === "color") {
const control = document.getElementById("el" + item.property); const control = document.getElementById("el" + item.property);
if (item.type === "range") {
drawObj[item.property] = parseInt(control.value);
}
else {
drawObj[item.property] = control.value; drawObj[item.property] = control.value;
} }
}
}); });
console.log(drawObj); console.log(drawObj);
@ -84,7 +93,7 @@ function render() {
} }
ctx.font = "48px serif"; ctx.font = "48px serif";
ctx.fillStyle = "white" ctx.fillStyle = "white"
ctx.fillText( Math.floor(trueTimestamp) + "ms", centerX-150, centerY+400); ctx.fillText(Math.floor(trueTimestamp) + "ms", centerX - 100, centerY + 400);
// drawCenter(300) // drawCenter(300)
}); });
render(); render();
@ -98,6 +107,16 @@ document
let toolbarShowing = true; let toolbarShowing = true;
document.addEventListener("keydown", toggleSettings); document.addEventListener("keydown", toggleSettings);
window.addEventListener("resize", () => {
resizeCooledDown = false;
ctx.canvas.width = window.innerWidth;
ctx.canvas.height = window.innerHeight;
centerX = ctx.canvas.width / 2;
centerY = ctx.canvas.height / 2;
})
function manualToggleSettings() { function manualToggleSettings() {
console.log("hi") console.log("hi")
toolbarShowing = !toolbarShowing; toolbarShowing = !toolbarShowing;
@ -140,9 +159,12 @@ function Reset() {
currentFrame = 0; currentFrame = 0;
} }
function ForwardFrame() { function ForwardFrame(event) {
rotation += deg_per_sec / fps; // was = j = innerRotation, now = rotation rotation += deg_per_sec / 60; // was = j = innerRotation, now = rotation
currentFrame += 1; // was = i trueTimestamp += event.offsetX * 10
console.log(event)
console.log(event.clientX)
console.log(event.x)
} }
function BackwardFrame() { function BackwardFrame() {
rotation -= deg_per_sec / fps; // was = j = innerRotation, now = rotation rotation -= deg_per_sec / fps; // was = j = innerRotation, now = rotation

View File

@ -15,7 +15,7 @@ class BaseShape {
const { element, listener } = addControl({ const { element, listener } = addControl({
type: "range", type: "range",
min: 1, min: 1,
max: 500, max: 1000,
defaultValue: 100, defaultValue: 100,
property: "speedMultiplier", property: "speedMultiplier",
}, this); }, this);
@ -26,6 +26,7 @@ class BaseShape {
this.controls.forEach(({ element, listener }) => { this.controls.forEach(({ element, listener }) => {
if (element && listener) { if (element && listener) {
element.removeEventListener("input", listener); element.removeEventListener("input", listener);
element.removeEventListener("click", listener);
} }
if (element && element.parentElement) { if (element && element.parentElement) {
element.parentElement.removeChild(element); element.parentElement.removeChild(element);
@ -226,3 +227,96 @@ class Larry extends BaseShape {
} }
} }
class PolyTwistColourWidth extends BaseShape {
// constructor(sides, width, line_width, depth, rotation, speedMultiplier, colour1, colour2) {
constructor(sides, width, line_width, depth, rotation, colour1, colour2) {
super();
this.sides = sides;
this.width = width;
this.line_width = line_width;
this.depth = depth;
this.rotation = rotation;
this.colour1 = colour1;
this.colour2 = colour2;
}
draw(elapsed, timestamp) {
// rotation *= (this.speedMultiplier / 100)
timestamp /= 1000
timestamp *= (this.speedMultiplier / 100)
let out_angle = 0;
const innerAngle = 180 - ((this.sides - 2) * 180) / this.sides;
const scopeAngle = timestamp - (innerAngle * Math.floor(timestamp / innerAngle));
if (scopeAngle < innerAngle / 2) {
out_angle = innerAngle / (2 * Math.cos((2 * Math.PI * scopeAngle) / (3 * innerAngle))) - innerAngle / 2;
} else {
out_angle = -innerAngle / (2 * Math.cos(((2 * Math.PI) / 3) - ((2 * Math.PI * scopeAngle) / (3 * innerAngle)))) + (innerAngle * 3) / 2;
}
let minWidth = Math.sin(rad(innerAngle / 2)) * (0.5 / Math.tan(rad(innerAngle / 2))) * 2;
let widthMultiplier = minWidth / Math.sin(Math.PI / 180 * (90 + innerAngle / 2 - out_angle + innerAngle * Math.floor(out_angle / innerAngle)));
for (let i = 0; i < this.depth; i++) {
const fraction = i / this.depth;
const ncolour = LerpHex(this.colour1, this.colour2, fraction);
DrawPolygon(this.sides, this.width * widthMultiplier ** i, out_angle * i + this.rotation, ncolour, this.line_width);
}
}
}
class TestParent extends BaseShape {
constructor() {
super();
this.children = []
this.selectedChild = ""
}
draw(elapsed, timestamp) {
// rotation *= (this.speedMultiplier / 100)
timestamp /= 1000
timestamp *= (this.speedMultiplier / 100)
// console.log(this.selectedChild)
for (let i = 0; i < this.children.length; i++) {
this.children[i].draw()
}
}
setSelectedChild(SelectedChild){
console.log(this.selectedChild)
}
addChild() {
let x = Math.random()*1920
let y = Math.random()*1080
let r = Math.random()*360
let w = Math.random()*200+100
let s = Math.floor(Math.random()*10)+3
let newChild = new TestChild(s,w,x,y,r)
this.children.push(newChild)
console.log(this.children)
}
}
class TestChild extends BaseShape {
constructor(sides, width, x, y,rotation) {
super();
this.sides = sides;
this.width = width;
this.x = x;
this.y = y;
this.rotation = rotation;
}
draw(elapsed, timestamp) {
// rotation *= (this.speedMultiplier / 100)
timestamp /= 1000
timestamp *= (this.speedMultiplier / 100)
DrawPolygonPosition(this.sides, this.width, this.rotation,this.x,this.y, "#4287f5", 3);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

3
docs/.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"liveServer.settings.port": 5501
}