Add bats!

This commit is contained in:
Trenton Zimmer 2024-10-12 23:50:48 -04:00
parent ba7f53f726
commit 5582de9ea9
3 changed files with 220 additions and 0 deletions

View File

@ -48,6 +48,14 @@
</noscript>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
<!-- Bats! -->
<script src="https://code.jquery.com/jquery.js"></script>
<script src="/assets/halloween-bats.js"></script>
<script type="text/javascript">
window.halloweenBats = $.halloweenBats({
image: "/assets/bats.png",
});
</script>
<!-- built files will be auto injected -->
<audio id="audio" src="/assets/sounds/konami.mp3" class="hidden">
</body>

BIN
public/assets/bats.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1,212 @@
(function ($) {
'use strict';
var innerWidth,
innerHeight;
function Bat($body, options) {
this._options = options;
this._initialize($body);
}
Bat.prototype._initialize = function ($body) {
this._$bat = $('<div class="halloween-bat"/>');
this._x = this.randomPosition('horizontal');
this._y = this.randomPosition('vertical');
this._tx = this.randomPosition('horizontal');
this._ty = this.randomPosition('vertical');
this._dx = -5 + Math.random() * 10;
this._dy = -5 + Math.random() * 10;
this._positionUpdateTimer = this._getPositionUpdateTime();
this._frame = Math.random() * this._options.frames;
this._frame = Math.round(this._frame);
this._$bat.css({
position: 'absolute',
left: this._x + 'px',
top: this._y + 'px',
zIndex: this._options.zIndex,
width: this._options.width + 'px',
height: this._options.height + 'px',
backgroundImage: 'url(' + this._options.image + ')',
backgroundRepeat: 'no-repeat'
});
$body.append(this._$bat);
};
/**
* @returns {number}
* @private
*/
Bat.prototype._getPositionUpdateTime = function () {
return 0.5 + Math.random();
};
/**
* @param {string} direction
* @returns {number}
*/
Bat.prototype.randomPosition = function (direction) {
var screenLength,
imageLength;
if (direction === 'horizontal') {
screenLength = innerWidth;
imageLength = this._options.width;
}
else {
screenLength = innerHeight;
imageLength = this._options.height;
}
return Math.random() * (screenLength - imageLength);
};
Bat.prototype.move = function (deltaTime) {
var left,
top,
length,
dLeft,
dTop,
ddLeft,
ddTop;
left = this._tx - this._x;
top = this._ty - this._y;
length = Math.sqrt(left * left + top * top);
length = Math.max(1, length);
dLeft = this._options.speed * (left / length);
dTop = this._options.speed * (top / length);
ddLeft = (dLeft - this._dx) / this._options.flickering;
ddTop = (dTop - this._dy) / this._options.flickering;
this._dx += ddLeft * deltaTime * 25;
this._dy += ddTop * deltaTime * 25;
this._x += this._dx * deltaTime * 25;
this._y += this._dy * deltaTime * 25;
this._x = Math.max(0, Math.min(this._x, innerWidth - this._options.width));
this._y = Math.max(0, Math.min(this._y, innerHeight - this._options.height));
this.applyPosition();
this._positionUpdateTimer -= deltaTime;
if (this._positionUpdateTimer < 0) {
this._tx = this.randomPosition('horizontal');
this._ty = this.randomPosition('vertical');
this._positionUpdateTimer = this._getPositionUpdateTime();
}
};
Bat.prototype.applyPosition = function () {
this._$bat.css({
left: this._x + 'px',
top: this._y + 'px'
});
};
Bat.prototype.animate = function (deltaTime) {
var frame;
this._frame += 5 * deltaTime;
if (this._frame >= this._options.frames) {
this._frame -= this._options.frames;
}
frame = Math.floor(this._frame);
this._$bat.css(
'backgroundPosition',
'0 ' + (frame * -this._options.height) + 'px'
);
};
$.halloweenBats = function (options) {
var $window = $(window),
$target,
plugin,
isRunning = false,
isActiveWindow = true,
bats = [],
defaults = {
image: 'bats.png', // Path to the image.
zIndex: 10000, // The z-index you need.
amount: 3, // Bat amount.
width: 35, // Image width.
height: 20, // Animation frame height.
frames: 4, // Amount of animation frames.
speed: 20, // Higher value = faster.
flickering: 15, // Higher value = slower.
target: 'body' // Target element
};
options = $.extend({}, defaults, options);
$target = $(options.target);
innerWidth = $target.innerWidth();
innerHeight = $target.innerHeight();
plugin = {
isRunning: false,
start: function() {
var lastTime = Date.now();
isRunning = true;
function animate() {
var time = Date.now(),
deltaTime = (time - lastTime) / 1000;
lastTime = time;
if (isActiveWindow) {
$.each(bats, function (index, bat) {
bat.move(deltaTime);
bat.animate(deltaTime);
});
}
if (isRunning) {
requestAnimationFrame(animate);
}
}
animate();
},
stop: function() {
isRunning = false;
}
};
while (bats.length < options.amount) {
bats.push(new Bat($target, options));
}
plugin.start();
$window.resize(function () {
innerWidth = $target.innerWidth();
innerHeight = $target.innerHeight();
});
$window.focus(function() {
isActiveWindow = true;
});
$window.blur(function() {
isActiveWindow = false;
});
return plugin;
};
}(jQuery));