diff --git a/assets/resources/game/map/map_rpg.prefab b/assets/resources/game/map/map_rpg.prefab index ab83e7a5..bbb5c879 100644 --- a/assets/resources/game/map/map_rpg.prefab +++ b/assets/resources/game/map/map_rpg.prefab @@ -27,18 +27,18 @@ ], "_active": true, "_components": [ - { - "__id__": 66 - }, - { - "__id__": 68 - }, { "__id__": 70 + }, + { + "__id__": 72 + }, + { + "__id__": 74 } ], "_prefab": { - "__id__": 72 + "__id__": 76 }, "_lpos": { "__type__": "cc.Vec3", @@ -196,18 +196,18 @@ ], "_active": true, "_components": [ - { - "__id__": 59 - }, - { - "__id__": 61 - }, { "__id__": 63 + }, + { + "__id__": 65 + }, + { + "__id__": 67 } ], "_prefab": { - "__id__": 65 + "__id__": 69 }, "_lpos": { "__type__": "cc.Vec3", @@ -251,20 +251,20 @@ "__id__": 8 }, { - "__id__": 38 + "__id__": 42 }, { - "__id__": 50 + "__id__": 54 } ], "_active": true, "_components": [ { - "__id__": 56 + "__id__": 60 } ], "_prefab": { - "__id__": 58 + "__id__": 62 }, "_lpos": { "__type__": "cc.Vec3", @@ -311,14 +311,14 @@ "_active": true, "_components": [ { - "__id__": 33 + "__id__": 37 }, { - "__id__": 35 + "__id__": 39 } ], "_prefab": { - "__id__": 37 + "__id__": 41 }, "_lpos": { "__type__": "cc.Vec3", @@ -371,14 +371,14 @@ "_active": true, "_components": [ { - "__id__": 28 + "__id__": 32 }, { - "__id__": 30 + "__id__": 34 } ], "_prefab": { - "__id__": 32 + "__id__": 36 }, "_lpos": { "__type__": "cc.Vec3", @@ -697,10 +697,16 @@ }, { "__id__": 25 + }, + { + "__id__": 27 + }, + { + "__id__": 29 } ], "_prefab": { - "__id__": 27 + "__id__": 31 }, "_lpos": { "__type__": "cc.Vec3", @@ -804,6 +810,74 @@ "__type__": "cc.CompPrefabInfo", "fileId": "66D90QlYtEvKkAU6KcReVW" }, + { + "__type__": "cc.RigidBody2D", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 22 + }, + "_enabled": true, + "__prefab": { + "__id__": 28 + }, + "enabledContactListener": false, + "bullet": true, + "awakeOnLoad": true, + "_group": 1, + "_type": 0, + "_allowSleep": false, + "_gravityScale": 0, + "_linearDamping": 0, + "_angularDamping": 0, + "_linearVelocity": { + "__type__": "cc.Vec2", + "x": 0, + "y": 0 + }, + "_angularVelocity": 0, + "_fixedRotation": false, + "_id": "" + }, + { + "__type__": "cc.CompPrefabInfo", + "fileId": "fa0hN7/dVNJp+ZtcBdqwHp" + }, + { + "__type__": "cc.BoxCollider2D", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 22 + }, + "_enabled": true, + "__prefab": { + "__id__": 30 + }, + "tag": 0, + "_group": 1, + "_density": 1, + "_sensor": false, + "_friction": 0.1, + "_restitution": 0, + "_offset": { + "__type__": "cc.Vec2", + "x": -1.1, + "y": -27.5 + }, + "_size": { + "__type__": "cc.Size", + "width": 1177.9, + "height": 830 + }, + "_id": "" + }, + { + "__type__": "cc.CompPrefabInfo", + "fileId": "fexeczFgpEObyOHYY30dp9" + }, { "__type__": "cc.PrefabInfo", "root": { @@ -827,7 +901,7 @@ }, "_enabled": true, "__prefab": { - "__id__": 29 + "__id__": 33 }, "_contentSize": { "__type__": "cc.Size", @@ -855,7 +929,7 @@ }, "_enabled": true, "__prefab": { - "__id__": 31 + "__id__": 35 }, "_customMaterial": null, "_srcBlendFactor": 2, @@ -913,7 +987,7 @@ }, "_enabled": true, "__prefab": { - "__id__": 34 + "__id__": 38 }, "_contentSize": { "__type__": "cc.Size", @@ -941,10 +1015,10 @@ }, "_enabled": true, "__prefab": { - "__id__": 36 + "__id__": 40 }, "bgImg": { - "__id__": 30 + "__id__": 34 }, "_id": "" }, @@ -975,17 +1049,17 @@ }, "_children": [ { - "__id__": 39 + "__id__": 43 } ], "_active": true, "_components": [ { - "__id__": 47 + "__id__": 51 } ], "_prefab": { - "__id__": 49 + "__id__": 53 }, "_lpos": { "__type__": "cc.Vec3", @@ -1022,23 +1096,23 @@ "_objFlags": 0, "__editorExtras__": {}, "_parent": { - "__id__": 38 + "__id__": 42 }, "_children": [], "_active": true, "_components": [ - { - "__id__": 40 - }, - { - "__id__": 42 - }, { "__id__": 44 + }, + { + "__id__": 46 + }, + { + "__id__": 48 } ], "_prefab": { - "__id__": 46 + "__id__": 50 }, "_lpos": { "__type__": "cc.Vec3", @@ -1075,11 +1149,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 39 + "__id__": 43 }, "_enabled": true, "__prefab": { - "__id__": 41 + "__id__": 45 }, "_contentSize": { "__type__": "cc.Size", @@ -1103,11 +1177,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 39 + "__id__": 43 }, "_enabled": true, "__prefab": { - "__id__": 43 + "__id__": 47 }, "_customMaterial": null, "_srcBlendFactor": 2, @@ -1171,11 +1245,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 39 + "__id__": 43 }, "_enabled": true, "__prefab": { - "__id__": 45 + "__id__": 49 }, "templateMode": false, "watchPath": "data.name", @@ -1206,11 +1280,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 38 + "__id__": 42 }, "_enabled": true, "__prefab": { - "__id__": 48 + "__id__": 52 }, "_contentSize": { "__type__": "cc.Size", @@ -1253,14 +1327,14 @@ "_active": true, "_components": [ { - "__id__": 51 + "__id__": 55 }, { - "__id__": 53 + "__id__": 57 } ], "_prefab": { - "__id__": 55 + "__id__": 59 }, "_lpos": { "__type__": "cc.Vec3", @@ -1297,11 +1371,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 50 + "__id__": 54 }, "_enabled": true, "__prefab": { - "__id__": 52 + "__id__": 56 }, "_contentSize": { "__type__": "cc.Size", @@ -1325,11 +1399,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 50 + "__id__": 54 }, "_enabled": true, "__prefab": { - "__id__": 54 + "__id__": 58 }, "_id": "" }, @@ -1360,7 +1434,7 @@ }, "_enabled": true, "__prefab": { - "__id__": 57 + "__id__": 61 }, "_contentSize": { "__type__": "cc.Size", @@ -1401,7 +1475,7 @@ }, "_enabled": true, "__prefab": { - "__id__": 60 + "__id__": 64 }, "_contentSize": { "__type__": "cc.Size", @@ -1429,7 +1503,7 @@ }, "_enabled": true, "__prefab": { - "__id__": 62 + "__id__": 66 }, "camera": { "__id__": 3 @@ -1438,13 +1512,13 @@ "__id__": 7 }, "mapLayer": { - "__id__": 35 + "__id__": 39 }, "floorLayer": { - "__id__": 38 + "__id__": 42 }, "entityLayer": { - "__id__": 53 + "__id__": 57 }, "isFollowPlayer": true, "_id": "" @@ -1463,9 +1537,8 @@ }, "_enabled": true, "__prefab": { - "__id__": 64 + "__id__": 68 }, - "boss": null, "_id": "" }, { @@ -1495,7 +1568,7 @@ }, "_enabled": true, "__prefab": { - "__id__": 67 + "__id__": 71 }, "_contentSize": { "__type__": "cc.Size", @@ -1523,7 +1596,7 @@ }, "_enabled": true, "__prefab": { - "__id__": 69 + "__id__": 73 }, "_cameraComponent": { "__id__": 3 @@ -1545,7 +1618,7 @@ }, "_enabled": true, "__prefab": { - "__id__": 71 + "__id__": 75 }, "_alignFlags": 45, "_target": null, diff --git a/assets/resources/game/monster/monster.prefab b/assets/resources/game/monster/monster.prefab index 2f45290a..3d1b7b5d 100644 --- a/assets/resources/game/monster/monster.prefab +++ b/assets/resources/game/monster/monster.prefab @@ -811,7 +811,7 @@ "tag": 0, "_group": 2, "_density": 1, - "_sensor": true, + "_sensor": false, "_friction": 0.2, "_restitution": 0, "_offset": { @@ -846,9 +846,9 @@ "bullet": true, "awakeOnLoad": true, "_group": 2, - "_type": 1, + "_type": 2, "_allowSleep": false, - "_gravityScale": 0, + "_gravityScale": 1, "_linearDamping": 0, "_angularDamping": 0, "_linearVelocity": { diff --git a/assets/resources/game/monster/niu.prefab b/assets/resources/game/monster/niu.prefab index c71597e5..0e075600 100644 --- a/assets/resources/game/monster/niu.prefab +++ b/assets/resources/game/monster/niu.prefab @@ -117,8 +117,8 @@ }, "_lscale": { "__type__": "cc.Vec3", - "x": -1, - "y": 1, + "x": -1.5, + "y": 1.5, "z": 1 }, "_mobility": 0, @@ -651,6 +651,7 @@ "__prefab": { "__id__": 31 }, + "_ospeed": 100, "_id": "" }, { @@ -669,10 +670,10 @@ "__prefab": { "__id__": 33 }, - "tag": 0, + "tag": 90, "_group": 2, "_density": 1, - "_sensor": true, + "_sensor": false, "_friction": 0.2, "_restitution": 0, "_offset": { @@ -707,9 +708,9 @@ "bullet": true, "awakeOnLoad": true, "_group": 2, - "_type": 1, + "_type": 2, "_allowSleep": false, - "_gravityScale": 0, + "_gravityScale": 1, "_linearDamping": 0, "_angularDamping": 0, "_linearVelocity": { diff --git a/assets/resources/gui/animation.anim b/assets/resources/gui/animation.anim deleted file mode 100644 index 61bb4bf3..00000000 --- a/assets/resources/gui/animation.anim +++ /dev/null @@ -1,192 +0,0 @@ -[ - { - "__type__": "cc.AnimationClip", - "_name": "animation", - "_objFlags": 0, - "__editorExtras__": { - "embeddedPlayerGroups": [] - }, - "_native": "", - "sample": 60, - "speed": 1, - "wrapMode": 2, - "enableTrsBlending": false, - "_duration": 0.3333333333333333, - "_hash": 500763545, - "_tracks": [ - { - "__id__": 1 - } - ], - "_exoticAnimation": null, - "_events": [], - "_embeddedPlayers": [], - "_additiveSettings": { - "__id__": 11 - }, - "_auxiliaryCurveEntries": [] - }, - { - "__type__": "cc.animation.VectorTrack", - "_binding": { - "__type__": "cc.animation.TrackBinding", - "path": { - "__id__": 2 - }, - "proxy": null - }, - "_channels": [ - { - "__id__": 3 - }, - { - "__id__": 5 - }, - { - "__id__": 7 - }, - { - "__id__": 9 - } - ], - "_nComponents": 3 - }, - { - "__type__": "cc.animation.TrackPath", - "_paths": [ - "position" - ] - }, - { - "__type__": "cc.animation.Channel", - "_curve": { - "__id__": 4 - } - }, - { - "__type__": "cc.RealCurve", - "_times": [ - 0 - ], - "_values": [ - { - "__type__": "cc.RealKeyframeValue", - "interpolationMode": 0, - "tangentWeightMode": 0, - "value": 0, - "rightTangent": 0, - "rightTangentWeight": 1, - "leftTangent": 0, - "leftTangentWeight": 1, - "easingMethod": 0, - "__editorExtras__": null - } - ], - "preExtrapolation": 1, - "postExtrapolation": 1 - }, - { - "__type__": "cc.animation.Channel", - "_curve": { - "__id__": 6 - } - }, - { - "__type__": "cc.RealCurve", - "_times": [ - 0, - 0.1666666716337204, - 0.3333333432674408 - ], - "_values": [ - { - "__type__": "cc.RealKeyframeValue", - "interpolationMode": 0, - "tangentWeightMode": 0, - "value": 0, - "rightTangent": 0, - "rightTangentWeight": 1, - "leftTangent": 0, - "leftTangentWeight": 1, - "easingMethod": 0, - "__editorExtras__": null - }, - { - "__type__": "cc.RealKeyframeValue", - "interpolationMode": 0, - "tangentWeightMode": 0, - "value": 30, - "rightTangent": 0, - "rightTangentWeight": 1, - "leftTangent": 0, - "leftTangentWeight": 1, - "easingMethod": 0, - "__editorExtras__": { - "tangentMode": 0 - } - }, - { - "__type__": "cc.RealKeyframeValue", - "interpolationMode": 0, - "tangentWeightMode": 0, - "value": 0, - "rightTangent": 0, - "rightTangentWeight": 1, - "leftTangent": 0, - "leftTangentWeight": 1, - "easingMethod": 0, - "__editorExtras__": { - "tangentMode": 0 - } - } - ], - "preExtrapolation": 1, - "postExtrapolation": 1 - }, - { - "__type__": "cc.animation.Channel", - "_curve": { - "__id__": 8 - } - }, - { - "__type__": "cc.RealCurve", - "_times": [ - 0 - ], - "_values": [ - { - "__type__": "cc.RealKeyframeValue", - "interpolationMode": 0, - "tangentWeightMode": 0, - "value": 0, - "rightTangent": 0, - "rightTangentWeight": 1, - "leftTangent": 0, - "leftTangentWeight": 1, - "easingMethod": 0, - "__editorExtras__": null - } - ], - "preExtrapolation": 1, - "postExtrapolation": 1 - }, - { - "__type__": "cc.animation.Channel", - "_curve": { - "__id__": 10 - } - }, - { - "__type__": "cc.RealCurve", - "_times": [], - "_values": [], - "preExtrapolation": 1, - "postExtrapolation": 1 - }, - { - "__type__": "cc.AnimationClipAdditiveSettings", - "enabled": false, - "refClip": null - } -] \ No newline at end of file diff --git a/assets/resources/gui/animation.anim.meta b/assets/resources/gui/animation.anim.meta deleted file mode 100644 index 39c9e9a4..00000000 --- a/assets/resources/gui/animation.anim.meta +++ /dev/null @@ -1,13 +0,0 @@ -{ - "ver": "2.0.3", - "importer": "animation-clip", - "imported": true, - "uuid": "9fbb4e9a-8a4f-42b0-b402-4f56823ca4af", - "files": [ - ".cconb" - ], - "subMetas": {}, - "userData": { - "name": "animation" - } -} diff --git a/assets/script/Main.ts b/assets/script/Main.ts index fca6b1a2..e4bc3472 100644 --- a/assets/script/Main.ts +++ b/assets/script/Main.ts @@ -24,13 +24,13 @@ export class Main extends Root { protected async run() { smc.initialize = ecs.getEntity(Initialize); smc.monsters = [ - {profession:'m1',speed:50}, - {profession:'m2',speed:60}, - {profession:'m3',speed:70}, - {profession:'m4',speed:80}, + {name:'niu',profession:'m1',speed:50}, + {name:'niu',profession:'m2',speed:100}, + {name:'niu',profession:'m3',speed:50}, + {name:'niu',profession:'m4',speed:100}, ] smc.heros = [ - {profession:'war',speed:50}, + {name:'hero',profession:'war',speed:50}, // {profession:'magic',speed:50}, // {profession:'heath',speed:50}, // {profession:'war',speed:50}, diff --git a/assets/script/game/common/config/BoxSet.ts b/assets/script/game/common/config/BoxSet.ts index 542f837d..c9d0a545 100644 --- a/assets/script/game/common/config/BoxSet.ts +++ b/assets/script/game/common/config/BoxSet.ts @@ -8,10 +8,12 @@ /** 碰撞分组 */ export enum BoxSet { DEFAULT = 0, - MONSTER = 2, - HERO = 4, - MONSTER_SKILL = 8, - HERO_SKILL = 16, + MONSTER = 90, + HERO = 10, + MONSTER_SKILL = 91, + HERO_SKILL = 11, BOX_WIDTH = 64, - BOX_HEIGHT = 64 + BOX_HEIGHT = 64, + LETF_END = -400, + RIGHT_END = 400 } \ No newline at end of file diff --git a/assets/script/game/map/view/MapViewComp.ts b/assets/script/game/map/view/MapViewComp.ts index a1f5b9bd..d2bca601 100644 --- a/assets/script/game/map/view/MapViewComp.ts +++ b/assets/script/game/map/view/MapViewComp.ts @@ -4,7 +4,9 @@ import { CCComp } from "../../../../../extensions/oops-plugin-framework/assets/m import { smc } from "../../common/SingletonModuleComp"; import { Role } from "../../role/Role"; import { Niu } from "../../monster/niu/Niu"; +import { BoxSet } from "../../common/config/BoxSet"; import { Hero } from "../../heros/Hero"; +import { Monster } from "../../monster/Monster"; // import MapRoadUtils from "./map/road/MapRoadUtils"; import { MapViewScene } from "./MapViewScene"; import { Timer } from "../../../../../extensions/oops-plugin-framework/assets/core/common/timer/Timer"; @@ -15,8 +17,7 @@ const { ccclass, property } = _decorator; @ecs.register('MapView', false) export class MapViewComp extends CCComp { scene: MapViewScene = null!; - @property(Prefab) - boss: Prefab = null!; + /** 是否正在转场 */ @@ -55,17 +56,32 @@ export class MapViewComp extends CCComp { /** 添加玩家 */ private addHero() { - this.scene.node.active = true - - if (smc.monsters.length>0){ - let monster = ecs.getEntity(Niu); - monster.load(v3(360,-60),smc.monsters[0].speed); + this.addMonster(smc.monsters[0].name,smc.monsters[0].speed) smc.monsters.splice(0,1) } - + // if(smc.heros.length>0) { + // this.addMonster(smc.heros[0].name,100) + // } } + + private addMonster(name:string = "niu",speed:number = 100) { + let monster = null + switch (name) { + case "niu": + monster = ecs.getEntity(Niu); + break; + case "hero": + monster = ecs.getEntity(Monster); + break; + default: + break; + } + monster.load(v3(BoxSet.RIGHT_END,-60),speed); + } + + private getRandomInt(min: number, max: number): number { min = Math.ceil(min); max = Math.floor(max); diff --git a/assets/script/game/monster/MonsterViewComp.ts b/assets/script/game/monster/MonsterViewComp.ts index 49d5eca9..3bdb1547 100644 --- a/assets/script/game/monster/MonsterViewComp.ts +++ b/assets/script/game/monster/MonsterViewComp.ts @@ -64,7 +64,7 @@ export class MonsterViewComp extends CCComp { smc.monsters_in.forEach((element,index) => { if(element.eid == this.ent.eid){ - console.log("index:"+index) + // console.log("index:"+index) element.pos_x = this.node.position.x; } }); diff --git a/assets/script/game/monster/niu/Niu.ts b/assets/script/game/monster/niu/Niu.ts index d44fe0c4..a15e6dbb 100644 --- a/assets/script/game/monster/niu/Niu.ts +++ b/assets/script/game/monster/niu/Niu.ts @@ -39,7 +39,7 @@ export class Niu extends ecs.Entity { var node = instantiate(prefab); var scene = smc.map.MapView.scene; node.parent = scene.entityLayer!.node!; - var as = node.getComponent(MonsterSpine); + // var as = node.getComponent(MonsterSpine); node.setPosition(pos) var mv = node.getComponent(NiuViewComp)!; diff --git a/assets/script/game/monster/niu/NiuViewComp.ts b/assets/script/game/monster/niu/NiuViewComp.ts index 6ce66a72..f7ad30c8 100644 --- a/assets/script/game/monster/niu/NiuViewComp.ts +++ b/assets/script/game/monster/niu/NiuViewComp.ts @@ -5,7 +5,7 @@ * @LastEditTime: 2022-08-17 12:36:18 */ -import { Vec3, _decorator ,tween, v3,Collider2D,Contact2DType,PhysicsSystem2D,IPhysics2DContact} from "cc"; +import { Vec3, _decorator ,tween, v3,Collider2D,Contact2DType,PhysicsSystem2D,IPhysics2DContact,EPhysics2DDrawFlags} from "cc"; import { ecs } from "../../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; import { CCComp } from "../../../../../extensions/oops-plugin-framework/assets/module/common/CCComp"; import { MonsterSpine } from "./../MonsterSpine"; @@ -23,18 +23,63 @@ export class NiuViewComp extends CCComp { /** 角色动画 */ as: MonsterSpine = null!; speed: number = 100; - ospeed: number = 100; + @property + private _ospeed: number = 100; + @property + set ospeed(val: number) { + this._ospeed = val; + } + get ospeed() { + return this._ospeed; + } Tpos: Vec3 = v3(0,-60,0); timer: number = 0; /** 视图层逻辑代码分离演示 */ start () { - + // 注册单个碰撞体的回调函数 + let collider = this.getComponent(Collider2D); + if (collider) { + collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this); + collider.on(Contact2DType.END_CONTACT, this.onEndContact, this); + // collider.on(Contact2DType.PRE_SOLVE, this.onPreSolve, this); + collider.on(Contact2DType.POST_SOLVE, this.onPostSolve, this); + } + } + onBeginContact (selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) { + // 只在两个碰撞体开始接触时被调用一次 + // console.log('onBeginContact otherCollider.tag :',otherCollider,selfCollider); + if ( otherCollider.tag == BoxSet.HERO || otherCollider.tag == BoxSet.MONSTER) { + console.log('onBeginContact otherCollider.tag :',otherCollider,selfCollider); + this.speed = 0; + this.timer = 1; + } + } + onEndContact (selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) { + // 只在两个碰撞体结束接触时被调用一次 + console.log('onEndContact'); + } + // onPreSolve (selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) { + // // 每次将要处理碰撞体接触逻辑时被调用 + // console.log('onPreSolve'); + // } + onPostSolve (selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) { + if (otherCollider.tag === BoxSet.HERO || otherCollider.tag === BoxSet.MONSTER) { + // console.log('onPostSolve otherCollider.tag :'+otherCollider.tag); + this.speed = 0; + this.timer = 1; + } } onLoad() { this.as = this.getComponent(MonsterSpine); - console.log('this.ent:',this); + this.ospeed= this.speed; + console.log('this.ospeed:'+this.ospeed); + PhysicsSystem2D.instance.debugDrawFlags = EPhysics2DDrawFlags.Aabb | + EPhysics2DDrawFlags.Pair | + EPhysics2DDrawFlags.CenterOfMass | + EPhysics2DDrawFlags.Joint | + EPhysics2DDrawFlags.Shape; } update(dt: number){ @@ -45,10 +90,10 @@ export class NiuViewComp extends CCComp { this.timer = 0; } } - if(this.node.position.x > -360){ + if(this.node.position.x > BoxSet.LETF_END){ this.move(dt); } - if(this.node.position.x < -300){ + if(this.node.position.x < BoxSet.LETF_END){ console.log(this.node,this.ent) smc.monsters_in = smc.monsters_in.filter(element => element.eid !== this.ent.eid); this.node.destroy(); @@ -63,7 +108,7 @@ export class NiuViewComp extends CCComp { smc.monsters_in.forEach((element,index) => { if(element.eid == this.ent.eid){ - console.log("index:"+index) + // console.log("index:"+index) element.pos_x = this.node.position.x; } }); diff --git a/doc/core/common/audio.md b/doc/core/common/audio.md new file mode 100644 index 00000000..632d77a1 --- /dev/null +++ b/doc/core/common/audio.md @@ -0,0 +1,84 @@ + +### 功能说明 +Oops Framework-音频管理模块主要处理游戏背景音乐、游戏音效两大类功能。 + +### [演示程序](https://gitee.com/dgflash/oops-framework/tree/master/assets/demo/audio) + +### 使用说明 +##### 播放背景音乐 +``` +oops.audio.playMusic("audios/nocturne"); +``` +注:调用此方法后,后台会异步下载音乐资源,完成后开始播放音乐 + +##### 背景音乐播放完成回调设置 +``` +oops.audio.setMusicComplete(() => { + console.log("音乐播放完成"); +}); +``` + +##### 获取或设置背景音乐音量 +``` +oops.audio.musicVolume = 0.5; +``` +注:音量范围 (0 ~ 1) + +##### 背景音乐开关 +``` +oops.audio.switchMusic = false; +``` + +##### 获取或设置音乐播放进度 +``` +oops.audio.progressMusic = 0.5; +``` +注:音量进度 (0 ~ 1) + +##### 播放音效 +``` +oops.audio.playEffect("audios/Gravel"); +``` +注:调用此方法后,后台会异步下载音乐资源,完成后开始播放音乐 + +##### 获取或设置音效音量 +``` +oops.audio.volumeEffect = 0.5; +``` +注:音量范围 (0 ~ 1) + +##### 音效音乐开关 +``` +oops.audio.switchEffect = false; +``` + +##### 恢复暂停的所有音乐播放 +``` +oops.audio.resumeAll(); +``` + +##### 暂停当前音乐与音效的播放 +``` +oops.audio.pauseAll(); +``` + +##### 停止当前音乐与音效的播放 +``` +oops.audio.stopAll(); +``` + +##### 停止当前音乐与音效的播放 +``` +oops.audio.stopAll(); +``` + +##### 保存音乐音效的音量、开关配置数据到本地 +``` +oops.audio.save(); +``` + +##### 本地加载音乐音效的音量、开关配置数据并设置到游戏中 +``` +oops.audio.load(); +``` + diff --git a/doc/core/common/event.md b/doc/core/common/event.md new file mode 100644 index 00000000..b46d6350 --- /dev/null +++ b/doc/core/common/event.md @@ -0,0 +1,44 @@ +### 功能说明 +Oops Framework-全局事件管理主要在设计上降低对象之间的耦合问题,避免相互调用API导致对象强依赖,从而在项目中后期需求变更或扩展时,增加维护成本。 + +### 使用说明 +##### 注册持续监听的全局事件 +``` +export class RoleViewComp extends Component{ + onLoad(){ + // 监听全局事件 + oops.message.on(GameEvent.GameServerConnected, this.onHandler, this); + } + + protected onDestroy() { + // 对象释放时取消注册的全局事件 + oops.message.off(GameEvent.GameServerConnected, this.onHandler, this); + } + + private onHandler(event: string, args: any) { + switch (event) { + case GameEvent.GameServerConnected: + console.log("处理游戏服务器连接成功后的逻辑"); + break; + } + } +} +``` + +##### 注册只触发一次的全局事件 +``` +export class RoleViewComp extends Component{ + onLoad(){ + // 监听一次事件,事件响应后,该监听自动移除 + oops.message.once(GameEvent.GameServerConnected, this.onHandler, this); + } + + private onHandler(event: string, args: any) { + switch (event) { + case GameEvent.GameServerConnected: + console.log("处理游戏服务器连接成功后的逻辑"); + break; + } + } +} +``` \ No newline at end of file diff --git a/doc/core/common/loader.md b/doc/core/common/loader.md new file mode 100644 index 00000000..1fc59aa6 --- /dev/null +++ b/doc/core/common/loader.md @@ -0,0 +1,91 @@ +### 功能说明 +Oops Framework-资源管理模块主要处理游戏各种类型的资源的加载与释放功能。 + +### 使用说明 +##### 加载远程资源 +``` +var opt: IRemoteOptions = { ext: ".png" }; +var onComplete = (err: Error | null, data: ImageAsset) => { + const texture = new Texture2D(); + texture.image = data; + + const spriteFrame = new SpriteFrame(); + spriteFrame.texture = texture; + + var sprite = this.sprite.addComponent(Sprite); + sprite.spriteFrame = spriteFrame; +} +resLoader.loadRemote(this.url, opt, onComplete); +``` + +##### 加载资源包配置信息 +``` +var serverUrl = "http://192.168.1.13:8082/"; // 服务器地址 +var md5 = "8e5c0"; // Cocos Creator 构建后的MD5字符 +await resLoader.loadBundle(serverUrl,md5); +``` + +##### 加载单个资源 +``` +var path = "model"; +resLoader.load(path, sp.SkeletonData, (err: Error | null, sd: sp.SkeletonData) => { + if (err) { + console.error(`资源不存在`); + return; + } + + this.spine.skeletonData = sd; +}); +``` + +加载其它bundle中资源 +``` +var path = "model"; +resLoader.load("bundleName", path, sp.SkeletonData, (err: Error | null, sd: sp.SkeletonData) => { + if (err) { + console.error(`资源不存在`); + return; + } + + this.spine.skeletonData = sd; +}); +``` + +##### 加载一个文件夹中的资源 +``` +/** 加载进度事件 */ +var onProgressCallback = (finished: number, total: number, item: any) => { + console.log("资源加载进度", finished, total); +} + +/** 加载完成事件 */ +var onCompleteCallback = () => { + console.log("资源加载完成"); +} +resLoader.loadDir("game", onProgressCallback, onCompleteCallback); +``` + +##### 释放一个资源 +``` +resLoader.release("model", "resources"); +``` +注:第二个参数"resources"为默认值,为引擎默认bundle。如果需要释放其它bundle里的资源修改此参数即可 + +##### 释放一个文件夹的资源 +``` +resLoader.releaseDir("model", "resources"); +``` +注:第二个参数"resources"为默认值,为引擎默认bundle。如果需要释放其它bundle里的资源修改此参数即可 + +##### 获取缓存中资源 +``` +resLoader.get("common/anim/button_scale_start", AnimationClip, "resources") +``` +注:第三个参数"resources"为默认值,为引擎默认bundle。如果需要获取其它bundle里的资源修改此参数即可 + + +##### 打印缓存中所有资源信息 +``` +resLoader.dump(); +``` +注:用于调试时观察是资源是否正确释放 \ No newline at end of file diff --git a/doc/core/common/log.md b/doc/core/common/log.md new file mode 100644 index 00000000..4e3d8bb0 --- /dev/null +++ b/doc/core/common/log.md @@ -0,0 +1,30 @@ +### 功能说明 +Oops Framework-日志管理主要封装console对象日志输出功能,方便在复杂的业务逻辑中,提供更很清晰的信息排查问题。 + +### 使用说明 +##### 打印代码段的执行时间 +``` +oops.log.start(); +... +省略N行代码 +... +oops.log.end(); +``` + +##### 打印表格 +``` +var object:any = {uid:1000, name:"oops"}; +oops.log.table(object); +``` + +##### 打印日志 +``` +oops.log.trace("默认标准日志"); +oops.log.logConfig("灰色配置日志"); +oops.log.logNet("橙色网络日志"); +oops.log.logModel("紫色数据日志"); +oops.log.logBusiness("蓝色业务日志"); +oops.log.logView("绿色视图日志"); + +// 日志格式:[11:31:07:293][标准日志][Generator.ts->next]:'默认标准日志' +``` \ No newline at end of file diff --git a/doc/core/common/random.md b/doc/core/common/random.md new file mode 100644 index 00000000..c0300990 --- /dev/null +++ b/doc/core/common/random.md @@ -0,0 +1,44 @@ +### 功能说明 +Oops Framework-随机数生成管理模块,封装了[seedrandom](https://www.npmjs.com/package/seedrandom) 第三方随机数据库 + +### 使用说明 +##### 设置随机种子 +``` +// 随机种子可由服务端派发给其它客户端,同样的种子,多端随机同样次数时,结果是相同的 +RandomManager.instance.setSeed(123456789); +``` + +##### 生成指定范围的随机整数 +``` +var min = 1; +var max = 10; +// [min,max) 得到一个两数之间的随机整数,这个值不小于min(如果min不是整数的话,得到一个向上取整的 min),并且小于(但不等于)max +RandomManager.instance.getRandomInt(min, max, 1); + +// [min,max] 得到一个两数之间的随机整数,包括两个数在内,这个值比min大(如果min不是整数,那就不小于比min大的整数),但小于(但不等于)max +RandomManager.instance.getRandomInt(min, max, 2); + +// (min,max) 得到一个两数之间的随机整数 +RandomManager.instance.getRandomInt(min, max, 3); +``` + +##### 根据最大值,最小值范围生成随机数数组 +``` +var min = 1; +var max = 10; +var n = 10; +// 生成10个1~10之间的随机数数组 +RandomManager.instance.getRandomByMinMaxList(min, max, n); +``` + +##### 获取数组中随机对象 +``` +var objs = [1,2,3,4,5,6,7,8,9] +RandomManager.instance.getRandomByObjectList(objs, 3); +``` + +##### 定和随机分配 +``` +// 随机5个整数,5个数的和为100 +RandomManager.instance.getRandomBySumList(5,100); +``` \ No newline at end of file diff --git a/doc/core/common/storage.md b/doc/core/common/storage.md new file mode 100644 index 00000000..e05196fb --- /dev/null +++ b/doc/core/common/storage.md @@ -0,0 +1,38 @@ +### 功能说明 +Oops Framework-本地存储模块主要封装了Cocos Crator引擎里sys.localStorage对象的跨平台平地存储功能,同时在此基础上添加了数据加密与不同帐号区分的功能。 + +### 使用说明 +##### 初始化本地存储加密 +``` +oops.storage.init("key", "vi"); +``` +注:调试模式下不会触发数据加密,方便明文调试。发布模式自动启动数据加密 + +##### 初始化本地存储加密 +``` +var uid = 10000; // 用户唯一编号数据 +oops.storage.setUser(uid); +``` +注:用于区分不同账号本地存储数据,避免同名key的数据被其它账号登录时覆盖 + +##### 设置指定关键字的数据 +``` +oops.storage.set(key, value); +``` + +##### 获取指定关键字的数据 +``` +var data = oops.storage.get(key); +``` + +##### 删除指定关键字的数据 +``` +oops.storage.remove(key); +``` + +##### 清空整个本地存储 +``` +oops.storage.clear(); +``` + + diff --git a/doc/core/common/timer.md b/doc/core/common/timer.md new file mode 100644 index 00000000..b0bf7001 --- /dev/null +++ b/doc/core/common/timer.md @@ -0,0 +1,92 @@ +### 功能说明 +Oops Framework-时间管理模块主要实现在游戏中不同类型的定时器功能。 + +### 使用说明 +##### 获取游戏开始到现在逝去的时间 +``` +oops.timer.getTime(); +``` + +##### 获取本地时间刻度 +``` +oops.timer.getLocalTime(); +``` + +##### 注册一个固定间隔时间的触发器 +``` +oops.timer.schedule(()=>{ + // 每秒触发一次 +}, 1000); +``` + +##### 注册一个只触发一次的延时的触发器 +``` +oops.timer.scheduleOnce(()=>{ + // 1秒后触发一次后不会在触发 +}, 1000); +``` + +##### 删除一个时间触发器 +``` +var uuid = oops.timer.schedule(()=>{ + // 每秒触发一次 +}, 1000); + +// 删除指定标识的触发器 +oops.timer.unschedule(uuid); +``` + +##### 删除所有时间触发器 +``` +oops.timer.unscheduleAll(); +``` + +##### 在指定对象上注册一个倒计时的回调管理器 +``` +export class Test extends Component { + private timeId!: string; + + start() { + // 在指定对象上注册一个倒计时的回调管理器 + this.timeId = oops.timer.register(this, "countDown", this.onSecond, this.onComplete); + } + + private onSecond() { + console.log("每秒触发一次"); + } + + private onComplete() { + console.log("倒计时完成触发"); + } +} +``` + +##### 在指定对象上注销一个倒计时的回调管理器 +``` +export class Test extends Component { + private timeId!: string; + + start() { + this.timeId = oops.timer.register(this, "countDown", this.onSecond, this.onComplete); + } + + onDestroy() { + // 在指定对象上注销一个倒计时的回调管理器 + oops.timer.unRegister(this.timeId); + } +} +``` + +##### 定时跳动组件 +``` +export class Test extends Component { + // 创建一个定时跳动组件 + private timer: Timer = new Timer(1); + + update(dt: number) { + if (this.timer.update(this.dt)) { + console.log(每一秒触发一次); + } + } +} +``` \ No newline at end of file diff --git a/doc/core/gui/gui.md b/doc/core/gui/gui.md new file mode 100644 index 00000000..a6d9329f --- /dev/null +++ b/doc/core/gui/gui.md @@ -0,0 +1,77 @@ +### 功能说明 +Oops Framework-界面管理模块,主要实现游戏中不同类型的窗口管理,例如常住主界面窗口、弹出窗口、模式窗口,系统提示窗口等。 + +### 使用说明 +##### 窗口配置字段 +| 字段 | 介绍 | +| ------ | -------- | +| layer | 窗口层级 | +| prefab | 预制资源相对路径 | +| bundle | 远程包名 | + +##### 窗口配置数据 +``` +/** 界面唯一标识 */ +export enum UIID { + /** 资源加载界面 */ + Loading = 1, + /** 弹窗界面 */ + Window, + /** 加载与延时提示界面 */ + Netinstable +} + +/** 打开界面方式的配置数据 */ +export var UIConfigData: { [key: number]: UIConfig } = { + [UIID.Loading]: { layer: LayerType.UI, prefab: "loading/prefab/loading", bundle: "resources" }, + [UIID.Netinstable]: { layer: LayerType.PopUp, prefab: "common/prefab/netinstable" }, + [UIID.Window]: { layer: LayerType.Dialog, prefab: "common/prefab/window" } +} +``` + +##### 打开一个窗口 +``` +var uic: UICallbacks = { + // 窗口添加到界面完成事件 + onAdded: (node: Node, params: any) => { + var comp = node.getComponent(LoadingViewComp) as ecs.Comp; + } + + // 窗口节点 destroy 之后回调 + onRemoved:(node: Node | null, params: any) => { + + } +}; +oops.gui.open(UIID.Loading, null, uic); +``` + +##### 异步函数打开一个窗口 +``` +var node = await oops.gui.openAsync(UIID.Loading); +``` + +##### 关闭一个窗口 +``` +oops.gui.remove(UIID.Loading); +``` + +##### 指定一个节点来删除窗口 +``` +oops.gui.removeByNode(cc.Node); +``` +注:这里的Node必须是通过oops.gui.open或openAsync打开的才会执行关闭 + +##### 缓存中是否存在指定标识的窗口 +``` +oops.gui.has(UIID.Loading); +``` + +##### 渐隐飘过提示 +``` +oops.gui.toast("提示内容"); +``` + +##### 清除所有窗口 +``` +oops.gui.clear(); +``` diff --git a/doc/core/network.md b/doc/core/network.md new file mode 100644 index 00000000..3252b129 --- /dev/null +++ b/doc/core/network.md @@ -0,0 +1,109 @@ +### 功能说明 +Oops Framework-网络模块WebSocket处理客户端与服务之间保持长链接通讯。 + +### 使用说明 +##### 自定义网络通讯数据协议(GZip压缩) +``` +class GameProtocol extends NetProtocolPako { + /** 心跳协议 */ + getHearbeat(): NetData { + return `{"action":"LoginAction","method":"heart","data":"null","isCompress":false,"channelid":1,"callback":"LoginAction_heart"}`; + } +} +``` + +##### 创建一个WebSocket网络连接对象 +``` +var net = new NetNodeGame(); +var ws = new WebSock(); // WebSocket 网络连接对象 +var gp = new GameProtocol(); // 网络通讯协议对象 +var gt = new NetGameTips() // 网络提示对象 +net.init(ws, gp, gt); +NetManager.getInstance().setNetNode(net, NetChannelType.Game); +``` + +##### 连接游戏服务器 +``` +var options = { + url: `ws://127.0.0.1:3000`, + autoReconnect: 0 // -1 永久重连,0不自动重连,其他正整数为自动重试次数 +} +NetManager.getInstance().connect(options, NetChannelType.Game); +``` + +##### 断开游戏服务器连接 +``` +NetManager.getInstance().close(undefined, undefined, NetChannelType.Game); + +``` + +##### 游戏服务器提示 +``` +export class NetGameTips implements INetworkTips { + /** 连接提示 */ + connectTips(isShow: boolean): void { + if (isShow) { + Logger.logNet("游戏服务器正在连接"); + tips.netInstableOpen(); + } + else { + Logger.logNet("游戏服务器连接成功"); + tips.netInstableClose(); + Message.dispatchEvent(GameEvent.GameServerConnected); + } + } + + /** 重连接提示 */ + reconnectTips(isShow: boolean): void { + if (isShow) { + Logger.logNet("重连开始"); + } + else { + Logger.logNet("重连成功"); + } + } + + /** 请求提示 */ + requestTips(isShow: boolean): void { + if (isShow) { + Logger.logNet("请求数据开始"); + } + else { + Logger.logNet("请求数据完成"); + } + } + + /** 响应错误码提示 */ + responseErrorCode(code: number): void { + console.log("游戏服务器错误码", code); + } +} +``` + +##### 请求服务器数据 +``` +var params: any = { + playerId: 10000 +} + +let onComplete = { + target: this, + callback: (data: any) => { + // 服务器返回数据 + console.log(data); + } +} +// net为NetNodeGame对象 +net.req("LoginAction", "loadPlayer", params, onComplete); +``` + +##### 监听服务器推送数据 +``` +var onComplete = (data: any) => { + // 服务器返回数据 + console.log(data); +} + +// net为NetNodeGame对象 +net.setResponeHandler("notify", onComplete, this); +``` \ No newline at end of file diff --git a/doc/ecs/ecs.md b/doc/ecs/ecs.md new file mode 100644 index 00000000..1994105b --- /dev/null +++ b/doc/ecs/ecs.md @@ -0,0 +1,357 @@ +# 简介 +libs/ecs 这是一个 Typescript 语言版的Entity-Component-System框架架。 + +# 使用说明 +创建实体 +```Typescript +ecs.getEntity(ecs.Entity); +``` + +## 组件 +自定义组件必须继承ecs.Comp,并且需要使用ecs.register注册组件。 +```TypeScript +@ecs.register('Hello') +export class HelloComponent extends ecs.Comp { + info: string; + data: number; + + // 组件被回收前会调用这个方法。 + reset() { + this.info = ''; + this.data = 0; + } +} +``` + +## ecs.register功能 +- 能通过```entity.Hello```获得组件对象; +- 将组件的构造函数存入ecs上下文中,并且给该类组件分配一个组件id。 + +## 实体 +为了能利用Typescript的类型提示机制,在使用实体的时候需要用户自己继承ecs.Entity。 +```TypeScript +ecs.register('HelloEntity') +export class HelloEntity extends ecs.Entity { + Hello: HelloComponent; // 这里的Hello要和ecs.register中填入的参数一致 +} +``` + +- 管理子实体 +```TypeScript +// 添加子实体 +entity.addChild(ecs.Entity); + +// 移除子实体 +entity.removeChild(ecs.Entity); +``` + +- 添加组件: +```TypeScript +entity.add(HelloComponent); // 添加组件时会优先从组件缓存池中获取无用的组件对象,如果没有才会新创建一个组件对象 +``` + +- 添加组件对象:注意,外部创建的组件对象ecs系统不负责回收,需要用户自己管理该组件对象的声明周期。 +```Typescript +let compObj = new HelloComponent(); +entity.add(compObj) +``` + +- 删除组件: +```TypeScript +entity.remove(HelloComponent); // 组件对象会从实体身上移除并放入组件缓存池中 +``` + +- 删除组件但不删除组件对象:实际开发中,组件身上有很多属性,如果删除了后面再添加,属性值还原是个麻烦的问题, +remove方法可以删除组件,但是不真正从实体身上移除该组件对象,这样下次重新添加组件时还是会添加那个组件对象。 +```Typescript +entity.remove(HelloComponent, false) +``` + +- 获得组件对象 +```TypeScript +entity.Hello; // 见上方自定义实体操作 + +entity.get(HelloComponent); +``` + +- 判断是否拥有组件: +```TypeScript +entity.has(HelloComponent); + +!!entity.Hello; +``` + +- 销毁实体: +```TypeScript +entity.destroy() // 销毁实体时会先删除实体身上的所有组件,然后将实体放入实体缓存池中 +``` + +## 实体筛选 +目前提供了四种类型的筛选能力,但是这四种筛选能力可以组合从而提供更强大的筛选功能。 +- anyOf: 用来描述包含任意一个这些组件的实体; +- allOf: 用来描述同时包含了这些组件的实体; +- onlyOf: 用来描述只包含了这些组件的实体;不是特殊情况不建议使用onlyOf,因为onlyOf会监听所有组件的添加和删除事件; +- excludeOf: 表示不包含所有这里面的组件(与关系); + +使用方式: + +- 表示同时拥有多个组件 +```TypeScript +ecs.allOf(AComponent, BComponent, CComponent); +``` +- 表示拥有任意一个组件 +```Typescript +ecs.anyOf(AComponent, BComponent); +``` +- 表示拥有某些组件,并且不包含某些组件 +```Typescript +// 不包含CComponent或者DComponent +ecs.allOf(AComponent, BComponent).excludeOf(CComponent, DComponent); + +// 不同时包含CComponent和DComponent +ecs.allOf(AComponent, BComponent).excludeOf(CComponent).excludeOf(DComponent); +``` + +### 直接查询并获得实体 +```Typescript +ecs.query(ecs.allOf(Comp1, Comp2)) +``` + +## 系统 +- ecs.System: 用来组合某一功能所包含的System; +- ecs.RootSystem: System的root; +- ecs.ComblockSystem: 抽象类,组合式的System。默认情况,如果该System有实体,则每帧都会执行update方法; +- ecs.IEntityEnterSystem: 实现这个接口表示关注实体的首次进入; +- ecs.IEntityRemoveSystem: 实现这个接口表示关注实体的移除; +- ecs.ISystemFirstUpdate: 实现这个接口会在System第一次执行update前执行一次firstUpdate +- ecs.ISystemUpdate:实现这个接口会在System中每帧出发update方法 + +# 怎么使用 +1、声明组件 +```TypeScript +@ecs.register('Node') +export class NodeComponent extends ecs.Comp { + val: cc.Node = null; + + reset() { + this.val = null; + } +} + +@ecs.reigster('Move') +export class MoveComponent extends ecs.Comp { + heading: cc.Vec2 = cc.v2(); + speed: number = 0; + + reset() { + this.heading.x = 0; + this.heading.y = 0; + this.speed = 0; + } +} + +@ecs.register('Transform') +export class TransformComponent extends ecs.Comp { + position: cc.Vec2 = cc.v2(); + angle: number; + reset() { + + } +} + +export class AvatarEntity extends ecs.Entity { + Node: NodeComponent; + Move: MoveComponent; + Transform: TransformComponent; +} +``` + +2、创建系统 +```TypeScript +export class RoomSystem extends ecs.RootSystem { + constructor() { + super(); + this.add(new MoveSystem()); + this.add(new RenderSystem()); + } +} + +export class MoveSystem extends ecs.ComblockSystem implements ecs.IEntityEnterSystem, ecs.ISystemUpdate { + init() { + + } + + filter(): ecs.IMatcher { + return ecs.allOf(MoveComponent, TransformComponent); + } + + // 实体第一次进入MoveSystem会进入此方法 + entityEnter(e: AvatarEntity) { + e.Move.speed = 100; + } + + // 每帧都会更新 + update(e: AvatarEntity) { + let moveComp = e.Move; // e.get(MoveComponent); + lel position = e.Transform.position; + + position.x += moveComp.heading.x * moveComp.speed * this.dt; + position.y += moveComp.heading.y * moveComp.speed * this.dt; + + e.Transform.angle = cc.misc.lerp(e.Transform.angle, Math.atan2(moveComp.speed.y, moveComp.speed.x) * cc.macro.DEG, dt); + } +} + +export class RenderSystem extends ecs.ComblockSystem implements ecs.IEntityEnterSystem, ecs.IEntityRemoveSystem, ecs.ISystemUpdate { + filter(): ecs.IMatcher { + return ecs.allOf(NodeComponent, TransformComponent); + } + + // 实体第一次进入MoveSystem会进入此方法 + entityEnter(e: AvatarEntity) { + e.Node.val.active = true; + } + + entityRemove(e: AvatarEntity) { + + } + + update(e: AvatarEntity) { + e.Node.val.setPosition(e.Transform.position); + e.Node.val.angle = e.Transform.angle; + } +} +``` + +3、驱动ecs框架 +```TypeScript +const { ccclass, property } = cc._decorator; +@ccclass +export class GameControllerBehaviour extends Component { + rootSystem: RootSystem = null; + + onLoad() { + this.rootSystem = new RootSystem(); + this.rootSystem.init(); + } + + createAvatar(node: cc.Node) { + let entity = ecs.createEntityWithComps(NodeComponent, TransformComponent, MoveComponent); + entity.Node.val = node; + } + + update(dt: number) { + this.rootSystem.execute(dt); + } +} + +``` + +# 和Cocos Creator的组件混合使用 +## 创建基类 +```Typescript +import { Component, _decorator } from "cc"; +import { ecs } from "../../../Libs/ECS"; +const { ccclass, property } = _decorator; + +@ccclass('CCComp') +export abstract class CCComp extends Component implements ecs.IComp { + static tid: number = -1; + static compName: string; + + canRecycle: boolean; + ent: ecs.Entity; + + onLoad() { + this.ent = ecs.createEntity(); + this.ent.add(this); + } + + abstract reset(): void; +} +``` + +## 创建ecs组件并且赋予序列化的功能,这样就能在Cocos Creator的“属性检查器”上修改参数 +```Typescript +import { _decorator, toDegree, v3, Node, Vec3 } from "cc"; +import { ecs } from "../../../Libs/ECS"; +const { ccclass, property } = _decorator; + +let outV3 = v3(); +@ccclass('MovementComponent') +@ecs.register('Movement') +export class MovementComponent extends CCComp { + pos: Vec3 = v3(); + angle: number = 0; + speed: number = 0; + + @property + acceleration: number = 0; + + @property + private _maxSpeed: number = 0; + @property + set maxSpeed(val: number) { + this._maxSpeed = val; + } + get maxSpeed() { + return this._maxSpeed; + } + + @property + heading: Vec3 = v3(); + + @property + targetHeading: Vec3 = v3(); + + reset() { + + } + + update(dt: number) { + if(!Vec3.equals(this.heading, this.targetHeading, 0.01)) { + Vec3.subtract(outV3, this.targetHeading, this.heading); + outV3.multiplyScalar(0.025); + this.heading.add(outV3); + this.heading.normalize(); + this.angle = toDegree(Math.atan2(this.heading.y, this.heading.x)) - 90; + } + + this.speed = Math.min(this.speed + this.acceleration * dt, this._maxSpeed); + + this.pos.add3f(this.heading.x * this.speed * dt, this.heading.y * this.speed * dt, 0); + } + + calcAngle() { + this.angle = toDegree(Math.atan2(this.heading.y, this.heading.x)) - 90; + return this.angle; + } +} + +``` + +## 创建面向Cocos Creator的组件 +```Typescript +import { Component, _decorator } from "cc"; +const { ccclass, property } = _decorator; +@ccclass('Player') +@ecs.register('Player', false) +export class Player extends CCComp { + @property({ + type: MovementComponent + }) + movement: MovementComponent; + + onLoad() { + super.onLoad(); + + // 添加MovementComponent组件对象 + this.ent.add(this.movement); + } +} +``` + +# 调试 +添加如下代码 +```TypeScript +windows['ecs'] = ecs; \ No newline at end of file diff --git a/doc/img/module.png b/doc/img/module.png new file mode 100644 index 00000000..1153c434 Binary files /dev/null and b/doc/img/module.png differ diff --git a/doc/img/oops-plug-in1.jpg b/doc/img/oops-plug-in1.jpg new file mode 100644 index 00000000..ca2f1039 Binary files /dev/null and b/doc/img/oops-plug-in1.jpg differ diff --git a/doc/img/oops-plug-in2.jpg b/doc/img/oops-plug-in2.jpg new file mode 100644 index 00000000..b6806eea Binary files /dev/null and b/doc/img/oops-plug-in2.jpg differ diff --git a/doc/img/tools.jpg b/doc/img/tools.jpg new file mode 100644 index 00000000..3e2fb7cb Binary files /dev/null and b/doc/img/tools.jpg differ diff --git a/doc/mvvm/MvvmInfo.md b/doc/mvvm/MvvmInfo.md new file mode 100644 index 00000000..b82dd301 --- /dev/null +++ b/doc/mvvm/MvvmInfo.md @@ -0,0 +1,51 @@ +### 原创作者上有2.x的DEMO +Github 地址: https://github.com/wsssheep/cocos_creator_mvvm_tools + +### 项目结构 + +核心脚本文件存放在 assets\Script\modelView 路径,要使用必须全部引入 + +- **JsonOb.ts** - 实现基础的 观察者模式, 改变绑定的数据会自动调用回调函数。你可以随时替换成自己写的观察者。 +- **ViewModel.ts** - VM的核心模块,动态管理ViewModel,使用 cc.director.emit 通知 游戏内的节点组件改变状态。 +- **VMBase.ts** - VM监听核心组件,用于接收ViewModel 的数值变动消息。VMCustom /VMEvent 之类的衍生组件都是继承自VMBase +- **VMParent.ts** - VM父组件,适合 多实例的 prefab 弹窗使用, 它将数据绑定在继承 VMparent 的组件上,只属于此次创建的实例。 需要以特殊方式继承使用。 + +**** + +### 组件简介 + +- `VMCustom` — 挂载VMCustom,然后会自动识别当前节点的组件(也可以自行设置)。填上你的数值路径,大功告成。 +- `VMLabel` — 挂在VMLabel ,不用担心你的数值是整是零,使用模板语法 {{0:int}}自动格式化,解决文本数据显示的问题 +- `VMState` — 解决节点状态的切换问题 +- `VMProgress` — 解决进度条显示问题 +- `VMEvent `—挂载VMEventCall, 触发事件。在值变化时调用其他组件方法(结合其他组件使用事半功倍) +- `VMParent` — 定义局部范围使用 的 ViewModel数据 + +定义数据模型: `VM.add(data,"tag")` + +一直被 cc.find、getChildByName,getComponent, 所以一直想要整理个好的方案。部分参考了Vue(OS:假装参考了), 以适合 Creator 组件化的方式引入 MVVM。你甚至可以不写一行代码就完成大部分的复杂的UI逻辑,非常适合高强度的细节修改 (os:让策划自己改去)。 +这套工具核心在于提供的组件集合,而不是Mvvm本身。使用的是低耦合度的组件脚本来控制数值监听的绑定,侵入性较低。 + +**** + +### 用法说明 + +- **导入框架** - 导入 assets\Script\modelView 中的所有脚本 + +- **建立数据模型** - 任意位置新建一个数据脚本,定义自己的数据模型,使用`VM.add(data,'tag')` 添加viewModel。 可以通过VM直接管理该数据,或者自己全局管理 data 数据模型。 + +- **挂脚本** - 编辑器中直接添加组件 VMCustom ,它会自动识别绑定到需要设置值的组件和组件的属性,比如cc.Label、cc.Progress等。 你只要填写对应的watchPath, 就会自动赋值到组件的属性上。比如填写 global.play.hp ,就会在游戏运行时赋值给绑定的组件属性。 + +- **改数据** - 在游戏中任意改变 global.play.hp的值,对应的label 就会自动改变数值。 + +- **全局注册VM**: (全局自由使用路径) VM.add(data,'tag'); // + +- **局部组件使用VM**: (只在组件内使用的相对路径) + + 1.继承VMParent 组件 + + 2.在组件内设置 data 数据(data属性) + + 3.相对路径 使用 *.name 的方式设置 watchPath,VMParent 会在 onLoad 的时候自动将 * 替换成 实际的 ViewModel 标签,以便监听数据变化。 + +**** diff --git a/doc/mvvm/VMBase.md b/doc/mvvm/VMBase.md new file mode 100644 index 00000000..83fa210e --- /dev/null +++ b/doc/mvvm/VMBase.md @@ -0,0 +1,39 @@ +## VM Base + +### 介绍 + +VM基础组件,只实现了数据绑定, 需要被继承使用。你可以通过继承VM Base来实现自己的VM组件。当然一般情况下使用这个工具所提供的其他组件脚本就够用了。 + +### 脚本属性 + +- `watchPath` - 需要监听的路径,,你在VM怎么定义的结构,就在这里写上取值的路径。 + + 比如global 标签的 viewModel 要取值player.atk, 就是gloabl.player.atk。 + +- `watchPathArr` - 需要监听的多路径 数组, 和上面一样,不过需要监听的是一个路径的数组。 + +- `templateMode` - 模板模式(多路径模式),启用后才能监听 watchPathArr 数组中的所有路径 + +- `templateValueArr` - 缓存监听路径的值,当监听某个路径的值发生变动时,会自动更新该数组中缓存的值。一般不需要考虑使用。 + +- `VM` - VMManager 对象的引用,参考ViewModel 的说明 + +- `onLoad()` - 提前拆分、并且解析 监听的路径,可以捕获一些错误 + + **如果需要重写onLoad 方法**,请根据顺序调用 **super.onLoad()**,执行默认方法。直接覆盖将会导致函数的功能丢失。 + +- `onEnable()` - 激活节点时,更新对象初始值,同时开启对 watchPath 的监听。 + + **可重写**,重写时需要调用 super.onEnable() 处理父方法 + +- `onDisable()`- 关闭节点时,关闭对 watchPath 的监听。 + + **可重写**,重写时需要调用 super.onDisable() 处理父方法 + +- `onValueInit()`- 初始化值时调用函数 + + 虚方法,可以直接被重写。 + +- `onValueChanged(newValue,oldValue,pathArray)` - 当值改变时调用函数 + + 虚方法,可以直接被重写。 \ No newline at end of file diff --git a/doc/mvvm/VMCompsEdit.md b/doc/mvvm/VMCompsEdit.md new file mode 100644 index 00000000..5b48f548 --- /dev/null +++ b/doc/mvvm/VMCompsEdit.md @@ -0,0 +1,31 @@ +## VM Component Edit + +### 介绍 + +VM组件编辑,提供一些基础的功能。可以搜索当前节点下的 组件内容,便于查询出被绑定的节点,方便调试信息。 + +### 编辑器属性 + +- `Find List` - 需要查询的组件名称 + +- `Action Type` - 操作行为 + + `SEARCH_COMPONENT` - 查询组件 + + `ENABLE_COMPONENT` - 激活关闭组件 + + `REPLACE_WATCH_PATH` - 替换组件路径 + + `DELETE_COMPONENT` - 删除所有匹配组件 + +- `Trigger` - 勾选框就会立刻执行对应的命令, 不同模式下Trigger名称不同 + +- `Can Collect Nodes` - 将节点收集起来 放在 Collect Nodes 中,Action Type 为 SEARCH_COMPONENT 类型时 才能使用 + +- `Target Path` - 准备搜索的目标路径,Action Type 为 REPLACE_WATCH_PATH 时可用 + +- `Replace Path` - 准备替换的路径值,Action Type 为 REPLACE_WATCH_PATH 时可用 + +### 手动编辑器 + +在层级管理器中 搜索 t:VMBase, 也可以查询到所有VM组件的节点,然后你可以进行手动的管理操作 \ No newline at end of file diff --git a/doc/mvvm/VMCustom.md b/doc/mvvm/VMCustom.md new file mode 100644 index 00000000..442335a1 --- /dev/null +++ b/doc/mvvm/VMCustom.md @@ -0,0 +1,17 @@ +## VM Custom + +### 介绍 + +VM组件自定义, 可以设置需要监听的 组件名称和组件属性,并且挂载时还能自动识别组件名。比较泛用。适合任意的自制组件。(如果想自动识别自己写的组件名,可以修改脚本配置内容)。 + +### 编辑器属性 + +- `Controller` - 激活controller,以开启双向绑定,否则只能接收消息 +- `Watch Path` - 绑定数值监听路径 + +- `Component Name` - 绑定组件的名字 (会根据脚本配置自动识别) + +- `Component Property` - 绑定组件上需要监听的属性 (会根据脚本配置自动识别) + +- `refreshRate` - 刷新间隔频率 (只影响脏检查的频率) ,controller开启后生效 + diff --git a/doc/mvvm/VMEvent.md b/doc/mvvm/VMEvent.md new file mode 100644 index 00000000..7f726b20 --- /dev/null +++ b/doc/mvvm/VMEvent.md @@ -0,0 +1,22 @@ +## VM Event + +### 介绍 + +VM组件事件,监听watchPath 路径 数值的变动情况,调用回调函数。可以同时监听复数路径的值。适合需要自己处理数值变化行为的场合。比如获得1金币,想让数字闪烁一下,有了VMEvent ,你就不用手动去让数字闪烁了。可以在编辑器中直接设置回调,来触发别的组件的函数。 + +### 编辑器属性 + +- `Template Mode` - 多路径模板模式,开启后可以监听多路径 +- `Watch Path ` - 绑定数值监听路径 + +- `Watch PathArr` - 绑定数值监听的路径数组 (多路径模板模式开启后出现) + +- `Component Name` - 绑定组件的名字 (会根据脚本配置自动识别) + +- `Component Property` - 绑定组件上需要监听的属性 (会根据脚本配置自动识别) + +- `Trigger Once` - 事件通知只传递一次,然后自动 disabled 该组件 + +- `Filter Mode` - 根据条件过滤通知事件,比如 当值>=30 才会通知事件去调用 Change Events + +- `Change Events` - 值路径改变事件,和按钮回调事件类似 在编辑器里绑定对应要执行的节点函数 \ No newline at end of file diff --git a/doc/mvvm/VMLabel.md b/doc/mvvm/VMLabel.md new file mode 100644 index 00000000..aa0486a2 --- /dev/null +++ b/doc/mvvm/VMLabel.md @@ -0,0 +1,34 @@ + +## VM Label + +### 介绍 + +VM组件文本监听,用于处理 Label 的监听问题。监听watchPath 路径 数值的变动情况,变动Label文本内容。使用模板模式,还可以将输入的字符串格式化。可以监听多路径,来同时在一个label上显示多个数据源的信息。 + +### 编辑器属性 + +- `Template Mode` - 多路径模板模式,开启后可以监听多路径,并且可以设置文本模板 +- `Watch Path ` - 绑定数值监听路径 + +- `Watch PathArr` - 绑定数值监听的路径数组 (多路径模板模式开启后出现) + +- `Label Type` - 只读属性,自动绑定cc.Label 或者 cc.RichText,你可以在脚本修改自己定义的Label + + + +### 关于模板解析 + +使用 {{0}} {{1}} {{2}} 方式设置模板内容(设置label 的 String 默认值)。在运行时,会动态的获取多路径监听的值,按数组内index 顺序替换掉 {{index}}。你可以额外添加修饰符号来格式化信息源,比如 {{0:int}} 会将数字内容以整数显示,{{0:time}} 以时间格式显示时间戳 等。 + +以下是目前支持的格式化内容: + +- `int` - 只显示整数部分 +- `fix(n)` -显示小数位数 +- `kmbt` - 以 K M B T 单位 缩短数字长度 +- `per ` - 显示百分比 +- `sep` - 以千位分号分割数字 +- `limit(n)` - 限制文本字符长度 + +### 自定义模板格式 + +所有 文本格式处理 都放在 StringFormat 类中,你可以根据自定义需要修改其中的函数。 \ No newline at end of file diff --git a/doc/mvvm/VMModify.md b/doc/mvvm/VMModify.md new file mode 100644 index 00000000..96d63997 --- /dev/null +++ b/doc/mvvm/VMModify.md @@ -0,0 +1,29 @@ +## VM Modify + +### 介绍 + +VM组件 修改数据,修改指定 路径 watchPath 的 数据。一般配合 cc.Button 组件使用,可以点击按钮后直接修改指定路径的值。 + +### 编辑器属性 + +- `Watch Path ` - 绑定数值监听路径 +- `Value Clamp` - 是否限制数字的修改范围 +- `Value Min` - 限制最小值不低于 +- `Value Min` - 限制最大值不高于 + +### 使用方式 + +类似 Click Events 的设置调用节点上组件的方法, 去调用VMModify 组件上的对应函数,就可以修改 watch Path 监听的 路径的值。 + +- `vAddInt` - 增加整数 +- `vSubInt` - 减少整数 +- `vMulInt` - 乘以整数 +- `vDivInt` - 除以整数 +- `vAdd` - 增加浮点数 +- `vSub` - 减少浮点数 +- `vMul` - 乘以浮点数 +- `vDiv` - 除以浮点数 +- `vString` - 设置字符串 +- `vNumberInt` - 设置 整数 +- `vNumber` - 设置 浮点数 + diff --git a/doc/mvvm/VMParent.md b/doc/mvvm/VMParent.md new file mode 100644 index 00000000..d88acecf --- /dev/null +++ b/doc/mvvm/VMParent.md @@ -0,0 +1,23 @@ +## VM Parent + +### 介绍 + +如果你想要让你的组件具有 动态监听数据的能力,需要继承 VMParent 使用。监听的数据类型为组件实例自身所有,是局部的数据而非全局数据。 + +### 属性 + +`data` - 定义需要绑定的数据类型,只在该组件内有效。定义后,这些数据就会被自动绑定。 + +`onBind()` - 数据绑定完成后调用该方法 + +`onUnBind()` - 数据绑定解除之前调用该方法 + +`tag` - 绑定的标签,可以通过这个tag 获取 当前的 vm 实例 + +`VM` - VM 管理对象,可以使用该对象获取值路径 + +### 注意事项 + +- 如果你不清楚继承机制,不要随意覆盖 onLoad() 事件,请使用 onBind() 函数代替 onLoad() 函数, onUnBind() 函数代替 onDestroy() 函数。如果你熟悉,可以使用super.onLoad() 的方式 调用父方法 +- 不要过多的嵌套使用VMParent, 在绑定时可能会影响一点性能 + diff --git a/doc/mvvm/VMProgress.md b/doc/mvvm/VMProgress.md new file mode 100644 index 00000000..f8ef46fc --- /dev/null +++ b/doc/mvvm/VMProgress.md @@ -0,0 +1,14 @@ +## VM Progress + +### 介绍 + +VM组件 进度条设置,适合任意的进度条组件,比如 ProgressBar,cc.Slider 等。接受两个watchPath 的值,最后会将变动结果反映在 progress 属性上。使用方式和 VM Custom 组件一致。 + +### 编辑器属性 + +- `Controller` - 激活controller,以开启双向绑定,否则只能接收消息 +- `Watch Path Arr` - 绑定数值监听路径数组,注意你必须设置一个 长度为 2 的数组,第一个值是最小值,第二个值是最大值,这样才会正确的计算出 progres 属性 +- `Component Name` - 绑定组件的名字 (会根据脚本配置自动识别) +- `Component Property` - 绑定组件上需要监听的属性 (会根据脚本配置自动识别) +- `refreshRate` - 刷新间隔频率 (只影响脏检查的频率) ,controller开启后生效 + diff --git a/doc/mvvm/VMState.md b/doc/mvvm/VMState.md new file mode 100644 index 00000000..c9c5e1d1 --- /dev/null +++ b/doc/mvvm/VMState.md @@ -0,0 +1,42 @@ +## VM State + +### 介绍 + +VM组件 状态条件,根据watchPath 路径,判断值是不是符合条件,再设置对应节点的状态。 可以根据数据改变节点的颜色,节点的激活与关闭等等情况。 + +### 编辑器属性 + +- `Watch Path ` - 绑定数值监听路径 +- `Foreach Child Mode` - 特殊的比较值的方式,它会拿当前节点下的所有子节点的名字作为值的比较,来控制所有子节点的显示状态。 +- `Foreach Child Type` - `NODE_INDEX` 比较节点的index 值 或者 `NODE_NAME` 比较节点的名字 +- `Condition` - 判断条件,判断值的的大小是否符合条件 +- `Value Action`- 效果行为,当状态满足时候执行的条件 +- `Watch Nodes` - 需要变化状态的节点,如果不设置,默认就会改变本节点以及子节点的所有状态。 + +### 效果行为 + +- `NODE_ACTIVE` - 改变节点的激活状态(挂载到本节点无效) + +- `NODE_VISIBLE` - 改变节点的显示状态(不透明度切换) ,挂载到本节点有效,只影响显示。 + +- `NODE_OPACITY` - 改变节点的不透明度 + + `Action Opacity` - 设置 不透明的值 + +- `NODE_COLOR` - 改变节点的颜色 + + `Action Color` - 设置颜色的值 + +- `COMPONENT_CUSTOM` - 完全自定义改变组件属性 + + `Component Name` - 组件名 + + `Component Property` - 组件上的属性 + + `Default Value` - 默认值 + + `Action Value` - 满足条件改变的值 + +### 注意事项 + +NODE_ACTIVE 条件 不会改变自身节点的 激活状态 \ No newline at end of file diff --git a/doc/mvvm/ViewModelScript.md b/doc/mvvm/ViewModelScript.md new file mode 100644 index 00000000..a6261dca --- /dev/null +++ b/doc/mvvm/ViewModelScript.md @@ -0,0 +1,107 @@ +## View Model Script + +### 介绍 + +View Model 的脚本用法 + +### 方法 + +VM是 VMManager 的实例, 用于管理所有的 ViewModel 实例。ViewModel实例 主要用于实现数据的双向绑定,内部使用了 cc.director.emit 方法 来发送数据变动的消息,在使用时你可以不用关注于这些细节。 + +我们可以通过 import VM(VMManager) 对象 来管理 所有的 ViewModel ,**不建议**直接去使用 ViewModel 实例。 + +```typescript +//TS 使用 import 引入 +import { VM } from './ViewModel'; + +//JS 可以使用 require 的方式引入,其他用法没有区别 +const { VM } = require('./ViewModel'); +``` + +- `add` - 创建并且添加一个 ViewModel 对象 + + ``` typescript + VM.add(data,tag); + //data - 你想要进行 绑定 的数据对象 + //tag - 该数据对象的索引标签,用于之后获取该 ViewModel 对象 + ``` + +- `get` - 获取 + + ```typescript + let vm = VM.get(tag);//获取的结果是一个 ViewModel 对象 + let data = vm.$data; //获取 vm 绑定的 data 对象 + vm.active = false; // 关闭 vm 的数据通知功能 + ``` + +- `remove` - 移除 + + ```typescript + VM.remove(tag);//移除一个指定 tag 的 ViewModel 对象 + ``` +- `setValue` - 设置一个值(以tag开头的全局路径) + + ```typescript + VM.setValue('global.player.name','wss'); + //注意 global 是 ViewModel 的标签,player.name 是 ViewModel 内部的取值路径 + //使用 VM 全局管理,必须按这种全局路径的方式设置值 + ``` +- `addValue` - 累加一个值(以tag开头的全局路径) + + ```typescript + VM.addValue('global.player.hp',10); + ``` + +- `getValue` - 获取一个值(以tag开头的全局路径) + + ```typescript + VM.getValue('global.player.name',default);//default 是 默认值 + ``` + +- `setObjValue` - 以路径的形式 设置 一个 对象的值 +- `getObjValue` - 以路径的形式 获取 一个 对象的值 +- `bindPath` - 绑定需要监听的路径 +- `unbindPath` - 取消绑定需要监听的路径 +- `active` - 激活 数值变动的事件通知 +- `inactive` - 关闭 数值变动的事件通知 + +### 例子 + +```typescript +import { VM } from './ViewModel'; + +//构建数据对象 +let data = { + name:'user', + gold:12200, + info:{ + id:0 + } +} +//创建 VM 对象,并且添加到 VMManager 来进行管理, 标记为 'user' 标签 +VM.add(data,'user'); + + //通过 'user' 标签获取一个 ViewModel 的实例 +let vm = VM.get('user'); +vm.$data; // vm.$data === data; + + //设置新的属性值 +vm.setValue('name','new Name'); + +//获取属性 +vm.getValue('gold'); + + //通过相对路径获取属性 +vm.getValue('info.id'); + +//一旦修改值,将会通知 cc.director, 使用emit 发送消息 +data.name = 'my_name'; + +//关闭激活状态后,就不会通知 cc.director 传递信息了 +vm.active = false; + +//移除ViewModel,并且释放 data 的引用 +VM.remove('user'); +data = null; +``` + diff --git a/doc/using.md b/doc/using.md new file mode 100644 index 00000000..1abba27f --- /dev/null +++ b/doc/using.md @@ -0,0 +1,20 @@ +### 框架使用说明 +Oops Framework从3.5.2版本开始以Cocos Creator插件方式提供使用,这样设计的目的是为了方便作者升级框架功能与修复问题时,方便的去更新框架。 + +### 自动更新最新分支框架版本 +打开Cocos Creator项目目录,执行下列命令 + +###### windows +``` +md extensions +cd extensions +git clone -b master https://gitee.com/dgflash/oops-plugin-framework.git +git pull +``` +###### mac +``` +mkdir -p extensions +cd extensions +git clone -b master https://gitee.com/dgflash/oops-plugin-framework.git +git pull +``` \ No newline at end of file diff --git a/settings/v2/packages/project.json b/settings/v2/packages/project.json index 3a58fe59..0c6977b9 100644 --- a/settings/v2/packages/project.json +++ b/settings/v2/packages/project.json @@ -43,11 +43,11 @@ } ], "collisionMatrix": { - "0": 1, - "1": 20, - "2": 10, - "3": 4, - "4": 2 + "0": 31, + "1": 23, + "2": 11, + "3": 5, + "4": 3 } } }