PIXIJS学习笔记

视频学习来源:01-Pixi初识和搭建Pixi应用_哔哩哔哩_bilibili

GitHub代码仓库:https://github.com/anyeyongzhou/PIXI

图片资源也在GitHub代码仓库中

PIXIJS官网地址:PixiJS

在项目中安装pixi:pnpm add pixi

Pixi是一个超快的2D渲染引擎。

它会帮助你用JavaScript或者其他HTML5技术来显示媒体,创建动画或管理交互式图像,从而制作一个游戏或应用

Pixi的画布对象将会默认选择WebGL引擎渲染模式,它更快并且可以让你使用一些壮观的视觉特效。但是如果你需要强制使用Canvas引擎绘制而抛弃WebGL,你可以设置forceCanvas选项为true

创建一个PIXI的实例,并展示出来,通常需要以下几步:

        创建一个舞台 (stage)

        创建一个画布 (render)

        把画布插入DOM中

        创建一个精灵 (sprite)

        把精灵加入画布

        把画布加入舞台

        刷新舞台

下面代码做了前三步

//导入pixi.js
import * as PIXI from 'pixi.js'
//创建应用
const app: any = new PIXI.Application({
  width: window.innerWidth,
  height: window.innerHeight,
  backgroundColor: 0x1099bb,
  //屏幕的像素比例
  resolution: window.devicePixelRatio || 1,
  //制使用Canvas引擎绘制而抛弃WebGL
  forceCanvas: true
})
//将画布添加到DOM中
document.body.appendChild(app.view)

一.绘制矩形

//创建一个图形

const rectangle = new PIXI.Graphics()

//设置边框的样式:线宽、颜色、透明度

rectangle.lineStyle(4, 0xff0000, 1)

//填充颜色,透明度

rectangle.beginFill(0x66ccff, 0.5)

//绘制矩形

rectangle.drawRect(200, 200, 164, 64)

//结束填充

rectangle.endFill()

//图形的缩放

rectangle.scale.set(2, 2)

//图形的位移

rectangle.position.set(100, 100)

//图形的旋转

rectangle.rotation = 0.5

//将矩形添加到舞台

app.stage.addChild(rectangle)

二.绘制更多图形

1.绘制一个圆形

const cicle = new PIXI.Graphics()

cicle.beginFill(0x66ccff, 0.9)

cicle.drawCircle(0, 0, 32)

cicle.position.set(100, 100)

cicle.endFill()

app.stage.addChild(cicle)

2.绘制一个圆角矩形

const roundedRectangle = new PIXI.Graphics()

roundedRectangle.beginFill(0x66ccff, 0.9)

roundedRectangle.drawRoundedRect(0, 0, 164, 64, 10)

roundedRectangle.position.set(500, 500)

roundedRectangle.endFill()

app.stage.addChild(roundedRectangle)

3.绘制一个椭圆

const ellipse = new PIXI.Graphics()

ellipse.beginFill(0x66ccff, 0.9)

ellipse.drawEllipse(0, 0, 164, 64)

ellipse.position.set(400, 400)

ellipse.endFill()

app.stage.addChild(ellipse)

4.绘制一个多边形

const polygon = new PIXI.Graphics()

polygon.beginFill(0x66ccff, 0.9)

//每两个值代表一个坐标

polygon.drawPolygon(0, 0, 100, 0, 100, 100, 0, 100)

polygon.position.set(100, 300)

polygon.endFill()

app.stage.addChild(polygon)

5.绘制一个圆弧

const arc = new PIXI.Graphics()

arc.beginFill(0x66ccff, 0.9)

arc.arc(0, 0, 32, 0, Math.PI, false)

arc.position.set(100, 500)

arc.endFill()

app.stage.addChild(arc)

6.绘制一个线段

const line = new PIXI.Graphics()

line.lineStyle(4, 0xff0000, 1)

line.moveTo(0, 0)

line.lineTo(100, 100)

line.lineTo(100, 200)

line.position.set(500, 50)

app.stage.addChild(line)

三.纹理,精灵,动画

1.创建一个纹理PIXI.Texture

const texture = PIXI.Texture.from('../public/wenli.webp.jpg')

2.创建一个精灵PIXI.Sprite

const sprite = new PIXI.Sprite(texture)

//设置精灵的位置

sprite.x = app.screen.width / 2

sprite.y = app.screen.height / 2

//设置精灵的锚点

sprite.anchor.set(0.5, 0.5)

//设置旋转

sprite.rotation = Math.PI / 4

//设置缩放

sprite.scale.set(2, 2)

//设置透明度

sprite.alpha = 0.5

//设置精灵混合模式

sprite.blendMode = PIXI.BLEND_MODES.ADD

app.stage.addChild(sprite)

3.ticker实现动画app.ticker.add

app.ticker.add((delta: any) => {

sprite.rotation += 0.01 * delta

})

四.事件交互sprite.interactive

//创建一个纹理

const texture = PIXI.Texture.from('../public/wenli.webp.jpg')

//创建一个精灵

const sprite = new PIXI.Sprite(texture)

app.stage.addChild(sprite)

//ticker实现动画

app.ticker.add((delta: any) => {

sprite.rotation += 0.01 * delta

})

//为精灵添加交互事件

sprite.interactive = true

sprite.on('click', () => {

console.log(1)

})

sprite.on('pointerenter', () => {

sprite.alpha = 1

})

sprite.on('pointerout', () => {

sprite.alpha = 0.5

})

交互事件Event详情请看Event事件大全

图形也可以交互

五.资源加载

1.PIXI.Assets.add

2.PIXI.Assets.load

3.PIXI.Container()

//添加资源

PIXI.Assets.add('jian', '../public/mujian.webp.jpg')

PIXI.Assets.add('man', '../public/man.webp.jpg')

PIXI.Assets.add('women', '../public/women.webp.jpg')

PIXI.Assets.add('wenli', '../public/wenli.webp.jpg')

//异步加载资源

const texturePromise = PIXI.Assets.load(

['jian', 'man', 'women', 'wenli'],

(progress) => {

console.log('加载完成', progress)

}

)

//加载后完成精灵创建

texturePromise.then((textures: any) => {

//创建一个容器:作用是分组,更好的控制样式

const container = new PIXI.Container()

//创建一个精灵

const sprite = new PIXI.Sprite(textures.jian)

//设置精灵的位置

sprite.x = app.screen.width / 2

sprite.y = app.screen.height / 2

//设置精灵的锚点

sprite.anchor.set(0.5, 0.5)

//设置旋转

sprite.rotation = Math.PI / 4

//设置缩放

sprite.scale.set(1, 1)

//设置透明度

sprite.alpha = 0.5

//设置精灵混合模式

sprite.blendMode = PIXI.BLEND_MODES.ADD

//设置精灵交互

sprite.interactive = true

//设置精灵鼠标事件

sprite.on('pointerdown', () => {

console.log('pointerdown')

})

container.addChild(sprite)

//ticker实现动画

// app.ticker.add((delta: any) => {

// sprite.rotation += 0.01 * delta

// })

const sprite2 = new PIXI.Sprite(textures.man)

sprite2.scale.set(0.1)

container.addChild(sprite2)

app.stage.addChild(container)

})

4.分场景加载资源PIXI.Assets.addBundle

//添加场景1的资源

PIXI.Assets.addBundle('scene1', {

jian: '../public/mujian.webp.jpg',

man: '../public/man.webp.jpg',

wenli: '../public/wenli.webp.jpg'

})

//添加场景2的资源

PIXI.Assets.addBundle('scene2', {

women: '../public/women.webp.jpg'

})

//异步加载资源

const texturePromise = PIXI.Assets.loadBundle('scene1', (progress) => {

console.log('加载完成', progress)

})

//加载后完成精灵创建

texturePromise.then((textures: any) => {

//创建一个容器

const container = new PIXI.Container()

//创建一个精灵

const sprite = new PIXI.Sprite(textures.jian)

//设置精灵的位置

sprite.x = app.screen.width / 2

sprite.y = app.screen.height / 2

//设置精灵的锚点

sprite.anchor.set(0.5, 0.5)

//设置旋转

sprite.rotation = Math.PI / 4

//设置缩放

sprite.scale.set(1, 1)

//设置透明度

sprite.alpha = 0.5

//设置精灵混合模式

sprite.blendMode = PIXI.BLEND_MODES.ADD

//设置精灵交互

sprite.interactive = true

//设置精灵鼠标事件

sprite.on('pointerdown', () => {

console.log('pointerdown')

})

//app.stage.addChild(sprite)

container.addChild(sprite)

//ticker实现动画

// app.ticker.add((delta: any) => {

// sprite.rotation += 0.01 * delta

// })

const sprite2 = new PIXI.Sprite(textures.man)

sprite2.scale.set(0.1)

//app.stage.addChild(sprite2)

container.addChild(sprite2)

app.stage.addChild(container)

})

六.遮罩

遮罩可以是图形,可以是文件,还可以是精灵

1.PIXI.Text

2.sprite.mask

//显示文字

const text = new PIXI.Text('Hello World', {

fontFamily: 'Arial',

fontSize: 80,

fill: 0xff0000,

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, 0.5)

//绘制一个圆形

const cicle = new PIXI.Graphics()

cicle.beginFill(0x66ccff, 0.9)

cicle.drawCircle(app.screen.width / 2, app.screen.height / 2, 32)

cicle.endFill()

const mujian = PIXI.Sprite.from('../public/mujian1.jpg')

//设置遮罩:设置精灵

const bunny = PIXI.Sprite.from('../public/zhezhao.webp.jpg')

//精灵铺满整个屏幕

bunny.width = app.screen.width

bunny.height = app.screen.height

//使用文字作为精灵的遮罩

//bunny.mask = text

//使用圆作为精灵的遮罩

bunny.mask = cicle

//使用图片作为精灵的遮罩

//bunny.mask = mujian

app.stage.addChild(bunny)

七.滤镜

1.PIXI自带的滤镜

(1)BlurFilter模糊滤镜

//创建模糊滤镜

const blurFilter = new PIXI.BlurFilter()

//设置模糊程度

blurFilter.blur = 20

//将模糊滤镜添加到精灵上

sprite.filters = [blurFilter]

(2)DisplacementFilter置换滤镜

//添加精灵

const displaymentSprite = PIXI.Sprite.from('../public/zhihuantietu.jpg')

displaymentSprite.scale.set(0.5)

//设置纹理的重复模式:解决纹理太大,滤镜的图片太小

displaymentSprite.texture.baseTexture.wrapMode = PIXI.WRAP_MODES.REPEAT

const displacementFilter = new PIXI.DisplacementFilter(displaymentSprite)

container.addChild(displaymentSprite)

//将置换滤镜放到container上

container.filters = [displacementFilter]

2.pixi-filters

PIXI自带的滤镜很少,需要更多的滤镜效果需要去GitHub - pixijs/filters: Collection of community-authored custom display filters for PixiJS上找

安装:pnpm add pixi-filters

(1)OutlineFilter轮廓滤镜

import { OutlineFilter } from 'pixi-filters'

//创建轮廓滤镜

const outlineFilter = new OutlineFilter(5, 0xffff00) //5为轮廓宽度,后面为轮廓颜色

sprite.filters = [outlineFilter]

(2) GlowFilter发光滤镜

import { GlowFilter } from 'pixi-filters'

//创建发光滤镜

const glowFilter = new GlowFilter({

//发光的距离

distance: 50,

//外围发光强度

outerStrength: 2,

//内围发光强度

innerStrength: 0,

//发光颜色

color: 0xff0000,

//透明度

quality: 0.5

})

sprite.filters = [glowFilter]

(3)ShockwaveFilter水波纹滤镜

import { ShockwaveFilter } from 'pixi-filters'

//添加震波滤镜

const shockwaveFilter: any = new ShockwaveFilter(

//震波发生的位置

[Math.random() * app.screen.width, Math.random() * app.screen.height],

//震波参数

{

radius: Math.random() * 1000, //半径

wavelength: 30, //波长

amplitude: 10, //振幅

speed: 200 //扩散速度

},

//开始时间

0

)

container.filters = [ shockwaveFilter]

const createWave = (waveFilter: any, resetTime: any) => {

waveFilter.time += 0.01

if (waveFilter.time > resetTime) {

waveFilter.time = 0

waveFilter.center = [

Math.random() * app.screen.width,

Math.random() * app.screen.height

]

}

}

//ticker实现动画

app.ticker.add((delta: any) => {

createWave(shockwaveFilter, 1)

})

八.恐龙小游戏

1.PIXI.BaseTexture

const baseTexture = PIXI.BaseTexture.from('../public/game.png')

const dinoTexture = new PIXI.Texture(

  baseTexture,

  new PIXI.Rectangle(38, 0, 44, 50)

)

2.PIXI.AnimatedSprite

//恐龙跑步动画

const runTextuers = []

for (let i = 0; i < 2; i++) {

runTextuers.push(

new PIXI.Texture(baseTexture, new PIXI.Rectangle(935 + i * 44, 0, 44, 50))

)

}

const runAnimation = new PIXI.AnimatedSprite(runTextuers)

runAnimation.animationSpeed = 0.1

runAnimation.play()

runAnimation.visible = false

container.addChild(runAnimation)

3.PIXI.TilingSprite

//地面精灵

const groundTexture = new PIXI.Texture(

baseTexture,

new PIXI.Rectangle(0, 50, 1233, 17)

)

const groundSprite = new PIXI.TilingSprite(groundTexture)

groundSprite.width = window.innerWidth

groundSprite.height = 17

<template>
  <div></div>
</template>

<script setup lang="ts">
//导入pixi.js
import * as PIXI from 'pixi.js'
//创建应用
const app: any = new PIXI.Application({
  width: window.innerWidth,
  height: window.innerHeight,
  backgroundColor: 0xffffff,
  //屏幕的像素比例
  resolution: window.devicePixelRatio || 1,
  //抗锯齿
  antialias: true
})
//将画布添加到DOM中
document.body.appendChild(app.view)
//创建容器
const container = new PIXI.Container()
//将容器添加到舞台
app.stage.addChild(container)

//添加恐龙游戏的精灵纹理
const baseTexture = PIXI.BaseTexture.from('../public/game.png')

//创建恐龙纹理
const dinoTexture = new PIXI.Texture(
  baseTexture,
  new PIXI.Rectangle(38, 0, 44, 50)
)
//创建恐龙精灵
const dino = new PIXI.Sprite(dinoTexture)
//一开始并不想显示
dino.visible = false
container.addChild(dino)

//恐龙跑步动画
const runTextuers = []
for (let i = 0; i < 2; i++) {
  runTextuers.push(
    new PIXI.Texture(baseTexture, new PIXI.Rectangle(935 + i * 44, 0, 44, 50))
  )
}
const runAnimation = new PIXI.AnimatedSprite(runTextuers)
runAnimation.animationSpeed = 0.1
runAnimation.play()
runAnimation.visible = false
container.addChild(runAnimation)

//恐龙跳跃精灵
const junmTextuer = new PIXI.Texture(
  baseTexture,
  new PIXI.Rectangle(848, 0, 44, 50)
)
const jumpSprite = new PIXI.Sprite(junmTextuer)
jumpSprite.x = 60
jumpSprite.y = window.innerHeight - 50 - 50
jumpSprite.visible = false
container.addChild(jumpSprite)

//恐龙死亡精灵
const deathTextuer = new PIXI.Texture(
  baseTexture,
  new PIXI.Rectangle(1111, 0, 60, 50)
)
const deathSprite = new PIXI.Sprite(deathTextuer)
deathSprite.x = 60
deathSprite.y = window.innerHeight - 50 - 50
deathSprite.visible = false
container.addChild(deathSprite)

//地面精灵
const groundTexture = new PIXI.Texture(
  baseTexture,
  new PIXI.Rectangle(0, 50, 1233, 17)
)
const groundSprite = new PIXI.TilingSprite(groundTexture)
groundSprite.width = window.innerWidth
groundSprite.height = 17
//设置地面精灵的位置
groundSprite.position.set(0, window.innerHeight - 50)
//groundSprite.visible = false
container.addChild(groundSprite)

//仙人掌精灵
const cactusTexture = new PIXI.Texture(
  baseTexture,
  new PIXI.Rectangle(332, 0, 23, 50)
)
const cactusSprite = new PIXI.Sprite(cactusTexture)
//设置仙人掌精灵的位置
cactusSprite.x = window.innerWidth / 2
cactusSprite.y = window.innerHeight - 50 - 50
//cactusSprite.visible = false
container.addChild(cactusSprite)

//开始游戏文字
let startText = new PIXI.Text('开始游戏', {
  fontFamily: 'Arial',
  fontSize: 36,
  fill: 0x333333,
  align: 'center'
})
startText.anchor.set(0.5, 0.5)
startText.x = window.innerWidth / 2
startText.y = window.innerHeight / 2
//startText.visible = false
container.addChild(startText)

//游戏得分
let score = 0
//最后得分文字
let overText = new PIXI.Text('', {
  fontFamily: 'Arial',
  fontSize: 36,
  fill: 0x333333,
  align: 'center'
})
overText.anchor.set(0.5, 0.5)
overText.x = window.innerWidth / 2
overText.y = window.innerHeight / 2
overText.visible = false
container.addChild(overText)

startText.interactive = true
startText.on('click', () => {
  playGame()
})

//游戏开始标记
let isGameing = false
//结束开始标记
let isGameover = false
//开始游戏函数
const playGame = () => {
  isGameing = true
  //开始游戏文字消失
  startText.visible = false
  //显示恐龙的跑步动画
  runAnimation.visible = true
  runAnimation.x = 60
  runAnimation.y = window.innerHeight - 50 - 50
}

//结束游戏函数
const Gameover = () => {
  isGameover = true
  runAnimation.visible = false
  deathSprite.visible = true
}

//初始化恐龙跳跃的速度
let jumpVelocity = 20
//初始化重力
let gravity = 1
//游戏循环
app.ticker.add((delta: any) => {
  if (isGameover) return
  if (isGameing) {
    //地面移动
    groundSprite.tilePosition.x -= 10
    //仙人掌移动
    cactusSprite.x -= 10
    if (cactusSprite.x < -30) {
      cactusSprite.x = window.innerWidth
      score++
    }
  }
  if (jumpSprite.visible) {
    jumpVelocity -= gravity
    jumpSprite.y -= jumpVelocity
    //每次跳跃落地后需重置jumpSprite的数据
    if (jumpSprite.y > window.innerHeight - 50 - 50) {
      jumpSprite.y = window.innerWidth - 50 - 50
      jumpVelocity = 20
      jumpSprite.x = 60
      jumpSprite.y = window.innerHeight - 50 - 50
      jumpSprite.visible = false
      runAnimation.visible = true
    }
  }
  //检测碰撞
  if (
    jumpSprite.y > cactusSprite.y - 50 &&
    jumpSprite.x + 44 > cactusSprite.x &&
    cactusSprite.x > jumpSprite.x - 44
  ) {
    Gameover()
    //显示最后得分
    overText.text = '游戏结束,最后得分为' + score.toString()
    overText.visible = true

    overText.interactive = true
    overText.on('click', () => {
      location.reload()
    })
  }
})

//点击空格恐龙跳跃
window.addEventListener('keydown', (e) => {
  if (e.code == 'Space') {
    runAnimation.visible = false
    jumpSprite.visible = true
    jumpVelocity = 20
  }
})
</script>
<style lang="less" scoped></style>

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值