123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391 |
- /** @format */
- // import { Color, Component, Node, PhysicsSystem, Quat, Vec3, _decorator, ccenum } from 'cc';
- import {cBody} from './Body'
- import {cCollider} from './Collider'
- import {ShapeType, cBox, cCapsule, cShape, cSphere} from './Shape'
- import {Data} from '../GameControl'
- import Box = cc.Collider.Box
- const {ccclass, property} = cc._decorator
- cc.Enum(ShapeType)
- export enum Trigger {
- default = 0,
- enter = 1,
- stay = 2,
- exit = 3,
- }
- export enum Dirty {
- R = 1,
- T = 2,
- S = 4,
- RTS = 7,
- RS = R | S,
- NON = 0,
- }
- //从名字获取碰撞分组id, name->group
- export const GroupIdxByName = function (name: string) {
- const id = cc.game['groupList'].indexOf(name)
- return id >= 0 ? 1 << id : 0
- }
- //从分组id获取碰撞掩码, group->mask
- export const MaskBitByGroupIndex = function (groupIndex: number) {
- let maskBits = 0
- let bits = cc.game['collisionMatrix'][groupIndex]
- for (let i = 0; i < bits.length; i++) {
- if (!bits[i]) continue
- maskBits |= 1 << i
- }
- return maskBits
- }
- @ccclass
- export class cObject extends cc.Component {
- @property()
- trigger: boolean = true //碰撞开关
- @property({type: ShapeType})
- type: ShapeType = ShapeType.Box //相交形状类型
- @property({})
- center: cc.Vec3 = new cc.Vec3() //偏移位置,是shape相对node节点的中心偏移
- @property({
- visible() {
- return this.type == ShapeType.Box
- },
- })
- size: cc.Vec3 = new cc.Vec3() //方块的长宽高
- @property({
- visible() {
- return this.type != ShapeType.Box
- },
- })
- radius: number = 0 //半径,sphere 或者 capsule
- @property({
- visible() {
- return this.type == ShapeType.Capsule
- },
- })
- height: number = 0 //半高 ,capsule 专用
- @property()
- agent: boolean = false //碰撞开关
- @property({
- type: cc.Integer,
- visible() {
- return this.agent
- },
- })
- priority: number = 0 //Agent避让优先级,越大优先级越高
- @property({
- visible() {
- return this.agent
- },
- })
- maxRadius: number = 0 //Agent碰撞半径,小于等于物体体积
- @property({
- visible() {
- return this.agent
- },
- })
- maxVelocity: number = 0 //Agent最大速度,小于等于物体速度
- //常用变量
- @property()
- velocity: cc.Vec3 = new cc.Vec3(0, 0, 0) //当前速度
- speed: number = 0 //最大速度
- angle: number = 0 //旋转角度
- isDirty: Dirty = Dirty.RTS
- shape: cShape = null
- body: cBody = null
- containsBody: Map<number, cBody> = null
- curInBody: number[] = []
- curOutBody: number[] = []
- onLoad() {}
- private _worldScale: cc.Vec3 = new cc.Vec3()
- private _worldRTMat3: cc.Mat3 = new cc.Mat3()
- private _worldMatrix: cc.Mat4 = new cc.Mat4()
- private _worldPosition: cc.Vec3 = new cc.Vec3()
- private _worldRotation: cc.Quat = new cc.Quat()
- get worldScale() {
- this.updateWorldRTS()
- //this.node["getWorldScale"](this._worldScale);
- return this._worldScale
- }
- get worldPosition() {
- this.updateWorldRTS()
- //this.node["getWorldPosition"](this._worldPosition);
- return this._worldPosition
- }
- get worldRotation() {
- this.updateWorldRTS()
- //this.node["getWorldRotation"](this._worldRotation);
- return this._worldRotation
- }
- get worldRotatioMat3() {
- this.updateWorldRTS()
- return this._worldRTMat3
- }
- //同步瞄点,2D专用
- setAnchor(anchor: cc.Vec2) {
- let c0 = this.center
- let c1 = this.shape.center
- this.node.setAnchorPoint(anchor)
- let s = this.node.getContentSize()
- c1.x = (0.5 - anchor.x) * s.width + c0.x
- c1.y = (0.5 - anchor.y) * s.height + c0.y
- this.isDirty |= Dirty.T
- }
- //同步角度2D专用
- setAngle(angle: number) {
- this.node.angle = angle
- this.isDirty |= Dirty.R
- }
- getAngle() {
- return this.node.angle
- } //旋转角度2d 专用
- //同步位置到body
- setPosition(position: cc.Vec3) {
- this.node.setPosition(position)
- this.isDirty |= Dirty.T
- }
- //同步旋转3D专用
- setRotation(rotation: cc.Quat) {
- this.node.setRotation(rotation)
- this.isDirty |= Dirty.R
- }
- //同步缩放到body
- setScale(scale: cc.Vec3) {
- this.node.setScale(scale)
- this.isDirty |= Dirty.S
- }
- private _scale: cc.Vec3 = new cc.Vec3()
- private _rotation: cc.Quat = new cc.Quat()
- private _position: cc.Vec3 = new cc.Vec3()
- getRotation() {
- this.node.getRotation(this._rotation)
- return this._rotation
- }
- getPosition() {
- this.node.getPosition(this._position)
- return this._position
- }
- getScale() {
- this.node.getScale(this._scale)
- return this._scale
- }
- //移除node, 是否回收body ?
- remove(retrieve: boolean = true) {
- //移除body,是否回收body
- cCollider.inst.remove(this.body, retrieve)
- //从父节点移除
- this.node.removeFromParent(false)
- //最后node用户自己控制
- //this.remove().destroy() // 马上释放
- //pool.push(this.remove()); //回收复用
- return this.node
- }
- //重新添加到父节点
- insert(parent: cc.Node) {
- cCollider.inst.insert(this.body, true)
- //添加到父节点
- if (this.node.parent != parent) parent.addChild(this.node)
- }
- setAnimation(name: string) {}
- setColor(color: cc.Color) {}
- init(groupIndex: number, entity) {
- //创建碰撞形状 暂时只有圆形
- switch (this.type) {
- case ShapeType.Box:
- this.shape = new cBox(this.center, this.size)
- break
- case ShapeType.Sphere:
- this.shape = new cSphere(this.center, this.radius)
- break
- case ShapeType.Capsule:
- this.shape = new cCapsule(this.center, this.radius, this.height)
- break
- }
- // this.node.is3DNode = true; //全局使用3d坐标系
- //创建碰撞body容器
- this.body = cCollider.inst.create(this)
- this.body.entity = entity
- // 暂时去掉agent
- //this.body.isAgent = this.agent // agent 检测开关
- //this.body.priority = this.priority //agent 避让优先级
- //this.body.neighborDist = this.maxRadius // agent 体积半径
- //this.body.maxVelocity = this.maxVelocity // agent 最大速度
- this.body.isAgent = false
- this.body.shape = this.shape //绑定碰撞形状
- // 动态修改碰撞组
- //this.body.group = 1 << this.node.groupIndex //碰撞分组
- this.body.group = 1 << groupIndex //碰撞分组
- this.body.mask = Data.game.maskBitByGroupIndex(groupIndex) //碰撞掩码
- //把body加入碰撞管理 在ecs系统中加入和移除
- //cCollider.inst.insert(this.body)
- this.isDirty = Dirty.RTS //首次更新标记
- //还在碰撞的元素放入碰撞体内
- this.containsBody = new Map()
- this.curInBody.length = 0
- this.curOutBody.length = 0
- }
- removeNotInBody() {
- this.containsBody.forEach((value, key) => {
- if (value.isRemove) {
- this.containsBody.delete(key)
- }
- })
- }
- updateSphereShape(radius) {
- this.radius = radius
- this.shape = new cSphere(this.center, this.radius)
- this.body.shape = this.shape //绑定碰撞形状
- this.isDirty = Dirty.RTS
- }
- updateBoxShape(x, y) {
- this.size.x = x
- this.size.y = y
- this.shape = new cBox(this.center, this.size)
- this.body.shape = this.shape //绑定碰撞形状
- this.isDirty = Dirty.RTS
- }
- //trigger 回调 enter,stay exit
- onTrigger(b: cBody, trigger: Trigger) {
- switch (trigger) {
- case Trigger.enter:
- //onTriggerEnter();
- if (b.entity != 0 && !this.containsBody.has(b.entity)) {
- // console.log(
- // Data.game.groupList[this.body.group.toString(2).length - 1],
- // Data.game.groupList[b.group.toString(2).length - 1],
- // '发生碰撞',
- // b.entity,
- // '进入',
- // )
- this.containsBody.set(b.entity, b)
- this.curInBody.push(b.entity)
- }
- break
- case Trigger.stay:
- //onTriggerStay();
- break
- case Trigger.exit:
- //onTriggerExit();
- // console.log(
- // Data.game.groupList[this.body.group.toString(2).length - 1],
- // Data.game.groupList[b.group.toString(2).length - 1],
- // '碰撞离开',
- // b.entity,
- // '离开',
- // )
- this.containsBody.delete(b.entity)
- this.curOutBody.push(b.entity)
- break
- }
- }
- onDestroy() {
- this.unscheduleAllCallbacks()
- this.shape = null
- this.body = null
- }
- updateWorldRTS(dirty: Dirty = Dirty.NON) {
- dirty |= this.isDirty
- if (dirty == Dirty.NON) return
- //更新当前节点世界矩阵
- // this.node.getWorldMatrix(this._worldMatrix)
- // const m = this._worldMatrix.m
- //这是个特别优化,确保上层父节点上已更新的前提下可用
- //如果没有正常运行,请使用上面两行代替,或者提前手动刷新parent.getWorldMatrix()
- this.node['_calculWorldMatrix']()
- const m = this.node['_worldMatrix'].m
- if (dirty & Dirty.T) {
- const t = this._worldPosition
- t.x = m[12]
- t.y = m[13]
- t.z = m[14]
- //console.log('更新世界矩阵', t.x, t.y)
- }
- const s = this._worldScale
- if (dirty & Dirty.S) {
- s.x = Math.sqrt(m[0] * m[0] + m[1] * m[1] + m[2] * m[2])
- s.y = Math.sqrt(m[4] * m[4] + m[5] * m[5] + m[6] * m[6])
- s.z = Math.sqrt(m[8] * m[8] + m[9] * m[9] + m[10] * m[10])
- }
- const m3 = this._worldRTMat3.m
- if (dirty & Dirty.R) {
- const sx = 1.0 / s.x,
- sy = 1.0 / s.y,
- sz = 1.0 / s.z
- m3[0] = m[0] * sx
- m3[1] = m[1] * sx
- m3[2] = m[2] * sx
- m3[3] = m[4] * sy
- m3[4] = m[5] * sy
- m3[5] = m[6] * sy
- m3[6] = m[8] * sz
- m3[7] = m[9] * sz
- m3[8] = m[10] * sz
- cc.Quat.fromMat3(this._worldRotation, this._worldRTMat3)
- }
- }
- }
|