feng 发布的文章

cannon.js 物理引擎使用

我在开发大富翁游戏中,希望骰子能跟现实一样投掷,因为three.js中并没有物理引擎的引入,所以我需要引入cannon.js
cannon.js属于一个轻量级引擎,对cpu的性能要求比较低,非常适合放在web游戏中使用.
简单记录一下cannon.js使用过程中的要点,以便后面查阅.

大富翁源码地址:https://github.com/aoobao/backpacker

cannon.js 文档地址: https://schteppe.github.io/cannon.js

创建物理引擎世界

this.world = new CANNON.World()
this.world.gravity.set(0, 0, -9.8 * 70)    // 重力加速度设置 这里乘以70是因为之前创建的物体设置的比较大,所以需要加大重力加速度矫正

创建刚体

// 设置材质 这里设置了地面,墙壁,骰子三种材质
const cubeMaterial = new CANNON.Material('cube')
const material = new CANNON.Material('ground')
const wallMaterial = new CANNON.Material('wall')

// 地面
const bodyGround = new CANNON.Body({
      mass: 0,
      position: new CANNON.Vec3(0, 0, 0.1),
      shape: new CANNON.Plane(),
      material: material,
})

const wall1 = new CANNON.Body({
      mass: 0,
      position: new CANNON.Vec3(WIDTH / 2, 0, 0),
      shape: new CANNON.Plane(),
      material: wallMaterial,
})

wall1.quaternion.setFromAxisAngle(new CANNON.Vec3(0, 1, 0), -Math.PI / 2)

// 注意CANNON.Plane底部是包含材质的,并不是只有一个平面,假设 position: new CANNON.Vec3(0, 0, 0), 那么z方向<0的都是存在材质,物体如果在z方向<0 会被挤到上来,在z+方向有一个力
// 设置两个材质之间的参数值,因为我不希望骰子斜靠在墙上,所以墙壁和骰子的摩擦力设置成了0.
const groundContactMaterial = new CANNON.ContactMaterial(material, cubeMaterial, {
      friction: 0.1,    // 摩擦力
      restitution: 0.5, // 弹性
})

const wallContactMaterial = new CANNON.ContactMaterial(wallMaterial, cubeMaterial, {
      friction: 0,
      restitution: 1,
})

创建骰子,并给予初速度及角速度

addBox(cube: Cube, speed = 1) {
    return new Promise<void>((resolve, reject) => {
      const pos = cube.instance.position
      const qua = cube.instance.quaternion
      const size = cube.size
      const halfExtents = new CANNON.Vec3(size / 2, size / 2, size / 2)
      const bodyBox = new CANNON.Body({
        mass: 5,
        position: new CANNON.Vec3(pos.x, pos.y, pos.z),
        shape: new CANNON.Box(halfExtents),
        quaternion: new CANNON.Quaternion(qua.x, qua.y, qua.z, qua.w),
        linearDamping: 0.01,
        angularDamping: 0.05,
        material: cubeMaterial,
      })

      const x = 500 * speed * randPM()
      const y = 500 * speed * randPM()
      const z = 300 + 300 * speed

      bodyBox.velocity.set(x, y, z)
      bodyBox.angularVelocity.set(rendAngular(), rendAngular(), (50 + 50 * Math.random()) * randPM())

      function rendAngular() {
        return (10 + 10 * Math.random()) * randPM()
      }

      const box: PhysicsBody = {
        type: 'cube',
        cube,
        bodyBox,
        resolve,
        reject,
        timer: new Date().getTime(),
      }

      this.world.addBody(bodyBox)
      this.bodyList.push(box)
    })
  }

每帧渲染的时候更新计算

// updatePhysics
  render(res: any) {
    const delta = res.delta as number
    if (delta) {
      // console.log(delta)
      this.world.step(fixedTimeStep, delta, maxSubSteps)
      for (let i = this.bodyList.length - 1; i >= 0; i--) {
        const box = this.bodyList[i]
        // 将物理引擎中的计算值同步到threejs中的对象中(position,quaternion),并判断CANNON.Body的速度和角速度是否低于某个阈值,
        // 如果低于阈值后,则可以认为骰子已经停止运动了,可以读取骰子的朝向及点数值了.
        if (this.syncInstanceValue(box)) {
          this.bodyList.splice(i, 1)

          // 延迟去除,多个骰子
          setTimeout(() => {
            this.world.remove(box.bodyBox)
          }, 5000)
          box.resolve()
        }
      }
    }
  }

以上记录了比较关键的内容,源码可以参考https://github.com/aoobao/backpacker/blob/master/src/assets/physics.ts

threejs+vue3.0+typescript开发的大富翁小游戏

立了flag要在2021年开发一款3d休闲小游戏,勉强做了一个大富翁1.0,还有不少需要修改的地方,本来想修改完成后来发博客,下半年为了赚钱稍微忙了点...停了一段时间后就一直没继续了.
先发个github的地址链接,后面有时间,再发些文章记录一些开发web游戏的坑...

背包客自由行

游戏规则参考
https://j9981168.pixnet.net/blog/post/239327645

后面有时间在游戏里补上帮助(逃ε=ε=ε=┏(゜ロ゜;)┛)

在VBA变量中存储数组公式结果

之前在编写VBA程序时如果遇到需要用数组公式来计算结果的时候,我都会通过往单元格写入数组函数来得到数组函数的结果,然后获取单元格的内容将结果放到VBA变量中,这样做会导致VBA效率大大降低,一直以为没什么好办法,没想到偶然搜索找到了解决的办法:

代码如下:

Sub j2()
a = Application.Evaluate("SUM(((品名=""春羔皮"")*(规格=""1-2"")*(单价>100))*金额)")
 MsgBox a
End Sub

原文链接

CSS 毛玻璃特效开发

之前在我的博客中有写磨砂玻璃的效果开发,但是会存在很多的局限.
附上链接: 磨砂波理效果开发
最近发现css又多了个backdrop-filter的属性,能够非常简单的实现毛玻璃的效果.
真的是太感动了

附上效果图:
http://qn.fengyitong.name/backdrop-filter.png

附上官方文档说明:
https://developer.mozilla.org/en-US/docs/Web/CSS/backdrop-filter#result

附上浏览器当前支持程度:
http://qn.fengyitong.name/can-i-use-backdrop-filter.png

顺便附上效果图参考代码(官方文档的示例代码)

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .box {
      background-color: rgba(255, 255, 255, 0.3);
      border-radius: 5px;
      font-family: sans-serif;
      text-align: center;
      line-height: 1;
      -webkit-backdrop-filter: blur(10px);
      backdrop-filter: blur(10px);
      max-width: 50%;
      max-height: 50%;
      padding: 20px 40px;
    }

    html,
    body {
      height: 100%;
      width: 100%;
    }

    body {
      background-image: url(https://picsum.photos/id/1080/6858/4574), linear-gradient(rgb(219, 166, 166), rgb(0, 0, 172));
      background-position: center center;
      background-repeat: no-repeat;
      background-size: cover;
    }

    .container {
      align-items: center;
      display: flex;
      justify-content: center;
      height: 100%;
      width: 100%;
    }
  </style>
</head>

<body>
  <div class="container">
    <div class="box">
      <p>backdrop-filter: blur(10px)</p>
    </div>
  </div>
</body>

</html>