noname/extension/coin/extension.js

1645 lines
47 KiB
JavaScript
Raw Normal View History

2024-04-15 16:50:54 +00:00
import { lib, game, ui, get, ai, _status } from "../../noname.js";
game.import("play", function () {
2017-04-15 00:25:50 +00:00
return {
2024-04-15 16:50:54 +00:00
name: "coin",
init: function () {
if (
lib.config.mode != "chess" ||
get.config("chess_mode") != "leader"
) {
_status.coin = 0;
2015-12-28 07:30:15 +00:00
}
2017-04-15 00:25:50 +00:00
},
2024-04-15 16:50:54 +00:00
arenaReady: function () {
if (_status.video || _status.connectMode) return;
if (
lib.config.mode != "chess" ||
get.config("chess_mode") != "leader"
) {
2017-04-15 00:25:50 +00:00
var str;
2024-04-15 16:50:54 +00:00
if (lib.config.coin_display_playpackconfig == "text") {
str = "<span>" + lib.config.coin + "</span><span>金</span>";
} else {
str =
'<span style="position:absolute">㉤</span><span style="margin-left:18px;font-family:xinwei;line-height:10px">' +
lib.config.coin +
"</span>";
2017-04-15 00:25:50 +00:00
}
2024-04-15 16:50:54 +00:00
if (lib.config.coin_canvas_playpackconfig) {
ui.window.classList.add("canvas_top");
2017-04-15 00:25:50 +00:00
}
2024-04-15 16:50:54 +00:00
ui.coin = ui.create.system(str, null, true);
if (lib.config.snowFall) {
game.haveFun.list.snow.bought = true;
setTimeout(function () {
2017-04-15 00:25:50 +00:00
game.haveFun.snow();
2024-04-15 16:50:54 +00:00
}, 500);
2017-04-15 00:25:50 +00:00
}
2024-04-15 16:50:54 +00:00
lib.setPopped(
ui.coin,
function () {
var uiintro = ui.create.dialog("hidden");
uiintro.classList.add("coin_menu");
uiintro.add("商店");
uiintro.listen(function (e) {
e.stopPropagation();
});
var clickBuy = function () {
if (this.innerHTML == "停止") {
game.haveFun[this.name + "Stop"]();
} else if (this.innerHTML == "开始") {
2017-04-15 00:25:50 +00:00
game.haveFun[this.name]();
2024-04-15 16:50:54 +00:00
} else if (this.innerHTML.indexOf("金") != -1) {
if (lib.config.coin >= this.content.cost) {
this.content.bought = true;
game.changeCoin(-this.content.cost);
game.haveFun[this.name]();
if (this.content.onbuy) {
this.content.onbuy.call(this);
}
} else {
return;
2017-04-15 00:25:50 +00:00
}
}
2024-04-15 16:50:54 +00:00
ui.click.window();
};
for (var i in game.haveFun.list) {
var item = game.haveFun.list[i];
uiintro.add(
'<div class="coin_buy">' +
item.name +
'<div class="menubutton">' +
item.cost +
"金</span></div></div>"
);
var buy =
uiintro.content.lastChild.lastChild.lastChild;
if (lib.config.coin < item.cost && !item.bought) {
buy.classList.add("disabled");
2015-12-30 04:00:49 +00:00
}
2024-04-15 16:50:54 +00:00
if (item.bought) {
if (item.running) {
buy.innerHTML = "停止";
if (item.control) {
var node = item.control();
if (node) {
buy.parentNode.appendChild(
node,
buy
);
}
2017-04-15 00:25:50 +00:00
}
2024-04-15 16:50:54 +00:00
} else {
buy.innerHTML = "开始";
2015-12-31 07:03:13 +00:00
}
}
2024-04-15 16:50:54 +00:00
buy.name = i;
buy.content = item;
buy.listen(clickBuy);
2015-12-28 09:08:52 +00:00
}
2015-12-30 04:00:49 +00:00
2024-04-15 16:50:54 +00:00
if (!game.phaseNumber && !game.online) {
uiintro.add("下注");
uiintro.add(
'<div class="coin_buy">本局获胜<div class="menubutton">20金</span></div></div>'
);
var bet =
uiintro.content.lastChild.lastChild.lastChild;
bet.listen(function () {
if (_status.betWin) return;
_status.betWin = true;
game.changeCoin(-20);
this.innerHTML = "已下注";
});
if (_status.betWin) {
bet.innerHTML = "已下注";
}
} else if (_status.betWin) {
uiintro.add("下注");
uiintro.add(
'<div class="coin_buy">本局获胜<div class="menubutton">已下注</span></div></div>'
);
2017-04-15 00:25:50 +00:00
}
2015-12-28 09:08:52 +00:00
2024-04-15 16:50:54 +00:00
uiintro.classList.add("noleave");
2015-12-30 04:00:49 +00:00
2024-04-15 16:50:54 +00:00
return uiintro;
},
220,
400
);
2015-12-15 05:13:47 +00:00
}
2018-04-17 07:32:43 +00:00
},
2024-04-15 16:50:54 +00:00
game: {
changeCoin: function (num) {
if (typeof num == "number" && ui.coin) {
game.saveConfig("coin", lib.config.coin + num);
2017-04-15 00:25:50 +00:00
var str;
2024-04-15 16:50:54 +00:00
if (lib.config.coin_display_playpackconfig == "text") {
str =
"<span>" +
lib.config.coin +
"</span><span>金</span>";
} else {
str =
'<span style="position:absolute">㉤</span><span style="margin-left:18px;font-family:xinwei;line-height:10px">' +
lib.config.coin +
"</span>";
2017-04-15 00:25:50 +00:00
}
2024-04-15 16:50:54 +00:00
ui.coin.innerHTML = str;
2017-04-15 00:25:50 +00:00
}
},
2024-04-15 16:50:54 +00:00
haveFun: {
list: {
firework: {
name: "烟花",
cost: 50,
2017-04-15 00:25:50 +00:00
},
2024-04-15 16:50:54 +00:00
snow: {
name: "下雪",
cost: 20,
size: "large",
control: function () {
var size = ui.create.div(".menubutton");
if (game.haveFun.list.snow.size == "small") {
size.innerHTML = "大雪";
} else {
size.innerHTML = "小雪";
2017-04-15 00:25:50 +00:00
}
size.listen(game.haveFun.snowSize);
return size;
2024-04-15 16:50:54 +00:00
},
2017-04-15 00:25:50 +00:00
},
2024-04-15 16:50:54 +00:00
star: {
name: "星云",
cost: 10,
},
blink: {
name: "闪烁",
cost: 10,
2017-04-15 00:25:50 +00:00
},
2015-12-30 04:00:49 +00:00
},
2024-04-15 16:50:54 +00:00
alwaysSnow: function () {
game.saveConfig("snowFall", !lib.config.snowFall);
2017-04-15 00:25:50 +00:00
game.reload();
2015-12-30 04:00:49 +00:00
},
2024-04-15 16:50:54 +00:00
blink: function () {
if (game.haveFun.list.blink.running) return;
game.haveFun.list.blink.running = true;
if (game.haveFun.blinkLoop) {
2017-04-15 00:25:50 +00:00
game.haveFun.blinkLoop();
2024-04-15 16:50:54 +00:00
} else {
2017-04-15 00:25:50 +00:00
var canvas = document.createElement("canvas");
ui.window.appendChild(canvas);
2024-04-15 16:50:54 +00:00
canvas.classList.add("fun");
canvas.style.zIndex = 20;
2017-04-15 00:25:50 +00:00
var ctx = canvas.getContext("2d");
//Make the canvas occupy the full page
2024-04-15 16:50:54 +00:00
var W = ui.window.offsetWidth,
H = ui.window.offsetHeight;
2015-12-30 04:00:49 +00:00
canvas.width = W;
canvas.height = H;
2024-04-15 16:50:54 +00:00
lib.onresize.push(function () {
var W = ui.window.offsetWidth,
H = ui.window.offsetHeight;
2017-04-15 00:25:50 +00:00
canvas.width = W;
canvas.height = H;
});
2015-12-30 04:00:49 +00:00
2017-04-15 00:25:50 +00:00
var particles = [];
var mouse = {};
2015-12-30 04:00:49 +00:00
2017-04-15 00:25:50 +00:00
//Lets create some particles now
var particle_count = 25;
2015-12-30 04:00:49 +00:00
2017-04-15 00:25:50 +00:00
//finally some mouse tracking
2024-04-15 16:50:54 +00:00
ui.window.addEventListener("mousemove", function (e) {
2017-04-15 00:25:50 +00:00
//since the canvas = full page the position of the mouse
//relative to the document will suffice
2024-04-15 16:50:54 +00:00
mouse.x = e.pageX / game.documentZoom;
mouse.y = e.pageY / game.documentZoom;
2017-04-15 00:25:50 +00:00
});
2024-04-15 16:50:54 +00:00
ui.window.addEventListener("touchmove", function (e) {
mouse.x = e.touches[0].clientX / game.documentZoom;
mouse.y = e.touches[0].clientY / game.documentZoom;
2017-04-15 00:25:50 +00:00
});
2015-12-30 04:00:49 +00:00
2024-04-15 16:50:54 +00:00
var particle = function () {
2017-04-15 00:25:50 +00:00
//speed, life, location, life, colors
//speed.x range = -2.5 to 2.5
//speed.y range = -15 to -5 to make it move upwards
//lets change the Y speed to make it look like a flame
2024-04-15 16:50:54 +00:00
this.speed = {
x: -2.5 + Math.random() * 5,
y: -5 + Math.random() * 10,
};
this.speed.x /= 4;
this.speed.y /= 4;
2017-04-15 00:25:50 +00:00
//location = mouse coordinates
//Now the flame follows the mouse coordinates
2024-04-15 16:50:54 +00:00
if (mouse.x && mouse.y) {
this.location = { x: mouse.x, y: mouse.y };
} else {
this.location = { x: W / 2, y: H / 2 };
2017-04-15 00:25:50 +00:00
}
//radius range = 10-30
2024-04-15 16:50:54 +00:00
this.radius = 10 + Math.random() * 20;
2017-04-15 00:25:50 +00:00
//life range = 20-30
2024-04-15 16:50:54 +00:00
this.radius /= 4;
this.life = 20 + Math.random() * 10;
this.life *= 4;
2017-04-15 00:25:50 +00:00
this.remaining_life = this.life;
//colors
2024-04-15 16:50:54 +00:00
this.r = Math.round(Math.random() * 255);
this.g = Math.round(Math.random() * 255);
this.b = Math.round(Math.random() * 255);
};
for (var i = 0; i < particle_count; i++) {
2017-04-15 00:25:50 +00:00
particles.push(new particle());
2015-12-30 04:00:49 +00:00
}
2024-04-15 16:50:54 +00:00
var draw = function () {
if (!game.haveFun.list.blink.running) {
canvas.width = W;
canvas.height = H;
2017-04-15 00:25:50 +00:00
return;
}
ctx.clearRect(0, 0, W, H);
//Painting the canvas black
//Time for lighting magic
//particles are painted with "lighter"
//In the next frame the background is painted normally without blending to the
//previous frame
ctx.globalCompositeOperation = "lighter";
2024-04-15 16:50:54 +00:00
for (var i = 0; i < particles.length; i++) {
2017-04-15 00:25:50 +00:00
var p = particles[i];
ctx.beginPath();
//changing opacity according to the life.
//opacity goes to 0 at the end of life of a particle
2024-04-15 16:50:54 +00:00
p.opacity =
Math.round(
(p.remaining_life / p.life) * 100
) / 100;
2017-04-15 00:25:50 +00:00
//a gradient instead of white fill
2024-04-15 16:50:54 +00:00
var gradient = ctx.createRadialGradient(
p.location.x,
p.location.y,
0,
p.location.x,
p.location.y,
p.radius
);
gradient.addColorStop(
0,
"rgba(" +
p.r +
", " +
p.g +
", " +
p.b +
", " +
p.opacity +
")"
);
gradient.addColorStop(
0.5,
"rgba(" +
p.r +
", " +
p.g +
", " +
p.b +
", " +
p.opacity +
")"
);
gradient.addColorStop(
1,
"rgba(" +
p.r +
", " +
p.g +
", " +
p.b +
", 0)"
);
2017-04-15 00:25:50 +00:00
ctx.fillStyle = gradient;
2024-04-15 16:50:54 +00:00
ctx.arc(
p.location.x,
p.location.y,
p.radius,
Math.PI * 2,
false
);
2017-04-15 00:25:50 +00:00
ctx.fill();
//lets move the particles
p.remaining_life--;
2024-04-15 16:50:54 +00:00
p.radius -= 0.2;
2017-04-15 00:25:50 +00:00
p.location.x += p.speed.x;
p.location.y += p.speed.y;
//regenerate particles
2024-04-15 16:50:54 +00:00
if (p.remaining_life < 0 || p.radius < 0) {
2017-04-15 00:25:50 +00:00
//a brand new particle replacing the dead one
particles[i] = new particle();
}
2015-12-30 04:00:49 +00:00
}
2017-04-15 00:25:50 +00:00
requestAnimationFrame(draw);
2024-04-15 16:50:54 +00:00
};
2015-12-30 04:00:49 +00:00
2017-04-15 00:25:50 +00:00
draw();
2024-04-15 16:50:54 +00:00
game.haveFun.blinkLoop = draw;
game.haveFun.blinkStop = function () {
game.haveFun.list.blink.running = false;
};
2015-12-30 04:00:49 +00:00
}
2017-04-15 00:25:50 +00:00
},
2024-04-15 16:50:54 +00:00
star: function () {
if (game.haveFun.list.star.running) return;
game.haveFun.list.star.running = true;
if (game.haveFun.starLoop) {
2017-04-15 00:25:50 +00:00
game.haveFun.starLoop();
2024-04-15 16:50:54 +00:00
} else {
2017-04-15 00:25:50 +00:00
//******************************************************
// Yet Another Particle Engine
var cos = Math.cos,
2018-04-17 07:32:43 +00:00
sin = Math.sin,
sqrt = Math.sqrt,
abs = Math.abs,
atan2 = Math.atan2,
log = Math.log,
random = Math.random,
PI = Math.PI,
2024-04-15 16:50:54 +00:00
sqr = function (v) {
return v * v;
},
2018-04-17 07:32:43 +00:00
particles = [],
drawScale = 1,
emitters = [],
2024-04-15 16:50:54 +00:00
forces = [],
2018-04-17 07:32:43 +00:00
collidedMass = 0,
maxParticles = 100,
emissionRate = 1,
2017-04-15 00:25:50 +00:00
minParticleSize = 2;
//-------------------------------------------------------
// Vectors, and not the kind you put stuff in
2024-04-15 16:50:54 +00:00
var Vector = function (x, y, z) {
this.x = x || 0;
this.y = y || 0;
this.z = z || 0;
};
2017-04-15 00:25:50 +00:00
Vector.prototype = {
2024-04-15 16:50:54 +00:00
add: function (vector) {
this.x += vector.x;
this.y += vector.y;
this.z += vector.z;
return this;
},
subtract: function (vector) {
this.x -= vector.x;
this.y -= vector.y;
this.z -= vector.z;
return this;
},
multiply: function (another) {
this.x /= another.x;
this.y /= another.y;
this.z /= another.z;
return this;
},
divide: function (another) {
this.x /= another.x;
this.y /= another.y;
this.z /= another.z;
return this;
},
scale: function (factor) {
this.x *= factor;
this.y *= factor;
this.z *= factor;
return this;
},
magnitude: function () {
return sqrt(sqr(this.x + this.y));
},
distance: function (another) {
return abs(
sqrt(
sqr(this.x - another.x) +
sqr(this.y - another.y)
)
);
},
angle: function (angle, magnitude) {
if (angle && magnitude)
return Vector.fromAngle(angle, magnitude);
return atan2(this.y, this.x);
},
clone: function () {
return new Vector(this.x, this.y, this.z);
},
equals: function (another) {
return (
this.x === another.x &&
this.y === another.y &&
this.z === another.z
);
},
random: function (r) {
this.x += random() * r * 2 - r;
this.y += random() * r * 2 - r;
return this;
},
2017-04-15 00:25:50 +00:00
};
Vector.fromAngle = function (angle, magnitude) {
2024-04-15 16:50:54 +00:00
return new Vector(
magnitude * cos(angle),
magnitude * sin(angle),
magnitude * sin(angle)
);
2017-04-15 00:25:50 +00:00
};
//******************************************************
// A thing with mass, position, and velocity - like your mom
2024-04-15 16:50:54 +00:00
var Particle = function (pt, vc, ac, mass) {
this.pos = pt || new Vector(0, 0);
this.vc = vc || new Vector(0, 0);
this.ac = ac || new Vector(0, 0);
this.mass = mass || 1;
this.alive = true;
};
2017-04-15 00:25:50 +00:00
Particle.prototype.move = function () {
2024-04-15 16:50:54 +00:00
this.vc.add(this.ac);
this.pos.add(this.vc);
2017-04-15 00:25:50 +00:00
};
Particle.prototype.reactToForces = function (fields) {
2024-04-15 16:50:54 +00:00
var totalAccelerationX = 0;
var totalAccelerationY = 0;
for (var i = 0; i < fields.length; i++) {
var field = fields[i];
var vectorX = field.pos.x - this.pos.x;
var vectorY = field.pos.y - this.pos.y;
var distance = this.pos.distance(field.pos);
if (distance < 1) field.grow(this);
if (distance < 100) this.doubleSize = true;
var force = G(
this.forceBetween(field, distance)
);
totalAccelerationX += vectorX * force;
totalAccelerationY += vectorY * force;
2018-04-17 07:32:43 +00:00
}
2024-04-15 16:50:54 +00:00
this.ac = new Vector(
totalAccelerationX,
totalAccelerationY
);
totalAccelerationX = 0;
totalAccelerationY = 0;
for (var i = 0; i < particles.length; i++) {
var field = particles[i];
if (field === this || !field.alive) continue;
var vectorX = field.pos.x - this.pos.x;
var vectorY = field.pos.y - this.pos.y;
var distance = this.pos.distance(field.pos);
if (distance < 1) {
if (this.mass >= field.mass) {
var massRatio = this.mass / field.mass;
if (
particles.length <= maxParticles &&
this.mass > 40
) {
this.alive = false;
this.nova = true;
collidedMass += this.mass;
} else this.grow(field);
} else this.alive = false;
}
if (this.alive) {
var force = G(
this.forceBetween(field, distance)
);
totalAccelerationX += vectorX * G(force);
totalAccelerationY += vectorY * G(force);
}
2018-04-17 07:32:43 +00:00
}
2024-04-15 16:50:54 +00:00
var travelDist = this.pos.distance(
this.lastPos ? this.lastPos : this.pos
);
this.velocity =
travelDist -
(this.lastDistance
? this.lastDistance
: travelDist);
this.lastDistance = travelDist;
this.lastPos = this.pos.clone();
this.ac.add(
new Vector(
totalAccelerationX,
totalAccelerationY
)
);
this.lastPos = this.pos.clone();
// if(this.mass > 20) {
// var chance = 1 / (this.mass - 20);
// if(Math.random()>chance) {
// this.supernova = true;
// this.supernovaDur = 10;
// this.alive = false;
// if(particles.length <= maxParticles) collidedMass += this.mass;
// delete this.size;
// }
// }
2017-04-15 00:25:50 +00:00
};
Particle.prototype.grow = function (another) {
2024-04-15 16:50:54 +00:00
this.mass += another.mass;
this.nova = true;
another.alive = false;
delete this.size;
2017-04-15 00:25:50 +00:00
};
2024-04-15 16:50:54 +00:00
Particle.prototype.breakApart = function (
minMass,
maxParts
) {
if (!minMass) minMass = 1;
if (!maxParts) maxParts = 2;
var remainingMass = this.mass;
var num = 0;
while (remainingMass > 0) {
var np = new Particle(
this.pos.clone().random(this.mass),
new Vector(0, 0)
);
np.mass =
1 + Math.random() * (remainingMass - 1);
if (num >= maxParts - 1)
np.mass = remainingMass;
np.mass = np.mass < minMass ? minMass : np.mass;
remainingMass -= np.mass;
num++;
}
this.nova = true;
delete this.size;
this.alive = false;
2017-04-15 00:25:50 +00:00
};
2024-04-15 16:50:54 +00:00
Particle.prototype.forceBetween = function (
another,
distance
) {
var distance = distance
? distance
: this.pos.distance(another.pos);
return (this.mass * another.mass) / sqr(distance);
2017-04-15 00:25:50 +00:00
};
//******************************************************
//This certainly doesn't *sub*mit to particles, that's for sure
2024-04-15 16:50:54 +00:00
var ParticleEmitter = function (pos, vc, ang) {
// to do config options for emitter - random, static, show emitter, emitter color, etc
this.pos = pos;
this.vc = vc;
this.ang = ang || 0.09;
this.color = "#999";
};
ParticleEmitter.prototype.emit = function () {
var angle =
this.vc.angle() +
this.ang -
Math.random() * this.ang * 2;
var magnitude = this.vc.magnitude();
var position = this.pos.clone();
position.add(
2018-04-17 07:32:43 +00:00
new Vector(
2024-04-15 16:50:54 +00:00
~~(Math.random() * 100 - 50) * drawScale,
~~(Math.random() * 100 - 50) * drawScale
)
);
var velocity = Vector.fromAngle(angle, magnitude);
return new Particle(position, velocity);
2017-04-15 00:25:50 +00:00
};
//******************************************************
// Use it, Luke
// to do collapse functionality into particle
2024-04-15 16:50:54 +00:00
var Force = function (pos, m) {
this.pos = pos;
this.mass = m || 100;
};
2017-04-15 00:25:50 +00:00
Force.prototype.grow = function (another) {
2024-04-15 16:50:54 +00:00
this.mass += another.mass;
this.burp = true;
another.alive = false;
2017-04-15 00:25:50 +00:00
};
2015-12-30 04:00:49 +00:00
2024-04-15 16:50:54 +00:00
var G = function (data) {
return 0.00674 * data;
};
2015-12-30 04:00:49 +00:00
2017-04-15 00:25:50 +00:00
//******************************************************
2024-04-15 16:50:54 +00:00
var canvas = document.createElement("canvas");
canvas.classList.add("fun");
2017-04-15 00:25:50 +00:00
ui.window.appendChild(canvas);
2024-04-15 16:50:54 +00:00
var ctx = canvas.getContext("2d");
2015-12-30 04:00:49 +00:00
canvas.width = ui.window.offsetWidth;
canvas.height = ui.window.offsetHeight;
2017-04-15 00:25:50 +00:00
var canvasWidth = canvas.width;
var canvasHeight = canvas.height;
2024-04-15 16:50:54 +00:00
lib.onresize.push(function () {
2017-04-15 00:25:50 +00:00
canvas.width = ui.window.offsetWidth;
canvas.height = ui.window.offsetHeight;
canvasWidth = canvas.width;
canvasHeight = canvas.height;
});
2015-12-30 04:00:49 +00:00
2024-04-15 16:50:54 +00:00
var renderToCanvas = function (
width,
height,
renderFunction
) {
var buffer = document.createElement("canvas");
2018-04-17 07:32:43 +00:00
buffer.width = width;
buffer.height = height;
2024-04-15 16:50:54 +00:00
renderFunction(buffer.getContext("2d"));
2018-04-17 07:32:43 +00:00
return buffer;
2017-04-15 00:25:50 +00:00
};
maxParticles = 500;
emissionRate = 1;
drawScale = 1.3;
minParticleSize = 2;
emitters = [
2024-04-15 16:50:54 +00:00
//br
new ParticleEmitter(
new Vector(
(canvasWidth / 2) * drawScale + 400,
(canvasHeight / 2) * drawScale
),
Vector.fromAngle(2, 5),
1
),
// // bl
// new ParticleEmitter(
// new Vector(
// canvasWidth / 2 * drawScale - 400,
// canvasHeight / 2 * drawScale + 400
// ),
// Vector.fromAngle(1.5, 1),
// 1
// ),
2018-04-17 07:32:43 +00:00
// tl
2024-04-15 16:50:54 +00:00
new ParticleEmitter(
new Vector(
(canvasWidth / 2) * drawScale - 400,
(canvasHeight / 2) * drawScale
),
Vector.fromAngle(5, 5),
1
),
// // tr
// new ParticleEmitter(
// new Vector(
// canvasWidth / 2 * drawScale + 400,
// canvasHeight / 2 * drawScale - 400
// ),
// Vector.fromAngle(4.5, 1),
// 1
// )
2017-04-15 00:25:50 +00:00
];
2024-04-15 16:50:54 +00:00
forces = [
new Force(
new Vector(
(canvasWidth / 2) * drawScale,
(canvasHeight / 2) * drawScale
),
1800
),
2017-04-15 00:25:50 +00:00
];
2024-04-15 16:50:54 +00:00
var loop = function () {
if (!game.haveFun.list.star.running) {
canvas.width = ui.window.offsetWidth;
canvas.height = ui.window.offsetHeight;
2017-04-15 00:25:50 +00:00
return;
}
clear();
update();
draw();
queue();
2024-04-15 16:50:54 +00:00
};
game.haveFun.starLoop = loop;
game.haveFun.starStop = function () {
game.haveFun.list.star.running = false;
2017-04-15 00:25:50 +00:00
};
2015-12-30 04:00:49 +00:00
2024-04-15 16:50:54 +00:00
var clear = function () {
ctx.clearRect(0, 0, canvas.width, canvas.height);
};
2015-12-30 04:00:49 +00:00
2017-04-15 00:25:50 +00:00
var ctr = 0;
var c = [
2024-04-15 16:50:54 +00:00
"rgba(255,255,255,",
"rgba(0,150,255,",
"rgba(255,255,128,",
"rgba(255,255,255,",
2017-04-15 00:25:50 +00:00
];
2024-04-15 16:50:54 +00:00
var rndc = function () {
return c[~~(Math.random() * c.length - 1)];
};
var c2 = "rgba(255,64,32,";
var addNewParticles = function () {
var _emit = function () {
var ret = 0;
for (var i = 0; i < emitters.length; i++) {
for (var j = 0; j < emissionRate; j++) {
var p = emitters[i].emit();
p.color =
ctr % 10 === 0
? Math.random() * 5 <= 1
? c2
: rndc()
: rndc();
p.mass = ~~(Math.random() * 5);
particles.push(p);
ret += p.mass;
ctr++;
}
}
return ret;
};
if (collidedMass !== 0) {
while (collidedMass !== 0) {
collidedMass -= _emit();
collidedMass =
collidedMass < 0 ? 0 : collidedMass;
}
2018-04-17 07:32:43 +00:00
}
2024-04-15 16:50:54 +00:00
if (particles.length > maxParticles) return;
_emit();
};
2015-12-30 04:00:49 +00:00
2017-04-15 00:25:50 +00:00
var CLIPOFFSCREEN = 1,
2018-04-17 07:32:43 +00:00
BUFFEROFFSCREEN = 2,
LOOPSCREEN = 3;
2017-04-15 00:25:50 +00:00
2024-04-15 16:50:54 +00:00
var isPositionAliveAndAdjust = function (
particle,
check
) {
return true;
// var pos = particle.pos;
// if(!check) check = BUFFEROFFSCREEN;
// if(check === CLIPOFFSCREEN) {
// return !(!particle.alive ||
// pos.x < 0 ||
// (pos.x / drawScale) > boundsX ||
// pos.y < 0 ||
// (pos.y / drawScale) > boundsY);
// } else if(check === BUFFEROFFSCREEN) {
// return !(!particle.alive ||
// pos.x < -boundsX * drawScale ||
// pos.x > 2 * boundsX * drawScale ||
// pos.y < -boundsY * drawScale ||
// pos.y > 2 * boundsY * drawScale);
// } else if(check === LOOPSCREEN) {
// if (pos.x < 0) pos.x = boundsX * drawScale;
// if ((pos.x / drawScale) > boundsX) pos.x = 0;
// if (pos.y < 0) pos.y = boundsY * drawScale;
// if ((pos.y / drawScale) > boundsY) pos.y = 0;
// return true;
// }
};
2015-12-30 04:00:49 +00:00
2024-04-15 16:50:54 +00:00
var plotParticles = function (boundsX, boundsY) {
var currentParticles = [];
for (var i = 0; i < particles.length; i++) {
var particle = particles[i];
particle.reactToForces(forces);
if (!isPositionAliveAndAdjust(particle))
continue;
particle.move();
currentParticles.push(particle);
}
};
2015-12-30 04:00:49 +00:00
2017-04-15 00:25:50 +00:00
var offscreenCache = {};
2024-04-15 16:50:54 +00:00
var renderParticle = function (p) {
2018-04-17 07:32:43 +00:00
var position = p.pos;
2024-04-15 16:50:54 +00:00
if (!p.size) p.size = Math.floor(p.mass / 100);
2018-04-17 07:32:43 +00:00
2024-04-15 16:50:54 +00:00
if (!p.opacity) p.opacity = 0.05;
if (p.velocity > 0) {
if (p.opacity <= 0.18) p.opacity += 0.04;
2018-04-17 07:32:43 +00:00
}
2024-04-15 16:50:54 +00:00
if (p.opacity > 0.08) p.opacity -= 0.02;
2018-04-17 07:32:43 +00:00
var actualSize = p.size / drawScale;
2024-04-15 16:50:54 +00:00
actualSize =
actualSize < minParticleSize
? minParticleSize
: actualSize;
if (p.mass > 8) actualSize *= 2;
if (p.nova) {
actualSize *= 4;
p.nova = false;
2018-04-17 07:32:43 +00:00
}
2024-04-15 16:50:54 +00:00
if (p.doubleSize) {
p.doubleSize = false;
actualSize *= 2;
2018-04-17 07:32:43 +00:00
}
// if(p.supernova) {
// actualSize *= 6;
// opacity = 0.15;
// p.supernovaDur = p.supernovaDur - 1;
// if(p.supernovaDur === 0)
// p.supernova = false;
// }
2024-04-15 16:50:54 +00:00
var cacheKey =
actualSize + "_" + p.opacity + "_" + p.color;
2018-04-17 07:32:43 +00:00
var cacheValue = offscreenCache[cacheKey];
2024-04-15 16:50:54 +00:00
if (!cacheValue) {
cacheValue = renderToCanvas(
actualSize * 32,
actualSize * 32,
function (ofsContext) {
var opacity = p.opacity;
var fills = [
{
size: actualSize / 2,
opacity: 1,
},
{
size: actualSize,
opacity: opacity,
},
{
size: actualSize * 2,
opacity: opacity / 2,
},
{
size: actualSize * 4,
opacity: opacity / 3,
},
{
size: actualSize * 8,
opacity: opacity / 5,
},
{
size: actualSize * 16,
opacity: opacity / 16,
},
];
ofsContext.beginPath();
for (var f in fills) {
f = fills[f];
ofsContext.fillStyle =
p.color + f.opacity + ")";
ofsContext.arc(
actualSize * 16,
actualSize * 16,
f.size,
0,
Math.PI * 2,
true
);
ofsContext.fill();
}
ofsContext.closePath();
}
);
offscreenCache[cacheKey] = cacheValue;
2018-04-17 07:32:43 +00:00
}
2024-04-15 16:50:54 +00:00
var posX = p.pos.x / drawScale;
2018-04-17 07:32:43 +00:00
var posY = p.pos.y / drawScale;
ctx.drawImage(cacheValue, posX, posY);
2024-04-15 16:50:54 +00:00
};
2015-12-30 04:00:49 +00:00
2017-04-15 00:25:50 +00:00
var fills = [
2024-04-15 16:50:54 +00:00
{ size: 15, opacity: 1 },
{ size: 25, opacity: 0.3 },
{ size: 50, opacity: 0.1 },
];
2017-04-15 00:25:50 +00:00
2024-04-15 16:50:54 +00:00
var renderScene = function (ofsContext) {
for (var i = 0; i < forces.length; i++) {
var p = forces[i];
var position = p.pos;
var opacity = 1;
ofsContext.beginPath();
for (var f in fills) {
f = fills[f];
var o = p.burp === true ? 1 : f.opacity;
p.burp = false;
// ofsContext.fillStyle = 'rgba(255,255,255,' + o + ')';
// ofsContext.arc(position.x / drawScale,
// position.y / drawScale,
// f.size / drawScale, 0, Math.PI*2, true);
// ofsContext.fill();
}
ofsContext.closePath();
2018-04-17 07:32:43 +00:00
}
2017-04-15 00:25:50 +00:00
2024-04-15 16:50:54 +00:00
for (var i = 0; i < particles.length; i++) {
var p = particles[i];
renderParticle(p);
}
};
2015-12-30 04:00:49 +00:00
2024-04-15 16:50:54 +00:00
var draw = function () {
renderScene(ctx);
};
2015-12-30 04:00:49 +00:00
2024-04-15 16:50:54 +00:00
var update = function () {
addNewParticles();
plotParticles(canvas.width, canvas.height);
};
2015-12-30 04:00:49 +00:00
2024-04-15 16:50:54 +00:00
var queue = function () {
window.requestAnimationFrame(loop);
};
2015-12-30 04:00:49 +00:00
2017-04-15 00:25:50 +00:00
loop();
2015-12-28 09:08:52 +00:00
}
2017-04-15 00:25:50 +00:00
},
2024-04-15 16:50:54 +00:00
snow: function () {
game.haveFun.list.snow.running = true;
if (game.haveFun.snowStart) {
2017-04-15 00:25:50 +00:00
game.haveFun.snowStart();
2024-04-15 16:50:54 +00:00
} else {
2017-04-15 00:25:50 +00:00
/*
2024-04-15 16:50:54 +00:00
* 自由下雪 snowFall
* authorxuanfeng
* time: 2014-01-11
*/
2017-04-15 00:25:50 +00:00
// 控制下雪
var canvas;
2024-04-15 16:50:54 +00:00
var snowFall = function (snow) {
2017-04-15 00:25:50 +00:00
// 可配置属性
snow = snow || {};
2024-04-15 16:50:54 +00:00
this.maxFlake = snow.maxFlake || 200; //最多片数
this.flakeSize = snow.flakeSize || 10; //雪花形状
this.fallSpeed = snow.fallSpeed || 2; //坠落速度
this.status = 0; //0-初始化、1-开始下雪、2-停止下雪、3-暂停下雪、4-继续下雪
};
2015-12-28 09:08:52 +00:00
2017-04-15 00:25:50 +00:00
// 兼容写法
2024-04-15 16:50:54 +00:00
var requestAnimationFrame =
window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame ||
function (callback) {
setTimeout(callback, 1000 / 60);
};
var cancelAnimationFrame =
window.cancelAnimationFrame ||
window.mozCancelAnimationFrame ||
window.webkitCancelAnimationFrame ||
window.msCancelAnimationFrame ||
window.oCancelAnimationFrame;
2017-04-15 00:25:50 +00:00
// 开始下雪
2024-04-15 16:50:54 +00:00
snowFall.prototype.start = function () {
if (this.status == 1 || this.status == 4) {
2017-04-15 00:25:50 +00:00
// 已经在下雪则不作处理
return false;
}
this.status = 1;
// 创建画布
snowCanvas.apply(this);
// 创建雪花形状
createFlakes.apply(this);
// 画雪
2024-04-15 16:50:54 +00:00
drawSnow.apply(this);
};
2015-12-28 09:08:52 +00:00
2017-04-15 00:25:50 +00:00
// 停止下雪
2024-04-15 16:50:54 +00:00
snowFall.prototype.stop = function () {
if (
this.status == 2 ||
this.status == 0 ||
!this.canvas
) {
2017-04-15 00:25:50 +00:00
return false;
}
// 停止动画循环
this.pause();
this.status = 2;
// 删除画布
this.canvas.parentNode.removeChild(this.canvas);
this.canvas = null;
2024-04-15 16:50:54 +00:00
};
2015-12-28 09:08:52 +00:00
2017-04-15 00:25:50 +00:00
// 暂停下雪
2024-04-15 16:50:54 +00:00
snowFall.prototype.pause = function () {
if (this.status == 3) {
2017-04-15 00:25:50 +00:00
return false;
}
this.status = 3;
2024-04-15 16:50:54 +00:00
cancelAnimationFrame(this.loop);
2017-04-15 00:25:50 +00:00
};
// 继续下雪
2024-04-15 16:50:54 +00:00
snowFall.prototype.resume = function () {
if (this.status == 3 && this.canvas) {
2017-04-15 00:25:50 +00:00
this.status = 4;
// 动画的计时控制
2024-04-15 16:50:54 +00:00
var that = this;
this.loop = requestAnimationFrame(function () {
drawSnow.apply(that);
2017-04-15 00:25:50 +00:00
});
}
};
2015-12-28 09:08:52 +00:00
2017-04-15 00:25:50 +00:00
// 创建画布
2024-04-15 16:50:54 +00:00
var snowCanvas = function () {
2017-04-15 00:25:50 +00:00
// 添加Dom结点
var snowcanvas = document.createElement("canvas");
2024-04-15 16:50:54 +00:00
snowcanvas.classList.add("fun");
2017-04-15 00:25:50 +00:00
snowcanvas.id = "snowfall";
ui.window.appendChild(snowcanvas);
2024-04-15 16:50:54 +00:00
canvas = snowcanvas;
2017-04-15 00:25:50 +00:00
this.canvas = snowcanvas;
this.ctx = snowcanvas.getContext("2d");
// 窗口大小改变的处理
2024-04-15 16:50:54 +00:00
lib.onresize.push(function () {
2017-04-15 00:25:50 +00:00
snowcanvas.width = ui.window.offsetWidth;
2024-04-15 16:50:54 +00:00
snowcanvas.height = ui.window.offsetHeight;
2017-04-15 00:25:50 +00:00
});
snowcanvas.width = ui.window.offsetWidth;
snowcanvas.height = ui.window.offsetHeight;
2024-04-15 16:50:54 +00:00
};
2015-12-28 09:08:52 +00:00
2017-04-15 00:25:50 +00:00
// 雪运动对象
2024-04-15 16:50:54 +00:00
var flakeMove = function (
canvasWidth,
canvasHeight,
flakeSize,
fallSpeed
) {
this.x = Math.floor(Math.random() * canvasWidth); //x坐标
this.y = Math.floor(Math.random() * canvasHeight); //y坐标
this.size = Math.random() * flakeSize + 2; //形状
this.maxSize = flakeSize; //最大形状
this.speed = Math.random() * 1 + fallSpeed; //坠落速度
this.fallSpeed = fallSpeed; //坠落速度
this.velY = this.speed; //Y方向速度
this.velX = 0; //X方向速度
this.stepSize = Math.random() / 30; //步长
this.step = 0; //步数
};
2015-12-28 09:08:52 +00:00
2024-04-15 16:50:54 +00:00
flakeMove.prototype.update = function () {
2017-04-15 00:25:50 +00:00
var x = this.x,
2018-04-17 07:32:43 +00:00
y = this.y;
2015-12-28 09:08:52 +00:00
2017-04-15 00:25:50 +00:00
// 左右摆动(余弦)
this.velX *= 0.98;
if (this.velY <= this.speed) {
2024-04-15 16:50:54 +00:00
this.velY = this.speed;
2017-04-15 00:25:50 +00:00
}
2024-04-15 16:50:54 +00:00
this.velX +=
Math.cos((this.step += 0.05)) * this.stepSize;
2015-12-28 09:08:52 +00:00
2017-04-15 00:25:50 +00:00
this.y += this.velY;
this.x += this.velX;
// 飞出边界的处理
2024-04-15 16:50:54 +00:00
if (
this.x >= canvas.width ||
this.x <= 0 ||
this.y >= canvas.height ||
this.y <= 0
) {
this.reset(canvas.width, canvas.height);
2017-04-15 00:25:50 +00:00
}
};
// 飞出边界-放置最顶端继续坠落
2024-04-15 16:50:54 +00:00
flakeMove.prototype.reset = function (width, height) {
2017-04-15 00:25:50 +00:00
this.x = Math.floor(Math.random() * width);
this.y = 0;
this.size = Math.random() * snow.flakeSize + 2;
this.speed = Math.random() * 1 + snow.fallSpeed;
this.velY = this.speed;
this.velX = 0;
};
// 渲染雪花-随机形状
2024-04-15 16:50:54 +00:00
flakeMove.prototype.render = function (ctx) {
var snowFlake = ctx.createRadialGradient(
this.x,
this.y,
0,
this.x,
this.y,
this.size
);
snowFlake.addColorStop(
0,
"rgba(255, 255, 255, 0.9)"
);
snowFlake.addColorStop(
0.5,
"rgba(255, 255, 255, 0.5)"
);
2017-04-15 00:25:50 +00:00
snowFlake.addColorStop(1, "rgba(255, 255, 255, 0)");
ctx.save();
ctx.fillStyle = snowFlake;
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
ctx.fill();
ctx.restore();
};
// 创建雪花-定义形状
2024-04-15 16:50:54 +00:00
var createFlakes = function () {
2017-04-15 00:25:50 +00:00
var maxFlake = this.maxFlake,
2024-04-15 16:50:54 +00:00
flakes = (this.flakes = []),
2017-04-15 00:25:50 +00:00
canvas = this.canvas;
for (var i = 0; i < 200; i++) {
2024-04-15 16:50:54 +00:00
flakes.push(
new flakeMove(
canvas.width,
canvas.height,
this.flakeSize,
this.fallSpeed
)
);
2017-04-15 00:25:50 +00:00
}
2024-04-15 16:50:54 +00:00
};
2015-12-28 09:08:52 +00:00
2017-04-15 00:25:50 +00:00
// 画雪
2024-04-15 16:50:54 +00:00
var drawSnow = function () {
2017-04-15 00:25:50 +00:00
var maxFlake = this.maxFlake,
flakes = this.flakes;
2024-04-15 16:50:54 +00:00
var ctx = this.ctx,
canvas = this.canvas,
that = this;
2017-04-15 00:25:50 +00:00
// 清空雪花
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (var e = 0; e < maxFlake; e++) {
flakes[e].update();
flakes[e].render(ctx);
}
// 一帧一帧的画
2024-04-15 16:50:54 +00:00
this.loop = requestAnimationFrame(function () {
2017-04-15 00:25:50 +00:00
drawSnow.apply(that);
});
2024-04-15 16:50:54 +00:00
};
2015-12-28 09:08:52 +00:00
2017-04-15 00:25:50 +00:00
// 调用及控制方法
var snow = new snowFall();
2024-04-15 16:50:54 +00:00
game.haveFun.snowStart = function () {
2017-04-15 00:25:50 +00:00
snow.start();
2024-04-15 16:50:54 +00:00
};
game.haveFun.snowStop = function () {
game.haveFun.list.snow.running = false;
2017-04-15 00:25:50 +00:00
snow.stop();
2024-04-15 16:50:54 +00:00
};
game.haveFun.snowSize = function () {
if (game.haveFun.list.snow.size == "large") {
game.haveFun.list.snow.size = "small";
snow.maxFlake = 80;
snow.flakeSize = 3;
snow.fallSpeed = 1;
if (this && this.innerHTML) {
this.innerHTML = "大雪";
2017-04-15 00:25:50 +00:00
}
2024-04-15 16:50:54 +00:00
game.saveConfig("coinSnowSize", true);
} else {
game.haveFun.list.snow.size = "large";
snow.maxFlake = 200;
snow.flakeSize = 10;
snow.fallSpeed = 2;
if (this && this.innerHTML) {
this.innerHTML = "小雪";
2017-04-15 00:25:50 +00:00
}
2024-04-15 16:50:54 +00:00
game.saveConfig("coinSnowSize", false);
2017-04-15 00:25:50 +00:00
}
2024-04-15 16:50:54 +00:00
};
if (lib.config.coinSnowSize) {
2017-04-15 00:25:50 +00:00
game.haveFun.snowSize();
2015-12-30 04:00:49 +00:00
}
2017-04-15 00:25:50 +00:00
snow.start();
2015-12-30 04:00:49 +00:00
}
2017-04-15 00:25:50 +00:00
},
2024-04-15 16:50:54 +00:00
firework: function () {
if (game.haveFun.list.firework.running) return;
game.haveFun.list.firework.running = true;
if (game.haveFun.fireworkLoop) {
2017-04-15 00:25:50 +00:00
game.haveFun.fireworkLoop();
2024-04-15 16:50:54 +00:00
} else {
2017-04-15 00:25:50 +00:00
// when animating on canvas, it is best to use requestAnimationFrame instead of setTimeout or setInterval
// not supported in all browsers though and sometimes needs a prefix, so we need a shim
2024-04-15 16:50:54 +00:00
var requestAnimFrame = (function () {
return (
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function (callback) {
window.setTimeout(callback, 1000 / 60);
}
);
2017-04-15 00:25:50 +00:00
})();
// now we will setup our basic variables for the demo
2024-04-15 16:50:54 +00:00
var canvas = document.createElement("canvas"),
ctx = canvas.getContext("2d"),
// full screen dimensions
cw = ui.window.offsetWidth,
ch = ui.window.offsetHeight,
// firework collection
fireworks = [],
// particle collection
particles = [],
// starting hue
hue = 120,
// when launching fireworks with a click, too many get launched at once without a limiter, one launch per 5 loop ticks
limiterTotal = 5,
limiterTick = 0,
// this will time the auto launches of fireworks, one launch per 80 loop ticks
timerTotal = 80,
timerTick = 0,
mousedown = false,
// mouse x coordinate,
mx,
// mouse y coordinate
my;
2017-04-15 00:25:50 +00:00
// set canvas dimensions
2015-12-28 07:30:15 +00:00
canvas.width = cw;
canvas.height = ch;
2017-04-15 00:25:50 +00:00
ui.window.appendChild(canvas);
2024-04-15 16:50:54 +00:00
canvas.classList.add("fun");
lib.onresize.push(function () {
cw = ui.window.offsetWidth;
ch = ui.window.offsetHeight;
2017-04-15 00:25:50 +00:00
canvas.width = cw;
canvas.height = ch;
});
2015-12-28 07:30:15 +00:00
2017-04-15 00:25:50 +00:00
// now we are going to setup our function placeholders for the entire demo
2015-12-28 07:30:15 +00:00
2017-04-15 00:25:50 +00:00
// get a random number within a range
2024-04-15 16:50:54 +00:00
var random = function (min, max) {
return Math.random() * (max - min) + min;
};
2015-12-28 07:30:15 +00:00
2017-04-15 00:25:50 +00:00
// calculate the distance between two points
2024-04-15 16:50:54 +00:00
var calculateDistance = function (p1x, p1y, p2x, p2y) {
2017-04-15 00:25:50 +00:00
var xDistance = p1x - p2x,
2024-04-15 16:50:54 +00:00
yDistance = p1y - p2y;
return Math.sqrt(
Math.pow(xDistance, 2) + Math.pow(yDistance, 2)
);
};
2015-12-28 07:30:15 +00:00
2017-04-15 00:25:50 +00:00
// create firework
2024-04-15 16:50:54 +00:00
var Firework = function (sx, sy, tx, ty) {
2017-04-15 00:25:50 +00:00
// actual coordinates
this.x = sx;
this.y = sy;
// starting coordinates
this.sx = sx;
this.sy = sy;
// target coordinates
this.tx = tx;
this.ty = ty;
// distance from starting point to target
2024-04-15 16:50:54 +00:00
this.distanceToTarget = calculateDistance(
sx,
sy,
tx,
ty
);
2017-04-15 00:25:50 +00:00
this.distanceTraveled = 0;
// track the past coordinates of each firework to create a trail effect, increase the coordinate count to create more prominent trails
this.coordinates = [];
this.coordinateCount = 3;
// populate initial coordinate collection with the current coordinates
2024-04-15 16:50:54 +00:00
while (this.coordinateCount--) {
this.coordinates.push([this.x, this.y]);
2017-04-15 00:25:50 +00:00
}
2024-04-15 16:50:54 +00:00
this.angle = Math.atan2(ty - sy, tx - sx);
2017-04-15 00:25:50 +00:00
this.speed = 2;
this.acceleration = 1.05;
2024-04-15 16:50:54 +00:00
this.brightness = random(50, 70);
2017-04-15 00:25:50 +00:00
// circle target indicator radius
2015-12-28 07:30:15 +00:00
this.targetRadius = 1;
2024-04-15 16:50:54 +00:00
};
2015-12-28 07:30:15 +00:00
2017-04-15 00:25:50 +00:00
// update firework
2024-04-15 16:50:54 +00:00
Firework.prototype.update = function (index) {
2017-04-15 00:25:50 +00:00
// remove last item in coordinates array
this.coordinates.pop();
// add current coordinates to the start of the array
2024-04-15 16:50:54 +00:00
this.coordinates.unshift([this.x, this.y]);
2017-04-15 00:25:50 +00:00
// cycle the circle target indicator radius
2024-04-15 16:50:54 +00:00
if (this.targetRadius < 8) {
2017-04-15 00:25:50 +00:00
this.targetRadius += 0.3;
} else {
this.targetRadius = 1;
}
// speed up the firework
this.speed *= this.acceleration;
// get the current velocities based on angle and speed
2024-04-15 16:50:54 +00:00
var vx = Math.cos(this.angle) * this.speed,
vy = Math.sin(this.angle) * this.speed;
2017-04-15 00:25:50 +00:00
// how far will the firework have traveled with velocities applied?
2024-04-15 16:50:54 +00:00
this.distanceTraveled = calculateDistance(
this.sx,
this.sy,
this.x + vx,
this.y + vy
);
2017-04-15 00:25:50 +00:00
// if the distance traveled, including velocities, is greater than the initial distance to the target, then the target has been reached
2024-04-15 16:50:54 +00:00
if (
this.distanceTraveled >= this.distanceToTarget
) {
createParticles(this.tx, this.ty);
2017-04-15 00:25:50 +00:00
// remove the firework, use the index passed into the update function to determine which to remove
2024-04-15 16:50:54 +00:00
fireworks.splice(index, 1);
2017-04-15 00:25:50 +00:00
} else {
// target not reached, keep traveling
this.x += vx;
this.y += vy;
}
2024-04-15 16:50:54 +00:00
};
2015-12-28 07:30:15 +00:00
2017-04-15 00:25:50 +00:00
// draw firework
2024-04-15 16:50:54 +00:00
Firework.prototype.draw = function () {
2017-04-15 00:25:50 +00:00
ctx.beginPath();
// move to the last tracked coordinate in the set, then draw a line to the current x and y
2024-04-15 16:50:54 +00:00
ctx.moveTo(
this.coordinates[
this.coordinates.length - 1
][0],
this.coordinates[this.coordinates.length - 1][1]
);
ctx.lineTo(this.x, this.y);
ctx.strokeStyle =
"hsl(" +
hue +
", 100%, " +
this.brightness +
"%)";
2017-04-15 00:25:50 +00:00
ctx.stroke();
2015-12-28 07:30:15 +00:00
2017-04-15 00:25:50 +00:00
ctx.beginPath();
// draw the target for this firework with a pulsing circle
2024-04-15 16:50:54 +00:00
ctx.arc(
this.tx,
this.ty,
this.targetRadius,
0,
Math.PI * 2
);
2017-04-15 00:25:50 +00:00
ctx.stroke();
2024-04-15 16:50:54 +00:00
};
2015-12-28 07:30:15 +00:00
2017-04-15 00:25:50 +00:00
// create particle
2024-04-15 16:50:54 +00:00
var Particle = function (x, y) {
2017-04-15 00:25:50 +00:00
this.x = x;
this.y = y;
// track the past coordinates of each particle to create a trail effect, increase the coordinate count to create more prominent trails
this.coordinates = [];
this.coordinateCount = 5;
2024-04-15 16:50:54 +00:00
while (this.coordinateCount--) {
this.coordinates.push([this.x, this.y]);
2017-04-15 00:25:50 +00:00
}
// set a random angle in all possible directions, in radians
2024-04-15 16:50:54 +00:00
this.angle = random(0, Math.PI * 2);
this.speed = random(1, 10);
2017-04-15 00:25:50 +00:00
// friction will slow the particle down
this.friction = 0.95;
// gravity will be applied and pull the particle down
this.gravity = 1;
// set the hue to a random number +-20 of the overall hue variable
2024-04-15 16:50:54 +00:00
this.hue = random(hue - 20, hue + 20);
this.brightness = random(50, 80);
2017-04-15 00:25:50 +00:00
this.alpha = 1;
// set how fast the particle fades out
2024-04-15 16:50:54 +00:00
this.decay = random(0.015, 0.03);
};
2015-12-28 07:30:15 +00:00
2017-04-15 00:25:50 +00:00
// update particle
2024-04-15 16:50:54 +00:00
Particle.prototype.update = function (index) {
2017-04-15 00:25:50 +00:00
// remove last item in coordinates array
this.coordinates.pop();
// add current coordinates to the start of the array
2024-04-15 16:50:54 +00:00
this.coordinates.unshift([this.x, this.y]);
2017-04-15 00:25:50 +00:00
// slow down the particle
this.speed *= this.friction;
// apply velocity
2024-04-15 16:50:54 +00:00
this.x += Math.cos(this.angle) * this.speed;
this.y +=
Math.sin(this.angle) * this.speed +
this.gravity;
2017-04-15 00:25:50 +00:00
// fade out the particle
this.alpha -= this.decay;
// remove the particle once the alpha is low enough, based on the passed in index
2024-04-15 16:50:54 +00:00
if (this.alpha <= this.decay) {
particles.splice(index, 1);
2017-04-15 00:25:50 +00:00
}
2024-04-15 16:50:54 +00:00
};
2015-12-28 07:30:15 +00:00
2017-04-15 00:25:50 +00:00
// draw particle
2024-04-15 16:50:54 +00:00
Particle.prototype.draw = function () {
ctx.beginPath();
2017-04-15 00:25:50 +00:00
// move to the last tracked coordinates in the set, then draw a line to the current x and y
2024-04-15 16:50:54 +00:00
ctx.moveTo(
this.coordinates[
this.coordinates.length - 1
][0],
this.coordinates[this.coordinates.length - 1][1]
);
ctx.lineTo(this.x, this.y);
ctx.strokeStyle =
"hsla(" +
this.hue +
", 100%, " +
this.brightness +
"%, " +
this.alpha +
")";
2017-04-15 00:25:50 +00:00
ctx.stroke();
2024-04-15 16:50:54 +00:00
};
2015-12-28 07:30:15 +00:00
2017-04-15 00:25:50 +00:00
// create particle group/explosion
2024-04-15 16:50:54 +00:00
var createParticles = function (x, y) {
2017-04-15 00:25:50 +00:00
// increase the particle count for a bigger explosion, beware of the canvas performance hit with the increased particles though
var particleCount = 30;
2024-04-15 16:50:54 +00:00
while (particleCount--) {
particles.push(new Particle(x, y));
2017-04-15 00:25:50 +00:00
}
2024-04-15 16:50:54 +00:00
};
2015-12-28 07:30:15 +00:00
2017-04-15 00:25:50 +00:00
// main demo loop
2024-04-15 16:50:54 +00:00
var loop = function () {
2017-04-15 00:25:50 +00:00
// if(lib.config.coin_free_playpackconfig&&!_status.imchoosing){
// canvas.style.display='none';
// }
// else{
// canvas.style.display='';
// }
// this function will run endlessly with requestAnimationFrame
2024-04-15 16:50:54 +00:00
if (!game.haveFun.list.firework.running) {
canvas.width = cw;
canvas.height = ch;
2017-04-15 00:25:50 +00:00
return;
2024-04-15 16:50:54 +00:00
} else {
requestAnimFrame(loop);
2017-04-15 00:25:50 +00:00
}
2015-12-28 07:30:15 +00:00
2017-04-15 00:25:50 +00:00
// increase the hue to get different colored fireworks over time
hue += 0.5;
// normally, clearRect() would be used to clear the canvas
// we want to create a trailing effect though
// setting the composite operation to destination-out will allow us to clear the canvas at a specific opacity, rather than wiping it entirely
2024-04-15 16:50:54 +00:00
ctx.globalCompositeOperation = "destination-out";
2017-04-15 00:25:50 +00:00
// decrease the alpha property to create more prominent trails
2024-04-15 16:50:54 +00:00
ctx.fillStyle = "rgba(0, 0, 0, 0.5)";
ctx.fillRect(0, 0, cw, ch);
2017-04-15 00:25:50 +00:00
// change the composite operation back to our main mode
// lighter creates bright highlight points as the fireworks and particles overlap each other
2024-04-15 16:50:54 +00:00
ctx.globalCompositeOperation = "lighter";
2017-04-15 00:25:50 +00:00
// loop over each firework, draw it, update it
var i = fireworks.length;
2024-04-15 16:50:54 +00:00
while (i--) {
fireworks[i].draw();
fireworks[i].update(i);
2015-12-28 07:30:15 +00:00
}
2017-04-15 00:25:50 +00:00
// loop over each particle, draw it, update it
var i = particles.length;
2024-04-15 16:50:54 +00:00
while (i--) {
particles[i].draw();
particles[i].update(i);
2017-04-15 00:25:50 +00:00
}
// launch fireworks automatically to random coordinates, when the mouse isn't down
2024-04-15 16:50:54 +00:00
if (timerTick >= timerTotal) {
if (!mousedown) {
2017-04-15 00:25:50 +00:00
// start the firework at the bottom middle of the screen, then set the random target coordinates, the random y coordinates will be set within the range of the top half of the screen
2024-04-15 16:50:54 +00:00
fireworks.push(
new Firework(
cw / 2,
ch,
random(0, cw),
random(0, ch / 2)
)
);
2017-04-15 00:25:50 +00:00
timerTick = 0;
}
} else {
timerTick++;
}
// limit the rate at which fireworks get launched when mouse is down
2024-04-15 16:50:54 +00:00
if (limiterTick >= limiterTotal) {
if (mousedown) {
2017-04-15 00:25:50 +00:00
// start the firework at the bottom middle of the screen, then set the current mouse coordinates as the target
2024-04-15 16:50:54 +00:00
fireworks.push(
new Firework(cw / 2, ch, mx, my)
);
2017-04-15 00:25:50 +00:00
limiterTick = 0;
}
} else {
limiterTick++;
2015-12-28 07:30:15 +00:00
}
2024-04-15 16:50:54 +00:00
};
2015-12-28 07:30:15 +00:00
2024-04-15 16:50:54 +00:00
if (lib.config.touchscreen) {
ui.window.addEventListener(
"touchmove",
function (e) {
mx =
e.touches[0].clientX /
game.documentZoom -
canvas.offsetLeft;
my =
e.touches[0].clientY /
game.documentZoom -
canvas.offsetTop;
}
);
ui.window.addEventListener(
"touchstart",
function (e) {
mousedown = true;
}
);
ui.window.addEventListener(
"touchend",
function (e) {
mousedown = false;
}
);
} else {
2017-04-15 00:25:50 +00:00
// mouse event bindings
// update the mouse coordinates on mousemove
2024-04-15 16:50:54 +00:00
ui.window.addEventListener(
"mousemove",
function (e) {
mx =
e.pageX / game.documentZoom -
canvas.offsetLeft;
my =
e.pageY / game.documentZoom -
canvas.offsetTop;
}
);
2015-12-28 07:30:15 +00:00
2017-04-15 00:25:50 +00:00
// toggle mousedown state and prevent canvas from being selected
2024-04-15 16:50:54 +00:00
ui.window.addEventListener(
"mousedown",
function (e) {
e.preventDefault();
mousedown = true;
}
);
2015-12-28 07:30:15 +00:00
2024-04-15 16:50:54 +00:00
ui.window.addEventListener("mouseup", function (e) {
2017-04-15 00:25:50 +00:00
e.preventDefault();
mousedown = false;
});
}
2015-12-28 07:30:15 +00:00
2017-04-15 00:25:50 +00:00
// once the window loads, we are ready for some fireworks!
2024-04-15 16:50:54 +00:00
game.haveFun.fireworkLoop = loop;
(game.haveFun.fireworkStop = function () {
game.haveFun.list.firework.running = false;
}),
loop();
2017-04-15 00:25:50 +00:00
}
2024-04-15 16:50:54 +00:00
},
},
},
help: {
富甲天下:
"<ul><li>每完成一次对局,可获得一定数量的金币" +
"<li>战斗胜利可额外获得20金币每杀死一个敌人可获得10金币托管无效" +
"<li>使用的武将越强,获得的金币数越少" +
"<li>执行以下操作时,将扣除金币:<ul><li>作弊20金币<li>换将卡3金币<li>" +
"自由选将10金币<li>手气卡3金币<li>换人10金币</ul>" +
"<li>金币可用于购买烟花等游戏特效(点击右上角的金币按钮)" +
"<li>修改金币:<br>game.changCoin" +
"<li>默认下雪:<br>game.haveFun.alwaysSnow",
2017-04-15 00:25:50 +00:00
},
};
2017-04-14 23:35:56 +00:00
});