mirror of
https://github.com/NohamR/Pocket-Bird.git
synced 2026-05-24 19:59:36 +00:00
Move anim class and stylesheet
This commit is contained in:
48
src/anim.js
Normal file
48
src/anim.js
Normal file
@@ -0,0 +1,48 @@
|
||||
import Frame from "./frame.js";
|
||||
import { BirdType } from "./sprites";
|
||||
|
||||
class Anim {
|
||||
/**
|
||||
* @param {Frame[]} frames
|
||||
* @param {number[]} durations
|
||||
* @param {boolean} loop
|
||||
*/
|
||||
constructor(frames, durations, loop = true) {
|
||||
this.frames = frames;
|
||||
this.durations = durations;
|
||||
this.loop = loop;
|
||||
}
|
||||
|
||||
getAnimationDuration() {
|
||||
return this.durations.reduce((a, b) => a + b, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {CanvasRenderingContext2D} ctx
|
||||
* @param {number} direction
|
||||
* @param {number} timeStart The start time of the animation in milliseconds
|
||||
* @param {number} canvasPixelSize The size of a canvas pixel in pixels
|
||||
* @param {BirdType} [species] The species to use for the animation
|
||||
* @returns {boolean} Whether the animation is complete
|
||||
*/
|
||||
draw(ctx, direction, timeStart, canvasPixelSize, species) {
|
||||
let time = Date.now() - timeStart;
|
||||
const duration = this.getAnimationDuration();
|
||||
if (this.loop) {
|
||||
time %= duration;
|
||||
}
|
||||
let totalDuration = 0;
|
||||
for (let i = 0; i < this.durations.length; i++) {
|
||||
totalDuration += this.durations[i];
|
||||
if (time < totalDuration) {
|
||||
this.frames[i].draw(ctx, direction, canvasPixelSize, species);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Draw the last frame if the animation is complete
|
||||
this.frames[this.frames.length - 1].draw(ctx, direction, canvasPixelSize, species);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export default Anim;
|
||||
50
src/birb.js
50
src/birb.js
@@ -11,6 +11,7 @@ import {
|
||||
|
||||
import Frame from './frame.js';
|
||||
import Layer from './layer.js';
|
||||
import Anim from './anim.js';
|
||||
|
||||
// @ts-ignore
|
||||
const SHARED_CONFIG = {
|
||||
@@ -70,49 +71,6 @@ let userSettings = {};
|
||||
|
||||
const STYLESHEET = `___STYLESHEET___`;
|
||||
|
||||
class Anim {
|
||||
/**
|
||||
* @param {Frame[]} frames
|
||||
* @param {number[]} durations
|
||||
* @param {boolean} loop
|
||||
*/
|
||||
constructor(frames, durations, loop = true) {
|
||||
this.frames = frames;
|
||||
this.durations = durations;
|
||||
this.loop = loop;
|
||||
}
|
||||
|
||||
getAnimationDuration() {
|
||||
return this.durations.reduce((a, b) => a + b, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {CanvasRenderingContext2D} ctx
|
||||
* @param {number} direction
|
||||
* @param {number} timeStart The start time of the animation in milliseconds
|
||||
* @param {BirdType} [species] The species to use for the animation
|
||||
* @returns {boolean} Whether the animation is complete
|
||||
*/
|
||||
draw(ctx, direction, timeStart, species) {
|
||||
let time = Date.now() - timeStart;
|
||||
const duration = this.getAnimationDuration();
|
||||
if (this.loop) {
|
||||
time %= duration;
|
||||
}
|
||||
let totalDuration = 0;
|
||||
for (let i = 0; i < this.durations.length; i++) {
|
||||
totalDuration += this.durations[i];
|
||||
if (time < totalDuration) {
|
||||
this.frames[i].draw(ctx, direction, CANVAS_PIXEL_SIZE, species);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Draw the last frame if the animation is complete
|
||||
this.frames[this.frames.length - 1].draw(ctx, direction, CANVAS_PIXEL_SIZE, species);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const DEFAULT_BIRD = "bluebird";
|
||||
|
||||
const SPRITE_WIDTH = 32;
|
||||
@@ -710,7 +668,7 @@ Promise.all([
|
||||
}
|
||||
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
if (currentAnimation.draw(ctx, direction, animStart, SPECIES[currentSpecies])) {
|
||||
if (currentAnimation.draw(ctx, direction, animStart, CANVAS_PIXEL_SIZE, SPECIES[currentSpecies])) {
|
||||
setAnimation(Animations.STILL);
|
||||
}
|
||||
|
||||
@@ -909,7 +867,7 @@ Promise.all([
|
||||
return;
|
||||
}
|
||||
// Draw the decoration
|
||||
DECORATION_ANIMATIONS.mac.draw(decorationCtx, Directions.LEFT, Date.now());
|
||||
DECORATION_ANIMATIONS.mac.draw(decorationCtx, Directions.LEFT, CANVAS_PIXEL_SIZE, Date.now());
|
||||
// Add the decoration to the page
|
||||
document.body.appendChild(decorationCanvas);
|
||||
makeDraggable(decorationCanvas, false);
|
||||
@@ -945,7 +903,7 @@ Promise.all([
|
||||
if (!featherCtx) {
|
||||
return;
|
||||
}
|
||||
FEATHER_ANIMATIONS.feather.draw(featherCtx, Directions.LEFT, Date.now(), type);
|
||||
FEATHER_ANIMATIONS.feather.draw(featherCtx, Directions.LEFT, Date.now(), CANVAS_PIXEL_SIZE, type);
|
||||
document.body.appendChild(featherCanvas);
|
||||
onClick(featherCanvas, () => {
|
||||
unlockBird(birdType);
|
||||
|
||||
344
src/stylesheet.css
Normal file
344
src/stylesheet.css
Normal file
@@ -0,0 +1,344 @@
|
||||
:root {
|
||||
--birb-border-size: 2px;
|
||||
--birb-neg-border-size: calc(var(--birb-border-size) * -1);
|
||||
--birb-double-border-size: calc(var(--birb-border-size) * 2);
|
||||
--birb-neg-double-border-size: calc(var(--birb-neg-border-size) * 2);
|
||||
--birb-highlight: #ffa3cb;
|
||||
--birb-border-color: var(--birb-highlight);
|
||||
--birb-background-color: #ffecda;
|
||||
--birb-mix-color: color-mix(in srgb, var(--birb-highlight) 50%, var(--birb-background-color));
|
||||
--birb-scale: ${BIRB_CSS_SCALE};
|
||||
--birb-ui-scale: ${UI_CSS_SCALE};
|
||||
}
|
||||
|
||||
#birb {
|
||||
image-rendering: pixelated;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
transform: scale(var(--birb-scale)) !important;
|
||||
transform-origin: bottom;
|
||||
z-index: 2147483638 !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.birb-absolute {
|
||||
position: absolute !important;
|
||||
}
|
||||
|
||||
.birb-decoration {
|
||||
image-rendering: pixelated;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
transform: scale(var(--birb-scale)) !important;
|
||||
transform-origin: bottom;
|
||||
z-index: 2147483630 !important;
|
||||
}
|
||||
|
||||
.birb-window {
|
||||
font-family: "Monocraft", monospace !important;
|
||||
line-height: initial !important;
|
||||
color: #000000 !important;
|
||||
z-index: 2147483639 !important;
|
||||
position: fixed;
|
||||
background-color: var(--birb-background-color);
|
||||
box-shadow:
|
||||
var(--birb-border-size) 0 var(--birb-border-color),
|
||||
var(--birb-neg-border-size) 0 var(--birb-border-color),
|
||||
0 var(--birb-neg-border-size) var(--birb-border-color),
|
||||
0 var(--birb-border-size) var(--birb-border-color),
|
||||
var(--birb-double-border-size) 0 var(--birb-border-color),
|
||||
var(--birb-neg-double-border-size) 0 var(--birb-border-color),
|
||||
0 var(--birb-neg-double-border-size) var(--birb-border-color),
|
||||
0 var(--birb-double-border-size) var(--birb-border-color),
|
||||
0 0 0 var(--birb-border-size) var(--birb-border-color),
|
||||
0 0 0 var(--birb-double-border-size) white,
|
||||
var(--birb-double-border-size) 0 0 var(--birb-border-size) white,
|
||||
var(--birb-neg-double-border-size) 0 0 var(--birb-border-size) white,
|
||||
0 var(--birb-neg-double-border-size) 0 var(--birb-border-size) white,
|
||||
0 var(--birb-double-border-size) 0 var(--birb-border-size) white;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
transform: scale(var(--birb-ui-scale)) !important;
|
||||
animation: pop-in 0.08s;
|
||||
transition-timing-function: ease-in;
|
||||
}
|
||||
|
||||
#birb-menu {
|
||||
transition-duration: 0.2s;
|
||||
transition-timing-function: ease-out;
|
||||
min-width: 140px;
|
||||
z-index: 2147483639 !important;
|
||||
}
|
||||
|
||||
#birb-menu-exit {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 2147483637 !important;
|
||||
}
|
||||
|
||||
@keyframes pop-in {
|
||||
0% {
|
||||
opacity: 1;
|
||||
transform: scale(0.1);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: scale(var(--birb-ui-scale));
|
||||
}
|
||||
}
|
||||
|
||||
.birb-window-header {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 7px;
|
||||
padding-top: 3px;
|
||||
padding-bottom: 3px;
|
||||
padding-left: 30px;
|
||||
padding-right: 30px;
|
||||
background-color: var(--birb-highlight);
|
||||
box-shadow:
|
||||
var(--birb-border-size) 0 var(--birb-highlight),
|
||||
var(--birb-neg-border-size) 0 var(--birb-highlight),
|
||||
0 var(--birb-neg-border-size) var(--birb-highlight),
|
||||
var(--birb-neg-border-size) var(--birb-border-size) var(--birb-border-color),
|
||||
var(--birb-border-size) var(--birb-border-size) var(--birb-border-color);
|
||||
color: var(--birb-border-color) !important;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.birb-window-title {
|
||||
text-align: center;
|
||||
flex-grow: 1;
|
||||
user-select: none;
|
||||
color: var(--birb-background-color);
|
||||
}
|
||||
|
||||
.birb-window-close {
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
right: 0;
|
||||
color: var(--birb-background-color);
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.birb-window-close:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.birb-window-content {
|
||||
box-sizing: border-box;
|
||||
background-color: var(--birb-background-color);
|
||||
margin-top: var(--birb-border-size);
|
||||
flex-grow: 1;
|
||||
box-shadow:
|
||||
var(--birb-border-size) 0 var(--birb-background-color),
|
||||
var(--birb-neg-border-size) 0 var(--birb-background-color),
|
||||
0 var(--birb-border-size) var(--birb-background-color),
|
||||
0 var(--birb-neg-border-size) var(--birb-border-color),
|
||||
0 var(--birb-border-size) var(--birb-border-color);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding-top: calc(var(--birb-double-border-size));
|
||||
padding-bottom: var(--birb-border-size);
|
||||
}
|
||||
|
||||
.birb-pico-8-content {
|
||||
background: #111111;
|
||||
box-shadow: none;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.birb-pico-8-content iframe {
|
||||
width: 300px;
|
||||
margin-left: -15px;
|
||||
margin-right: -30px;
|
||||
margin-top: -10px;
|
||||
margin-bottom: -23px;
|
||||
border: none;
|
||||
aspect-ratio: 1;
|
||||
}
|
||||
|
||||
.birb-music-player-content {
|
||||
background: var(--birb-background-color);
|
||||
box-shadow:
|
||||
var(--birb-border-size) 0 var(--birb-background-color),
|
||||
var(--birb-neg-border-size) 0 var(--birb-background-color),
|
||||
0 var(--birb-border-size) var(--birb-background-color),
|
||||
0 var(--birb-neg-border-size) var(--birb-border-color),
|
||||
0 var(--birb-border-size) var(--birb-border-color);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.birb-menu-item {
|
||||
width: calc(100% - var(--birb-double-border-size));
|
||||
font-size: 14px;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
box-sizing: border-box;
|
||||
opacity: 0.7 !important;
|
||||
user-select: none;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
cursor: pointer;
|
||||
color: black !important;
|
||||
}
|
||||
|
||||
.birb-menu-item:hover {
|
||||
opacity: 1 !important;
|
||||
background: var(--birb-highlight) !important;
|
||||
color: white !important;
|
||||
box-shadow:
|
||||
var(--birb-border-size) 0 var(--birb-highlight),
|
||||
var(--birb-neg-border-size) 0 var(--birb-highlight),
|
||||
0 var(--birb-neg-border-size) var(--birb-highlight),
|
||||
0 var(--birb-border-size) var(--birb-highlight);
|
||||
}
|
||||
|
||||
.birb-menu-item-arrow {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.birb-window-separator {
|
||||
width: 100%;
|
||||
height: var(--birb-border-size);
|
||||
background-color: var(--birb-border-color);
|
||||
box-sizing: border-box;
|
||||
margin-top: var(--birb-double-border-size);
|
||||
margin-bottom: var(--birb-double-border-size);
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
#birb-field-guide {
|
||||
width: 340px;
|
||||
}
|
||||
|
||||
.birb-grid-content {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
flex-direction: row;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.birb-grid-item {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
overflow: hidden;
|
||||
margin-top: 6px;
|
||||
margin-bottom: 6px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.birb-grid-item:hover {
|
||||
border-color: var(--birb-highlight);
|
||||
}
|
||||
|
||||
.birb-grid-item canvas {
|
||||
image-rendering: pixelated;
|
||||
transform: scale(2);
|
||||
padding-bottom: var(--birb-border-size);
|
||||
}
|
||||
|
||||
.birb-grid-item, .birb-field-guide-description, .birb-message-content {
|
||||
border: var(--birb-border-size) solid rgb(255, 207, 144);
|
||||
box-shadow: 0 0 0 var(--birb-border-size) white;
|
||||
background: rgba(255, 221, 177, 0.5);
|
||||
}
|
||||
|
||||
.birb-grid-item-locked {
|
||||
cursor: auto;
|
||||
filter: grayscale(100%) sepia(30%);
|
||||
}
|
||||
|
||||
.birb-grid-item-locked canvas {
|
||||
filter: contrast(90%);
|
||||
}
|
||||
|
||||
.birb-grid-item-selected {
|
||||
border: var(--birb-border-size) solid var(--birb-highlight);
|
||||
background: var(--birb-mix-color);
|
||||
}
|
||||
|
||||
.birb-field-guide-description {
|
||||
width: calc(100% - 20px);
|
||||
margin-top: 5px;
|
||||
padding: 8px;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
margin-bottom: 10px;
|
||||
font-size: 14px;
|
||||
box-sizing: border-box;
|
||||
color: rgb(124, 108, 75);
|
||||
}
|
||||
|
||||
#birb-feather {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.birb-message-content {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
margin-top: 10px;
|
||||
padding: 8px;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
font-size: 14px;
|
||||
color: rgb(124, 108, 75);
|
||||
}
|
||||
|
||||
.birb-sticky-note {
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.birb-sticky-note > .birb-window-content {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.birb-sticky-note-input {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 10px !important;
|
||||
resize: both !important;
|
||||
min-width: 175px !important;
|
||||
min-height: 135px !important;
|
||||
box-sizing: border-box !important;
|
||||
font-family: "Monocraft", monospace !important;
|
||||
font-size: 14px !important;
|
||||
color: black !important;
|
||||
background-color: transparent !important;
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.birb-sticky-note-input:focus {
|
||||
outline: none;
|
||||
}
|
||||
Reference in New Issue
Block a user