Browse Source

first commit

main
James Fenn 1 month ago
commit
011c938440
7 changed files with 281 additions and 0 deletions
  1. BIN
      Punch Deck - Elegance in Simplicity.wav
  2. BIN
      Punch Deck - Snowfall.wav
  3. BIN
      Punch Deck - Under the Stars.wav
  4. BIN
      beep.mp3
  5. +26
    -0
      index.html
  6. BIN
      scene-desk.jpg
  7. +255
    -0
      sketch.js

BIN
Punch Deck - Elegance in Simplicity.wav View File


BIN
Punch Deck - Snowfall.wav View File


BIN
Punch Deck - Under the Stars.wav View File


BIN
beep.mp3 View File


+ 26
- 0
index.html View File

@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>James Fenn</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/p5.js" crossorigin="anonymous"></script>
<script src="sketch.js"></script>
<style>
body {
padding: 0;
margin: 0;
background-color: #c6c6c6;
}

canvas {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
</style>
</head>
<body>
<div style="position: absolute; width: 100vw; height: 100vh; z-index: 100; pointer-events: none;" id="elementContainer"></div>
</body>
</html>

BIN
scene-desk.jpg View File

Before After
Width: 1209  |  Height: 907  |  Size: 136 KiB

+ 255
- 0
sketch.js View File

@@ -0,0 +1,255 @@
const _images = {};
const _sounds = {
beep: new Audio("./beep.mp3"),
music: new Audio("./Punch Deck - Snowfall.wav")
};

const _musicList = ["./Punch Deck - Snowfall.wav", "./Punch Deck - Elegance in Simplicity.wav", "./Punch Deck - Under the Stars.wav"]

const _elements = {};
const _elementAttrs = {};

let _scene = "desk";

let _message = {
text: 'Welcome to my intro assignment! Hover/click on the objects on my desk to interact. Have fun!',
visible: true
};

let _mouseIsClicked = false;
let _mouseWasClicked = false;

function setup() {
windowResized(); // create scaled canvas
frameRate(15);
background('black');

_elements.twitchFrame = createElement("iframe"); _elements.twitchFrame.parent('#elementContainer');
_elementAttrs.twitchFrame = {
src: "https://player.twitch.tv/?video=877583964&parent=localhost&autoplay=true&controls=false&muted=true&time=0h7m0s",
frameborder: 0,
scrolling: 'no',
allowfullscreen: true
};
}

function preload() {
_images.desk = loadImage('./scene-desk.jpg');
}

function draw() {
fill(0, 0, 0);
noStroke();

// per-frame mouse click handling
if (mouseIsPressed && !_mouseIsClicked && !_mouseWasClicked) {
_mouseIsClicked = true;
_mouseWasClicked = true;
} else {
_mouseIsClicked = false;
if (!mouseIsPressed)
_mouseWasClicked = false;
}

if (_scene) {
window[`draw_${_scene}`]();
}

// apply new attrs to elements (once per-frame)
Object.entries(_elements).forEach(([key, element]) => {
Object.entries(_elementAttrs[key]).forEach(([name, value]) => {
if (value != element.attribute(name))
element.attribute(name, value);
});
});

// draw message (if visible)
if (_message.visible) {
stroke(0, 0, 40);
strokeWeight(1);
fill(255, 255, 255);
rect(...percent(0, 60, 100, 40));

if (typeof _message.length === 'undefined')
_message.length = 0;

if (_message.length < _message.text.length) {
_message.length += 3;
_sounds.beep.pause();
_sounds.beep.currentTime = 0;
_sounds.beep.volume = 0.1;
_sounds.beep.play();
}

fill(0, 0, 0);
textSize(width/40);
text(_message.text.substring(0, _message.length), ...percent(5, 65, 90));

if (_mouseIsClicked) {
_mouseIsClicked = false;
_message.visible = false;
(_message.onclose || (() => {}))();
}

Object.entries(_elements).forEach(([key, element]) => {
element.attribute("style", "display:none;");
});
}

if (!_sounds.music.paused) {
// music playing; draw credits
fill(50, 50, 50);
noStroke();
textSize(width/60);
text("Playing music by Punch Deck (Creative Commons)...", ...percent(5, 5, 90));
}
}

function draw_desk() {
if (!_images.desk)
return;

image(_images.desk, ...percent(0, 0, 100, 100));

fill(0, 0, 0);
noStroke();
textSize(width/30);
text("James Fenn - he/him", ...percent(5, 10, 90));

const canvasRect = canvas.getBoundingClientRect();
const twitchPosition = percent(6.8, 52, 25, 20.5);
_elementAttrs.twitchFrame.style = `
position: absolute;
left: ${canvasRect.x + twitchPosition[0]}px;
top: ${canvasRect.y + twitchPosition[1]}px;
width: ${twitchPosition[2]}px;
height: ${twitchPosition[3]}px;
transform: rotateX(0.2deg) rotateY(3deg) rotateZ(-3deg);
`.replace(/\n/g, ' ');

// twitch box
create_arrow(...percent(3, 45, 30, 30), {
message: "I stream on twitch! Sometimes.",
click: () => location.href = "https://twitch.tv/fennifith"
});

// headphones box
create_arrow(...percent(0, 82, 18, 18), {
message: "Listen to some music!",
click: () => {
// play a song! (if it isn't playing already)
if (_sounds.music.paused) {
_sounds.music = new Audio(_musicList[Math.floor(Math.random() * _musicList.length)])
_sounds.music.volume = 0.2;
_sounds.music.play();
} else {
_sounds.music.pause();
}
}
});

// gpu box
create_arrow(...percent(33, 56, 15, 20), {
message: "My eGPU",
click: () => {
_message = {
text: "I've recently been setting up an external GPU for my laptop! The laptop runs Arch Linux - not Windows - and has a complicated window manager that makes things difficult. Sometimes when I run Zoom, the GPU decides it doesn't want to, and causes a kernel panic that locks out my entire PC!",
visible: true
};
}
});

// keyboard box
create_arrow(...percent(25, 85, 40, 15), {
message: "Mechanical keyboards are great!",
click: () => {
_message = {
text: "My keyboard is admittedly nothing special - an ET I-500 with Gateron Blue switches - but it is a lot more satisfying than the alternative options! It does get a bit noisy at times, but the clicky feedback (and the fact that I no longer get terrible wrist pains) is definitely worth any downsides!",
visible: true
};
}
});

// second monitor (programming) box
create_arrow(...percent(50, 38, 48, 42), {
message: "Open Source Software",
click: () => {
_message = {
text: "I write software! I'm a CS major, so that would make sense, but I've also published a few open source tools & libraries on my site (jfenn.me) - notably, an alarm clock I've been writing for 4 years! It still has some reliability issues, though - and I can't debug it if it doesn't wake me up!",
visible: true
};
}
});
}

function create_arrow(x, y, w, h, { message, hover, click }) {
if (mouseInRect(...absolute(x, y, w, h)) && !_message.visible) {
// draw floating arrow
const floatDiff = Math.sin(frameCount / Math.PI) * 10;
fill(50, 50, 255);
triangle(
x + (w * .5) - 10, y + floatDiff,
x + (w * .5) + 10, y + floatDiff,
x + (w * .5), y + 20 + floatDiff
);

if (message) {
textSize(width/60);
const tw = textWidth(message);
fill(0, 0, 0);
noStroke();
rect(x + (w * .5) - (tw * .5) - 5, y - (.03 * width) - (width/60), tw + 10, (width/60) * 1.5);
fill(255, 255, 255);
text(message, x + (w * .5) - (tw * .5), y - (.03 * width));
}

// debug rect
//stroke(0, 0, 0);
//noFill();
//rect(x, y, w, h);

// hover/click actions
if (hover) hover();
if (click && _mouseIsClicked) {
_mouseIsClicked = false;
click();
}
}
}

function windowResized() {
let scaledWidth = Math.min(windowHeight * (4/3), windowWidth) * 0.9;
let scaledHeight = Math.min(windowWidth * (3/4), windowHeight) * 0.9;
createCanvas(scaledWidth, scaledHeight);

document.getElementById('elementContainer').style.perspective = `${Math.floor(.1 * scaledWidth)}px`;
}

function percent(...nums) {
return nums.map((value, index) => {
if (index % 2 == 0) { // index 0 or 2: width parameter
return (value*width) / 100;
} else { // index 1 or 3: height parameter
return (value*height) / 100;
}
});
}

function absolute(...nums) {
return nums.map((value, index) => {
if (index % 2 == 0) { // index 0 or 2: width parameter
return (value*100) / width;
} else { // index 1 or 3: height parameter
return (value*100) / height;
}
})
}

function mousePos() {
return [mouseX*100/width, mouseY*100/height];
}

function mouseInRect(x, y, w, h) {
const [mouseX, mouseY] = mousePos();
return mouseX > x && mouseY > y && mouseX < x+w && mouseY < y+h;
}

Loading…
Cancel
Save