Larry stuff
other animations now work. carrots added. Added header control type. callbacks for input changes. Screen resizing. speed controls fixed/changed.
After Width: | Height: | Size: 170 KiB |
|
@ -1,3 +1,7 @@
|
|||
:root {
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
body {
|
||||
-webkit-box-sizing: border-box;
|
||||
/* Safari/Chrome, other WebKit */
|
||||
|
@ -25,7 +29,8 @@ canvas {
|
|||
padding: 0px 20px 0px 20px;
|
||||
width: 500px;
|
||||
height: 100vh;
|
||||
background-color: rgb(189, 189, 189);
|
||||
background-color: rgba(32, 32, 32, 0.616);
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
#custom {
|
||||
|
@ -34,10 +39,25 @@ canvas {
|
|||
height: 100%;
|
||||
|
||||
/* position: absolute; */
|
||||
padding: 0px 20px 0px 20px;
|
||||
padding: 20px 0px 0px 0px;
|
||||
/* width: 500px; */
|
||||
/* 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 {
|
||||
|
|
|
@ -12,17 +12,16 @@
|
|||
<div id="toolbar">
|
||||
<br>
|
||||
<select id="shape-selector">
|
||||
<option value="TestParent">Test Parent</option>
|
||||
<option value="PolyTwistColourWidth">PolyTwistColourWidth</option>
|
||||
<option value="Larry">Larry</option>
|
||||
<option value="Larry">Snails</option>
|
||||
<option value="Larry">Background</option>
|
||||
</select>
|
||||
<div id="custom"></div>
|
||||
<div id="custom">
|
||||
</div>
|
||||
<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>
|
||||
<p>Speed</p>
|
||||
<input type="text" id="inputDegPerSec" value="10" onchange="ChangeDegPerSec(this.value)">
|
||||
|
@ -30,8 +29,8 @@
|
|||
<p>Controls</p>
|
||||
<div class="controls">
|
||||
<button class="controlFrameButton button-8" onclick="BackwardFrame()"><</button>
|
||||
<button class="controlPauseButton button-8" id="pauseButton" onclick="TogglePause()">Play</button>
|
||||
<button class="controlFrameButton button-8" onclick="ForwardFrame()">></button>
|
||||
<button class="controlPauseButton button-8" id="pauseButton" onclick="TogglePause()">Pause</button>
|
||||
<button class="controlFrameButton button-8" onclick="ForwardFrame(event)">></button>
|
||||
</div>
|
||||
<button class="buttonReset button-8" id="resetButton" onclick="Reset()">Reset Rotation</button>
|
||||
</div>
|
||||
|
|
|
@ -5,12 +5,15 @@ async function fetchConfig(className) {
|
|||
{
|
||||
type: "range",
|
||||
min: 1,
|
||||
max: 5,
|
||||
defaultValue: 1,
|
||||
max: 10,
|
||||
defaultValue: 5,
|
||||
property: "magnitude",
|
||||
callback: (instance, newValue) => instance.setMagnitude(newValue)
|
||||
},
|
||||
// Dropdown control to select food
|
||||
{
|
||||
type: "header",
|
||||
text: "---Food---"
|
||||
},
|
||||
{
|
||||
type: "dropdown",
|
||||
property: "selectedFood",
|
||||
|
@ -24,8 +27,8 @@ async function fetchConfig(className) {
|
|||
{
|
||||
type: "range",
|
||||
min: 0,
|
||||
max: 100,
|
||||
defaultValue: 50,
|
||||
max: 200,
|
||||
defaultValue: 100,
|
||||
property: "eatSpeed"
|
||||
},
|
||||
{
|
||||
|
@ -41,6 +44,41 @@ async function fetchConfig(className) {
|
|||
label: "Start Eating",
|
||||
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
|
||||
{
|
||||
type: "dropdown",
|
||||
|
@ -60,34 +98,6 @@ async function fetchConfig(className) {
|
|||
label: "Apply Hat",
|
||||
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
|
||||
{
|
||||
type: "dropdown",
|
||||
|
@ -122,6 +132,32 @@ async function fetchConfig(className) {
|
|||
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
|
||||
};
|
||||
return config[className];
|
||||
|
@ -136,6 +172,7 @@ const hatConfig = {
|
|||
|
||||
const foodConfig = {
|
||||
apple: { sizeMult: 0.25, n: 4 },
|
||||
carrot: { sizeMult: 0.25, n: 6 },
|
||||
nothing: { sizeMult: 2, n: 5 },
|
||||
};
|
||||
|
||||
|
@ -183,13 +220,38 @@ function addControl(item, instance) {
|
|||
const newValue = event.target.value;
|
||||
instance[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.id = "el" + item.property;
|
||||
}
|
||||
|
||||
if (item.type != "button" && item.type != "header") {
|
||||
parentDiv.appendChild(title);
|
||||
}
|
||||
parentDiv.appendChild(control);
|
||||
|
||||
return { element: control };
|
||||
|
@ -301,6 +363,7 @@ function drawEyelidAccident(x1, y1) {
|
|||
}
|
||||
|
||||
function DrawPolygon(sides, width, rotation, colour, line_width) {
|
||||
console.log("drawing polygon")
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(
|
||||
centerX + width * Math.cos((rotation * Math.PI) / 180),
|
||||
|
@ -318,6 +381,29 @@ function DrawPolygon(sides, width, rotation, colour, line_width) {
|
|||
}
|
||||
ctx.strokeStyle = colour;
|
||||
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();
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,9 @@ let drawObj = null;
|
|||
function createInstance(className, args) {
|
||||
const classMap = {
|
||||
Larry: Larry,
|
||||
PolyTwistColourWidth: PolyTwistColourWidth,
|
||||
TestParent: TestParent,
|
||||
TestChild: TestChild,
|
||||
|
||||
// Add more class constructors here as needed
|
||||
};
|
||||
|
@ -34,7 +37,7 @@ function createInstance(className, args) {
|
|||
}
|
||||
|
||||
|
||||
|
||||
//recreate this for child objects?
|
||||
async function updateDrawObj() {
|
||||
const shapeSelector = document.getElementById("shape-selector");
|
||||
const selectedShape = shapeSelector.value;
|
||||
|
@ -51,10 +54,16 @@ async function updateDrawObj() {
|
|||
|
||||
// Update instance properties based on control values
|
||||
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);
|
||||
if (item.type === "range") {
|
||||
drawObj[item.property] = parseInt(control.value);
|
||||
}
|
||||
else {
|
||||
drawObj[item.property] = control.value;
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
console.log(drawObj);
|
||||
|
@ -74,7 +83,7 @@ function render() {
|
|||
if (drawObj) {
|
||||
// drawObj.draw(rotation);
|
||||
|
||||
drawObj.draw(elapsed,trueTimestamp);
|
||||
drawObj.draw(elapsed, trueTimestamp);
|
||||
|
||||
}
|
||||
|
||||
|
@ -84,7 +93,7 @@ function render() {
|
|||
}
|
||||
ctx.font = "48px serif";
|
||||
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)
|
||||
});
|
||||
render();
|
||||
|
@ -98,6 +107,16 @@ document
|
|||
let toolbarShowing = true;
|
||||
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() {
|
||||
console.log("hi")
|
||||
toolbarShowing = !toolbarShowing;
|
||||
|
@ -140,9 +159,12 @@ function Reset() {
|
|||
currentFrame = 0;
|
||||
}
|
||||
|
||||
function ForwardFrame() {
|
||||
rotation += deg_per_sec / fps; // was = j = innerRotation, now = rotation
|
||||
currentFrame += 1; // was = i
|
||||
function ForwardFrame(event) {
|
||||
rotation += deg_per_sec / 60; // was = j = innerRotation, now = rotation
|
||||
trueTimestamp += event.offsetX * 10
|
||||
console.log(event)
|
||||
console.log(event.clientX)
|
||||
console.log(event.x)
|
||||
}
|
||||
function BackwardFrame() {
|
||||
rotation -= deg_per_sec / fps; // was = j = innerRotation, now = rotation
|
||||
|
|
|
@ -15,7 +15,7 @@ class BaseShape {
|
|||
const { element, listener } = addControl({
|
||||
type: "range",
|
||||
min: 1,
|
||||
max: 500,
|
||||
max: 1000,
|
||||
defaultValue: 100,
|
||||
property: "speedMultiplier",
|
||||
}, this);
|
||||
|
@ -26,6 +26,7 @@ class BaseShape {
|
|||
this.controls.forEach(({ element, listener }) => {
|
||||
if (element && listener) {
|
||||
element.removeEventListener("input", listener);
|
||||
element.removeEventListener("click", listener);
|
||||
}
|
||||
if (element && element.parentElement) {
|
||||
element.parentElement.removeChild(element);
|
||||
|
@ -118,7 +119,7 @@ class Larry extends BaseShape {
|
|||
const eatMaxHeight = 20;
|
||||
// const eatingYOffset = ((Math.cos((adjustedTimestamp -Math.PI/2+ 0.5 * Math.PI) * (this.eatSpeed/100)*0.1 - Math.PI / 2) + 1) / 2) * eatMaxHeight;
|
||||
// const eatingYOffset = ((Math.sin((adjustedTimestamp/1000 * 2 * Math.PI * this.eatSpeed / 100 * 0.1) - Math.PI / 2) + 1) / 2) * eatMaxHeight;
|
||||
const eatingYOffset = (Math.sin(((adjustedTimestamp/1000)* (this.eatSpeed/100))* Math.PI * 2 - (Math.PI/2))*0.5+0.5) * eatMaxHeight;
|
||||
const eatingYOffset = (Math.sin(((adjustedTimestamp / 1000) * (this.eatSpeed / 100)) * Math.PI * 2 - (Math.PI / 2)) * 0.5 + 0.5) * eatMaxHeight;
|
||||
headY -= eatingYOffset;
|
||||
const n = this.eatDuration
|
||||
// console.log(adjustedTimestamp)
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 75 KiB |
After Width: | Height: | Size: 70 KiB |
After Width: | Height: | Size: 64 KiB |
After Width: | Height: | Size: 58 KiB |
After Width: | Height: | Size: 37 KiB |
After Width: | Height: | Size: 28 KiB |
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"liveServer.settings.port": 5501
|
||||
}
|