[工程?]关于一个博客的 js 特效是怎么一步一步变成游戏的

· · 科技·工程

算 archive,也算广告。

原版 js 特效?

初始的链接找不到了,当时好像存了一份代码。

var canvas = document.createElement("canvas")
var ctx = canvas.getContext("2d")
window.document.body.appendChild(canvas)
canvas.width = window.innerWidth
canvas.height = window.innerHeight
canvas.setAttribute('style', 'position:fixed;left:0;top:0;pointer-events:none;filter:blur(2px);')
var clicks = []
var points = [] //定义粒子数组
var live = 50 //存活50个周期
var colors = [  //备选粒子颜色数组
    "236, 204, 104",
    "255, 71, 87",
    "112, 161, 255",
    "123, 237, 159"
]
window.addEventListener("mousemove", function (evt) { //监听鼠标移动事件
    for (var i = 0; i < 15; i++) { //添加15个粒子
        points.push({
            sx: evt.x, //鼠标当前坐标作为粒子坐标
            sy: evt.y,
            vx: 0.5 - Math.random(), //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy: 0.5 - Math.random(),
            life: live, //存活周期
            color: colors[parseInt(Math.random() * colors.length)], //随机选择颜色
            size: Math.random() * 5 //随机粒子尺寸,取值范围为0~5
        })
    }
})
window.addEventListener("click", function (evt) { //监听点击事件
    for (var i = 0; i < 100; i++) {
        clicks.push({
            sx: evt.x,
            sy: evt.y,
            color: colors[parseInt(Math.random() * colors.length)],
            life: live,
            vx: 0.5 - Math.random(), //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy: 0.5 - Math.random(),
        })
    }
})
function drawpoints() { //绘制粒子
    ctx.clearRect(0, 0, canvas.width, canvas.height) //清屏
    for (var i = 0; i < points.length; i++) { //遍历粒子
        point = points[i] //定义单个粒子
        ctx.beginPath()
        ctx.arc(point.sx, point.sy, point.size, Math.PI * 2, false) //根据粒子属性画圆
        ctx.fillStyle = "rgba(" + point.color + "," + point.life / live + ")" //根据粒子属性设置填充颜色及透明度
        ctx.fill() //填充颜色
        point.life-- //生命值减1
        if (point.life <= 0) { //生命值为0则从粒子数组中删除
            points.splice(i, 1)
        }
        point.sx += point.vx * 3  //根据向量值改变粒子位置
        point.sy += point.vy * 3
        point.vy += 0.03
    }
    for (var i = 0; i < clicks.length; i++) { //绘制点击效果
        click = clicks[i]
        ctx.fillStyle = "rgba(" + click.color + "," + click.life / live + ")"
        ctx.fillRect(click.sx, click.sy, 3, 3)
        click.sx += click.vx * 10
        click.sy += click.vy * 10
        click.vy += 0.02
        click.life--
        if (click.life <= 0) {
            clicks.splice(i, 1)
        }
    }
}
setInterval(drawpoints, 20) //20毫秒绘制一次

改版 1(split)

当时最开始是准备当脚本用的,于是是在篡改猴写的,后面改版都是如此,直到开始写正式的游戏版。

// ==UserScript==
// @name         New Userscript
// @namespace    http://tampermonkey.net/
// @version      2024-04-16
// @description  try to take over the world!
// @author       You
// @match        *://*/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=microsoft.com
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    var canvas = document.createElement("canvas")
var ctx = canvas.getContext("2d")
window.document.body.appendChild(canvas)
canvas.width = window.innerWidth
canvas.height = window.innerHeight
canvas.setAttribute('style', 'position:fixed;left:0;top:0;pointer-events:none;filter:blur(2px);')
var clicks = []
var points = [] //定义粒子数组
var live = 50 //存活50个周期
var colors = [ //备选粒子颜色数组
    "236, 204, 104",
    "255, 71, 87",
    "112, 161, 255",
    "123, 237, 159"
]
window.addEventListener("mousemove", function (evt) { //监听鼠标移动事件
    for (var i = 0; i < 1; i++) { //添加15个粒子
        points.push({
            sx: evt.x, //鼠标当前坐标作为粒子坐标
            sy: evt.y,
            vx: 1.5 - Math.random()*3, //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy: 1.5 - Math.random()*3,
            life: live, //存活周期
            life2:3,
            color: colors[parseInt(Math.random() * colors.length)], //随机选择颜色
            size:7 //随机粒子尺寸,取值范围为0~5
        })
    }
})
window.addEventListener("mousedown", function (evt) { //监听点击事件
    for (var i = 0; i < 100; i++) {
        clicks.push({
            sx: evt.x,
            sy: evt.y,
            color: colors[parseInt(Math.random() * colors.length)],
            life: live,
            vx: 0.5 - Math.random(), //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy: 0.5 - Math.random(),
        })
    }
})
function drawpoints() { //绘制粒子
    ctx.clearRect(0, 0, canvas.width, canvas.height) //清屏
    for (let i = 0; i < points.length; i++) { //遍历粒子
        let point = points[i] //定义单个粒子
        ctx.beginPath()
        ctx.arc(point.sx, point.sy, point.size, Math.PI * 2, false) //根据粒子属性画圆
        ctx.fillStyle = "rgba(" + point.color + "," + point.life / live + ")" //根据粒子属性设置填充颜色及透明度
        ctx.fill() //填充颜色
        point.life-- //生命值减1
        if (point.life <= 0) { //生命值为0则从粒子数组中删除
        if(point.life2){
        for (let i = 0; i < 5; i++) { //添加15个粒子
        points.push({
            sx: point.sx, //鼠标当前坐标作为粒子坐标
            sy: point.sy,
            vx:(point.life2)*(0.5 - Math.random()), //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy: (point.life2)*(0.5 - Math.random()),
            life: live, //存活周期
            life2:point.life2-1,
            color: colors[parseInt(Math.random() * colors.length)], //随机选择颜色
            size:(point.life2-1)*2+1 //随机粒子尺寸,取值范围为0~5
        })
    }
        }
            points.splice(i, 1)
        }
        point.sx += point.vx * 3 //根据向量值改变粒子位置
        point.sy += point.vy * 3
    }
    for (let i = 0; i < clicks.length; i++) { //绘制点击效果
        let click = clicks[i]
        ctx.fillStyle = "rgba(" + click.color + "," + (25-click.life)/ live + ")"
        ctx.fillRect(click.sx, click.sy, 3, 3)
        click.sx += click.vx * 10
        click.sy += click.vy * 10
        click.life--
        if (click.life <= 0) {
            for (let i = 0; i < 15; i++) { //添加15个粒子
        points.push({
            sx: click.sx, //鼠标当前坐标作为粒子坐标
            sy: click.sy,
            vx: 2 - Math.random()*4, //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy: 2 - Math.random()*4,
            life: live, //存活周期
            life2:1,
            color: colors[parseInt(Math.random() * colors.length)], //随机选择颜色
            size: Math.random() * 5 //随机粒子尺寸,取值范围为0~5
        })
    }
            clicks.splice(i, 1)
        }
    }
}
setInterval(drawpoints, 20) //20毫秒绘制一次
    // Your code here...
})();

改版 2(return)

// ==UserScript==
// @name         New Userscript
// @namespace    http://tampermonkey.net/
// @version      2024-04-16
// @description  try to take over the world!
// @author       You
// @match        *://*/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=microsoft.com
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    var canvas = document.createElement("canvas")
var ctx = canvas.getContext("2d")
window.document.body.appendChild(canvas)
canvas.width = window.innerWidth
canvas.height = window.innerHeight
canvas.setAttribute('style', 'position:fixed;left:0;top:0;pointer-events:none;filter:blur(2px);')
var clicks = []
var points = [] //定义粒子数组
var srolls = [] //定义粒子数组
var live = 50 //存活50个周期
var colors = [ //备选粒子颜色数组
    "236, 204, 104",
    "255, 71, 87",
    "112, 161, 255",
    "123, 237, 159"
]
window.addEventListener("mousedownmousewheel", function (evt) { //监听鼠标移动事件
    for (var i = 0; i < 15; i++) { //添加15个粒子
        points.push({
            sx: evt.x, //鼠标当前坐标作为粒子坐标
            sy: evt.y,
            vx: 1.5 - Math.random()*3, //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy: 1.5 - Math.random()*3,
            life: live, //存活周期
            life2:3,
            color: colors[parseInt(Math.random() * colors.length)], //随机选择颜色
            size:8 //随机粒子尺寸,取值范围为0~5
        })
    }
})
window.addEventListener("mousewheel", function (evt) { //监听点击事件
    for (var i = 0; i < 5; i++) {
        clicks.push({
            sx: evt.x,
            sy: evt.y,
            color: colors[parseInt(Math.random() * colors.length)],
            life: live*2,
            vx: 0.5 - Math.random(), //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy: 0.5 - Math.random(),
            size:5
        })
    }
})
window.addEventListener("mousemove", function (evt) { //监听点击事件
    for (var i = 0; i < 5; i++) { //添加15个粒子
        srolls.push({
            sx: evt.x, //鼠标当前坐标作为粒子坐标
            sy: evt.y,
           vx: 1*(0.5 - Math.random()), //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy:1*( 0.5 - Math.random()),
            life: live*2, //存活周期
            life2:1,
            color: colors[parseInt(Math.random() * colors.length)], //随机选择颜色
            size:5 //随机粒子尺寸,取值范围为0~5
        })
    }
})
var mv=1,cl=1,sr=1;
function drawpoints() { //绘制粒子
    ctx.clearRect(0, 0, canvas.width, canvas.height) //清屏
    if(mv){
    for (let i = 0; i < points.length; i++) { //遍历粒子
        if(i>1000){
            points.splice(i, 1);
            continue;
        }
        let point = points[i] //定义单个粒子
        ctx.beginPath()
        ctx.arc(point.sx, point.sy, point.size, Math.PI * 2, false) //根据粒子属性画圆
        ctx.fillStyle = "rgba(" + point.color + "," + point.life / live + ")" //根据粒子属性设置填充颜色及透明度
        ctx.fill() //填充颜色
        point.life-- //生命值减1
        if (point.life <= 0) { //生命值为0则从粒子数组中删除
        if(point.life2){
        for (let i = 0; i < 5; i++) { //添加15个粒子
        points.push({
            sx: point.sx, //鼠标当前坐标作为粒子坐标
            sy: point.sy,
            vx:(point.life2)*(0.5 - Math.random()), //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy: (point.life2)*(0.5 - Math.random()),
            life: live, //存活周期
            life2:point.life2-1,
            color: colors[parseInt(Math.random() * colors.length)], //随机选择颜色
            size:point.life2*2+2 //随机粒子尺寸,取值范围为0~5
        })
    }
        }
            points.splice(i, 1)
        }
        point.sx += point.vx * 3 //根据向量值改变粒子位置
        point.sy += point.vy * 3
    }
    }
    if(cl){
    for (let i = 0; i < clicks.length; i++) { //绘制点击效果
        if(i>1000){
            clicks.splice(i, 1);
            continue;
        }
        let click = clicks[i]
        ctx.beginPath()
        ctx.arc(click.sx, click.sy, click.size, Math.PI * 2, false) //根据粒子属性画圆
        ctx.fillStyle = "rgba(" + click.color + "," + click.life / live + ")" //根据粒子属性设置填充颜色及透明度
        ctx.fill() //填充颜色
        click.sx += click.vx * 10
        click.sy += click.vy * 10
        click.life--
        if (click.life <= 0) {
            for (let i = 0; i < 5; i++) { //添加15个粒子
        points.push({
            sx: click.sx, //鼠标当前坐标作为粒子坐标
            sy: click.sy,
            vx: 2 - Math.random()*4, //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy: 2 - Math.random()*4,
            life: live, //存活周期
            life2:1,
            color: colors[parseInt(Math.random() * colors.length)], //随机选择颜色
            size: 4 //随机粒子尺寸,取值范围为0~5
        })
    }
            clicks.splice(i, 1)
        }
    }
    }
    if(sr){
    for (let i = 0; i < srolls.length; i++) { //绘制点击效果
        if(i>1000){
            srolls.splice(i, 1);
            continue;
        }
        let sroll = srolls[i]
        ctx.beginPath()
        ctx.arc(sroll.sx, sroll.sy, sroll.size, Math.PI * 2, false) //根据粒子属性画圆
        ctx.fillStyle = "rgba(" + sroll.color + "," + sroll.life / live + ")" //根据粒子属性设置填充颜色及透明度
        ctx.fill() //填充颜色
        sroll.sx += sroll.vx * 10
        sroll.sy += sroll.vy * 10
        sroll.life--
        if (sroll.life <= 0) {
            if(sroll.life2){
                srolls.push({
                    sx: sroll.sx,
                    sy: sroll.sy,
                    vx:-sroll.vx*5, //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
                    vy:-sroll.vy*5,
                    life: live*2,
                    life2:0,
                    color:sroll.color,
                    size:5
                })
            }
            srolls.splice(i, 1)
        }
    }
    }
}
setInterval(drawpoints, 20) //20毫秒绘制一次
})();

改版 3(split2)

// ==UserScript==
// @name         New Userscript
// @namespace    http://tampermonkey.net/
// @version      2024-04-16
// @description  try to take over the world!
// @author       You
// @match        *://*/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=microsoft.com
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    var canvas = document.createElement("canvas")
var ctx = canvas.getContext("2d")
window.document.body.appendChild(canvas)
canvas.width = window.innerWidth
canvas.height = window.innerHeight
canvas.setAttribute('style', 'position:fixed;left:0;top:0;pointer-events:none;filter:blur(2px);')
var clicks = []
var points = [] //定义粒子数组
var srolls = [] //定义粒子数组
var live = 50 //存活50个周期
var colors = [ //备选粒子颜色数组
    "236, 204, 104",
    "255, 71, 87",
    "112, 161, 255",
    "123, 237, 159"
]
window.addEventListener("mousedown", function (evt) { //监听鼠标移动事件
    for (var i = 0; i < 15; i++) { //添加15个粒子
        points.push({
            sx: evt.x, //鼠标当前坐标作为粒子坐标
            sy: evt.y,
            vx: 1.5 - Math.random()*3, //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy: 1.5 - Math.random()*3,
            life: live, //存活周期
            life2:3,
            color: colors[parseInt(Math.random() * colors.length)], //随机选择颜色
            size:8 //随机粒子尺寸,取值范围为0~5
        })
    }
})
window.addEventListener("mousewheel", function (evt) { //监听点击事件
    for (var i = 0; i < 5; i++) {
        clicks.push({
            sx: evt.x,
            sy: evt.y,
            color: colors[parseInt(Math.random() * colors.length)],
            life: live*2,
            vx: 0.5 - Math.random(), //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy: 0.5 - Math.random(),
            size:5
        })
    }
})
document.onkeydown= function (evt) { //监听点击事件
    var xx=Math.random()*innerWidth,yy=Math.random()*innerHeight
    for (var i = 0; i < 50; i++) { //添加15个粒子
        srolls.push({
            sx:xx , //鼠标当前坐标作为粒子坐标
            sy:yy,
           vx: 1*(0.5 - Math.random()), //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy:1*( 0.5 - Math.random()),
            life: live*2, //存活周期
            life2:2,
            color: colors[parseInt(Math.random() * colors.length)], //随机选择颜色
            size:5 //随机粒子尺寸,取值范围为0~5
        })
    }
}
var mv=1,cl=1,sr=1;
function drawpoints() { //绘制粒子
    ctx.clearRect(0, 0, canvas.width, canvas.height) //清屏
    if(mv){
    for (let i = 0; i < points.length; i++) { //遍历粒子
        if(i>1000){
            points.splice(i, 1);
            continue;
        }
        let point = points[i] //定义单个粒子
        ctx.beginPath()
        ctx.arc(point.sx, point.sy, point.size, Math.PI * 2, false) //根据粒子属性画圆
        ctx.fillStyle = "rgba(" + point.color + "," + point.life / live + ")" //根据粒子属性设置填充颜色及透明度
        ctx.fill() //填充颜色
        point.life-- //生命值减1
        if (point.life <= 0) { //生命值为0则从粒子数组中删除
        if(point.life2){
        for (let i = 0; i < 5; i++) { //添加15个粒子
        points.push({
            sx: point.sx, //鼠标当前坐标作为粒子坐标
            sy: point.sy,
            vx:(point.life2)*(0.5 - Math.random()), //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy: (point.life2)*(0.5 - Math.random()),
            life: live, //存活周期
            life2:point.life2-1,
            color: colors[parseInt(Math.random() * colors.length)], //随机选择颜色
            size:point.life2*2+2 //随机粒子尺寸,取值范围为0~5
        })
    }
        }
            points.splice(i, 1)
        }
        point.sx += point.vx * 3 //根据向量值改变粒子位置
        point.sy += point.vy * 3
    }
    }
    if(cl){
    for (let i = 0; i < clicks.length; i++) { //绘制点击效果
        if(i>1000){
            clicks.splice(i, 1);
            continue;
        }
        let click = clicks[i]
        ctx.beginPath()
        ctx.arc(click.sx, click.sy, click.size, Math.PI * 2, false) //根据粒子属性画圆
        ctx.fillStyle = "rgba(" + click.color + "," + click.life / live + ")" //根据粒子属性设置填充颜色及透明度
        ctx.fill() //填充颜色
        click.sx += click.vx * 10
        click.sy += click.vy * 10
        click.life--
        if (click.life <= 0) {
            for (let i = 0; i < 5; i++) { //添加15个粒子
        points.push({
            sx: click.sx, //鼠标当前坐标作为粒子坐标
            sy: click.sy,
            vx: 2 - Math.random()*4, //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy: 2 - Math.random()*4,
            life: live, //存活周期
            life2:1,
            color: colors[parseInt(Math.random() * colors.length)], //随机选择颜色
            size: 4 //随机粒子尺寸,取值范围为0~5
        })
    }
            clicks.splice(i, 1)
        }
    }
    }
    if(sr){
    for (let i = 0; i < srolls.length; i++) { //绘制点击效果
        if(i>1000){
            srolls.splice(i, 1);
            continue;
        }
        let sroll = srolls[i]
        ctx.beginPath()
        ctx.arc(sroll.sx, sroll.sy, sroll.size, Math.PI * 2, false) //根据粒子属性画圆
        ctx.fillStyle = "rgba(" + sroll.color + "," + (sroll.life+50) / live + ")" //根据粒子属性设置填充颜色及透明度
        ctx.fill() //填充颜色
        sroll.sx += sroll.vx * 10
        sroll.sy += sroll.vy * 10
        sroll.life--
        if (sroll.life <= 0) {
            if(sroll.life2==2){
                srolls.push({
                    sx: sroll.sx,
                    sy: sroll.sy,
                    vx:-sroll.vx*5, //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
                    vy:-sroll.vy*5,
                    life: live*2/5,
                    life2:1,
                    color:sroll.color,
                    size:5
                })
            }
            if(sroll.life2==1){
                for (let i = 0; i < 5; i++) { //添加15个粒子
        points.push({
            sx: sroll.sx, //鼠标当前坐标作为粒子坐标
            sy: sroll.sy,
            vx: 5 - Math.random()*10, //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy: 5 - Math.random()*10,
            life: live*2, //存活周期
            life2:0,
            color: colors[parseInt(Math.random() * colors.length)], //随机选择颜色
            size: 4 //随机粒子尺寸,取值范围为0~5
        })
                }
            }
            srolls.splice(i, 1)
        }
    }
    }
}
setInterval(drawpoints, 20) //20毫秒绘制一次
})();

改版 4(rand)

粒子不再直线运动,并且按下键盘屏幕上随机位置会出现“炸弹”。

我博客最初的特效。

// ==UserScript==
// @name         New Userscript
// @namespace    http://tampermonkey.net/
// @version      2024-04-16
// @description  try to take over the world!
// @author       You
// @match        *://*/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=microsoft.com
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    var canvas = document.createElement("canvas")
var ctx = canvas.getContext("2d")
window.document.body.appendChild(canvas)
canvas.width = window.innerWidth
canvas.height = window.innerHeight
canvas.setAttribute('style', 'position:fixed;left:0;top:0;pointer-events:none;filter:blur(2px);')
var clicks = []
var points = [] //定义粒子数组
var srolls = [] //定义粒子数组
var live = 50 //存活50个周期
var colors = [ //备选粒子颜色数组
    "236, 204, 104",
    "255, 71, 87",
    "112, 161, 255",
    "123, 237, 159"
]
window.addEventListener("mousedown", function (evt) { //监听鼠标移动事件
    for (var i = 0; i < 15; i++) { //添加15个粒子
        points.push({
            sx: evt.x, //鼠标当前坐标作为粒子坐标
            sy: evt.y,
            vx: 1.5 - Math.random()*3, //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy: 1.5 - Math.random()*3,
            life: live, //存活周期
            life2:3,
            color: colors[parseInt(Math.random() * colors.length)], //随机选择颜色
            size:8, //随机粒子尺寸,取值范围为0~5
            rt:0
        })
    }
})
window.addEventListener("mousewheel", function (evt) { //监听点击事件
    for (var i = 0; i < 5; i++) {
        clicks.push({
            sx: evt.x,
            sy: evt.y,
            color: colors[parseInt(Math.random() * colors.length)],
            life: live*2,
            vx: 0.5 - Math.random(), //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy: 0.5 - Math.random(),
            size:5
        })
    }
})
document.onkeydown= function (evt) { //监听点击事件
    var xx=Math.random()*innerWidth,yy=Math.random()*innerHeight
    for (var i = 0; i < 50; i++) { //添加15个粒子
        srolls.push({
            sx:xx , //鼠标当前坐标作为粒子坐标
            sy:yy,
           vx: 1*(0.5 - Math.random()), //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy:1*( 0.5 - Math.random()),
            life: live*2, //存活周期
            life2:2,
            color: colors[parseInt(Math.random() * colors.length)], //随机选择颜色
            size:5 //随机粒子尺寸,取值范围为0~5
        })
    }
}
var mv=1,cl=1,sr=1;
function drawpoints() { //绘制粒子
    ctx.clearRect(0, 0, canvas.width, canvas.height) //清屏
    if(mv){
    for (let i = 0; i < points.length; i++) { //遍历粒子
        if(i>1000){
            points.splice(i, 1);
            continue;
        }
        let point = points[i] //定义单个粒子
        ctx.beginPath()
        ctx.arc(point.sx, point.sy, point.size, Math.PI * 2, false) //根据粒子属性画圆
        ctx.fillStyle = "rgba(" + point.color + "," + 255 + ")" //根据粒子属性设置填充颜色及透明度
        ctx.fill() //填充颜色
        point.life-- //生命值减1
        if (point.life <= 0) { //生命值为0则从粒子数组中删除
        if(point.life2){
        for (let i = 0; i < 5; i++) { //添加15个粒子
        points.push({
            sx: point.sx, //鼠标当前坐标作为粒子坐标
            sy: point.sy,
            vx:(point.life2)*(0.5 - Math.random()), //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy: (point.life2)*(0.5 - Math.random()),
            life: live, //存活周期
            life2:point.life2-1,
            color: colors[parseInt(Math.random() * colors.length)], //随机选择颜色
            size:point.life2*2+2, //随机粒子尺寸,取值范围为0~5
            rt:0 //随机粒子尺寸,取值范围为0~5
        })
    }
        }
            points.splice(i, 1)
        }
        point.sx += point.vx * 3 //根据向量值改变粒子位置
        point.sy += point.vy * 3
        point.vx+=2*Math.cos(point.rt)*(0.5 - Math.random());
        point.vy+=2*Math.sin(point.rt)*(0.5 - Math.random());
        point.rt++;
    }
    }
    if(cl){
    for (let i = 0; i < clicks.length; i++) { //绘制点击效果
        if(i>1000){
            clicks.splice(i, 1);
            continue;
        }
        let click = clicks[i]
        ctx.beginPath()
        ctx.arc(click.sx, click.sy, click.size, Math.PI * 2, false) //根据粒子属性画圆
        ctx.fillStyle = "rgba(" + click.color + "," + click.life / live + ")" //根据粒子属性设置填充颜色及透明度
        ctx.fill() //填充颜色
        click.sx += click.vx * 10
        click.sy += click.vy * 10
        click.life--
        if (click.life <= 0) {
            for (let i = 0; i < 5; i++) { //添加15个粒子
        points.push({
            sx: click.sx, //鼠标当前坐标作为粒子坐标
            sy: click.sy,
            vx: 2 - Math.random()*4, //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy: 2 - Math.random()*4,
            life: live, //存活周期
            life2:1,
            color: colors[parseInt(Math.random() * colors.length)], //随机选择颜色
            size: 4, //随机粒子尺寸,取值范围为0~5
            rt:0 //随机粒子尺寸,取值范围为0~5
        })
    }
            clicks.splice(i, 1)
        }
    }
    }
    if(sr){
    for (let i = 0; i < srolls.length; i++) { //绘制点击效果
        if(i>1000){
            srolls.splice(i, 1);
            continue;
        }
        let sroll = srolls[i]
        ctx.beginPath()
        ctx.arc(sroll.sx, sroll.sy, sroll.size, Math.PI * 2, false) //根据粒子属性画圆
        ctx.fillStyle = "rgba(" + sroll.color + "," + (sroll.life+50) / live + ")" //根据粒子属性设置填充颜色及透明度
        ctx.fill() //填充颜色
        sroll.sx += sroll.vx * 10
        sroll.sy += sroll.vy * 10
        sroll.life--
        if (sroll.life <= 0) {
            if(sroll.life2==2){
                srolls.push({
                    sx: sroll.sx,
                    sy: sroll.sy,
                    vx:-sroll.vx*5, //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
                    vy:-sroll.vy*5,
                    life: live*2/5,
                    life2:1,
                    color:sroll.color,
                    size:5
                })
            }
            if(sroll.life2==1){
                for (let i = 0; i < 5; i++) { //添加15个粒子
        points.push({
            sx: sroll.sx, //鼠标当前坐标作为粒子坐标
            sy: sroll.sy,
            vx: 5 - Math.random()*10, //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy: 5 - Math.random()*10,
            life: live*2, //存活周期
            life2:0,
            color: colors[parseInt(Math.random() * colors.length)], //随机选择颜色
            size: 7, //随机粒子尺寸,取值范围为0~5
            rt:0 //随机粒子尺寸,取值范围为0~5
        })
                }
            }
            srolls.splice(i, 1)
        }
    }
    }
}
setInterval(drawpoints, 20) //20毫秒绘制一次
})();

改版 5(game)

当时血量是在控制台输出的。

与其说是游戏不如说是碰撞检测,因为点击发射的子弹是从当前鼠标位置发出的,必定受到伤害……

// ==UserScript==
// @name         New Userscript
// @namespace    http://tampermonkey.net/
// @version      2024-04-16
// @description  try to take over the world!
// @author       You
// @match        *://*/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=microsoft.com
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
var canvas = document.createElement("canvas")
var ctx = canvas.getContext("2d")
window.document.body.appendChild(canvas)
canvas.width = window.innerWidth
canvas.height = window.innerHeight
canvas.setAttribute('style', 'position:fixed;left:0;top:0;pointer-events:none;filter:blur(2px);')
var clicks = []
var points = [] //定义粒子数组
var srolls = [] //定义粒子数组
var live = 50 //存活50个周期
var colors = [ //备选粒子颜色数组
    "236, 204, 104",
    "255, 71, 87",
    "112, 161, 255",
    "123, 237, 159"
]
var mx,my;
window.addEventListener("mousedown", function (evt) { //监听鼠标移动事件
    for (var i = 0; i < 15; i++) { //添加15个粒子
        points.push({
            sx: evt.x, //鼠标当前坐标作为粒子坐标
            sy: evt.y,
            vx: 1.5 - Math.random()*3, //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy: 1.5 - Math.random()*3,
            life: live, //存活周期
            life2:3,
            color: colors[parseInt(Math.random() * colors.length)], //随机选择颜色
            size:8, //随机粒子尺寸,取值范围为0~5
            rt:0
        })
    }
})
window.addEventListener("mousewheel", function (evt) { //监听点击事件
    for (var i = 0; i < 5; i++) {
        clicks.push({
            sx: evt.x,
            sy: evt.y,
            color: colors[parseInt(Math.random() * colors.length)],
            life: live*2,
            vx: 0.5 - Math.random(), //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy: 0.5 - Math.random(),
            size:5
        })
    }
})
window.addEventListener("mousemove", function (evt) { //监听点击事件
    mx=evt.x;
    my=evt.y;
})
document.onkeydown= function (evt) { //监听点击事件
    for (var i = 0; i < 50; i++) { //添加15个粒子
        srolls.push({
            sx:mx , //鼠标当前坐标作为粒子坐标
            sy:my,
           vx: 1*(0.5 - Math.random()), //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy:1*( 0.5 - Math.random()),
            life: live*2, //存活周期
            life2:2,
            color: colors[parseInt(Math.random() * colors.length)], //随机选择颜色
            size:5 //随机粒子尺寸,取值范围为0~5
        })
    }
}
var mv=1,cl=1,sr=1,cnt=100;
function drawpoints() { //绘制粒子
    ctx.clearRect(0, 0, canvas.width, canvas.height) //清屏
    for (let i = 0; i < points.length; i++){
        let point=points[i]
        if(Math.pow((mx-(point.sx+point.size/2)),2)+Math.pow((my-(point.sy+point.size/2)),2)<=Math.pow(point.size+3,2)){
            cnt--;
//            points.splice(i, 1);
        }
    }
    if(mv){
    for (let i = 0; i < points.length; i++) { //遍历粒子
        if(i>1000){
            points.splice(i, 1);
            continue;
        }
        let point = points[i] //定义单个粒子
        ctx.beginPath()
        ctx.arc(point.sx, point.sy, point.size, Math.PI * 2, false) //根据粒子属性画圆
        ctx.fillStyle = "rgba(" + point.color + "," + 255 + ")" //根据粒子属性设置填充颜色及透明度
        ctx.fill() //填充颜色
        point.life-- //生命值减1
        if (point.life <= 0) { //生命值为0则从粒子数组中删除
        if(point.life2){
        for (let i = 0; i < 5; i++) { //添加15个粒子
        points.push({
            sx: point.sx, //鼠标当前坐标作为粒子坐标
            sy: point.sy,
            vx:(point.life2)*(0.5 - Math.random()), //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy: (point.life2)*(0.5 - Math.random()),
            life: live, //存活周期
            life2:point.life2-1,
            color: colors[parseInt(Math.random() * colors.length)], //随机选择颜色
            size:point.life2*2+2, //随机粒子尺寸,取值范围为0~5
            rt:0 //随机粒子尺寸,取值范围为0~5
        })
    }
        }
            points.splice(i, 1)
        }
        point.sx += point.vx * 3 //根据向量值改变粒子位置
        point.sy += point.vy * 3
        point.vx+=2*Math.cos(point.rt)*(0.5 - Math.random());
        point.vy+=2*Math.sin(point.rt)*(0.5 - Math.random());
        point.rt++;
    }
    }
    if(cl){
    for (let i = 0; i < clicks.length; i++) { //绘制点击效果
        if(i>1000){
            clicks.splice(i, 1);
            continue;
        }
        let click = clicks[i]
        ctx.beginPath()
        ctx.arc(click.sx, click.sy, click.size, Math.PI * 2, false) //根据粒子属性画圆
        ctx.fillStyle = "rgba(" + click.color + "," + click.life / live + ")" //根据粒子属性设置填充颜色及透明度
        ctx.fill() //填充颜色
        click.sx += click.vx * 10
        click.sy += click.vy * 10
        click.life--
        if (click.life <= 0) {
            clicks.splice(i, 1)
        }
    }
    }
    if(sr){
    for (let i = 0; i < srolls.length; i++) { //绘制点击效果
        if(i>1000){
            srolls.splice(i, 1);
            continue;
        }
        let sroll = srolls[i]
        ctx.beginPath()
        ctx.arc(sroll.sx, sroll.sy, sroll.size, Math.PI * 2, false) //根据粒子属性画圆
        ctx.fillStyle = "rgba(" + sroll.color + "," + (sroll.life+50) / live + ")" //根据粒子属性设置填充颜色及透明度
        ctx.fill() //填充颜色
        sroll.sx += sroll.vx * 10
        sroll.sy += sroll.vy * 10
        sroll.life--
        if (sroll.life <= 0) {
            if(sroll.life2==2){
                srolls.push({
                    sx: sroll.sx,
                    sy: sroll.sy,
                    vx:-sroll.vx*5, //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
                    vy:-sroll.vy*5,
//                    vx: (mx-sroll.sx)/200, //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
//                    vy: (my-sroll.sy)/200,
                    life: live*2/5,
                    life2:1,
                    color:sroll.color,
                    size:5
                })
                srolls.push({
                    sx: sroll.sx,
                    sy: sroll.sy,
//                    vx:-sroll.vx*5, //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
//                    vy:-sroll.vy*5,
                    vx: (mx-sroll.sx)/200, //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
                    vy: (my-sroll.sy)/200,
                    life: live*2/5,
                    life2:1,
                    color:sroll.color,
                    size:5
                })
            }
            if(sroll.life2==1){
                for (let i = 0; i < 5; i++) { //添加15个粒子
        points.push({
            sx: sroll.sx, //鼠标当前坐标作为粒子坐标
            sy: sroll.sy,
            vx: 5*(1 - Math.random()*2), //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy: 5*(1 - Math.random()*2),
            life: live*2, //存活周期
            life2:0,
            color: colors[parseInt(Math.random() * colors.length)], //随机选择颜色
            size: 7, //随机粒子尺寸,取值范围为0~5
            rt:0 //随机粒子尺寸,取值范围为0~5
        })
                }
            }
            srolls.splice(i, 1)
        }
    }
    }
    console.log(cnt);
}
setInterval(drawpoints, 20) //20毫秒绘制一次
})();

改版 6(color)

太难看被弃用了。

// ==UserScript==
// @name         New Userscript
// @namespace    http://tampermonkey.net/
// @version      2024-04-16
// @description  try to take over the world!
// @author       You
// @match        *://*/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=microsoft.com
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
var canvas = document.createElement("canvas")
var ctx = canvas.getContext("2d")
window.document.body.appendChild(canvas)
canvas.width = window.innerWidth
canvas.height = window.innerHeight
canvas.setAttribute('style', 'position:fixed;left:0;top:0;pointer-events:none;filter:blur(2px);')
var clicks = []
var points = [] //定义粒子数组
var srolls = [] //定义粒子数组
var live = 50 //存活50个周期
var colors = [ //备选粒子颜色数组
    "236, 204, 104",
    "255, 71, 87",
    "112, 161, 255",
    "123, 237, 159",
    "255,255,255",
    "255,0,0",
    "0,0,0"
]
var mx,my;
window.addEventListener("mousedown", function (evt) { //监听鼠标移动事件
    for (var i = 0; i < 15; i++) { //添加15个粒子
        points.push({
            sx: evt.x, //鼠标当前坐标作为粒子坐标
            sy: evt.y,
            vx: 1.5 - Math.random()*3, //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy: 1.5 - Math.random()*3,
            life: live, //存活周期
            life2:3,
            color: colors[parseInt(Math.random() * colors.length)], //随机选择颜色
            size:8, //随机粒子尺寸,取值范围为0~5
            rt:0
        })
    }
})
window.addEventListener("mousewheel", function (evt) { //监听点击事件
    for (var i = 0; i < 5; i++) {
        clicks.push({
            sx: evt.x,
            sy: evt.y,
            color: colors[parseInt(Math.random() * colors.length)],
            life: live*2,
            vx: 0.5 - Math.random(), //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy: 0.5 - Math.random(),
            size:5
        })
    }
})
window.addEventListener("mousemove", function (evt) { //监听点击事件
    mx=evt.x;
    my=evt.y;
})
document.onkeydown= function (evt) { //监听点击事件
    for (var i = 0; i < 50; i++) { //添加15个粒子
        srolls.push({
            sx:mx , //鼠标当前坐标作为粒子坐标
            sy:my,
           vx: 1*(0.5 - Math.random()), //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy:1*( 0.5 - Math.random()),
            life: live*2, //存活周期
            life2:2,
            color: colors[6], //随机选择颜色
            size:5 //随机粒子尺寸,取值范围为0~5
        })
    }
}
var mv=1,cl=1,sr=1,cnt=100;
function drawpoints() { //绘制粒子
    ctx.clearRect(0, 0, canvas.width, canvas.height) //清屏
    for (let i = 0; i < points.length; i++){
        let point=points[i]
        if(Math.pow((mx-(point.sx+point.size/2)),2)+Math.pow((my-(point.sy+point.size/2)),2)<=Math.pow(point.size+3,2)){
            cnt--;
//            points.splice(i, 1);
        }
    }
    for (let i = 0; i < srolls.length; i++){
        let point=srolls[i]
        if(point.color==colors[5]&&Math.pow((mx-(point.sx+point.size/2)),2)+Math.pow((my-(point.sy+point.size/2)),2)<=Math.pow(point.size+3,2)){
            cnt--;
//            points.splice(i, 1);
        }
    }
    for (let i = 0; i < points.length; i++){
        let point=points[i]
        if(point.sx<=0){
            point.vx=-point.vx;
        }
        if(point.sx>=innerWidth){
            point.vx=-point.vx;
        }
        if(point.sy<=0){
            point.vy=-point.vy;
        }
        if(point.sy>=innerHeight){
            point.vy=-point.vy;
        }
    }
    for (let i = 0; i < srolls.length; i++){
        let point=srolls[i]
        if(point.sx<=0){
            point.vx=-point.vx;
        }
        if(point.sx>=innerWidth){
            point.vx=-point.vx;
        }
        if(point.sy<=0){
            point.vy=-point.vy;
        }
        if(point.sy>=innerHeight){
            point.vy=-point.vy;
        }
    }
    for (let i = 0; i < clicks.length; i++){
        let point=clicks[i]
        if(point.sx<=0){
            point.vx=-point.vx;
        }
        if(point.sx>=innerWidth){
            point.vx=-point.vx;
        }
        if(point.sy<=0){
            point.vy=-point.vy;
        }
        if(point.sy>=innerHeight){
            point.vy=-point.vy;
        }
    }
    if(mv){
    for (let i = 0; i < points.length; i++) { //遍历粒子
        if(i>1000){
            points.splice(i, 1);
            continue;
        }
        let point = points[i] //定义单个粒子
        ctx.beginPath()
        ctx.arc(point.sx, point.sy, point.size, Math.PI * 2, false) //根据粒子属性画圆
        ctx.fillStyle = "rgba(" + point.color + "," + 255 + ")" //根据粒子属性设置填充颜色及透明度
        ctx.fill() //填充颜色
        point.life-- //生命值减1
        if (point.life <= 0) { //生命值为0则从粒子数组中删除
        if(point.life2){
        for (let i = 0; i < 5; i++) { //添加15个粒子
        points.push({
            sx: point.sx, //鼠标当前坐标作为粒子坐标
            sy: point.sy,
            vx:(point.life2)*(0.5 - Math.random()), //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy: (point.life2)*(0.5 - Math.random()),
            life: live, //存活周期
            life2:point.life2-1,
            color: colors[parseInt(Math.random() * colors.length)], //随机选择颜色
            size:point.life2*2+2, //随机粒子尺寸,取值范围为0~5
            rt:0 //随机粒子尺寸,取值范围为0~5
        })
    }
        }
            points.splice(i, 1)
        }
        point.sx += point.vx * 3 //根据向量值改变粒子位置
        point.sy += point.vy * 3
        point.vx+=2*Math.cos(point.rt)*(0.5 - Math.random());
        point.vy+=2*Math.sin(point.rt)*(0.5 - Math.random());
        point.rt++;
    }
    }
    if(cl){
    for (let i = 0; i < clicks.length; i++) { //绘制点击效果
        if(i>1000){
            clicks.splice(i, 1);
            continue;
        }
        let click = clicks[i]
        ctx.beginPath()
        ctx.arc(click.sx, click.sy, click.size, Math.PI * 2, false) //根据粒子属性画圆
        ctx.fillStyle = "rgba(" + click.color + "," + click.life / live + ")" //根据粒子属性设置填充颜色及透明度
        ctx.fill() //填充颜色
        click.sx += click.vx * 10
        click.sy += click.vy * 10
        click.life--
        if (click.life <= 0) {
            clicks.splice(i, 1)
        }
    }
    }
    if(sr){
    for (let i = 0; i < srolls.length; i++) { //绘制点击效果
        if(i>1000){
            srolls.splice(i, 1);
            continue;
        }
        let sroll = srolls[i]
        ctx.beginPath()
        ctx.arc(sroll.sx, sroll.sy, sroll.size, Math.PI * 2, false) //根据粒子属性画圆
        if(sroll.color!='0,0,0'){
        ctx.fillStyle = "rgba(" + sroll.color + "," + (sroll.life+50) / live + ")" //根据粒子属性设置填充颜色及透明度
        }
        else{
            ctx.fillStyle = "rgba(" + sroll.color + "," + 0.05 + ")" //根据粒子属性设置填充颜色及透明度
        }
        ctx.fill() //填充颜色
        sroll.sx += sroll.vx * 10
        sroll.sy += sroll.vy * 10
        sroll.life--
        if (sroll.life <= 0) {
            if(sroll.life2==2){
                srolls.push({
                    sx: sroll.sx,
                    sy: sroll.sy,
                    vx:-sroll.vx*5, //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
                    vy:-sroll.vy*5,
//                    vx: (mx-sroll.sx)/200, //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
//                    vy: (my-sroll.sy)/200,
                    life: live,
                    life2:1,
                    color:colors[5],
                    size:5
                })
                srolls.push({
                    sx: sroll.sx,
                    sy: sroll.sy,
//                    vx:-sroll.vx*5, //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
//                    vy:-sroll.vy*5,
                    vx: (mx-sroll.sx)/150, //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
                    vy: (my-sroll.sy)/150,
                    life: live,
                    life2:1,
                    color:colors[5],
                    size:5
                })
            }
            if(sroll.life2==1){
                for (let i = 0; i < 5; i++) { //添加15个粒子
        points.push({
            sx: sroll.sx, //鼠标当前坐标作为粒子坐标
            sy: sroll.sy,
            vx: 5*(1 - Math.random()*2), //x轴及y轴的移动向量,取值范围为-0.5 ~ 0.5
            vy: 5*(1 - Math.random()*2),
            life: live*2, //存活周期
            life2:0,
            color: colors[5], //随机选择颜色
            size: 7, //随机粒子尺寸,取值范围为0~5
            rt:0 //随机粒子尺寸,取值范围为0~5
        })
                }
            }
            srolls.splice(i, 1)
        }
    }
    }
    console.log(cnt);
}
setInterval(drawpoints, 20) //20毫秒绘制一次
})();

游戏版

在我博客的侧边栏也可玩。