当前位置:   article > 正文

实战: 跨年烟花代码的实现(附源码)_跨年代码可复制2023

跨年代码可复制2023

目录

前言

一、pandas是什么?

二、代码结构

1.介绍主html代码

2. js文件介绍

GameCanvas.js

script.js

运行效果


前言

本文章将介绍跨年烟花代码的实现以及源代码


提示:以下是本篇文章正文内容

一、pandas是什么?

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

二、代码结构

1.介绍主html代码

代码如下:

  1. <!DOCTYPE html>
  2. <html lang="en" >
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>2023新年快乐</title>
  6. </head>
  7. <body>
  8. <script src='js/gameCanvas-4.0.js'></script>
  9. <script src="js/script.js"></script>
  10. <setTimeout(function() {
  11. setInterval(function() {
  12. fireworks.push(new Firework(Math.random() * width, height, Math.random() - 0.5, -(Math.random() * 7 + 5)));
  13. }, 200);
  14. }, 2000);
  15. fireworks.push(new Firework(width / 2, height, 0, -9.5, 10, "gold", true));
  16. setInterval(function() {
  17. fireworks.push(new Firework(width / 2, height, 0, -9.5, 10, "gold", true));
  18. }, 5000);
  19. for (var i = 0; i < 250; i++) {
  20. circle(
  21. Math.random() * width,
  22. Math.random() * height,
  23. 1,
  24. "rgb(200, 200, 200)"
  25. );
  26. }
  27. var starImage = canvasToImage();
  28. background("black");
  29. loop();
  30. function loop() {
  31. gc.ctx.globalCompositeOperation = "source-over";
  32. background("rgba(0, 0, 0, 0.1)");
  33. gc.ctx.drawImage(starImage, 0, 0);
  34. gc.ctx.globalCompositeOperation = "lighter";
  35. for (var i = 0; i < fireworks.length; i++) {
  36. var firework = fireworks[i];
  37. firework.update();
  38. firework.render();
  39. }
  40. for (var i = 0; i < particles.length; i++) {
  41. var particle = particles[i];
  42. particle.update();
  43. particle.render();
  44. }
  45. for (var i = 0; i < titleParticles.length; i++) {
  46. var p = titleParticles[i];
  47. p.update();
  48. p.render();
  49. }
  50. requestAnimationFrame(loop);
  51. }
  52. function TitleParticle(x, y, vx, vy) {
  53. this.x = x;
  54. this.y = y;
  55. this.vx = vx;
  56. this.vy = vy;
  57. this.ay = 0.2;
  58. this.radius = 4;
  59. this.maxHealth = 200;
  60. this.health = 200;
  61. this.update = function() {
  62. this.x += this.vx;
  63. this.y += this.vy;
  64. this.vx *= 0.95;
  65. this.vy *= 0.95;
  66. this.vy += this.ay;
  67. this.ay *= 0.95;
  68. this.radius = (this.health / this.maxHealth) * 4;
  69. this.health--;
  70. if (this.health <= 0) {
  71. titleParticles.splice(titleParticles.indexOf(this), 1);
  72. }
  73. }
  74. this.render = function() {
  75. circle(this.x, this.y, this.radius, "rgba(255, 255, 255, " + (this.health / this.maxHealth) + ")");
  76. }
  77. }
  78. function Firework(x, y, vx, vy, radius = 5, color = "white", title = false) {
  79. this.x = x;
  80. this.y = y;
  81. this.vx = vx;
  82. this.vy = vy;
  83. this.radius = radius;
  84. this.title = title;
  85. this.color = color;
  86. </body>
  87. </html>

可以看到引入了两个js文件,也同样在本地。 

2. js文件介绍

代码如下:

GameCanvas.js

  1. function GameCanvas(settings) {
  2. let top = this;
  3. this.functions = [];
  4. this.keys = [];
  5. this.images = [];
  6. this.spheres = [];
  7. this.font = "Arial";
  8. this.imageData = undefined;
  9. this.imageDataData = undefined;
  10. this.lastLoop = performance.now();
  11. this.calculateFPS = true;
  12. this.fps = -1;
  13. this.deltaTime = 1;
  14. let mouseLookupTable = [
  15. "left",
  16. "middle",
  17. "right"
  18. ];
  19. this.contextMenuDisabled = false;
  20. this.disableScrollOnMobile = false;
  21. this.eventFunctions = {
  22. "mousedown": typeof OnMouseDown !== "undefined",
  23. "mouseup": typeof OnMouseUp !== "undefined",
  24. "mousemove": typeof OnMouseMove !== "undefined",
  25. "contextmenu": typeof OnContextMenu !== "undefined",
  26. "touchstart": typeof OnTouchStart !== "undefined",
  27. "touchend": typeof OnTouchEnd !== "undefined",
  28. "touchmove": typeof OnTouchMove !== "undefined",
  29. };
  30. this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
  31. this.createCanvas = function() {
  32. let canvas = document.createElement("canvas");
  33. document.body.appendChild(canvas);
  34. return canvas;
  35. }
  36. this.setSize = function(width, height) {
  37. if (top.canvas) {
  38. top.canvas.width = top.width = width;
  39. top.canvas.height = top.height = height;
  40. window.width = this.width;
  41. window.height = this.height;
  42. }
  43. else {
  44. console.error("There is no canvas!");
  45. }
  46. }
  47. this.fillPageWithCanvas = function() {
  48. top.canvas.style.position = "fixed";
  49. top.canvas.style.top = "0px";
  50. top.canvas.style.left = "0px";
  51. top.setSize(window.innerWidth, window.innerHeight);
  52. top.disableScrollOnMobile = true;
  53. top.contextMenuDisabled = true;
  54. this.updateSizeOnResize = true;
  55. }
  56. this.requestFullscreen = function() {
  57. if (top.canvas.requestFullscreen)
  58. top.canvas.requestFullscreen();
  59. else if (top.canvas.mozRequestFullScreen)
  60. top.canvas.mozRequestFullScreen();
  61. else if (top.canvas.webkitRequestFullscreen)
  62. top.canvas.webkitRequestFullscreen();
  63. else if (top.canvas.msRequestFullscreen)
  64. top.canvas.msRequestFullscreen();
  65. }
  66. this.exitFullscreen = function() {
  67. if(document.exitFullscreen)
  68. document.exitFullscreen();
  69. else if(document.mozCancelFullScreen)
  70. document.mozCancelFullScreen();
  71. else if(document.webkitExitFullscreen)
  72. document.webkitExitFullscreen();
  73. else if(document.msExitFullscreen)
  74. document.msExitFullscreen();
  75. }
  76. this.lockPointer = function() {
  77. top.canvas.requestPointerLock = top.canvas.requestPointerLock || top.canvas.mozRequestPointerLock;
  78. top.canvas.requestPointerLock();
  79. }
  80. this.unlockPointer = function() {
  81. document.exitPointerLock = document.exitPointerLock || document.mozExitPointerLock;
  82. document.exitPointerLock();
  83. }
  84. this.disableContextMenu = function() {
  85. top.contextMenuDisabled = true;
  86. }
  87. this.enableContextMenu = function() {
  88. top.contextMenuDisabled = false;
  89. }
  90. this.key = function(key) {
  91. return top.keys[key];
  92. }
  93. this.update = function() {
  94. if (top.calculateFPS) {
  95. var thisLoop = performance.now();
  96. top.fps = 1000 / (thisLoop - top.lastLoop);
  97. top.deltaTime = 60 / top.fps;
  98. top.lastLoop = thisLoop;
  99. if (top.globalFunctions) {
  100. window.fps = top.fps;
  101. window.deltaTime = top.deltaTime;
  102. }
  103. }
  104. top.mouse.movementX = 0;
  105. top.mouse.movementY = 0;
  106. top.mouse.lastX = top.mouse.x;
  107. top.mouse.lastY = top.mouse.y;
  108. }
  109. /******************
  110. Rendering
  111. ******************/
  112. this.clearScreen = function() {
  113. top.ctx.clearRect(0, 0, top.width, top.height);
  114. }
  115. this.background = function(color) {
  116. top.ctx.fillStyle = color;
  117. top.ctx.fillRect(0, 0, top.width, top.height);
  118. }
  119. this.circle = function(x, y, radius, color, strokeColor, lineWidth) {
  120. top.ctx.beginPath();
  121. top.ctx.arc(x, y, radius, 0, Math.PI * 2);
  122. top.ctx.fillStyle = color;
  123. if (strokeColor) top.ctx.strokeStyle = strokeColor;
  124. if (lineWidth) top.ctx.lineWidth = lineWidth;
  125. top.ctx.fill();
  126. if (strokeColor) top.ctx.stroke();
  127. }
  128. this.ring = function(x, y, radius, color, lineWidth) {
  129. top.ctx.beginPath();
  130. top.ctx.arc(x, y, radius, 0, Math.PI * 2);
  131. top.ctx.strokeStyle = color;
  132. if (lineWidth) top.ctx.lineWidth = lineWidth;
  133. top.ctx.stroke();
  134. }
  135. this.ellipse = function(x, y, radiusX, radiusY, color, rotation = 0, strokeColor, lineWidth) {
  136. top.ctx.beginPath();
  137. top.ctx.ellipse(x, y, radiusX, radiusY, rotation, 0, Math.PI * 2);
  138. top.ctx.fillStyle = color;
  139. if (strokeColor) top.ctx.strokeStyle = strokeColor;
  140. if (lineWidth) top.ctx.lineWidth = lineWidth;
  141. top.ctx.fill();
  142. if (strokeColor) top.ctx.stroke();
  143. }
  144. this.rectangle = function(x, y, width, height, color, strokeColor, lineWidth) {
  145. top.ctx.fillStyle = color;
  146. if (lineWidth) top.ctx.lineWidth = lineWidth;
  147. if (strokeColor) {
  148. top.ctx.beginPath();
  149. top.ctx.strokeStyle = strokeColor;
  150. top.ctx.rect(x, y, width, height);
  151. top.ctx.fill();
  152. top.ctx.stroke();
  153. }
  154. else
  155. top.ctx.fillRect(x, y, width, height);
  156. }
  157. this.triangle = function(x1, y1, x2, y2, x3, y3, color, strokeColor, lineWidth) {
  158. top.ctx.beginPath();
  159. top.ctx.moveTo(x1, y1);
  160. top.ctx.lineTo(x2, y2);
  161. top.ctx.lineTo(x3, y3);
  162. top.ctx.closePath();
  163. top.ctx.fillStyle = color;
  164. if (lineWidth) top.ctx.lineWidth = lineWidth;
  165. top.ctx.fill();
  166. if (strokeColor) {
  167. top.ctx.strokeStyle = strokeColor;
  168. top.ctx.stroke();
  169. }
  170. }
  171. this.setLineCap = function(lineCap) {
  172. top.ctx.lineCap = lineCap;
  173. }
  174. this.resetLineCap = function() {
  175. top.ctx.lineCap = "butt";
  176. }
  177. this.line = function(x1, y1, x2, y2, strokeWeight, color) {
  178. top.ctx.beginPath();
  179. top.ctx.moveTo(x1, y1);
  180. top.ctx.lineTo(x2, y2);
  181. if (color) top.ctx.strokeStyle = color;
  182. if (strokeWeight) top.ctx.lineWidth = strokeWeight;
  183. top.ctx.stroke();
  184. }
  185. this.picture = function(url, x, y, width, height) {
  186. var imageElement = top.images[url];
  187. if (!imageElement) {
  188. var img = new Image();
  189. img.src = url;
  190. img.onload = function() {
  191. top.ctx.drawImage(img, x, y, width, height);
  192. }
  193. top.images[url] = img;
  194. }
  195. else if (imageElement.complete) {
  196. top.ctx.drawImage(imageElement, x, y, width, height);
  197. }
  198. }
  199. this.setFont = function(font) {
  200. top.font = font;
  201. }
  202. this.setTextAlign = function(align) {
  203. top.ctx.textAlign = align;
  204. }
  205. this.setTextXAlign = function(align) {
  206. top.ctx.textAlign = align;
  207. }
  208. this.setTextYAlign = function(align) {
  209. top.ctx.textBaseline = align;
  210. }
  211. this.resetTextXAlign = function() {
  212. top.ctx.textAlign = "left";
  213. }
  214. this.resetTextYAlign = function() {
  215. top.ctx.textBaseline = "alphabetic";
  216. }
  217. this.text = function(textString, x, y, fontSize, color, strokeColor, lineWidth) {
  218. top.ctx.beginPath();
  219. top.ctx.font = fontSize + "px " + top.font;
  220. top.ctx.fillStyle = color;
  221. if (lineWidth) top.ctx.lineWidth = lineWidth;
  222. top.ctx.fillText(textString, x, y);
  223. if (strokeColor) {
  224. top.ctx.strokeStyle = strokeColor;
  225. top.ctx.strokeText(textString, x, y);
  226. }
  227. }
  228. this.getPixelData = function() {
  229. top.imageData = top.ctx.getImageData(0, 0, top.width, top.height);
  230. top.imageDataData = top.imageData.data;
  231. }
  232. this.updatePixel = function(x, y, r, g, b, a = 255) {
  233. let i = (x + y * top.width) * 4;
  234. top.imageDataData[i] = r;
  235. top.imageDataData[i + 1] = g;
  236. top.imageDataData[i + 2] = b;
  237. top.imageDataData[i + 3] = a;
  238. }
  239. this.updatePixelIndex = function(index, r, g, b, a = 255) {
  240. var i = index * 4;
  241. top.imageDataData[i] = r;
  242. top.imageDataData[i + 1] = g;
  243. top.imageDataData[i + 2] = b;
  244. top.imageDataData[i + 3] = a;
  245. }
  246. this.getPixel = function(x, y) {
  247. let i = (x + y * top.width) * 4;
  248. return [
  249. top.imageDataData[i],
  250. top.imageDataData[i + 1],
  251. top.imageDataData[i + 2],
  252. top.imageDataData[i + 3]
  253. ];
  254. }
  255. this.getPixelIndex = function(index) {
  256. let i = index * 4;
  257. return [
  258. top.imageDataData[i],
  259. top.imageDataData[i + 1],
  260. top.imageDataData[i + 2],
  261. top.imageDataData[i + 3]
  262. ];
  263. }
  264. this.renderPixelData = function() {
  265. /*createImageBitmap(top.imageData).then(function(imgBitmap) {
  266. top.ctx.drawImage(imgBitmap, 0, 0);
  267. });*/
  268. top.ctx.putImageData(top.imageData, 0, 0);
  269. }
  270. this.save = function() {
  271. top.ctx.save();
  272. }
  273. this.restore = function() {
  274. top.ctx.restore();
  275. }
  276. this.rotate = function(angle) {
  277. top.ctx.rotate(angle);
  278. }
  279. this.translate = function(x, y) {
  280. top.ctx.translate(x, y);
  281. }
  282. this.beginPath = function() {
  283. top.ctx.beginPath();
  284. }
  285. this.closePath = function() {
  286. top.ctx.closePath();
  287. }
  288. this.moveTo = function(x, y) {
  289. top.ctx.moveTo(x, y);
  290. }
  291. this.lineTo = function(x, y) {
  292. top.ctx.lineTo(x, y);
  293. }
  294. this.fill = function() {
  295. top.ctx.fill();
  296. }
  297. this.stroke = function() {
  298. top.ctx.stroke();
  299. }
  300. this.fillStyle = function(color) {
  301. top.ctx.fillStyle = color;
  302. }
  303. this.strokeStyle = function(color) {
  304. top.ctx.strokeStyle = color;
  305. }
  306. this.setLineWidth = function(lineWidth) {
  307. top.ctx.lineWidth = lineWidth;
  308. }
  309. /******************
  310. 3D
  311. ******************/
  312. this.drawSphere = function(screenX, screenY, radius, color, lightDir = {x: 0, y: 0, z: 1}) {
  313. var id = (screenX + screenY) * radius * (color[0] + 1) * (color[1] + 1) * (color[2] + 1) * (lightDir.x + 1) * (lightDir.y + 1) * (lightDir.z + 1);
  314. if (top.spheres[id]) {
  315. if (top.spheres[id].imageData)
  316. top.ctx.putImageData(top.spheres[id].imageData, screenX - radius, screenY - radius);
  317. else if (top.spheres[id].image)
  318. top.ctx.drawImage(top.spheres[id].image, screenX - radius, screenY - radius);
  319. }
  320. else {
  321. var imageData = top.ctx.createImageData(radius * 2, radius * 2);
  322. for (var y = 0; y < radius * 2; y++) {
  323. for (var x = 0; x < radius * 2; x++) {
  324. var line = {
  325. origin: {x: x, y: y, z: 0},
  326. direction: {x: 0, y: 0, z: 1}
  327. };
  328. var o = {
  329. position: {x: radius, y: radius, z: radius * 2}
  330. }
  331. var oc = {
  332. x: line.origin.x - o.position.x,
  333. y: line.origin.y - o.position.y,
  334. z: line.origin.z - o.position.z
  335. };
  336. var loc = top.dot3D(line.direction, oc);
  337. var ocLength = top.getLength(oc.x, oc.y, oc.z);
  338. var underSqrt = loc * loc - (ocLength * ocLength - radius * radius);
  339. if (underSqrt >= 0) {
  340. var d = -loc - Math.sqrt(underSqrt);
  341. if (d > 0) { // Circle is not behind player and is closest to player
  342. var hitPoint = {
  343. x: line.origin.x + line.direction.x * d,
  344. y: line.origin.y + line.direction.y * d,
  345. z: line.origin.z + line.direction.z * d
  346. };
  347. var surfaceNormal = top.normalize3DVector({
  348. x: o.position.x - hitPoint.x,
  349. y: o.position.y - hitPoint.y,
  350. z: o.position.z - hitPoint.z
  351. });
  352. var diffuse = top.dot3D(lightDir, surfaceNormal);
  353. var index = (x + y * radius * 2) * 4;
  354. imageData.data[index] = color[0] * diffuse;
  355. imageData.data[index + 1] = color[1] * diffuse;
  356. imageData.data[index + 2] = color[2] * diffuse;
  357. imageData.data[index + 3] = 255;
  358. }
  359. }
  360. }
  361. }
  362. if (window.createImageBitmap) {
  363. top.spheres[id] = {imageData: undefined, image: undefined};
  364. createImageBitmap(imageData).then(function(imgBitmap) {
  365. top.ctx.drawImage(imgBitmap, screenX - radius, screenY - radius);
  366. top.spheres[id] = {imageData: undefined, image: imgBitmap};
  367. });
  368. }
  369. else {
  370. top.ctx.putImageData(imageData, screenX - radius, screenY - radius);
  371. top.spheres[id] = {imageData, image: undefined};
  372. }
  373. }
  374. }
  375. /******************
  376. Audio
  377. ******************/
  378. this.createSound = function(url, volume = 1, startTime = 0, looping = false) {
  379. var audio = new Audio(url);
  380. audio.loop = looping;
  381. audio.currentTime = startTime;
  382. audio.volume = volume;
  383. return {
  384. volume,
  385. startTime,
  386. audio
  387. };
  388. }
  389. this.playSound = function(sound) {
  390. sound.audio.currentTime = sound.startTime;
  391. sound.audio.volume = sound.volume;
  392. sound.audio.play();
  393. }
  394. this.stopSound = function(sound) {
  395. sound.audio.stop();
  396. }
  397. this.pauseSound = function(sound) {
  398. sound.audio.pause();
  399. }
  400. this.backgroundMusic = function(url) {
  401. var audio = new Audio(url);
  402. audio.loop = true;
  403. audio.play();
  404. return audio;
  405. }
  406. this.fadeOutSound = function(sound, time = 1) {
  407. var startVolume = sound.volume;
  408. var count = 0;
  409. var interv = setInterval(() => {
  410. sound.audio.volume = (startVolume / (time * 20)) * (time * 20 - count);
  411. count++;
  412. if (count > time * 20) {
  413. sound.audio.pause();
  414. clearInterval(interv);
  415. }
  416. }, 50);
  417. }
  418. this.playTone = function(freq = 440, time = 1, volume = 1, type = "sine") {
  419. var oscillator = top.audioContext.createOscillator();
  420. var gainNode = top.audioContext.createGain()
  421. gainNode.gain.value = volume;
  422. gainNode.connect(top.audioContext.destination);
  423. oscillator.type = type;
  424. oscillator.frequency.value = freq;
  425. oscillator.connect(gainNode);
  426. oscillator.start();
  427. setTimeout(() => {
  428. oscillator.stop();
  429. }, time * 1000);
  430. }
  431. /******************
  432. Math
  433. ******************/
  434. this.DegToRad = Math.PI / 180;
  435. this.RadToDeg = 180 / Math.PI;
  436. this.PI = Math.PI;
  437. this.TWO_PI = Math.PI * 2;
  438. this.TAU = this.TWO_PI;
  439. this.getDistanceSqr = function(x1, y1, x2, y2) {
  440. var a = x1 - x2;
  441. var b = y1 - y2;
  442. return a * a + b * b;
  443. }
  444. this.getDistanceSqr3D = function(x1, y1, x2, y2, z1, z2) {
  445. var a = x1 - x2;
  446. var b = y1 - y2;
  447. var c = z1 - z2;
  448. return a * a + b * b + c * c;
  449. }
  450. this.getDistance = function(x1, y1, x2, y2) {
  451. return Math.sqrt(top.getDistanceSqr(x1, y1, x2, y2));
  452. }
  453. this.getDistance3D = function(x1, y1, x2, y2, z1, z2) {
  454. return Math.sqrt(top.getDistanceSqr3D(x1, y1, x2, y2, z1, z2));
  455. }
  456. this.getAngle = function(x1, y1, x2, y2) {
  457. return Math.atan2(y2 - y1, x2 - x1);
  458. }
  459. this.normalize = function(x, y) {
  460. var len = Math.sqrt(x * x + y * y);
  461. return {
  462. x: x / len,
  463. y: y / len
  464. };
  465. }
  466. this.normalize3D = function(x, y, z) {
  467. var len = Math.sqrt(x * x + y * y + z * z);
  468. return {
  469. x: x / len,
  470. y: y / len,
  471. z: z / len
  472. };
  473. }
  474. this.normalize3DVector = function(x) {
  475. var len = Math.sqrt(x.x * x.x + x.y * x.y + x.z * x.z);
  476. return {
  477. x: x.x / len,
  478. y: x.y / len,
  479. z: x.z / len
  480. };
  481. }
  482. this.lengthVector = function(v) {
  483. return Math.sqrt(v.x * v.x + v.y * v.y);
  484. }
  485. this.length3DVector = function(v) {
  486. return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
  487. }
  488. this.getLength = function() {
  489. var sum = 0;
  490. for (var i = 0; i < arguments.length; i++) {
  491. var arg = arguments[i];
  492. sum += arg * arg;
  493. }
  494. return Math.sqrt(sum);
  495. }
  496. this.dot = function(a, b) {
  497. return a.x * b.x + a.y * b.y;
  498. }
  499. this.dot3D = function(a, b) {
  500. return a.x * b.x + a.y * b.y + a.z * b.z;
  501. }
  502. this.crossProduct3D = function(v1, v2) {
  503. return {
  504. x: v1.y * v2.z - v1.z * v2.y,
  505. y: v1.z * v2.x - v1.x * v2.z,
  506. z: v1.x * v2.y - v1.y * v2.x
  507. }
  508. }
  509. //Intersection
  510. this.rectanglesIntersect = function(x1, y1, w1, h1, x2, y2, w2, h2) {
  511. return x1 + w1 > x2 && x1 < x2 + w2 && y1 + h1 > y2 && y1 < y2 + h2;
  512. }
  513. this.circlesIntersect = function(x1, y1, r1, x2, y2, r2) {
  514. return top.getDistance(x1, y1, x2, y2) < r1 + r2;
  515. }
  516. this.circleRectangleIntersect = function(x1, y1, r1, x2, y2, w2, h2) {
  517. var circleDistanceX = Math.abs(x1 - (x2 + w2 / 2));
  518. var circleDistanceY = Math.abs(y1 - (y2 + h2 / 2));
  519. if (circleDistanceX > (w2 / 2 + r1)) return false;
  520. if (circleDistanceY > (h2 / 2 + r1)) return false;
  521. if (circleDistanceX <= (w2 / 2)) return true;
  522. if (circleDistanceY <= (h2 / 2)) return true;
  523. var a = circleDistanceX - w2 / 2;
  524. var b = circleDistanceY - h2 / 2;
  525. var cornerDistance_sq = a * a + b * b;
  526. return cornerDistance_sq <= (r1 * r1);
  527. }
  528. //Random
  529. this.random = function(max) {
  530. return Math.random() * max;
  531. }
  532. this.randomInt = function(max) {
  533. return Math.random() * max >> 0;
  534. }
  535. this.randomArray = function(array) {
  536. return array[Math.random() * array.length >> 0];
  537. }
  538. this.randomColor = function(colorDepth) {
  539. if (colorDepth) {
  540. var colorStep = 256 / colorDepth;
  541. var r = Math.ceil((Math.random() * 256 >> 0) / colorStep) * colorStep;
  542. var g = Math.ceil((Math.random() * 256 >> 0) / colorStep) * colorStep;
  543. var b = Math.ceil((Math.random() * 256 >> 0) / colorStep) * colorStep;
  544. return "rgb(" + r + "," + g + "," + b + ")";
  545. }
  546. else {
  547. return "rgb(" + (Math.random() * 256 >> 0) + "," + (Math.random() * 256 >> 0) + "," + (Math.random() * 256 >> 0) + ")";
  548. }
  549. }
  550. this.create2DArray = function(w, h, value = () => 0) {
  551. var array = new Array(w);
  552. for (var i = 0; i < w; i++) {
  553. array[i] = new Array(h);
  554. for (var j = 0; j < h; j++) {
  555. array[i][j] = value(i, j);
  556. }
  557. }
  558. return array;
  559. }
  560. /******************
  561. Export
  562. ******************/
  563. this.canvasToURL = function() {
  564. return top.canvas.toDataURL();
  565. }
  566. this.canvasToImage = function() {
  567. var img = new Image();
  568. img.src = top.canvas.toDataURL();
  569. return img;
  570. }
  571. this.saveToFile = function(filename = "canvas.png") {
  572. var a = document.createElement("a");
  573. a.download = filename;
  574. a.href = top.canvas.toDataURL();
  575. a.click();
  576. }
  577. /******************
  578. Cookies
  579. ******************/
  580. this.setCookie = function(name, value, expireDays = 36500) {
  581. let d = new Date();
  582. d.setTime(d.getTime() + (expireDays * 24 * 60 * 60 * 1000));
  583. let expires = "expires=" + d.toUTCString();
  584. document.cookie = name + "=" + value + ";" + expires + ";path=/";
  585. }
  586. this.getCookie = function(name) {
  587. if (name.length == 0)
  588. return false;
  589. var cname = name + "=";
  590. var split = document.cookie.split(";");
  591. for (let i = 0; i < split.length; i++) {
  592. let s = split[i];
  593. var index = s.indexOf(cname);
  594. if (index > 0) {
  595. return s.substr(index + cname.length);
  596. }
  597. }
  598. return false;
  599. }
  600. this.deleteCookie = function(name) {
  601. document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:00 UTC;path=/";
  602. }
  603. /******************
  604. Misc.
  605. ******************/
  606. //Battery level
  607. if (navigator.getBattery) {
  608. navigator.getBattery().then(function (battery) {
  609. battery.addEventListener('levelchange', function() {
  610. top.batteryLevel = battery.level * 100;
  611. });
  612. top.batteryLevel = battery.level * 100;
  613. });
  614. }
  615. this.getBatteryLevel = function() {
  616. return top.batteryLevel;
  617. }
  618. /******************
  619. Functions
  620. ******************/
  621. this.functions = [
  622. {func: this.createCanvas, name: "createCanvas"},
  623. {func: this.setSize, name: "setSize"},
  624. {func: this.fillPageWithCanvas, name: "fillPageWithCanvas"},
  625. {func: this.requestFullscreen, name: "requestFullscreen"},
  626. {func: this.exitFullscreen, name: "exitFullscreen"},
  627. {func: this.lockPointer, name: "lockPointer"},
  628. {func: this.unlockPointer, name: "unlockPointer"},
  629. {func: this.disableContextMenu, name: "disableContextMenu"},
  630. {func: this.enableContextMenu, name: "enableContextMenu"},
  631. {func: this.key, name: "key"},
  632. {func: this.update, name: "update"},
  633. {func: this.clearScreen, name: "clearScreen"},
  634. {func: this.background, name: "background"},
  635. {func: this.circle, name: "circle"},
  636. {func: this.ring, name: "ring"},
  637. {func: this.ellipse, name: "ellipse"},
  638. {func: this.rectangle, name: "rectangle"},
  639. {func: this.triangle, name: "triangle"},
  640. {func: this.picture, name: "picture"},
  641. {func: this.setLineCap, name: "setLineCap"},
  642. {func: this.resetLineCap, name: "resetLineCap"},
  643. {func: this.line, name: "line"},
  644. {func: this.setFont, name: "setFont"},
  645. {func: this.setTextAlign, name: "setTextAlign"},
  646. {func: this.setTextXAlign, name: "setTextXAlign"},
  647. {func: this.setTextYAlign, name: "setTextYAlign"},
  648. {func: this.resetTextXAlign, name: "resetTextXAlign"},
  649. {func: this.resetTextYAlign, name: "resetTextYAlign"},
  650. {func: this.text, name: "text"},
  651. {func: this.getPixelData, name: "getPixelData"},
  652. {func: this.updatePixel, name: "updatePixel"},
  653. {func: this.updatePixelIndex, name: "updatePixelIndex"},
  654. {func: this.getPixel, name: "getPixel"},
  655. {func: this.getPixelIndex, name: "getPixelIndex"},
  656. {func: this.renderPixelData, name: "renderPixelData"},
  657. {func: this.save, name: "save"},
  658. {func: this.restore, name: "restore"},
  659. {func: this.rotate, name: "rotate"},
  660. {func: this.translate, name: "translate"},
  661. {func: this.beginPath, name: "beginPath"},
  662. {func: this.closePath, name: "closePath"},
  663. {func: this.moveTo, name: "moveTo"},
  664. {func: this.lineTo, name: "lineTo"},
  665. {func: this.fill, name: "fill"},
  666. {func: this.stroke, name: "stroke"},
  667. {func: this.fillStyle, name: "fillStyle"},
  668. {func: this.strokeStyle, name: "strokeStyle"},
  669. {func: this.setLineWidth, name: "setLineWidth"},
  670. {func: this.drawSphere, name: "drawSphere"},
  671. {func: this.createSound, name: "createSound"},
  672. {func: this.playSound, name: "playSound"},
  673. {func: this.stopSound, name: "stopSound"},
  674. {func: this.pauseSound, name: "pauseSound"},
  675. {func: this.fadeOutSound, name: "fadeOutSound"},
  676. {func: this.playTone, name: "playTone"},
  677. {func: this.getDistanceSqr, name: "getDistanceSqr"},
  678. {func: this.getDistance, name: "getDistance"},
  679. {func: this.getDistanceSqr3D, name: "getDistanceSqr3D"},
  680. {func: this.getDistance3D, name: "getDistance3D"},
  681. {func: this.getAngle, name: "getAngle"},
  682. {func: this.normalize, name: "normalize"},
  683. {func: this.normalize3D, name: "normalize3D"},
  684. {func: this.normalize3D, name: "normalize3DVector"},
  685. {func: this.getLength, name: "getLength"},
  686. {func: this.dot, name: "dot"},
  687. {func: this.dot3D, name: "dot3D"},
  688. {func: this.crossProduct3D, name: "crossProduct3D"},
  689. {func: this.lengthVector, name: "lengthVector"},
  690. {func: this.length3DVector, name: "length3DVector"},
  691. {func: this.rectanglesIntersect, name: "rectanglesIntersect"},
  692. {func: this.circlesIntersect, name: "circlesIntersect"},
  693. {func: this.circleRectangleIntersect, name: "circleRectangleIntersect"},
  694. {func: this.random, name: "random"},
  695. {func: this.randomInt, name: "randomInt"},
  696. {func: this.randomArray, name: "randomArray"},
  697. {func: this.randomColor, name: "randomColor"},
  698. {func: this.create2DArray, name: "create2DArray"},
  699. {func: this.canvasToURL, name: "canvasToURL"},
  700. {func: this.canvasToImage, name: "canvasToImage"},
  701. {func: this.saveToFile, name: "saveToFile"},
  702. {func: this.setCookie, name: "setCookie"},
  703. {func: this.getCookie, name: "getCookie"},
  704. {func: this.deleteCookie, name: "deleteCookie"},
  705. {func: this.getBatteryLevel, name: "getBatteryLevel"}
  706. ];
  707. this.variables = [
  708. {variable: this.RadToDeg, name: "RadToDeg"},
  709. {variable: this.DegToRad, name: "DegToRad"},
  710. {variable: this.PI, name: "PI"},
  711. {variable: this.TWO_PI, name: "TWO_PI"},
  712. {variable: this.TAU, name: "TAU"}
  713. ];
  714. this.makeFunctionsGlobal = function() {
  715. this.globalFunctions = true;
  716. this.functions.forEach(item => {
  717. window[item.name] = item.func;
  718. });
  719. this.variables.forEach(item => {
  720. window[item.name] = item.variable;
  721. });
  722. window.fps = this.fps;
  723. window.deltaTime = this.deltaTime;
  724. }
  725. /******************
  726. Init
  727. ******************/
  728. this.settings = settings;
  729. if (typeof this.settings === 'undefined') {
  730. //Create a canvas and make it fullscreen
  731. this.canvas = this.createCanvas();
  732. this.fillPageWithCanvas();
  733. this.makeFunctionsGlobal();
  734. }
  735. else {
  736. if (typeof this.settings.canvas !== "undefined")
  737. this.canvas = this.settings.canvas;
  738. else {
  739. this.canvas = this.createCanvas();
  740. if (typeof this.settings.width === "undefined" &&
  741. typeof this.settings.height === "undefined")
  742. this.fillPageWithCanvas();
  743. if (typeof this.settings.globalFunctions === "undefined" || (typeof this.settings.globalFunctions !== "undefined" && this.settings.globalFunctions))
  744. this.makeFunctionsGlobal();
  745. }
  746. if (typeof this.settings.width !== "undefined") {
  747. this.width = this.settings.width;
  748. this.canvas.width = window.width = this.width;
  749. }
  750. if (typeof this.settings.height !== "undefined") {
  751. this.height = this.settings.height;
  752. this.canvas.height = window.height = this.height;
  753. }
  754. if (typeof this.settings.updateSizeOnResize !== "undefined") {
  755. this.updateSizeOnResize = this.settings.updateSizeOnResize;
  756. }
  757. }
  758. document.addEventListener("keydown", event => {
  759. this.keys[event.key] = this.keys[event.keyCode] = true;
  760. });
  761. document.addEventListener("keyup", event => {
  762. this.keys[event.key] = this.keys[event.keyCode] = false;
  763. });
  764. if (this.canvas) {
  765. this.ctx = this.canvas.getContext("2d");
  766. if (this.updateSizeOnResize) {
  767. window.addEventListener("resize", () => {
  768. this.setSize(window.innerWidth, window.innerHeight);
  769. });
  770. }
  771. this.mouse = {x: 0, y: 0, lastX: 0, lastY: 0, movementX: 0, movementY: 0, left: false, middle: false, right: false, down: false};
  772. this.touches = [];
  773. if (this.globalFunctions) {
  774. window.mouse = this.mouse;
  775. window.touches = this.touches;
  776. }
  777. this.canvas.addEventListener("mousemove", event => {
  778. let br = this.canvas.getBoundingClientRect();
  779. this.mouse.x = (event.clientX - br.left) / (br.width / this.width);
  780. this.mouse.y = (event.clientY - br.top) / (br.height / this.height);
  781. this.mouse.movementX = event.movementX;
  782. this.mouse.movementY = event.movementY;
  783. this.eventFunctions["mousemove"] && OnMouseMove(event);
  784. });
  785. this.canvas.addEventListener("mousedown", event => {
  786. let button = event.button;
  787. if (button < 3)
  788. this.mouse[mouseLookupTable[button]] = true;
  789. if (!this.audioContext)
  790. this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
  791. this.eventFunctions["mousedown"] && OnMouseDown(event);
  792. });
  793. this.canvas.addEventListener("mouseup", event => {
  794. let button = event.button;
  795. if (button < 3)
  796. this.mouse[mouseLookupTable[button]] = false;
  797. this.eventFunctions["mouseup"] && OnMouseUp(event);
  798. });
  799. this.canvas.addEventListener("contextmenu", event => {
  800. this.eventFunctions["contextmenu"] && OnContextMenu(event);
  801. if (this.contextMenuDisabled) {
  802. event.preventDefault();
  803. return false;
  804. }
  805. return true;
  806. });
  807. //Touch
  808. this.updateTouches = function() {
  809. let br = this.canvas.getBoundingClientRect();
  810. this.touches = [];
  811. for (let i = 0; i < event.touches.length; i++) {
  812. var e = event.touches[i];
  813. var x = (e.pageX - br.left) / (br.width / this.width);
  814. var y = (e.pageY - br.top) / (br.height / this.height);
  815. this.touches[i] = {x, y, id: e.identifier, force: e.force};
  816. }
  817. if (this.globalFunctions)
  818. window.touches = this.touches;
  819. }
  820. this.canvas.addEventListener("touchmove", event => {
  821. if (this.disableScrollOnMobile)
  822. event.preventDefault();
  823. this.updateTouches();
  824. this.mouse.x = this.touches[0].x;
  825. this.mouse.y = this.touches[0].y;
  826. this.eventFunctions["touchmove"] && OnTouchMove(event);
  827. });
  828. this.canvas.addEventListener("touchend", event => {
  829. if (this.disableScrollOnMobile)
  830. event.preventDefault();
  831. this.touches = [];
  832. if (this.globalFunctions)
  833. window.touches = this.touches;
  834. this.mouse.left = false;
  835. this.eventFunctions["touchend"] && OnTouchEnd(event);
  836. });
  837. this.canvas.addEventListener("touchstart", event => {
  838. if (this.disableScrollOnMobile)
  839. event.preventDefault();
  840. this.updateTouches();
  841. this.mouse.x = this.touches[0].x;
  842. this.mouse.y = this.touches[0].y;
  843. this.mouse.left = true;
  844. if (!this.audioContext)
  845. this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
  846. this.eventFunctions["touchstart"] && OnTouchStart(event);
  847. });
  848. }
  849. }

script.js

修改var points中包裹的文本可以改变烟花爆炸时出现的文字

  1. var gc = new GameCanvas();
  2. var points = textToPoints(" 2023新年快乐!", 15, "Anton");
  3. var titleParticles = [];
  4. var fireworks = [];
  5. var particles = [];
  6. var gravity = 0.1;
  7. setTimeout(function() {
  8. setInterval(function() {
  9. fireworks.push(new Firework(Math.random() * width, height, Math.random() - 0.5, -(Math.random() * 7 + 5)));
  10. }, 200);
  11. }, 2000);
  12. fireworks.push(new Firework(width / 2, height, 0, -9.5, 10, "gold", true));
  13. setInterval(function() {
  14. fireworks.push(new Firework(width / 2, height, 0, -9.5, 10, "gold", true));
  15. }, 5000);
  16. for (var i = 0; i < 250; i++) {
  17. circle(
  18. Math.random() * width,
  19. Math.random() * height,
  20. 1,
  21. "rgb(200, 200, 200)"
  22. );
  23. }
  24. var starImage = canvasToImage();
  25. background("black");
  26. loop();
  27. function loop() {
  28. gc.ctx.globalCompositeOperation = "source-over";
  29. background("rgba(0, 0, 0, 0.1)");
  30. gc.ctx.drawImage(starImage, 0, 0);
  31. gc.ctx.globalCompositeOperation = "lighter";
  32. for (var i = 0; i < fireworks.length; i++) {
  33. var firework = fireworks[i];
  34. firework.update();
  35. firework.render();
  36. }
  37. for (var i = 0; i < particles.length; i++) {
  38. var particle = particles[i];
  39. particle.update();
  40. particle.render();
  41. }
  42. for (var i = 0; i < titleParticles.length; i++) {
  43. var p = titleParticles[i];
  44. p.update();
  45. p.render();
  46. }
  47. requestAnimationFrame(loop);
  48. }
  49. function TitleParticle(x, y, vx, vy) {
  50. this.x = x;
  51. this.y = y;
  52. this.vx = vx;
  53. this.vy = vy;
  54. this.ay = 0.2;
  55. this.radius = 4;
  56. this.maxHealth = 200;
  57. this.health = 200;
  58. this.update = function() {
  59. this.x += this.vx;
  60. this.y += this.vy;
  61. this.vx *= 0.95;
  62. this.vy *= 0.95;
  63. this.vy += this.ay;
  64. this.ay *= 0.95;
  65. this.radius = (this.health / this.maxHealth) * 4;
  66. this.health--;
  67. if (this.health <= 0) {
  68. titleParticles.splice(titleParticles.indexOf(this), 1);
  69. }
  70. }
  71. this.render = function() {
  72. circle(this.x, this.y, this.radius, "rgba(255, 255, 255, " + (this.health / this.maxHealth) + ")");
  73. }
  74. }
  75. function Firework(x, y, vx, vy, radius = 5, color = "white", title = false) {
  76. this.x = x;
  77. this.y = y;
  78. this.vx = vx;
  79. this.vy = vy;
  80. this.radius = radius;
  81. this.title = title;
  82. this.color = color;
  83. this.update = function() {
  84. this.x += this.vx;
  85. this.y += this.vy;
  86. this.vy += gravity;
  87. if (this.vy >= 0) {
  88. fireworks.splice(fireworks.indexOf(this), 1);
  89. if (this.title) {
  90. var scale = 0.3;
  91. for (var i = 0; i < points.length; i++) {
  92. var p = points[i];
  93. var v = {
  94. x: (p.x - 60) * scale + (Math.random() - 0.5) * 0.1,
  95. y: (p.y - 20) * scale + (Math.random() - 0.5) * 0.1
  96. }
  97. var particle = new TitleParticle(this.x, this.y, v.x, v.y);
  98. titleParticles.push(particle);
  99. }
  100. }
  101. else {
  102. var color = [Math.random() * 256 >> 0, Math.random() * 256 >> 0, Math.random() * 256 >> 0];
  103. for (var i = 0; i < Math.PI * 2; i += 0.1) {
  104. var power = (Math.random() + 0.5) * 4;
  105. var vx = Math.cos(i) * power;
  106. var vy = Math.sin(i) * power;
  107. particles.push(new Particle(this.x, this.y, vx, vy, Math.random() + 3, color));
  108. }
  109. }
  110. }
  111. }
  112. this.render = function() {
  113. circle(this.x, this.y, this.radius, this.color);
  114. }
  115. }
  116. function Particle(x, y, vx, vy, radius, color) {
  117. this.x = x;
  118. this.y = y;
  119. this.vx = vx;
  120. this.vy = vy;
  121. this.life = 100;
  122. this.color = color;
  123. this.radius = radius;
  124. this.update = function() {
  125. this.x += this.vx;
  126. this.y += this.vy;
  127. this.vy += gravity;
  128. this.vx *= 0.95;
  129. this.vy *= 0.95;
  130. this.life--;
  131. if (this.life <= 0) {
  132. particles.splice(particles.indexOf(this), 1);
  133. }
  134. }
  135. this.render = function() {
  136. circle(this.x, this.y, 3 * (this.life / 100), "rgba(" + this.color[0] + ", " + this.color[1] + ", " + this.color[2] + ", " + (this.life / 100) + ")");
  137. }
  138. }
  139. function textToPoints(text, textSize, font) {
  140. var canvas = document.createElement("canvas");
  141. canvas.width = 1024;
  142. canvas.height = textSize * 1.3;
  143. var ctx = canvas.getContext("2d");
  144. ctx.textBaseline = "middle";
  145. ctx.font = textSize + "px " + font;
  146. ctx.fillText(text, 0, canvas.height / 2);
  147. var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  148. var data = imageData.data;
  149. var points = [];
  150. var index = (x, y) => (x + canvas.width * y) * 4;
  151. var threshold = 50;
  152. for (var i = 0; i < data.length; i += 4) {
  153. if (data[i + 3] > threshold) {
  154. var p = {
  155. x: (i / 4) % canvas.width,
  156. y: (i / 4) / canvas.width >> 0
  157. };
  158. if (data[index(p.x + 1, p.y) + 3] < threshold ||
  159. data[index(p.x - 1, p.y) + 3] < threshold ||
  160. data[index(p.x, p.y + 1) + 3] < threshold ||
  161. data[index(p.x, p.y - 1) + 3] < threshold) {
  162. points.push({
  163. x: (i / 4) % canvas.width,
  164. y: (i / 4) / canvas.width >> 0
  165. });
  166. }
  167. }
  168. }
  169. return points;
  170. }

运行效果

光说不练假把式,看图:

运行效果如下

 


总结

以上就是今天要讲的内容,本文介绍了跨年烟花代码使用。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/96337
推荐阅读
相关标签
  

闽ICP备14008679号