资源
课程
01-Pixi 初识和搭建 Pixi 应用
- 项目文件下命令行创建
Vue
项目(好家伙这就 100 来 MB……):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| <template> <div></div> </template>
<script setup> // 导入 pixi.js import * as PIXI from 'pixi.js';
// 创建应用 const app = new PIXI.Application({ width: window.innerWidth, height: window.innerHeight, backgroundColor: 0x1099bb, resolution: window.devicePixelRatio || 1, })
// 将应用画布添加到 DOM 中 document.body.appendChild(app.view);
// 创建一个矩形 const rectangle = new PIXI.Graphics(); rectangle.beginFill(0x66ccff); // 填充颜色 rectangle.drawRect(200, 200, 164, 64); // 绘制矩形 rectangle.endFill(); // 结束填充
// 将矩形添加至舞台 app.stage.addChild(rectangle);
</script>
<style> * { margin: 0; padding: 0; box-sizing: border-box; } canvas { width: 100vw; height: 100vh; position: fixed; left: 0; } </style>
|
HTML 下使用 <script src="https://pixijs.download/release/pixi.js"></script>
直接导入 pixi.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } canvas { width: 100vw; height: 100vh; position: fixed; left: 0; } </style> </head> <body> </body> <script src="https://pixijs.download/release/pixi.js"></script> <script>
const app = new PIXI.Application({ width: window.innerWidth, height: window.innerHeight, backgroundColor: 0x1099bb, resolution: window.devicePixelRatio || 1, })
document.body.appendChild(app.view);
const rectangle = new PIXI.Graphics(); rectangle.beginFill(0x66ccff); rectangle.drawRect(200, 200, 164, 64); rectangle.endFill();
app.stage.addChild(rectangle); </script> </html>
|
Vue 代码解释:
这部分定义了组件的 HTML 结构。在这个例子中,模板仅包含一个空的 <div>
元素。实际上,这个 <div>
在此示例中未直接使用,因为 PixiJS 的画布 (canvas
) 是通过脚本直接添加到 document.body
中的,而不是被插入到这个 <div>
内。
1 2 3
| <template> <div></div> </template>
|
这部分是组件的 JavaScript 逻辑,主要做了以下几件事情:
- 导入 PixiJS:使用
import
语句导入 PixiJS 库。
- 创建 PixiJS 应用:实例化一个新的 PixiJS
Application
对象,并设置其大小和背景颜色等属性。这个应用对象会自动生成一个 <canvas>
元素。
- 将
<canvas>
元素添加到 DOM:通过 document.body.appendChild(app.view);
将 PixiJS 创建的 <canvas>
元素添加到 HTML 文档的 <body>
中。
- 绘制图形:使用 PixiJS 的
Graphics
类创建一个矩形,并设置其填充颜色和位置,最后将这个矩形添加到 PixiJS 应用的舞台(stage
)上,以便显示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <script setup> // 导入 pixi.js import * as PIXI from 'pixi.js';
// 创建应用 const app = new PIXI.Application({ width: window.innerWidth, // 宽度设置为窗口宽度 height: window.innerHeight, // 高度设置为窗口高度 backgroundColor: 0x1099bb, // 背景颜色设置为浅蓝色 resolution: window.devicePixelRatio || 1, // 分辨率设置为设备的像素比或默认值 1 })
// 将应用画布添加到 DOM 中 document.body.appendChild(app.view);
// 创建一个矩形 const rectangle = new PIXI.Graphics(); rectangle.beginFill(0x66ccff); // 开始填充颜色为浅蓝色 rectangle.drawRect(200, 200, 164, 64); // 在坐标 (200, 200) 处绘制一个 164 x 64 大小的矩形 rectangle.endFill(); // 结束填充
// 将矩形添加至舞台 app.stage.addChild(rectangle); </script>
|
这部分定义了页面的 CSS 样式:
- 重置所有元素的
margin
和 padding
,并设置 box-sizing
为 border-box
,以确保布局的一致性。
- 设置
<canvas>
元素的样式,使其宽度和高度分别占满视口的宽度和高度,并通过 position: fixed
确保 <canvas>
始终覆盖整个视口。
1 2 3 4 5 6 7 8 9 10 11 12 13
| <style> * { margin: 0; padding: 0; box-sizing: border-box; } canvas { width: 100vw; height: 100vh; position: fixed; left: 0; } </style>
|
打开 http://localhost:8080/
:
02-Pixi图形Graphics具体应用
使用 Pixi 创建其它图形,设置:
- 缩放:
scale.set()
- 位移:
position.set()
- 旋转:
rotation
- 锚点:
pivot.set()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| const app = new PIXI.Application({ width: window.innerWidth, height: window.innerHeight, backgroundColor: 0x1099bb, resolution: window.devicePixelRatio || 1, antialias: true, })
document.body.appendChild(app.view);
const rectangle = new PIXI.Graphics(); rectangle.lineStyle(4, 0xff0000, 1); rectangle.beginFill(0x66ccff, 0.9); rectangle.drawRect(0, 0, 164, 64); rectangle.endFill();
rectangle.scale.set(2, 2);
rectangle.position.set(100, 100);
rectangle.rotation = 0.5;
rectangle.pivot.set(82, 32);
app.stage.addChild(rectangle);
const circle = new PIXI.Graphics(); circle.beginFill(0x66ccff, 0.9); circle.drawCircle(0, 0, 32); circle.endFill(); circle.position.set(300, 300); app.stage.addChild(circle);
|
03-Pixi绘制各种常见图形
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| const rectangle = new PIXI.Graphics(); rectangle.lineStyle(4, 0xff0000, 1); rectangle.beginFill(0x66ccff, 0.9); rectangle.drawRect(0, 0, 164, 64); rectangle.endFill();
rectangle.scale.set(2, 2);
rectangle.position.set(100, 100);
rectangle.rotation = 0.5;
rectangle.pivot.set(82, 32);
app.stage.addChild(rectangle);
|
1 2 3 4 5 6 7
| const circle = new PIXI.Graphics(); circle.beginFill(0x66ccff, 0.9); circle.drawCircle(0, 0, 32); circle.endFill(); circle.position.set(300, 300); app.stage.addChild(circle);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| const roundedRectangle = new PIXI.Graphics(); roundedRectangle.beginFill(0x66ccff, 0.9);
roundedRectangle.drawRoundedRect(0, 0, 164, 64, 10); roundedRectangle.endFill(); roundedRectangle.position.set(500, 500); app.stage.addChild(roundedRectangle);
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| const ellipse = new PIXI.Graphics(); ellipse.beginFill(0x66ccff, 0.9);
ellipse.drawEllipse(0, 0, 164, 164); ellipse.endFill(); ellipse.position.set(700, 700); app.stage.addChild(ellipse);
|
1 2 3 4 5 6 7 8
| const polygon = new PIXI.Graphics(); polygon.beginFill(0x66ccff, 0.9);
polygon.drawPolygon([0, 0, 100, 0, 100, 100, 0, 100]); polygon.endFill(); polygon.position.set(50, 300); app.stage.addChild(polygon);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| const arc = new PIXI.Graphics(); arc.beginFill(0x660000, 0.9);
arc.arc(0, 0, 32, 0, Math.PI, false); arc.endFill(); arc.position.set(300, 50); app.stage.addChild(arc);
|
1 2 3 4 5 6 7 8
| const line = new PIXI.Graphics(); line.lineStyle(4, 0xff0000, 1); line.moveTo(0, 0); line.lineTo(100, 100); line.lineTo(200, 0); line.position.set(500, 50); app.stage.addChild(line);
|
04-Pixi纹理与动画实现
使用代码创建一个木剑的旋转动画:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| const app = new PIXI.Application({ width: window.innerWidth, height: window.innerHeight, backgroundColor: 0x1099bb, resolution: window.devicePixelRatio || 1, antialias: true, })
document.body.appendChild(app.view);
const texture = PIXI.Texture.from("./textures/mujian.png");
const sprite = new PIXI.Sprite(texture);
sprite.anchor.set(0.5, 0.5);
sprite.x = app.screen.width / 2; sprite.y = app.screen.height / 2;
sprite.rotation = Math.PI / 4;
sprite.scale.set(2, 2);
sprite.alpha = 0.5;
app.stage.addChild(sprite);
app.ticker.add((delta) => { console.log(delta); sprite.rotation += 0.01 * delta; })
|
演示
05-Pixi事件交互
在上一节的代码上,继续追加交互的代码:
1 2 3 4
| sprite.interactive = true; sprite.on("click", () => { sprite.alpha = 1; });
|
1 2 3
| sprite.on("pointerenter", () => { sprite.alpha = 0.75; });
|
1 2 3
| sprite.on("pointerout", () => { sprite.alpha = 0.5; });
|
如下所示,当鼠标点击 / 移入 / 移出 木剑时,将产生一定的交互效果。
演示
06-Pixi资源管理
两种不同的资源加载方式:
1 2 3 4 5 6 7 8 9
| PIXI.Assets.add("sword", "./textures/jian.png"); PIXI.Assets.add("man", "./textures/man.png"); PIXI.Assets.add("woodenSword", "./textures/mujian.png");
const texturesPromise = PIXI.Assets.load(["sword", "man", "woodenSword"], (progress) => { console.log("加载完成:", progress); });
|
1 2 3 4 5 6 7 8 9 10
| PIXI.Assets.addBundle("scene1", { sword: "./textures/jian.png", man: "./textures/man.png", woodenSword: "./textures/mujian.png", });
const texturesPromise = PIXI.Assets.loadBundle("scene1", (progress) => { console.log("加载完成:", progress); });
|
操作一下所创建的资源对象 texturesPromise
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| texturesPromise.then((textures) => { const container = new PIXI.Container(); const sprite = new PIXI.Sprite(textures.sword); sprite.x = app.screen.width / 2; sprite.y = app.screen.height / 2; sprite.anchor.set(0.5); sprite.scale.set(0.5); sprite.alpha = 0.5; sprite.rotation = 0.5; sprite.blendMode = PIXI.BLEND_MODES.ADD; sprite.interactive = true; sprite.buttonMode = true; sprite.on("pointerdown", () => { console.log("pointerdown"); }); container.addChild(sprite);
const sprite2 = new PIXI.Sprite(textures.man); sprite2.scale.set(0.1); container.addChild(sprite2); app.stage.addChild(container); });
|
演示
07-Pixi文字与遮罩
new PIXI.Text()
创建文字对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| const text = new PIXI.Text("Hello World", { fontFamily: "Arial", fontSize: 120, fill: 0xff0000, align: "center", });
text.x = app.screen.width / 2; text.y = app.screen.height / 2;
text.anchor.set(0.5); app.stage.addChild(text);
|
演示
mask
给精灵设置另一个精灵做遮罩:
1 2 3 4 5 6 7 8
| const bg = PIXI.Sprite.from("./textures/bg.png"); bg.width = app.screen.width; bg.height = app.screen.height;
bg.mask = woodenSword; app.stage.addChild(bg); app.stage.addChild(woodenSword);
|
演示
使用文字作为遮罩:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| const text = new PIXI.Text("Hello World", { fontFamily: "Arial", fontSize: 120, fill: 0xff0000, align: "center", });
text.x = app.screen.width / 2; text.y = app.screen.height / 2;
text.anchor.set(0.5);
const bg = PIXI.Sprite.from("./textures/bg.png"); bg.width = app.screen.width; bg.height = app.screen.height;
bg.mask = text; app.stage.addChild(bg);
|
演示
08-Pixi滤镜特效
先创建一个精灵用于操作:
1 2 3 4 5 6 7 8 9 10 11 12 13
| const texture = PIXI.Texture.from("./textures/mujian.png");
const sprite = new PIXI.Sprite(texture);
sprite.x = app.screen.width / 2; sprite.y = app.screen.height / 2;
sprite.anchor.set(0.5);
app.stage.addChild(sprite);
|
自带滤镜:模糊
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| const blurFilter = new PIXI.BlurFilter();
blurFilter.blur = 20;
sprite.filters = [blurFilter];
sprite.interactive = true; sprite.on("pointerover", () =>{ blurFilter.blur = 0; }); sprite.on("pointerout", () =>{ blurFilter.blur = 20; });
|
演示
pixi-filters:扩展滤镜:轮廓与辉光
使用:
安装,然后使用
1
| import {XXXFilter} from "pixi-filters";
|
来导入。
Vue
下输入代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| <template> <div></div> </template>
<script setup> // 导入 pixi.js import * as PIXI from 'pixi.js'; import {OutlineFilter} from 'pixi-filters'; import {GlowFilter} from 'pixi-filters';
// 创建应用 const app = new PIXI.Application({ width: window.innerWidth, height: window.innerHeight, backgroundColor: 0x1099bb, resolution: window.devicePixelRatio || 1, antialias: true, // 设置抗锯齿 })
// 将应用画布添加到 DOM 中 document.body.appendChild(app.view);
// 创建一个纹理 const texture = PIXI.Texture.from("./textures/mujian.png"); // 创建一个精灵 const sprite = new PIXI.Sprite(texture); // 设置精灵的位置 sprite.x = app.screen.width / 2; sprite.y = app.screen.height / 2;
// 设置精灵的锚点 sprite.anchor.set(0.5);
// 将精灵添加到舞台 app.stage.addChild(sprite);
//创建轮廓滤镜 const outlineFilter = new OutlineFilter(5, 0xffff00); // 2 为轮廓宽度,0x000000 为轮廓颜色 // 创建发光滤镜 const glowFilter = new GlowFilter({ distance: 50, outerStrength: 1, innerStrength: 0, color: 0xff0000, quality: 0.5, }); // 将轮廓滤镜添加到精灵上 sprite.filters = [outlineFilter, glowFilter];
</script>
<style> * { margin: 0; padding: 0; box-sizing: border-box; } canvas { width: 100vw; height: 100vh; position: fixed; left: 0; } </style>
|
1
| <script src="https://cdn.jsdelivr.net/npm/pixi-filters@latest/dist/browser/pixi-filters.min.js"></script>
|
HTML 下使用代码(将 OutlineFilter
和 GlowFilter
分别改为 new PIXI.filters.OutlineFilter
和 PIXI.filters.GlowFilter
):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| const app = new PIXI.Application({ width: window.innerWidth, height: window.innerHeight, backgroundColor: 0x1099bb, resolution: window.devicePixelRatio || 1, antialias: true, })
document.body.appendChild(app.view);
const texture = PIXI.Texture.from("./textures/mujian.png");
const sprite = new PIXI.Sprite(texture);
sprite.x = app.screen.width / 2; sprite.y = app.screen.height / 2;
sprite.anchor.set(0.5);
app.stage.addChild(sprite);
const outlineFilter = new PIXI.filters.OutlineFilter(5, 0xffff00);
const glowFilter = new PIXI.filters.GlowFilter({ distance: 50, outerStrength: 1, innerStrength: 0, color: 0xff0000, quality: 0.5, });
sprite.filters = [outlineFilter, glowFilter];
|
演示
09-应用Pixi实现波浪水滴特效主页
创建场景:一个背景以及一个带阴影的文字对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| const app = new PIXI.Application({ width: window.innerWidth, height: window.innerHeight, backgroundColor: 0x1099bb, resolution: window.devicePixelRatio || 1, antialias: true, });
document.body.appendChild(app.view);
const texture = PIXI.Texture.from("./textures/car.jpg");
const sprite = new PIXI.Sprite(texture); sprite.width = app.screen.width; sprite.height = app.screen.height;
const container = new PIXI.Container();
container.addChild(sprite);
app.stage.addChild(container);
const text = new PIXI.Text("Hello PixiJS", { fontFamily: "Arial", fontSize: 30 + Math.floor(app.screen.width * 0.1), fill: 0xffffff, align: "center", dropShadow: true, dropShadowColor: "#000000", dropShadowBlur: 4, dropShadowAngle: Math.PI / 2, dropShadowDistance: 2, }); text.x = app.screen.width / 2; text.y = app.screen.height / 2; text.anchor.set(0.5); container.addChild(text);
|
添加置换滤镜:
1 2 3 4 5 6
| const displacementSprite = PIXI.Sprite.from("./textures/displacement.jpg"); displacementSprite.scale.set(0.5); displacementSprite.texture.baseTexture.wrapMode = PIXI.WRAP_MODES.REPEAT; const displacementFilter = new PIXI.DisplacementFilter(displacementSprite); container.addChild(displacementSprite);
|
一个置换图 displacement.jpg
实现画面涟漪的效果:
定义大、中、小三种震波滤镜(需要pixi-filter
支持):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| const shockwaveFilter1 = new PIXI.filters.ShockwaveFilter( [Math.random() * app.screen.width, Math.random() * app.screen.height], { radius: 80, waveLength: 40, amplitude: 40, speed: 200, }, 0 );
const shockwaveFilter2 = new PIXI.filters.ShockwaveFilter( [Math.random() * app.screen.width, Math.random() * app.screen.height], { radius: 100, waveLength: 45, amplitude: 80, speed: 240, }, 0 );
const shockwaveFilter3 = new PIXI.filters.ShockwaveFilter( [Math.random() * app.screen.width, Math.random() * app.screen.height], { radius: 160, waveLength: 65, amplitude: 105, speed: 300, }, 0 );
|
应用这些滤镜(app.ticker.add
有点像 Unity 里的 Update()
):
1 2 3 4 5 6
| container.filters = [ displacementFilter, shockwaveFilter1, shockwaveFilter2, shockwaveFilter3, ];
|
随机创建震波滤镜:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| app.ticker.add((delta) => { displacementSprite.x += 1; displacementSprite.y += 1; createWave(shockwaveFilter1, 1); createWave(shockwaveFilter2, 1.2); createWave(shockwaveFilter3, 0.7); });
function createWave(waveFilter, resetTime) { waveFilter.time += 0.01; if (waveFilter.time > resetTime) { waveFilter.time = 0; waveFilter.center = [ Math.random() * app.screen.width, Math.random() * app.screen.height, ]; } }
|
设置点击创建震波滤镜的效果:
1 2 3 4 5 6
| app.view.addEventListener("click", (e) => { console.log(e.clientX, e.clientY); shockwaveFilter3.center = [e.clientX, e.clientY]; shockwaveFilter3.time = 0; });
|
演示
10-pixijs开发谷歌恐龙跑酷小游戏
我在原教程的基础上魔改了一些内容。
创建应用,导入 baseTexture
(是一个雪碧图):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| const app = new PIXI.Application({ width: window.innerWidth, height: window.innerHeight, backgroundColor: 0xffffff, resolution: window.devicePixelRatio || 1, antialias: true, });
document.body.appendChild(app.view);
const container = new PIXI.Container();
app.stage.addChild(container);
const baseTexture = PIXI.BaseTexture.from("./textures/game.png");
|
设置恐龙的宽高:
1 2
| const frameWidth = 88; const frameHeight = 100;
|
创建各种资源:
1 2 3 4 5 6 7 8 9
| const dinoTexture = new PIXI.Texture( baseTexture, new PIXI.Rectangle(75, 0, frameWidth, frameHeight) );
const dino = new PIXI.Sprite(dinoTexture); dino.visible = false; container.addChild(dino);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| const runTexture = new PIXI.Texture( baseTexture, new PIXI.Rectangle(1675, 0, frameWidth, frameHeight) ); const runSprite = new PIXI.Sprite(runTexture); runSprite.visible = false; container.addChild(runSprite);
let runTextures = []; for (let i = 0; i < 2; i++) { runTextures.push( new PIXI.Texture( baseTexture, new PIXI.Rectangle(1680 + (2 + i) * frameWidth, 0, 82, frameHeight) ) ); } const runAnimation = new PIXI.AnimatedSprite(runTextures); runAnimation.animationSpeed = 0.1; runAnimation.play(); runAnimation.visible = false; container.addChild(runAnimation);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| let deadTextures = []; for (let i = 0; i < 2; i++) { deadTextures.push( new PIXI.Texture( baseTexture, new PIXI.Rectangle(1680 + (0 + i) * frameWidth, 0, 82, frameHeight) ) ); } const deadAnimation = new PIXI.AnimatedSprite(deadTextures); deadAnimation.animationSpeed = 0.1; deadAnimation.play(); deadAnimation.visible = false; container.addChild(deadAnimation);
|
1 2 3 4 5 6 7 8
| const jumpTexture = new PIXI.Texture( baseTexture, new PIXI.Rectangle(1680, 0, 82, frameHeight) ); const jumpSprite = new PIXI.Sprite(jumpTexture); jumpSprite.visible = false; container.addChild(jumpSprite);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| const groundTexture = new PIXI.Texture( baseTexture, new PIXI.Rectangle(50, 100, 2300, 30) );
groundTexture.baseTexture.wrapMode = PIXI.WRAP_MODES.REPEAT;
const groundSprite = new PIXI.TilingSprite(groundTexture); groundSprite.width = window.innerWidth; groundSprite.height = 30;
groundSprite.position.set(0, window.innerHeight - 50);
container.addChild(groundSprite);
|
1 2 3 4 5 6 7 8 9
| const cactusTexture = new PIXI.Texture( baseTexture, new PIXI.Rectangle(515, 0, 30, 60) ); const cactusSprite = new PIXI.Sprite(cactusTexture); cactusSprite.x = getRandomInt(window.innerWidth, window.innerWidth * 1.5); cactusSprite.y = window.innerHeight - 50 - 50; container.addChild(cactusSprite);
|
创建提示文字,点击 开始游戏
时,开始游戏:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| let hintsText = new PIXI.Text("开始游戏", { fontSize: 30, fill: 0x333333, align: "center", }); hintsText.x = app.screen.width / 2; hintsText.y = app.screen.height / 2; hintsText.anchor.set(0.5); container.addChild(hintsText); hintsText.interactive = true; hintsText.on("click", () => { playGame(); }); hintsText.addEventListener('touchstart', function (event) { playGame(); });
|
开始游戏的逻辑:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| let isGameing = false; let score = 0; let jumpVelocity = 1200; let gravity = 5000;
function playGame(e) { hintsText.text = "得分:" + score; runAnimation.x = 60; runAnimation.y = window.innerHeight - 50 - frameHeight; runAnimation.visible = true; deadAnimation.x = 60; deadAnimation.y = window.innerHeight - 50 - frameHeight; deadAnimation.visible = false; jumpSprite.x = 60; jumpSprite.y = window.innerHeight - 50 - frameHeight; jumpSprite.visible = false;
hintsText.interactive = false; hintsText.off("click"); hintsText.removeEventListener('touchstart', playGame);
setTimeout(() => { window.addEventListener("keydown", (e) => { if (e.code === "Space") { jump(); } }); app.view.addEventListener('click', jump); app.view.addEventListener('touchstart', jump); }, 100);
isGameing = true; }
|
跳跃逻辑:
1 2 3 4 5 6 7
| function jump() { if (isGameing && !jumpSprite.visible) { runAnimation.visible = false; jumpSprite.visible = true; jumpVelocity = 1200; } }
|
实时控制游戏逻辑:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| app.ticker.add((delta) => { if (isGameing) { hintsText.text = "得分:" + score; let deltaTime = app.ticker.deltaMS / 1000; const groundSpeed = 1000 * deltaTime * Math.log10(10 + score); const cactusSpeed = groundSpeed; groundSprite.tilePosition.x -= groundSpeed; cactusSprite.x -= cactusSpeed;
if (cactusSprite.x <= -30) { cactusSprite.x = getRandomInt(window.innerWidth, window.innerWidth * 2); score++; }
if (jumpSprite.visible) { jumpVelocity -= gravity * deltaTime; jumpSprite.y -= jumpVelocity * deltaTime;
if (jumpSprite.y >= window.innerHeight - 50 - frameHeight) { console.log("跳跃结束"); jumpSprite.y = window.innerHeight - 50 - frameHeight; runAnimation.visible = true; jumpSprite.visible = false; } }
if ( jumpSprite.y > cactusSprite.y - 60 && jumpSprite.x + 60 > cactusSprite.x && jumpSprite.x - 60 < cactusSprite.x ) { gameOver(); } } else { return; } });
|
游戏结束逻辑:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| function gameOver() { console.log("游戏结束"); isGameing = false; deadAnimation.visible = true; runAnimation.visible = false; jumpSprite.visible = false; hintsText.text = "游戏结束,最后得分:" + score; hintsText.interactive = true; hintsText.on("click", () => { location.reload(); }); hintsText.addEventListener('touchstart', function (event) { location.reload(); }); }
|
演示(emmm 手机上玩起来适配还不是很好……)