├── .gitignore ├── .vscode └── settings.json ├── README.md ├── assets ├── Prefab.meta ├── Scene.meta ├── Scene │ ├── PeekCard.fire │ └── PeekCard.fire.meta ├── Script.meta ├── Script │ ├── Base.meta │ ├── Base │ │ ├── BaseComponent.ts │ │ └── BaseComponent.ts.meta │ ├── Helloworld.ts │ ├── Helloworld.ts.meta │ ├── PeekCard.ts │ └── PeekCard.ts.meta ├── Texture.meta ├── Texture │ ├── singleColor.png │ └── singleColor.png.meta ├── resources.meta └── resources │ ├── Cards.meta │ ├── Cards │ ├── Cards000.png │ ├── Cards000.png.meta │ ├── Cards051.png │ ├── Cards051.png.meta │ ├── Cards052.png │ └── Cards052.png.meta │ ├── HelloWorld.png │ ├── HelloWorld.png.meta │ ├── shadow.png │ └── shadow.png.meta ├── creator.d.ts ├── jsconfig.json ├── project.json ├── settings ├── builder.json ├── builder.panel.json ├── project.json └── services.json ├── template-banner.png ├── template.json └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | library/ 2 | temp/ 3 | local/ 4 | packages/ 5 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.exclude": { 3 | "**/*.meta": true, 4 | "library/**": true, 5 | "local/**": true, 6 | "temp/**": true 7 | }, 8 | "editor.formatOnSave": true 9 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cccPeekCard 2 | cocosCreator mask遮罩实现360°搓牌(咪牌) 3 | 4 | 核心思路是: 遮罩与遮罩下子节点反向移动和旋转实现牌背禁止不动和牌面随触摸移动 5 | 6 | 如果想移植到cocos2dx 或者cocos2dx-js下需要更换向量API 以及实现坐标系的转换 左下角坐标系 <==> 锚点坐标系 7 | 8 | - 使用方法 9 | 10 | 1.拖动 PeekCard 脚本到场景中 执行组件的 reset 操作即可自动创建好所有节点 11 | // 设置搓牌区域大小 默认是Canvas设计分辨率大小 12 | this.peekCard.setTouchAreaSize(cc.size(1280, 720)) 13 | // 设置扑克牌大小 (原始纹理不拉伸情况下的大小) 14 | this.peekCard.setCardSize(cc.size(90 * 3, 130 * 3)) 15 | await this.peekCard.setCardBack("Cards/Cards051"); 16 | await this.peekCard.setCardFace("Cards/Cards000"); 17 | await this.peekCard.setShadow("shadow"); 18 | // 没有特殊需求时不需要设置手指纹理 如果有需要手指的大小和纹理需要在代码中再次调整 19 | await this.peekCard.setFinger(null); 20 | this.peekCard.directionLength = 20; 21 | this.peekCard.moveSpeed = 0.6; 22 | this.peekCard.angleFixed = 5; 23 | 24 | this.peekCard.init(); //搓牌前必须调用 25 | 26 | 2. 动态创建搓牌节点 27 | var peekCard = new cc.Node("PeekCard").addComponent(PeekCard); 28 | this.node.addChild(peekCard.node); 29 | // 动态创建时一定要第一时间设置好原始方向 30 | peekCard._originalDir = peekCard._dirType = PeekCard.DirType.vertical; 31 | // 设置搓牌区域大小 默认是Canvas设计分辨率大小 32 | this.peekCard.setTouchAreaSize(cc.size(1280, 720)) 33 | // 优先设置牌大小 34 | peekCard.setCardSize(cc.size(90 * 3 - 20, 130 * 3 - 30)); 35 | 36 | // 动态设置搓牌方向(允许在其他位置调用) 37 | peekCard.dirType = dirType; 38 | 39 | await peekCard.setCardBack("Cards/Cards051"); 40 | await peekCard.setCardFace("Cards/Cards000"); 41 | await peekCard.setShadow("shadow"); 42 | // 设置手指纹理和大小 43 | await peekCard.setFinger("HelloWorld", cc.size(40, 80)); 44 | 45 | peekCard.directionLength = 20; 46 | peekCard.moveSpeed = 0.6; 47 | peekCard.angleFixed = 5; 48 | 49 | peekCard.init(); //搓牌前必须调用 50 | 3. 做成预制动态加载 51 | ..... 52 | 53 | - 注意事项 54 | 55 | 自行根据项目实际需求调整参数 56 | 57 | 由于搓牌可能存在运行时动态设置搓牌方向的操作, 此操作会引起 SpriteFrame 被修改,如果可视范围内存在正在被使用的 SpriteFrame 则会引起形变。 58 | 推荐 59 | 1.搓牌的扑克牌资源独立 60 | 2.动态设置搓牌方向时确保当前屏幕可视范围内没有其他搓牌资源 61 | 62 | } 63 | -------------------------------------------------------------------------------- /assets/Prefab.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.1", 3 | "uuid": "e4a8fd1b-2d4d-41e2-b4de-a341e670cb73", 4 | "isSubpackage": false, 5 | "subpackageName": "", 6 | "subMetas": {} 7 | } -------------------------------------------------------------------------------- /assets/Scene.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.1", 3 | "uuid": "29f52784-2fca-467b-92e7-8fd9ef8c57b7", 4 | "isGroup": false, 5 | "subMetas": {} 6 | } -------------------------------------------------------------------------------- /assets/Scene/PeekCard.fire: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "__type__": "cc.SceneAsset", 4 | "_name": "", 5 | "_objFlags": 0, 6 | "_native": "", 7 | "scene": { 8 | "__id__": 1 9 | } 10 | }, 11 | { 12 | "__type__": "cc.Scene", 13 | "_objFlags": 0, 14 | "_parent": null, 15 | "_children": [ 16 | { 17 | "__id__": 2 18 | } 19 | ], 20 | "_active": false, 21 | "_level": 0, 22 | "_components": [], 23 | "_prefab": null, 24 | "_opacity": 255, 25 | "_color": { 26 | "__type__": "cc.Color", 27 | "r": 255, 28 | "g": 255, 29 | "b": 255, 30 | "a": 255 31 | }, 32 | "_contentSize": { 33 | "__type__": "cc.Size", 34 | "width": 0, 35 | "height": 0 36 | }, 37 | "_anchorPoint": { 38 | "__type__": "cc.Vec2", 39 | "x": 0, 40 | "y": 0 41 | }, 42 | "_scale": { 43 | "__type__": "cc.Vec3", 44 | "x": 0.5249433827860024, 45 | "y": 0.5249433827860024, 46 | "z": 1 47 | }, 48 | "_quat": { 49 | "__type__": "cc.Quat", 50 | "x": 0, 51 | "y": 0, 52 | "z": 0, 53 | "w": 1 54 | }, 55 | "groupIndex": 0, 56 | "autoReleaseAssets": false, 57 | "_id": "2d2f792f-a40c-49bb-a189-ed176a246e49" 58 | }, 59 | { 60 | "__type__": "cc.Node", 61 | "_name": "Canvas", 62 | "_objFlags": 0, 63 | "_parent": { 64 | "__id__": 1 65 | }, 66 | "_children": [ 67 | { 68 | "__id__": 3 69 | }, 70 | { 71 | "__id__": 5 72 | }, 73 | { 74 | "__id__": 8 75 | }, 76 | { 77 | "__id__": 10 78 | }, 79 | { 80 | "__id__": 12 81 | }, 82 | { 83 | "__id__": 14 84 | } 85 | ], 86 | "_active": true, 87 | "_level": 1, 88 | "_components": [ 89 | { 90 | "__id__": 30 91 | }, 92 | { 93 | "__id__": 31 94 | } 95 | ], 96 | "_prefab": null, 97 | "_opacity": 255, 98 | "_color": { 99 | "__type__": "cc.Color", 100 | "r": 252, 101 | "g": 252, 102 | "b": 252, 103 | "a": 255 104 | }, 105 | "_contentSize": { 106 | "__type__": "cc.Size", 107 | "width": 1280, 108 | "height": 720 109 | }, 110 | "_anchorPoint": { 111 | "__type__": "cc.Vec2", 112 | "x": 0.5, 113 | "y": 0.5 114 | }, 115 | "_position": { 116 | "__type__": "cc.Vec3", 117 | "x": 640, 118 | "y": 360, 119 | "z": 0 120 | }, 121 | "_scale": { 122 | "__type__": "cc.Vec3", 123 | "x": 1, 124 | "y": 1, 125 | "z": 1 126 | }, 127 | "_rotationX": 0, 128 | "_rotationY": 0, 129 | "_quat": { 130 | "__type__": "cc.Quat", 131 | "x": 0, 132 | "y": 0, 133 | "z": 0, 134 | "w": 1 135 | }, 136 | "_skewX": 0, 137 | "_skewY": 0, 138 | "groupIndex": 0, 139 | "_id": "a286bbGknJLZpRpxROV6M94" 140 | }, 141 | { 142 | "__type__": "cc.Node", 143 | "_name": "Main Camera", 144 | "_objFlags": 0, 145 | "_parent": { 146 | "__id__": 2 147 | }, 148 | "_children": [], 149 | "_active": true, 150 | "_level": 1, 151 | "_components": [ 152 | { 153 | "__id__": 4 154 | } 155 | ], 156 | "_prefab": null, 157 | "_opacity": 255, 158 | "_color": { 159 | "__type__": "cc.Color", 160 | "r": 255, 161 | "g": 255, 162 | "b": 255, 163 | "a": 255 164 | }, 165 | "_contentSize": { 166 | "__type__": "cc.Size", 167 | "width": 0, 168 | "height": 0 169 | }, 170 | "_anchorPoint": { 171 | "__type__": "cc.Vec2", 172 | "x": 0.5, 173 | "y": 0.5 174 | }, 175 | "_position": { 176 | "__type__": "cc.Vec3", 177 | "x": 0, 178 | "y": 0, 179 | "z": 0 180 | }, 181 | "_scale": { 182 | "__type__": "cc.Vec3", 183 | "x": 1, 184 | "y": 1, 185 | "z": 1 186 | }, 187 | "_rotationX": 0, 188 | "_rotationY": 0, 189 | "_quat": { 190 | "__type__": "cc.Quat", 191 | "x": 0, 192 | "y": 0, 193 | "z": 0, 194 | "w": 1 195 | }, 196 | "_skewX": 0, 197 | "_skewY": 0, 198 | "groupIndex": 0, 199 | "_id": "1dBeaVjl5OCp/B3sFiBUHm" 200 | }, 201 | { 202 | "__type__": "cc.Camera", 203 | "_name": "", 204 | "_objFlags": 0, 205 | "node": { 206 | "__id__": 3 207 | }, 208 | "_enabled": true, 209 | "_cullingMask": 4294967295, 210 | "_clearFlags": 7, 211 | "_backgroundColor": { 212 | "__type__": "cc.Color", 213 | "r": 0, 214 | "g": 0, 215 | "b": 0, 216 | "a": 255 217 | }, 218 | "_depth": -1, 219 | "_zoomRatio": 1, 220 | "_targetTexture": null, 221 | "_id": "a4+YQJ7CVJkZtceNmleZh6" 222 | }, 223 | { 224 | "__type__": "cc.Node", 225 | "_name": "background", 226 | "_objFlags": 0, 227 | "_parent": { 228 | "__id__": 2 229 | }, 230 | "_children": [], 231 | "_active": true, 232 | "_level": 0, 233 | "_components": [ 234 | { 235 | "__id__": 6 236 | }, 237 | { 238 | "__id__": 7 239 | } 240 | ], 241 | "_prefab": null, 242 | "_opacity": 255, 243 | "_color": { 244 | "__type__": "cc.Color", 245 | "r": 171, 246 | "g": 173, 247 | "b": 175, 248 | "a": 255 249 | }, 250 | "_contentSize": { 251 | "__type__": "cc.Size", 252 | "width": 1280, 253 | "height": 720 254 | }, 255 | "_anchorPoint": { 256 | "__type__": "cc.Vec2", 257 | "x": 0.5, 258 | "y": 0.5 259 | }, 260 | "_position": { 261 | "__type__": "cc.Vec3", 262 | "x": 0, 263 | "y": 0, 264 | "z": 0 265 | }, 266 | "_scale": { 267 | "__type__": "cc.Vec3", 268 | "x": 1, 269 | "y": 1, 270 | "z": 1 271 | }, 272 | "_rotationX": 0, 273 | "_rotationY": 0, 274 | "_quat": { 275 | "__type__": "cc.Quat", 276 | "x": 0, 277 | "y": 0, 278 | "z": 0, 279 | "w": 1 280 | }, 281 | "_skewX": 0, 282 | "_skewY": 0, 283 | "groupIndex": 0, 284 | "_id": "e2e0crkOLxGrpMxpbC4iQg1" 285 | }, 286 | { 287 | "__type__": "cc.Widget", 288 | "_name": "", 289 | "_objFlags": 0, 290 | "node": { 291 | "__id__": 5 292 | }, 293 | "_enabled": true, 294 | "alignMode": 0, 295 | "_target": null, 296 | "_alignFlags": 45, 297 | "_left": 0, 298 | "_right": 0, 299 | "_top": 0, 300 | "_bottom": 0, 301 | "_verticalCenter": 0, 302 | "_horizontalCenter": 0, 303 | "_isAbsLeft": true, 304 | "_isAbsRight": true, 305 | "_isAbsTop": true, 306 | "_isAbsBottom": true, 307 | "_isAbsHorizontalCenter": true, 308 | "_isAbsVerticalCenter": true, 309 | "_originalWidth": 200, 310 | "_originalHeight": 150, 311 | "_id": "6fK/13V5JBJ4DeloM4Cb9k" 312 | }, 313 | { 314 | "__type__": "cc.Sprite", 315 | "_name": "", 316 | "_objFlags": 0, 317 | "node": { 318 | "__id__": 5 319 | }, 320 | "_enabled": true, 321 | "_spriteFrame": { 322 | "__uuid__": "410fb916-8721-4663-bab8-34397391ace7" 323 | }, 324 | "_type": 1, 325 | "_sizeMode": 0, 326 | "_fillType": 0, 327 | "_fillCenter": { 328 | "__type__": "cc.Vec2", 329 | "x": 0, 330 | "y": 0 331 | }, 332 | "_fillStart": 0, 333 | "_fillRange": 0, 334 | "_isTrimmedMode": true, 335 | "_state": 0, 336 | "_atlas": null, 337 | "_srcBlendFactor": 770, 338 | "_dstBlendFactor": 771, 339 | "_id": "06xCVjNINMTa6SMIJQbS2g" 340 | }, 341 | { 342 | "__type__": "cc.Node", 343 | "_name": "cocos", 344 | "_objFlags": 0, 345 | "_parent": { 346 | "__id__": 2 347 | }, 348 | "_children": [], 349 | "_active": true, 350 | "_level": 0, 351 | "_components": [ 352 | { 353 | "__id__": 9 354 | } 355 | ], 356 | "_prefab": null, 357 | "_opacity": 255, 358 | "_color": { 359 | "__type__": "cc.Color", 360 | "r": 255, 361 | "g": 255, 362 | "b": 255, 363 | "a": 255 364 | }, 365 | "_contentSize": { 366 | "__type__": "cc.Size", 367 | "width": 195, 368 | "height": 270 369 | }, 370 | "_anchorPoint": { 371 | "__type__": "cc.Vec2", 372 | "x": 0.5, 373 | "y": 0.5 374 | }, 375 | "_position": { 376 | "__type__": "cc.Vec3", 377 | "x": 0, 378 | "y": 0, 379 | "z": 0 380 | }, 381 | "_scale": { 382 | "__type__": "cc.Vec3", 383 | "x": 1, 384 | "y": 1, 385 | "z": 1 386 | }, 387 | "_rotationX": 0, 388 | "_rotationY": 0, 389 | "_quat": { 390 | "__type__": "cc.Quat", 391 | "x": 0, 392 | "y": 0, 393 | "z": 0, 394 | "w": 1 395 | }, 396 | "_skewX": 0, 397 | "_skewY": 0, 398 | "groupIndex": 0, 399 | "_id": "c4f30YOS65G64U2TwufdJ+2" 400 | }, 401 | { 402 | "__type__": "cc.Sprite", 403 | "_name": "", 404 | "_objFlags": 0, 405 | "node": { 406 | "__id__": 8 407 | }, 408 | "_enabled": true, 409 | "_spriteFrame": { 410 | "__uuid__": "31bc895a-c003-4566-a9f3-2e54ae1c17dc" 411 | }, 412 | "_type": 0, 413 | "_sizeMode": 1, 414 | "_fillType": 0, 415 | "_fillCenter": { 416 | "__type__": "cc.Vec2", 417 | "x": 0, 418 | "y": 0 419 | }, 420 | "_fillStart": 0, 421 | "_fillRange": 0, 422 | "_isTrimmedMode": true, 423 | "_state": 0, 424 | "_atlas": null, 425 | "_srcBlendFactor": 770, 426 | "_dstBlendFactor": 771, 427 | "_id": "e7hkSffyhKhoKr6X+OamdW" 428 | }, 429 | { 430 | "__type__": "cc.Node", 431 | "_name": "label", 432 | "_objFlags": 0, 433 | "_parent": { 434 | "__id__": 2 435 | }, 436 | "_children": [], 437 | "_active": true, 438 | "_level": 0, 439 | "_components": [ 440 | { 441 | "__id__": 11 442 | } 443 | ], 444 | "_prefab": null, 445 | "_opacity": 255, 446 | "_color": { 447 | "__type__": "cc.Color", 448 | "r": 255, 449 | "g": 255, 450 | "b": 255, 451 | "a": 255 452 | }, 453 | "_contentSize": { 454 | "__type__": "cc.Size", 455 | "width": 0, 456 | "height": 60 457 | }, 458 | "_anchorPoint": { 459 | "__type__": "cc.Vec2", 460 | "x": 0.5, 461 | "y": 0.5 462 | }, 463 | "_position": { 464 | "__type__": "cc.Vec3", 465 | "x": 0, 466 | "y": -180, 467 | "z": 0 468 | }, 469 | "_scale": { 470 | "__type__": "cc.Vec3", 471 | "x": 1, 472 | "y": 1, 473 | "z": 1 474 | }, 475 | "_rotationX": 0, 476 | "_rotationY": 0, 477 | "_quat": { 478 | "__type__": "cc.Quat", 479 | "x": 0, 480 | "y": 0, 481 | "z": 0, 482 | "w": 1 483 | }, 484 | "_skewX": 0, 485 | "_skewY": 0, 486 | "groupIndex": 0, 487 | "_id": "31f1bH7V69Ajr1iXhluMpTB" 488 | }, 489 | { 490 | "__type__": "cc.Label", 491 | "_name": "", 492 | "_objFlags": 0, 493 | "node": { 494 | "__id__": 10 495 | }, 496 | "_enabled": true, 497 | "_useOriginalSize": false, 498 | "_string": "", 499 | "_N$string": "", 500 | "_fontSize": 60, 501 | "_lineHeight": 60, 502 | "_enableWrapText": true, 503 | "_N$file": null, 504 | "_isSystemFontUsed": true, 505 | "_spacingX": 0, 506 | "_batchAsBitmap": false, 507 | "_N$horizontalAlign": 1, 508 | "_N$verticalAlign": 1, 509 | "_N$fontFamily": "Arial", 510 | "_N$overflow": 0, 511 | "_N$cacheMode": 0, 512 | "_id": "e8pqb0XStHh7TgK8OioqEc" 513 | }, 514 | { 515 | "__type__": "cc.Node", 516 | "_name": "Cards000", 517 | "_objFlags": 0, 518 | "_parent": { 519 | "__id__": 2 520 | }, 521 | "_children": [], 522 | "_active": true, 523 | "_level": 2, 524 | "_components": [ 525 | { 526 | "__id__": 13 527 | } 528 | ], 529 | "_prefab": null, 530 | "_opacity": 255, 531 | "_color": { 532 | "__type__": "cc.Color", 533 | "r": 255, 534 | "g": 255, 535 | "b": 255, 536 | "a": 255 537 | }, 538 | "_contentSize": { 539 | "__type__": "cc.Size", 540 | "width": 90, 541 | "height": 130 542 | }, 543 | "_anchorPoint": { 544 | "__type__": "cc.Vec2", 545 | "x": 0.5, 546 | "y": 0.5 547 | }, 548 | "_position": { 549 | "__type__": "cc.Vec3", 550 | "x": -277, 551 | "y": 180, 552 | "z": 0 553 | }, 554 | "_scale": { 555 | "__type__": "cc.Vec3", 556 | "x": 1, 557 | "y": 1, 558 | "z": 1 559 | }, 560 | "_rotationX": 0, 561 | "_rotationY": 0, 562 | "_quat": { 563 | "__type__": "cc.Quat", 564 | "x": 0, 565 | "y": 0, 566 | "z": 0, 567 | "w": 1 568 | }, 569 | "_skewX": 0, 570 | "_skewY": 0, 571 | "groupIndex": 0, 572 | "_id": "bbW+poCDJEOowpYn/+GEWB" 573 | }, 574 | { 575 | "__type__": "cc.Sprite", 576 | "_name": "", 577 | "_objFlags": 0, 578 | "node": { 579 | "__id__": 12 580 | }, 581 | "_enabled": true, 582 | "_spriteFrame": { 583 | "__uuid__": "6b48946f-5c61-4560-9c84-3b1dada4dee4" 584 | }, 585 | "_type": 0, 586 | "_sizeMode": 1, 587 | "_fillType": 0, 588 | "_fillCenter": { 589 | "__type__": "cc.Vec2", 590 | "x": 0, 591 | "y": 0 592 | }, 593 | "_fillStart": 0, 594 | "_fillRange": 0, 595 | "_isTrimmedMode": true, 596 | "_state": 0, 597 | "_atlas": null, 598 | "_srcBlendFactor": 770, 599 | "_dstBlendFactor": 771, 600 | "_id": "f791tNrNxDh5cVO2wfd9qp" 601 | }, 602 | { 603 | "__type__": "cc.Node", 604 | "_name": "PeekCard", 605 | "_objFlags": 0, 606 | "_parent": { 607 | "__id__": 2 608 | }, 609 | "_children": [ 610 | { 611 | "__id__": 15 612 | }, 613 | { 614 | "__id__": 25 615 | }, 616 | { 617 | "__id__": 27 618 | } 619 | ], 620 | "_active": false, 621 | "_level": 2, 622 | "_components": [ 623 | { 624 | "__id__": 29 625 | } 626 | ], 627 | "_prefab": null, 628 | "_opacity": 255, 629 | "_color": { 630 | "__type__": "cc.Color", 631 | "r": 255, 632 | "g": 255, 633 | "b": 255, 634 | "a": 255 635 | }, 636 | "_contentSize": { 637 | "__type__": "cc.Size", 638 | "width": 1280, 639 | "height": 720 640 | }, 641 | "_anchorPoint": { 642 | "__type__": "cc.Vec2", 643 | "x": 0.5, 644 | "y": 0.5 645 | }, 646 | "_position": { 647 | "__type__": "cc.Vec3", 648 | "x": 0, 649 | "y": 0, 650 | "z": 0 651 | }, 652 | "_scale": { 653 | "__type__": "cc.Vec3", 654 | "x": 1, 655 | "y": 1, 656 | "z": 1 657 | }, 658 | "_rotationX": 0, 659 | "_rotationY": 0, 660 | "_quat": { 661 | "__type__": "cc.Quat", 662 | "x": 0, 663 | "y": 0, 664 | "z": 0, 665 | "w": 1 666 | }, 667 | "_skewX": 0, 668 | "_skewY": 0, 669 | "groupIndex": 0, 670 | "_id": "224Gjm+jlC4Y1Ze86swrjh" 671 | }, 672 | { 673 | "__type__": "cc.Node", 674 | "_name": "mask", 675 | "_objFlags": 0, 676 | "_parent": { 677 | "__id__": 14 678 | }, 679 | "_children": [ 680 | { 681 | "__id__": 16 682 | }, 683 | { 684 | "__id__": 18 685 | } 686 | ], 687 | "_active": true, 688 | "_level": 3, 689 | "_components": [ 690 | { 691 | "__id__": 24 692 | } 693 | ], 694 | "_prefab": null, 695 | "_opacity": 255, 696 | "_color": { 697 | "__type__": "cc.Color", 698 | "r": 255, 699 | "g": 255, 700 | "b": 255, 701 | "a": 255 702 | }, 703 | "_contentSize": { 704 | "__type__": "cc.Size", 705 | "width": 270, 706 | "height": 390 707 | }, 708 | "_anchorPoint": { 709 | "__type__": "cc.Vec2", 710 | "x": 0.5, 711 | "y": 0.5 712 | }, 713 | "_position": { 714 | "__type__": "cc.Vec3", 715 | "x": 0, 716 | "y": 0, 717 | "z": 0 718 | }, 719 | "_scale": { 720 | "__type__": "cc.Vec3", 721 | "x": 1, 722 | "y": 1, 723 | "z": 1 724 | }, 725 | "_rotationX": 0, 726 | "_rotationY": 0, 727 | "_quat": { 728 | "__type__": "cc.Quat", 729 | "x": 0, 730 | "y": 0, 731 | "z": 0, 732 | "w": 1 733 | }, 734 | "_skewX": 0, 735 | "_skewY": 0, 736 | "groupIndex": 0, 737 | "_id": "f8gRp33fBIJ5VLQbfjjB3J" 738 | }, 739 | { 740 | "__type__": "cc.Node", 741 | "_name": "cardBack", 742 | "_objFlags": 0, 743 | "_parent": { 744 | "__id__": 15 745 | }, 746 | "_children": [], 747 | "_active": true, 748 | "_level": 4, 749 | "_components": [ 750 | { 751 | "__id__": 17 752 | } 753 | ], 754 | "_prefab": null, 755 | "_opacity": 255, 756 | "_color": { 757 | "__type__": "cc.Color", 758 | "r": 255, 759 | "g": 255, 760 | "b": 255, 761 | "a": 255 762 | }, 763 | "_contentSize": { 764 | "__type__": "cc.Size", 765 | "width": 270, 766 | "height": 390 767 | }, 768 | "_anchorPoint": { 769 | "__type__": "cc.Vec2", 770 | "x": 0.5, 771 | "y": 0.5 772 | }, 773 | "_position": { 774 | "__type__": "cc.Vec3", 775 | "x": 0, 776 | "y": 0, 777 | "z": 0 778 | }, 779 | "_scale": { 780 | "__type__": "cc.Vec3", 781 | "x": 1, 782 | "y": 1, 783 | "z": 1 784 | }, 785 | "_rotationX": 0, 786 | "_rotationY": 0, 787 | "_quat": { 788 | "__type__": "cc.Quat", 789 | "x": 0, 790 | "y": 0, 791 | "z": 0, 792 | "w": 1 793 | }, 794 | "_skewX": 0, 795 | "_skewY": 0, 796 | "groupIndex": 0, 797 | "_id": "81+K/pUndK+Y6AfonRG2gw" 798 | }, 799 | { 800 | "__type__": "cc.Sprite", 801 | "_name": "", 802 | "_objFlags": 0, 803 | "node": { 804 | "__id__": 16 805 | }, 806 | "_enabled": true, 807 | "_spriteFrame": { 808 | "__uuid__": "71144251-e977-41c7-a175-a2b77f9050f2" 809 | }, 810 | "_type": 0, 811 | "_sizeMode": 0, 812 | "_fillType": 0, 813 | "_fillCenter": { 814 | "__type__": "cc.Vec2", 815 | "x": 0, 816 | "y": 0 817 | }, 818 | "_fillStart": 0, 819 | "_fillRange": 0, 820 | "_isTrimmedMode": true, 821 | "_state": 0, 822 | "_atlas": null, 823 | "_srcBlendFactor": 770, 824 | "_dstBlendFactor": 771, 825 | "_id": "7f1SaYX4lGvIQY9eM6ty5o" 826 | }, 827 | { 828 | "__type__": "cc.Node", 829 | "_name": "cardFace", 830 | "_objFlags": 0, 831 | "_parent": { 832 | "__id__": 15 833 | }, 834 | "_children": [ 835 | { 836 | "__id__": 19 837 | } 838 | ], 839 | "_active": true, 840 | "_level": 4, 841 | "_components": [ 842 | { 843 | "__id__": 23 844 | } 845 | ], 846 | "_prefab": null, 847 | "_opacity": 255, 848 | "_color": { 849 | "__type__": "cc.Color", 850 | "r": 255, 851 | "g": 255, 852 | "b": 255, 853 | "a": 255 854 | }, 855 | "_contentSize": { 856 | "__type__": "cc.Size", 857 | "width": 270, 858 | "height": 390 859 | }, 860 | "_anchorPoint": { 861 | "__type__": "cc.Vec2", 862 | "x": 0.5, 863 | "y": 0.5 864 | }, 865 | "_position": { 866 | "__type__": "cc.Vec3", 867 | "x": -270, 868 | "y": 0, 869 | "z": 0 870 | }, 871 | "_scale": { 872 | "__type__": "cc.Vec3", 873 | "x": 1, 874 | "y": 1, 875 | "z": 1 876 | }, 877 | "_rotationX": 0, 878 | "_rotationY": 0, 879 | "_quat": { 880 | "__type__": "cc.Quat", 881 | "x": 0, 882 | "y": 0, 883 | "z": 0, 884 | "w": 1 885 | }, 886 | "_skewX": 0, 887 | "_skewY": 0, 888 | "groupIndex": 0, 889 | "_id": "d3EPhv+dFGIbh1u/d25WtL" 890 | }, 891 | { 892 | "__type__": "cc.Node", 893 | "_name": "shadowMask", 894 | "_objFlags": 0, 895 | "_parent": { 896 | "__id__": 18 897 | }, 898 | "_children": [ 899 | { 900 | "__id__": 20 901 | } 902 | ], 903 | "_active": true, 904 | "_level": 5, 905 | "_components": [ 906 | { 907 | "__id__": 22 908 | } 909 | ], 910 | "_prefab": null, 911 | "_opacity": 255, 912 | "_color": { 913 | "__type__": "cc.Color", 914 | "r": 255, 915 | "g": 255, 916 | "b": 255, 917 | "a": 255 918 | }, 919 | "_contentSize": { 920 | "__type__": "cc.Size", 921 | "width": 270, 922 | "height": 390 923 | }, 924 | "_anchorPoint": { 925 | "__type__": "cc.Vec2", 926 | "x": 0.5, 927 | "y": 0.5 928 | }, 929 | "_position": { 930 | "__type__": "cc.Vec3", 931 | "x": 0, 932 | "y": 0, 933 | "z": 0 934 | }, 935 | "_scale": { 936 | "__type__": "cc.Vec3", 937 | "x": 1, 938 | "y": 1, 939 | "z": 1 940 | }, 941 | "_rotationX": 0, 942 | "_rotationY": 0, 943 | "_quat": { 944 | "__type__": "cc.Quat", 945 | "x": 0, 946 | "y": 0, 947 | "z": 0, 948 | "w": 1 949 | }, 950 | "_skewX": 0, 951 | "_skewY": 0, 952 | "groupIndex": 0, 953 | "_id": "f1jS+7gzdBNYyWWv2J0tdX" 954 | }, 955 | { 956 | "__type__": "cc.Node", 957 | "_name": "shadow", 958 | "_objFlags": 0, 959 | "_parent": { 960 | "__id__": 19 961 | }, 962 | "_children": [], 963 | "_active": true, 964 | "_level": 6, 965 | "_components": [ 966 | { 967 | "__id__": 21 968 | } 969 | ], 970 | "_prefab": null, 971 | "_opacity": 255, 972 | "_color": { 973 | "__type__": "cc.Color", 974 | "r": 255, 975 | "g": 255, 976 | "b": 255, 977 | "a": 255 978 | }, 979 | "_contentSize": { 980 | "__type__": "cc.Size", 981 | "width": 40, 982 | "height": 948.6832980505138 983 | }, 984 | "_anchorPoint": { 985 | "__type__": "cc.Vec2", 986 | "x": 0, 987 | "y": 0.5 988 | }, 989 | "_position": { 990 | "__type__": "cc.Vec3", 991 | "x": 270, 992 | "y": 390, 993 | "z": 0 994 | }, 995 | "_scale": { 996 | "__type__": "cc.Vec3", 997 | "x": 1, 998 | "y": 1, 999 | "z": 1 1000 | }, 1001 | "_rotationX": 0, 1002 | "_rotationY": 0, 1003 | "_quat": { 1004 | "__type__": "cc.Quat", 1005 | "x": 0, 1006 | "y": 0, 1007 | "z": 0, 1008 | "w": 1 1009 | }, 1010 | "_skewX": 0, 1011 | "_skewY": 0, 1012 | "groupIndex": 0, 1013 | "_id": "5ad3ewf5RK/r+7n9o+mQK+" 1014 | }, 1015 | { 1016 | "__type__": "cc.Sprite", 1017 | "_name": "", 1018 | "_objFlags": 0, 1019 | "node": { 1020 | "__id__": 20 1021 | }, 1022 | "_enabled": true, 1023 | "_spriteFrame": null, 1024 | "_type": 0, 1025 | "_sizeMode": 0, 1026 | "_fillType": 0, 1027 | "_fillCenter": { 1028 | "__type__": "cc.Vec2", 1029 | "x": 0, 1030 | "y": 0 1031 | }, 1032 | "_fillStart": 0, 1033 | "_fillRange": 0, 1034 | "_isTrimmedMode": true, 1035 | "_state": 0, 1036 | "_atlas": null, 1037 | "_srcBlendFactor": 770, 1038 | "_dstBlendFactor": 771, 1039 | "_id": "3bVe6km2NJ1rY/TgffKIjd" 1040 | }, 1041 | { 1042 | "__type__": "cc.Mask", 1043 | "_name": "", 1044 | "_objFlags": 0, 1045 | "node": { 1046 | "__id__": 19 1047 | }, 1048 | "_enabled": true, 1049 | "_spriteFrame": { 1050 | "__uuid__": "71144251-e977-41c7-a175-a2b77f9050f2" 1051 | }, 1052 | "_type": 2, 1053 | "_segments": 64, 1054 | "_N$alphaThreshold": 0.1, 1055 | "_N$inverted": false, 1056 | "_id": "b6ZK9SbNxDN52PzC0OBrHc" 1057 | }, 1058 | { 1059 | "__type__": "cc.Sprite", 1060 | "_name": "", 1061 | "_objFlags": 0, 1062 | "node": { 1063 | "__id__": 18 1064 | }, 1065 | "_enabled": true, 1066 | "_spriteFrame": { 1067 | "__uuid__": "6b48946f-5c61-4560-9c84-3b1dada4dee4" 1068 | }, 1069 | "_type": 0, 1070 | "_sizeMode": 0, 1071 | "_fillType": 0, 1072 | "_fillCenter": { 1073 | "__type__": "cc.Vec2", 1074 | "x": 0, 1075 | "y": 0 1076 | }, 1077 | "_fillStart": 0, 1078 | "_fillRange": 0, 1079 | "_isTrimmedMode": true, 1080 | "_state": 0, 1081 | "_atlas": null, 1082 | "_srcBlendFactor": 770, 1083 | "_dstBlendFactor": 771, 1084 | "_id": "dfqHmydXtNC7FLhECuKFUn" 1085 | }, 1086 | { 1087 | "__type__": "cc.Mask", 1088 | "_name": "", 1089 | "_objFlags": 0, 1090 | "node": { 1091 | "__id__": 15 1092 | }, 1093 | "_enabled": true, 1094 | "_spriteFrame": null, 1095 | "_type": 0, 1096 | "_segments": 64, 1097 | "_N$alphaThreshold": 0, 1098 | "_N$inverted": false, 1099 | "_id": "38JLasuXdHjY95015RYx1m" 1100 | }, 1101 | { 1102 | "__type__": "cc.Node", 1103 | "_name": "finger1", 1104 | "_objFlags": 0, 1105 | "_parent": { 1106 | "__id__": 14 1107 | }, 1108 | "_children": [], 1109 | "_active": false, 1110 | "_level": 3, 1111 | "_components": [ 1112 | { 1113 | "__id__": 26 1114 | } 1115 | ], 1116 | "_prefab": null, 1117 | "_opacity": 255, 1118 | "_color": { 1119 | "__type__": "cc.Color", 1120 | "r": 255, 1121 | "g": 255, 1122 | "b": 255, 1123 | "a": 255 1124 | }, 1125 | "_contentSize": { 1126 | "__type__": "cc.Size", 1127 | "width": 0, 1128 | "height": 0 1129 | }, 1130 | "_anchorPoint": { 1131 | "__type__": "cc.Vec2", 1132 | "x": 0.5, 1133 | "y": 0.5 1134 | }, 1135 | "_position": { 1136 | "__type__": "cc.Vec3", 1137 | "x": 0, 1138 | "y": 0, 1139 | "z": 0 1140 | }, 1141 | "_scale": { 1142 | "__type__": "cc.Vec3", 1143 | "x": 1, 1144 | "y": 1, 1145 | "z": 1 1146 | }, 1147 | "_rotationX": 0, 1148 | "_rotationY": 0, 1149 | "_quat": { 1150 | "__type__": "cc.Quat", 1151 | "x": 0, 1152 | "y": 0, 1153 | "z": 0, 1154 | "w": 1 1155 | }, 1156 | "_skewX": 0, 1157 | "_skewY": 0, 1158 | "groupIndex": 0, 1159 | "_id": "2dcNqWpKVALoIc3Y74O45f" 1160 | }, 1161 | { 1162 | "__type__": "cc.Sprite", 1163 | "_name": "", 1164 | "_objFlags": 0, 1165 | "node": { 1166 | "__id__": 25 1167 | }, 1168 | "_enabled": true, 1169 | "_spriteFrame": { 1170 | "__uuid__": "31bc895a-c003-4566-a9f3-2e54ae1c17dc" 1171 | }, 1172 | "_type": 0, 1173 | "_sizeMode": 0, 1174 | "_fillType": 0, 1175 | "_fillCenter": { 1176 | "__type__": "cc.Vec2", 1177 | "x": 0, 1178 | "y": 0 1179 | }, 1180 | "_fillStart": 0, 1181 | "_fillRange": 0, 1182 | "_isTrimmedMode": true, 1183 | "_state": 0, 1184 | "_atlas": null, 1185 | "_srcBlendFactor": 770, 1186 | "_dstBlendFactor": 771, 1187 | "_id": "50cyugnkRHFpZaAHTF9pCQ" 1188 | }, 1189 | { 1190 | "__type__": "cc.Node", 1191 | "_name": "finger2", 1192 | "_objFlags": 0, 1193 | "_parent": { 1194 | "__id__": 14 1195 | }, 1196 | "_children": [], 1197 | "_active": false, 1198 | "_level": 3, 1199 | "_components": [ 1200 | { 1201 | "__id__": 28 1202 | } 1203 | ], 1204 | "_prefab": null, 1205 | "_opacity": 255, 1206 | "_color": { 1207 | "__type__": "cc.Color", 1208 | "r": 255, 1209 | "g": 255, 1210 | "b": 255, 1211 | "a": 255 1212 | }, 1213 | "_contentSize": { 1214 | "__type__": "cc.Size", 1215 | "width": 0, 1216 | "height": 0 1217 | }, 1218 | "_anchorPoint": { 1219 | "__type__": "cc.Vec2", 1220 | "x": 0.5, 1221 | "y": 0.5 1222 | }, 1223 | "_position": { 1224 | "__type__": "cc.Vec3", 1225 | "x": 0, 1226 | "y": 0, 1227 | "z": 0 1228 | }, 1229 | "_scale": { 1230 | "__type__": "cc.Vec3", 1231 | "x": 1, 1232 | "y": 1, 1233 | "z": 1 1234 | }, 1235 | "_rotationX": 0, 1236 | "_rotationY": 0, 1237 | "_quat": { 1238 | "__type__": "cc.Quat", 1239 | "x": 0, 1240 | "y": 0, 1241 | "z": 0, 1242 | "w": 1 1243 | }, 1244 | "_skewX": 0, 1245 | "_skewY": 0, 1246 | "groupIndex": 0, 1247 | "_id": "a6rZ8028ZCfp5TAqvdgheO" 1248 | }, 1249 | { 1250 | "__type__": "cc.Sprite", 1251 | "_name": "", 1252 | "_objFlags": 0, 1253 | "node": { 1254 | "__id__": 27 1255 | }, 1256 | "_enabled": true, 1257 | "_spriteFrame": { 1258 | "__uuid__": "31bc895a-c003-4566-a9f3-2e54ae1c17dc" 1259 | }, 1260 | "_type": 0, 1261 | "_sizeMode": 0, 1262 | "_fillType": 0, 1263 | "_fillCenter": { 1264 | "__type__": "cc.Vec2", 1265 | "x": 0, 1266 | "y": 0 1267 | }, 1268 | "_fillStart": 0, 1269 | "_fillRange": 0, 1270 | "_isTrimmedMode": true, 1271 | "_state": 0, 1272 | "_atlas": null, 1273 | "_srcBlendFactor": 770, 1274 | "_dstBlendFactor": 771, 1275 | "_id": "96rctqA3pH1YpHCJc47HcM" 1276 | }, 1277 | { 1278 | "__type__": "f4c0c2hQ6pAO7eqiRfQyhfu", 1279 | "_name": "", 1280 | "_objFlags": 0, 1281 | "node": { 1282 | "__id__": 14 1283 | }, 1284 | "_enabled": true, 1285 | "_originalDir": 2, 1286 | "_dirType": 2, 1287 | "_cardSize": { 1288 | "__type__": "cc.Size", 1289 | "width": 270, 1290 | "height": 390 1291 | }, 1292 | "mask": { 1293 | "__id__": 24 1294 | }, 1295 | "cardBack": { 1296 | "__id__": 16 1297 | }, 1298 | "cardFace": { 1299 | "__id__": 18 1300 | }, 1301 | "shadowMask": { 1302 | "__id__": 22 1303 | }, 1304 | "shadow": { 1305 | "__id__": 20 1306 | }, 1307 | "finger1": { 1308 | "__id__": 25 1309 | }, 1310 | "finger2": { 1311 | "__id__": 27 1312 | }, 1313 | "_id": "d1Gw3vNfFIyqElpnKTGt7u" 1314 | }, 1315 | { 1316 | "__type__": "cc.Canvas", 1317 | "_name": "", 1318 | "_objFlags": 0, 1319 | "node": { 1320 | "__id__": 2 1321 | }, 1322 | "_enabled": true, 1323 | "_designResolution": { 1324 | "__type__": "cc.Size", 1325 | "width": 1280, 1326 | "height": 720 1327 | }, 1328 | "_fitWidth": false, 1329 | "_fitHeight": true, 1330 | "_id": "1aK+2MGUtFNY3zS7XgOR2Y" 1331 | }, 1332 | { 1333 | "__type__": "e1b90/rohdEk4SdmmEZANaD", 1334 | "_name": "", 1335 | "_objFlags": 0, 1336 | "node": { 1337 | "__id__": 2 1338 | }, 1339 | "_enabled": true, 1340 | "peekCard": { 1341 | "__id__": 29 1342 | }, 1343 | "_id": "f6R9drvPRMK6tfiB5G1uDw" 1344 | } 1345 | ] -------------------------------------------------------------------------------- /assets/Scene/PeekCard.fire.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.1", 3 | "uuid": "2d2f792f-a40c-49bb-a189-ed176a246e49", 4 | "asyncLoadAssets": false, 5 | "autoReleaseAssets": false, 6 | "subMetas": {} 7 | } -------------------------------------------------------------------------------- /assets/Script.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.1", 3 | "uuid": "4734c20c-0db8-4eb2-92ea-e692f4d70934", 4 | "isGroup": false, 5 | "subMetas": {} 6 | } -------------------------------------------------------------------------------- /assets/Script/Base.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.1", 3 | "uuid": "1fd38ea2-e9ab-4c1a-896c-4ca63921c0e9", 4 | "isSubpackage": false, 5 | "subpackageName": "", 6 | "subMetas": {} 7 | } -------------------------------------------------------------------------------- /assets/Script/Base/BaseComponent.ts: -------------------------------------------------------------------------------- 1 | 2 | const { ccclass, property } = cc._decorator; 3 | 4 | @ccclass 5 | /** 6 | * 组件基类 7 | * 自动引用被@property 装饰的子节点及子节点以下节点 8 | * 规则: 9 | * 1.扩展(占用)tooltip装饰 用来标记被装饰自定义属性的节点引用路径【相对路径】 10 | * tooltip用例: rootNode -> myComponent extends BaseComponent 11 | * ┗child1 -> 12 | * ┗child1_1 -> 13 | * ┗child1_2 -> 14 | * 若想在myComponent完成自动引用child1_1 ==> tooltip:"child1/child1_1" 15 | * 2.支持数组格式【以\n分割】 16 | * 同1节点结构:tooltip:"child1/child1_1\nchild1/child1_2" 17 | * 3.如果不指定tooltip则默认引用子节点下与属性同名节点 18 | * 4.不在编辑器显示的属性会被忽略 19 | * a.以'_'开头命名 20 | * b.指定 visible:false 21 | * 5.找不到的节点会在组建会被忽略并保持原有引用 22 | * 6.如果想引用其他节点上的节点或者组件或者资源类型,根据5的特性可按照原始方式:手动拖动到引用槽 23 | * 24 | * 备注:若有其他自动引用需求,可在resetInEditor2中diy特定或者复杂引用 25 | */ 26 | export default class BaseComponent extends cc.Component { 27 | 28 | @property({ tooltip: "重新创建当前属性所有引用\n无法被自动引用的属性将保持不变\n1.找不到的节点\n2.找不到的类型(图声字等资源类型)" }) 29 | get reset() { 30 | return false; 31 | } 32 | set reset(v) { 33 | this.resetInEditor(); 34 | } 35 | /** 36 | * resetInEditor被占用 37 | * 作为补偿提供一个resetInEditor的回调函数 38 | * 可在子类重写此函数 39 | */ 40 | resetInEditor2: () => void = undefined; 41 | resetInEditor() { 42 | let setProto = (key: string, uri: string, ctor: any, isArray: boolean = false) => { 43 | if (!uri) return; 44 | let node = cc.find(uri, this.node); 45 | let value = undefined; 46 | if (node) { 47 | value = ctor == cc.Node ? node : node.getComponent(ctor); 48 | } 49 | if (value) { 50 | if (isArray) { 51 | this[key].push(value); 52 | } 53 | else { 54 | this[key] = value; 55 | } 56 | } 57 | } 58 | let Attr = (cc.Class).Attr 59 | let cClass = cc.js.getClassByName(cc.js.getClassName(this)); 60 | let attrs = Attr.getClassAttrsProto(cClass); 61 | let DELIMETER = Attr.DELIMETER; 62 | for (const key in this) { 63 | let visible = attrs[key + DELIMETER + "visible"]; 64 | if (key[0] === '_' || visible === false) continue; 65 | //感谢Jare技术支持 66 | let ctor = attrs[key + DELIMETER + "ctor"]; 67 | let defaultValue = attrs[key + DELIMETER + "default"]; 68 | let tooltip: string = attrs[key + DELIMETER + "tooltip"]; 69 | if (this.hasOwnProperty(key) && ctor) { 70 | //自动查找引用 查找tooltip指定节点或同名节点 并获取对应的组件类型 71 | if (defaultValue && Array.isArray(defaultValue)) { //数组 72 | let uris = tooltip.split('\n'); 73 | this[key] = []; //重置 74 | for (let i = 0; i < uris.length; i++) { 75 | let uri = uris[i]; 76 | setProto(key, uri, ctor, true); 77 | } 78 | } 79 | else { 80 | let uri = tooltip ? tooltip : key; 81 | setProto(key, uri, ctor); 82 | } 83 | } 84 | } 85 | 86 | if (this.resetInEditor2) { 87 | this.resetInEditor2(); 88 | 89 | } 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /assets/Script/Base/BaseComponent.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.5", 3 | "uuid": "a70146a6-291f-4f99-8e9e-aa2d58cf51e1", 4 | "isPlugin": false, 5 | "loadPluginInWeb": true, 6 | "loadPluginInNative": true, 7 | "loadPluginInEditor": false, 8 | "subMetas": {} 9 | } -------------------------------------------------------------------------------- /assets/Script/Helloworld.ts: -------------------------------------------------------------------------------- 1 | import PeekCard from "./PeekCard"; 2 | 3 | const { ccclass, property } = cc._decorator; 4 | 5 | @ccclass 6 | export default class Helloworld extends cc.Component { 7 | 8 | @property(PeekCard) 9 | peekCard: PeekCard = undefined; 10 | 11 | 12 | async start() { 13 | 14 | 15 | if (false) { 16 | window["peekCard"] = this.peekCard; 17 | 18 | ////// 拖动 PeekCard 脚本到场景中 执行组件的 reset 操作即可自动创建好所有节点 19 | console.log("预先做好的搓牌节点 ", PeekCard.DirType[this.peekCard.dirType]); 20 | 21 | this.peekCard.node.active = true; 22 | 23 | // 设置搓牌区域大小 默认是Canvas设计分辨率大小 24 | this.peekCard.setTouchAreaSize(cc.size(1280, 720)) 25 | // 设置扑克牌大小 (原始纹理不拉伸情况下的大小) 26 | this.peekCard.setCardSize(cc.size(90 * 3, 130 * 3)) 27 | await this.peekCard.setCardBack("Cards/Cards051"); 28 | await this.peekCard.setCardFace("Cards/Cards000"); 29 | await this.peekCard.setShadow("shadow"); 30 | // 没有特殊需求时不需要设置手指纹理 如果有需要手指的大小和纹理需要在代码中再次调整 31 | await this.peekCard.setFinger(null); 32 | this.peekCard.directionLength = 20; 33 | this.peekCard.moveSpeed = 0.6; 34 | this.peekCard.angleFixed = 5; 35 | 36 | this.peekCard.init(); //搓牌前必须调用 37 | } 38 | else { 39 | this.peekCard.node.active = false; 40 | this.buildPeekCard(PeekCard.DirType.horizontal); 41 | } 42 | 43 | } 44 | 45 | async buildPeekCard(dirType: PeekCard["dirType"]) { 46 | console.log("动态创建搓牌节点 ", PeekCard.DirType[dirType]); 47 | var peekCard = new cc.Node("PeekCard").addComponent(PeekCard); 48 | window["peekCard"] = peekCard; 49 | this.node.addChild(peekCard.node); 50 | // 动态创建时一定要第一时间设置好原始方向 51 | peekCard._originalDir = peekCard._dirType = PeekCard.DirType.vertical; 52 | // 设置搓牌区域大小 默认是Canvas设计分辨率大小 53 | this.peekCard.setTouchAreaSize(cc.size(1280, 720)) 54 | // 优先设置牌大小 55 | peekCard.setCardSize(cc.size(90 * 3 - 20, 130 * 3 - 30)); 56 | 57 | // 动态设置搓牌方向(允许在其他位置调用) 58 | peekCard.dirType = dirType; 59 | 60 | await peekCard.setCardBack("Cards/Cards051"); 61 | await peekCard.setCardFace("Cards/Cards000"); 62 | await peekCard.setShadow("shadow"); 63 | await peekCard.setFinger("HelloWorld", cc.size(40, 80)); 64 | 65 | peekCard.directionLength = 20; 66 | peekCard.moveSpeed = 0.6; 67 | peekCard.angleFixed = 5; 68 | 69 | peekCard.init(); //搓牌前必须调用 70 | 71 | 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /assets/Script/Helloworld.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.5", 3 | "uuid": "e1b90feb-a217-4493-849d-9a611900d683", 4 | "isPlugin": false, 5 | "loadPluginInWeb": true, 6 | "loadPluginInNative": true, 7 | "loadPluginInEditor": false, 8 | "subMetas": {} 9 | } -------------------------------------------------------------------------------- /assets/Script/PeekCard.ts: -------------------------------------------------------------------------------- 1 | 2 | const { ccclass, property } = cc._decorator; 3 | 4 | enum DirType { 5 | horizontal = 1, 6 | vertical = 2 7 | } 8 | 9 | 10 | @ccclass 11 | export default class PeekCard extends cc.Component { 12 | 13 | @property 14 | _originalDir: DirType = DirType.vertical; 15 | @property({ type: cc.Enum(DirType), tooltip: "原始扑克牌纹理的方向" }) 16 | get originalDirType() { return this._originalDir } 17 | set originalDirType(type: DirType) { 18 | if (this._originalDir != type) { 19 | this._originalDir = type; 20 | } 21 | } 22 | @property 23 | _dirType: DirType = DirType.vertical 24 | @property({ type: cc.Enum(DirType), tooltip: "搓牌时扑克牌纹理的方向" }) 25 | get dirType() { return this._dirType } 26 | set dirType(type: DirType) { 27 | if (type != this.dirType) { 28 | this._dirType = type; 29 | } 30 | 31 | // 方向与原始方向一致时 不旋转精灵(复位) 32 | let isRotate = type != this.originalDirType; 33 | // 设置精灵旋转 34 | let sprite = this.cardBack.getComponent(cc.Sprite); 35 | let spf = sprite.spriteFrame; 36 | sprite.spriteFrame = null; 37 | let _isRotate = this._setSpriteFrameRotate(spf, isRotate); 38 | sprite.spriteFrame = spf; 39 | 40 | sprite = this.cardFace.getComponent(cc.Sprite); 41 | spf = sprite.spriteFrame; 42 | sprite.spriteFrame = null; 43 | this._setSpriteFrameRotate(spf, isRotate); 44 | sprite.spriteFrame = spf; 45 | 46 | this.init(); 47 | 48 | // cc.log(isRotate, this.cardBack.getContentSize(), this._cardSize); 49 | 50 | } 51 | @property 52 | private _cardSize: cc.Size = cc.size(0, 0); 53 | @property({ type: cc.Size, tooltip: "设置扑克牌的大小" }) 54 | get cardSize() { 55 | return this._cardSize; 56 | } 57 | set cardSize(size) { 58 | this.setCardSize(size); 59 | this.init(); 60 | } 61 | 62 | @property({ 63 | type: cc.Mask, 64 | readonly: true, 65 | }) 66 | private mask: cc.Mask = undefined; 67 | @property({ 68 | type: cc.Node, 69 | readonly: true, 70 | }) 71 | private cardBack: cc.Node = undefined; 72 | @property({ 73 | type: cc.Node, 74 | readonly: true, 75 | }) 76 | private cardFace: cc.Node = undefined; 77 | @property({ 78 | type: cc.Mask, 79 | readonly: true, 80 | }) 81 | private shadowMask: cc.Mask = undefined; 82 | @property({ 83 | type: cc.Node, 84 | readonly: true, 85 | }) 86 | private shadow: cc.Node = undefined; 87 | 88 | @property({ 89 | type: cc.Node, 90 | readonly: true, 91 | }) 92 | finger1: cc.Node = undefined; 93 | @property({ 94 | type: cc.Node, 95 | readonly: true, 96 | }) 97 | finger2: cc.Node = undefined; 98 | ////// 运行状态属性 /////// 99 | /** 100 | * 方向向量最小长度(滑动灵敏度) 值越大灵敏度越低 101 | * 在手机上手指较粗需要将滑动灵敏度降低 否则翻拍方向可能不是你预想的方向 102 | */ 103 | directionLength: number = 5; 104 | /** 105 | * 此速度是触摸移动速度的倍数 106 | * 备注:牌面移动速度是触摸速度的2倍 所以真正的翻牌速度是触摸速度的0.5倍 107 | */ 108 | moveSpeed: number = 0.5; 109 | /** 110 | * 此修正角度为触摸方向在水平或者竖直方向的偏移角度在修正角度内时,修正角度为水平或者竖直 111 | * 使更容易操作水平和竖直方向的搓牌 112 | */ 113 | angleFixed: number = 10; 114 | 115 | private _isOpenCard: boolean = false; //是否已经开牌 开牌后禁止一切触摸事件 116 | private _isMoveStart: boolean = false; 117 | private _tStartPos: cc.Vec2 = undefined; //触摸开始点 118 | private _tMoveVec: cc.Vec2 = undefined; //触摸移动向量 119 | private _rotation: number = 0; 120 | private _inFingers: number[] = []; 121 | 122 | private _finishCallBack: Function = undefined; //搓牌完成回调函数 123 | 124 | 125 | resetInEditor() { 126 | // 编辑器 reset 操作 127 | this.node.destroyAllChildren(); 128 | this._initNodes(); 129 | } 130 | 131 | private _initNodes() { 132 | function addCustomSprite(node: cc.Node) { 133 | let sprite = node.addComponent(cc.Sprite); 134 | sprite.sizeMode = cc.Sprite.SizeMode.CUSTOM; 135 | return sprite; 136 | } 137 | // 设置触摸区域 为全屏 138 | let canvas = cc.director.getScene().getComponentInChildren(cc.Canvas); 139 | this.setTouchAreaSize(canvas.designResolution); 140 | //this.node.setContentSize(canvas.designResolution); 141 | // 添加牌遮罩 142 | this.mask = new cc.Node("mask").addComponent(cc.Mask); 143 | this.node.addChild(this.mask.node); 144 | // 添加牌背 145 | this.cardBack = new cc.Node("cardBack"); 146 | addCustomSprite(this.cardBack); 147 | this.mask.node.addChild(this.cardBack) 148 | // 添加牌面 149 | this.cardFace = new cc.Node("cardFace"); 150 | addCustomSprite(this.cardFace); 151 | this.mask.node.addChild(this.cardFace); 152 | // 添加阴影遮罩 153 | this.shadowMask = new cc.Node("shadowMask").addComponent(cc.Mask); 154 | this.shadowMask.type = cc.Mask.Type.IMAGE_STENCIL; //遮罩类型设置为与牌面图相同 155 | this.shadowMask.alphaThreshold = 0.1; 156 | this.cardFace.addChild(this.shadowMask.node); 157 | // 添加阴影 158 | this.shadow = new cc.Node("shadow"); 159 | addCustomSprite(this.shadow); 160 | this.shadow.parent = this.shadowMask.node; 161 | this.shadow.setAnchorPoint(0, 0.5) 162 | // 添加手指 163 | this.finger1 = new cc.Node("finger1"); 164 | this.finger2 = new cc.Node("finger2"); 165 | addCustomSprite(this.finger1); 166 | addCustomSprite(this.finger2); 167 | this.node.addChild(this.finger1); 168 | this.node.addChild(this.finger2); 169 | } 170 | 171 | onLoad() { 172 | if (this.node.getChildByName("mask") == null) { 173 | this._initNodes(); 174 | } 175 | } 176 | 177 | 178 | 179 | start() { 180 | this.node.on(cc.Node.EventType.TOUCH_START, this._touchStart, this) 181 | this.node.on(cc.Node.EventType.TOUCH_MOVE, this._touchMove, this) 182 | this.node.on(cc.Node.EventType.TOUCH_END, this._touchEnd, this) 183 | } 184 | 185 | onEnable() { 186 | // this.dirType = this.dirType; 187 | } 188 | 189 | 190 | /** 191 | * 设置搓牌完成回调 192 | * @param {Function} callback 193 | */ 194 | setFinishCallBack(callback: Function) { 195 | this._finishCallBack = callback; 196 | } 197 | /** 198 | * 初始化搓牌(每次开始搓牌前必须调用) 199 | * 200 | * @date 2019-04-16 201 | * @memberof PeekCard 202 | */ 203 | init() { 204 | if (!this._cardSize) { 205 | this._cardSize = this.cardBack.getContentSize(); 206 | } 207 | 208 | this._initCardNode(this.mask.node, this._cardSize, this.dirType != this.originalDirType); 209 | this._initCardNode(this.cardBack, this._cardSize, this.dirType != this.originalDirType); 210 | this._initCardNode(this.cardFace, this._cardSize, this.dirType != this.originalDirType); 211 | this._initCardNode(this.shadowMask.node, this._cardSize, this.dirType != this.originalDirType); 212 | 213 | //设置牌面在遮罩左边 214 | this.cardFace.setPosition(-this.mask.node.width, 0); 215 | //设置阴影大小以及位置 216 | this.shadow.setRotation(0); 217 | 218 | this.shadow.height = Math.sqrt(Math.pow(this._cardSize.height, 2) + Math.pow(this._cardSize.width, 2)) * 2 219 | this.shadow.width = 40; 220 | var x = this.cardFace.width / 2 + this.shadowMask.node.width / 2; 221 | var y = this.cardFace.height / 2 + this.shadowMask.node.height / 2 222 | this.shadow.setPosition(x, y); 223 | //隐藏手指 224 | this._initFinger(); 225 | 226 | this._initStatus(); 227 | } 228 | private _touchStart(event?: cc.Event.EventTouch) { 229 | if (this._isOpenCard) { 230 | return; 231 | } 232 | this._tStartPos = event.getLocation(); 233 | } 234 | private _touchMove(event?: cc.Event.EventTouch) { 235 | if (this._isOpenCard || !this._tStartPos) { 236 | return; 237 | } 238 | let _tEndPos = event.getLocation(); 239 | let _tPrePos = event.getPreviousLocation(); 240 | if (_tEndPos.equals(_tPrePos)) { //忽略相同点 241 | return; 242 | } 243 | //规定方向向量为: 开始点到当前点的向量。 规定移动向量为: 上一个点到当前点的向量 244 | let startToEndVec = _tEndPos.sub(this._tStartPos); 245 | let preToEndVec = _tEndPos.sub(_tPrePos); 246 | 247 | //规定 达到最小长度才确定方向 248 | let length = startToEndVec.mag(); 249 | 250 | 251 | if (this._isMoveStart == false && length >= this.directionLength) { 252 | this._isMoveStart = true; 253 | this._tMoveVec = this._fixedDirection(startToEndVec); 254 | this._rotation = this._getSignAngle(this._tMoveVec, cc.v2(1, 0)); 255 | // cc.log("当前旋转角度::", this._rotation); 256 | //设置外接矩形 257 | let size = this._getOutRectSize(this.cardBack, this._rotation); 258 | this.mask.node.setContentSize(size); 259 | //设置旋转角度 260 | this.mask.node.rotation = this._rotation; 261 | this.cardBack.rotation = -this._rotation; 262 | this.cardFace.rotation = this._rotation; 263 | this.shadow.rotation = -this._rotation; 264 | //根据移动方向 设置牌面和阴影 移动前的起始位置 265 | let quadrant = this._getQuadrant(this._tMoveVec); 266 | let faceVertexs = this._getNodeVertexByNodeSpaceAR(this.cardFace); 267 | switch (quadrant) { 268 | case 1: 269 | case 5: 270 | // 牌面在遮罩左边 271 | this.cardFace.setPosition(-this.mask.node.width, this.cardBack.y); 272 | // 阴影设置在牌面的右下顶点 273 | this.shadow.setPosition(faceVertexs[2]); 274 | break; 275 | case 2: 276 | case 6: 277 | // 牌面在遮罩右边 278 | this.cardFace.setPosition(-this.mask.node.width, -this.cardBack.y); 279 | // 阴影设置在牌面的左下顶点 280 | this.shadow.setPosition(faceVertexs[3]); 281 | break; 282 | case 3: 283 | case 7: 284 | // 牌面在遮罩右边 285 | this.cardFace.setPosition(-this.mask.node.width, -this.cardBack.y); 286 | // 阴影设置在牌面的左上顶点 287 | this.shadow.setPosition(faceVertexs[0]); 288 | break; 289 | case 4: 290 | case 8: 291 | // 牌面在遮罩左边 292 | this.cardFace.setPosition(-this.mask.node.width, this.cardBack.y); 293 | // 阴影设置在牌面的右上顶点 294 | this.shadow.setPosition(faceVertexs[1]); 295 | break; 296 | default: 297 | cc.error("移动的方向向量为cc.Vec2(0, 0)"); //走进来算我输 298 | this._isMoveStart = false; 299 | break; 300 | } 301 | 302 | } 303 | else if (this._isMoveStart) { 304 | //移动向量在方向向量上的分量 305 | let unitV = preToEndVec.project(cc.v2(this._tMoveVec)); 306 | let _unitV = unitV.neg(); //反向移动向量 307 | 308 | if (unitV.mag() == 0) { 309 | return; 310 | } 311 | 312 | let speed = this.moveSpeed; 313 | //移动 314 | this._moveByVec2(this.mask.node, unitV, speed); 315 | this._moveByVec2(this.cardBack, _unitV, speed); 316 | this._moveByVec2(this.cardFace, unitV, speed); 317 | this._moveByVec2(this.shadow, _unitV, speed); 318 | 319 | //显示手指 320 | let vertexs = this._getNodeVertexByWorldSpaceAR(this.cardFace, -10); 321 | let maskPolygon = this._getNodeVertexByWorldSpaceAR(this.mask.node); 322 | //判断顶点是否落在多边形内 323 | this._inFingers = []; 324 | for (let i = 0; i < vertexs.length; i++) { 325 | if (cc.Intersection.pointInPolygon(vertexs[i], maskPolygon)) { 326 | this._inFingers.push(i); 327 | } 328 | } 329 | for (let i = 0; i < this._inFingers.length; i++) { 330 | var index = this._inFingers[i]; //顶点下标 331 | var finger: cc.Node = this["finger" + (i + 1)]; 332 | if (finger) { 333 | finger.active = true; 334 | finger.setPosition(finger.parent.convertToNodeSpaceAR(vertexs[index])); 335 | finger.rotation = this._rotation - 90; 336 | 337 | } 338 | } 339 | 340 | length = this._inFingers.length; 341 | //隐藏不必要的手指 342 | if (length == 0) { 343 | this.finger1.active = false 344 | this.finger2.active = false 345 | } 346 | else if (length == 1) { 347 | this.finger2.active = false 348 | } 349 | if (this._canOpen()) { 350 | //开牌 351 | this.openCard(); 352 | } 353 | if (unitV.x * this._tMoveVec.x <= 0 && unitV.y * this._tMoveVec.y <= 0 && length == 0) { 354 | this._touchEnd(); 355 | this._tStartPos = undefined; 356 | console.log("禁止继续回退"); 357 | } 358 | } 359 | 360 | } 361 | private _touchEnd(event?: cc.Event.EventTouch) { 362 | if (this._isOpenCard || !this._tStartPos) { 363 | return; 364 | } 365 | this.init(); 366 | } 367 | 368 | /** 369 | * 设置触摸区域的大小 370 | */ 371 | setTouchAreaSize(w: number | cc.Size, h?: number) { 372 | var size = this._getSize(w, h) 373 | this.node.setContentSize(size); 374 | } 375 | 376 | setCardSize(w: number | cc.Size, h?: number) { 377 | var size = this._getSize(w, h); 378 | this._cardSize = size; 379 | if (this.dirType != this.originalDirType) { 380 | size = cc.size(size.height, size.width); 381 | } 382 | 383 | this.mask.node.setContentSize(size); 384 | this.cardBack.setContentSize(size); 385 | this.cardFace.setContentSize(size); 386 | this.shadowMask.node.setContentSize(size); 387 | } 388 | 389 | async setCardBack(spf: string | cc.SpriteFrame) { 390 | spf = await this._setNodeSpriteFrame(this.cardBack, spf, this.dirType != this.originalDirType); 391 | //设置阴影的遮罩模板 392 | this.shadowMask.spriteFrame = spf; 393 | this.shadowMask.type = cc.Mask.Type.IMAGE_STENCIL; 394 | this.shadowMask.alphaThreshold = 0.1; 395 | } 396 | async setCardFace(spf: string | cc.SpriteFrame) { 397 | await this._setNodeSpriteFrame(this.cardFace, spf, this.dirType != this.originalDirType); 398 | } 399 | /** 400 | * 设置阴影 401 | * 注意:根据具体阴影图需要具体设置阴影精灵的锚点和宽高大小 402 | * 403 | * @date 2019-04-16 404 | * @param {(string | cc.SpriteFrame)} spf 405 | * @memberof PeekCard 406 | */ 407 | async setShadow(spf: string | cc.SpriteFrame) { 408 | await this._setNodeSpriteFrame(this.shadow, spf); 409 | } 410 | 411 | async setFinger(spf: string | cc.SpriteFrame, size?: cc.Size) { 412 | await this._setNodeSpriteFrame(this.finger1, spf); 413 | await this._setNodeSpriteFrame(this.finger2, spf); 414 | 415 | if (size instanceof cc.Size) { 416 | this.setFingerSize(size); 417 | } 418 | } 419 | 420 | setFingerSize(x: number | cc.Size, y?: number) { 421 | let size = this._getSize(x, y); 422 | this.finger1.setContentSize(size); 423 | this.finger2.setContentSize(size); 424 | } 425 | 426 | /** 427 | * 检测是否开牌 428 | */ 429 | _canOpen() { 430 | var length = this._getMoveLength(); 431 | var maxLength = this._getMoveMaxLength(); 432 | if (length > maxLength / 2) { 433 | return true; 434 | } 435 | return false; 436 | } 437 | _getMoveLength() { 438 | let localPos = this.mask.node.getPosition(); 439 | var length = localPos.mag(); //遮罩初始坐标是(0, 0) 此处坐标即向量 440 | return length; 441 | } 442 | _getMoveMaxLength() { 443 | var maxLength = this.mask.node.width; 444 | return maxLength; 445 | } 446 | 447 | openCard() { 448 | cc.log("开牌"); 449 | this.init(); 450 | //显示牌面 451 | this.cardFace.setPosition(0, 0); 452 | this._isOpenCard = true; 453 | if (typeof this._finishCallBack === "function") { 454 | this._finishCallBack(); 455 | } 456 | } 457 | 458 | 459 | /** 460 | * 获得最小外接矩形的大小 461 | * 462 | * @date 2019-04-16 463 | * @param {cc.Node} inRect 内接矩形 464 | * @param {number} angle -180~180的角度 465 | * @memberof PeekCardNode 466 | */ 467 | private _getOutRectSize(inRect: cc.Node, angle: number) { 468 | angle = Math.abs(angle); 469 | if (angle > 90 && angle <= 180) { 470 | angle = 180 - angle; 471 | } 472 | var radian = Math.PI / 180 * angle; 473 | var w = inRect.height * Math.sin(radian) + inRect.width * Math.cos(radian); 474 | var h = inRect.height * Math.cos(radian) + inRect.width * Math.sin(radian); 475 | return cc.size(w, h); 476 | } 477 | /** 478 | * 将节点沿 unitVec 方向移动 length 个 unitVec 长度 479 | * 480 | * @date 2019-04-16 481 | * @param {cc.Node} node 482 | * @param {cc.Vec2} unitVec 483 | * @param {number} length 484 | * @memberof PeekCardNode 485 | */ 486 | private _moveByVec2(node: cc.Node, unitVec: cc.Vec2, length: number = 1) { 487 | var wp1 = node.parent.convertToWorldSpaceAR(node.getPosition()); 488 | var wp2 = cc.v2(wp1.x + unitVec.x * length, wp1.y + unitVec.y * length); 489 | var localP = node.parent.convertToNodeSpaceAR(wp2); 490 | 491 | node.setPosition(localP); 492 | } 493 | /** 494 | * 获得 v1=>v2 的夹角 495 | * 496 | * @date 2019-04-16 497 | * @param {cc.Vec2} v1 498 | * @param {cc.Vec2} v2 499 | * @returns -180 ~ 180 500 | * @memberof PeekCard 501 | */ 502 | private _getSignAngle(v1: cc.Vec2, v2: cc.Vec2) { 503 | var radian = v1.signAngle(v2); 504 | var angle = 180 / Math.PI * radian; 505 | return angle; 506 | } 507 | /** 508 | * 修正水平或竖直方向 509 | * 510 | * @date 2019-04-19 511 | * @param {cc.Vec2} moveDirection 512 | * @returns 513 | * @memberof PeekCard 514 | */ 515 | private _fixedDirection(moveDirection: cc.Vec2) { 516 | if (this.angleFixed) { 517 | var fAngle = this.angleFixed; 518 | var xVec = cc.v2(1, 0) 519 | var angle = this._getSignAngle(moveDirection, xVec); 520 | if ((angle <= (fAngle + 0) && angle >= (-fAngle + 0)) || 521 | (angle <= (fAngle + (-180)) || angle >= (-fAngle + 180)) 522 | ) { 523 | moveDirection = moveDirection.project(xVec); 524 | return moveDirection; 525 | } 526 | var yVec = cc.v2(0, 1); 527 | var angle = this._getSignAngle(moveDirection, yVec); 528 | if ((angle <= (fAngle + 0) && angle >= (-fAngle + 0)) || 529 | (angle <= (fAngle + (-180)) || angle >= (-fAngle + 180)) 530 | ) { 531 | moveDirection = moveDirection.project(yVec); 532 | return moveDirection; 533 | } 534 | } 535 | return moveDirection; 536 | } 537 | /** 538 | * 获得节点的顶点坐标列表(基于世界坐标系) 539 | * 从左上角顶点开始顺时针存入数组 540 | * 541 | * @date 2019-04-16 542 | * @param {cc.Node} node 543 | * @param {number} [offset=0] 偏移量 即放大或缩放顶点围成矩形的大小 544 | * @returns cc.Vec2[] 顶点数组 545 | * @memberof PeekCardNode 546 | */ 547 | private _getNodeVertexByWorldSpaceAR(node: cc.Node, offset: number = 0) { 548 | let vertexs = this._getNodeVertexByNodeSpaceAR(node, offset); 549 | for (let i = 0; i < vertexs.length; i++) { 550 | vertexs[i] = node.convertToWorldSpaceAR(vertexs[i]); 551 | } 552 | return vertexs; 553 | } 554 | /** 555 | * 获得节点的顶点坐标列表(基于节点坐标系) 556 | * 从左上角顶点开始顺时针存入数组 557 | * 558 | * @date 2019-04-16 559 | * @param {cc.Node} node 560 | * @param {number} [offset=0] 偏移量 即放大或缩放顶点围成矩形的大小 561 | * @returns cc.Vec2[] [左上, 右上, 右下, 左下] 562 | * @memberof PeekCardNode 563 | */ 564 | private _getNodeVertexByNodeSpaceAR(node: cc.Node, offset: number = 0) { 565 | var left = node.width * node.anchorX + offset; 566 | var right = node.width * (1 - node.anchorX) + offset; 567 | var bottom = node.height * node.anchorY + offset; 568 | var top = node.height * (1 - node.anchorY) + offset; 569 | let lt = cc.v2(-left, top); 570 | let rt = cc.v2(right, top); 571 | let rb = cc.v2(right, -bottom); 572 | let lb = cc.v2(-left, -bottom); 573 | 574 | return [lt, rt, rb, lb]; 575 | } 576 | /** 577 | * 获取坐标所在象限 578 | * @returns 1 2 3 4 表示1~4象限 5x正轴 6y正轴 7x负轴 8y负轴 9原点 579 | */ 580 | private _getQuadrant(vec: cc.Vec2) { 581 | let x = vec.x, y = vec.y; 582 | 583 | if (x == 0) { 584 | if (y == 0) { 585 | return 9; // 原点 586 | } else if (y > 0) { 587 | return 6; // y正轴 588 | } else if (y < 0) { 589 | return 8; // y负轴 590 | } 591 | } else if (x > 0) { 592 | if (y == 0) { 593 | return 5; // x正轴 594 | } else if (y > 0) { 595 | return 1; // 第一象限 596 | } else if (y < 0) { 597 | return 4; // 第四象限 598 | } 599 | } else if (x < 0) { 600 | if (y == 0) { 601 | return 7; // x负轴 602 | } else if (y > 0) { 603 | return 2; // 第二象限 604 | } else if (y < 0) { 605 | return 3; // 第三象限 606 | } 607 | } 608 | 609 | cc.error("参数错误::" + JSON.stringify(vec)); 610 | return 0; 611 | } 612 | 613 | private _initCardNode(node: cc.Node, size: cc.Size, isRotate: boolean) { 614 | if (!size) { 615 | return; 616 | } 617 | if (this.dirType != this.originalDirType) { 618 | node.setContentSize(size.height, size.width); 619 | } 620 | else 621 | node.setContentSize(size); 622 | 623 | // 初始化精灵 624 | // let sprite = node.getComponent(cc.Sprite); 625 | // if (sprite && sprite.spriteFrame) { 626 | // this._setSpriteFrameRotate(sprite.spriteFrame, isRotate); 627 | // } 628 | 629 | node.setRotation(0); 630 | node.setPosition(0, 0); 631 | } 632 | 633 | private _initFinger() { 634 | this._inFingers = []; 635 | this.finger1.active = false; 636 | this.finger2.active = false; 637 | } 638 | 639 | private _initStatus() { 640 | this._isOpenCard = false; //改变状态 未开牌 641 | this._isMoveStart = false; 642 | this._rotation = 0; 643 | } 644 | 645 | 646 | private _getSize(x: number | cc.Size, y?: number) { 647 | if (x == undefined) { 648 | return cc.size(0, 0); 649 | } 650 | else if (x instanceof cc.Size) { 651 | return x; 652 | } 653 | else if (y != undefined) { 654 | return cc.size(x, y) 655 | } 656 | else { 657 | return cc.size(x, x) 658 | } 659 | } 660 | /** 661 | * 同步获取精灵帧 662 | * 663 | * @date 2019-04-16 664 | * @param {string} url 图片路径 665 | * @returns 666 | * @memberof PeekCard 667 | */ 668 | private async _loadSpriteFrameSync(url: string) { 669 | var res: cc.SpriteFrame = cc.loader.getRes(url, cc.SpriteFrame) 670 | if (res) { 671 | return res; 672 | } 673 | return new Promise((resolve) => { 674 | cc.loader.loadRes(url, cc.SpriteFrame, (err, res: cc.SpriteFrame) => { 675 | resolve(err ? null : res) 676 | }); 677 | }) 678 | } 679 | /** 680 | * 设置牌相关节点的精灵帧 681 | * 682 | * @date 2019-04-16 683 | * @param {cc.Node} node 684 | * @param {(string | cc.SpriteFrame)} spf 685 | * @memberof PeekCard 686 | */ 687 | private async _setNodeSpriteFrame(node: cc.Node, spf: string | cc.SpriteFrame, isRotate = false) { 688 | if (typeof spf === "string") { 689 | spf = await this._loadSpriteFrameSync(spf) 690 | } 691 | if (spf == null) { 692 | return; 693 | } 694 | 695 | // 精灵旋转 696 | this._setSpriteFrameRotate(spf, isRotate); 697 | // 刷新精灵显示 698 | let oldSpf = node.getComponent(cc.Sprite).spriteFrame; 699 | if (oldSpf == spf) { 700 | node.getComponent(cc.Sprite).spriteFrame = null; 701 | } 702 | 703 | node.getComponent(cc.Sprite).spriteFrame = spf; 704 | return spf; 705 | } 706 | 707 | private _setSpriteFrameRotate(spf: cc.SpriteFrame, isRotate: boolean) { 708 | if (!spf) { 709 | return false; 710 | } 711 | if (spf.isRotated() != isRotate) { 712 | let oldRect = spf.getRect(), newRect: cc.Rect; 713 | let texture = spf.getTexture(); 714 | if (texture.isValid == false) { 715 | return false; 716 | } 717 | if (this._checkDynamicAtlas(texture) == false) { 718 | // cc.log("非动态合图 旋转精灵", spf.isRotated(), isRotate, oldRect, spf.name) 719 | newRect = new cc.Rect(0, 0, oldRect.height, oldRect.width); 720 | } 721 | else { 722 | // cc.log("动态合图 旋转精灵", spf.isRotated(), isRotate, oldRect, spf.name) 723 | newRect = new cc.Rect(oldRect.x, oldRect.y, oldRect.height, oldRect.width); 724 | } 725 | 726 | spf.setRect(newRect); 727 | 728 | let oldSize = spf.getOriginalSize(); 729 | let newSize = cc.size(oldSize.height, oldSize.width); 730 | spf.setOriginalSize(newSize); 731 | 732 | spf.setRotated(isRotate); 733 | return true; 734 | } 735 | else { 736 | // cc.log("不旋转精灵", spf.isRotated(), isRotate, spf.name) 737 | } 738 | return false; 739 | } 740 | 741 | private _checkDynamicAtlas(texture: cc.Texture2D) { 742 | let dam = cc.dynamicAtlasManager; 743 | if (dam.enabled == false) { 744 | return false; 745 | } 746 | // 简单用纹理的size判断 747 | if (texture instanceof cc.RenderTexture && texture.width == dam.textureSize && texture.height == dam.textureSize) { 748 | return true; 749 | } 750 | 751 | return false; 752 | } 753 | 754 | static DirType = DirType; 755 | } 756 | -------------------------------------------------------------------------------- /assets/Script/PeekCard.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.5", 3 | "uuid": "f4c0cda1-43aa-403b-b7aa-8917d0ca17ee", 4 | "isPlugin": false, 5 | "loadPluginInWeb": true, 6 | "loadPluginInNative": true, 7 | "loadPluginInEditor": false, 8 | "subMetas": {} 9 | } -------------------------------------------------------------------------------- /assets/Texture.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.1", 3 | "uuid": "7b81d4e8-ec84-4716-968d-500ac1d78a54", 4 | "isGroup": false, 5 | "subMetas": {} 6 | } -------------------------------------------------------------------------------- /assets/Texture/singleColor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zPiggy/cccPeekCard/dce4a4059b5fdc888cf2062272c6657e4e1d9410/assets/Texture/singleColor.png -------------------------------------------------------------------------------- /assets/Texture/singleColor.png.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "2.2.0", 3 | "uuid": "a8027877-d8d6-4645-97a0-52d4a0123dba", 4 | "type": "sprite", 5 | "wrapMode": "clamp", 6 | "filterMode": "bilinear", 7 | "premultiplyAlpha": false, 8 | "subMetas": { 9 | "singleColor": { 10 | "ver": "1.0.3", 11 | "uuid": "410fb916-8721-4663-bab8-34397391ace7", 12 | "rawTextureUuid": "a8027877-d8d6-4645-97a0-52d4a0123dba", 13 | "trimType": "auto", 14 | "trimThreshold": 1, 15 | "rotated": false, 16 | "offsetX": 0, 17 | "offsetY": 0, 18 | "trimX": 0, 19 | "trimY": 0, 20 | "width": 2, 21 | "height": 2, 22 | "rawWidth": 2, 23 | "rawHeight": 2, 24 | "borderTop": 0, 25 | "borderBottom": 0, 26 | "borderLeft": 0, 27 | "borderRight": 0, 28 | "subMetas": {} 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /assets/resources.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.1", 3 | "uuid": "7183006f-4a88-4d9a-b277-8f908c0691ed", 4 | "isSubpackage": false, 5 | "subpackageName": "", 6 | "subMetas": {} 7 | } -------------------------------------------------------------------------------- /assets/resources/Cards.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.1", 3 | "uuid": "ed115bf5-57c5-4d75-8316-70c851710c51", 4 | "isSubpackage": false, 5 | "subpackageName": "", 6 | "subMetas": {} 7 | } -------------------------------------------------------------------------------- /assets/resources/Cards/Cards000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zPiggy/cccPeekCard/dce4a4059b5fdc888cf2062272c6657e4e1d9410/assets/resources/Cards/Cards000.png -------------------------------------------------------------------------------- /assets/resources/Cards/Cards000.png.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "2.2.0", 3 | "uuid": "dec5a1f8-70f0-43f3-8178-2e4596df3c85", 4 | "type": "sprite", 5 | "wrapMode": "clamp", 6 | "filterMode": "bilinear", 7 | "premultiplyAlpha": false, 8 | "subMetas": { 9 | "Cards000": { 10 | "ver": "1.0.3", 11 | "uuid": "6b48946f-5c61-4560-9c84-3b1dada4dee4", 12 | "rawTextureUuid": "dec5a1f8-70f0-43f3-8178-2e4596df3c85", 13 | "trimType": "auto", 14 | "trimThreshold": 1, 15 | "rotated": false, 16 | "offsetX": 0, 17 | "offsetY": 0, 18 | "trimX": 0, 19 | "trimY": 0, 20 | "width": 90, 21 | "height": 130, 22 | "rawWidth": 90, 23 | "rawHeight": 130, 24 | "borderTop": 0, 25 | "borderBottom": 0, 26 | "borderLeft": 0, 27 | "borderRight": 0, 28 | "subMetas": {} 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /assets/resources/Cards/Cards051.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zPiggy/cccPeekCard/dce4a4059b5fdc888cf2062272c6657e4e1d9410/assets/resources/Cards/Cards051.png -------------------------------------------------------------------------------- /assets/resources/Cards/Cards051.png.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "2.2.0", 3 | "uuid": "1f4d28b9-6ef6-4a3f-a059-b7492be6c0f8", 4 | "type": "sprite", 5 | "wrapMode": "clamp", 6 | "filterMode": "bilinear", 7 | "premultiplyAlpha": false, 8 | "subMetas": { 9 | "Cards051": { 10 | "ver": "1.0.3", 11 | "uuid": "71144251-e977-41c7-a175-a2b77f9050f2", 12 | "rawTextureUuid": "1f4d28b9-6ef6-4a3f-a059-b7492be6c0f8", 13 | "trimType": "auto", 14 | "trimThreshold": 1, 15 | "rotated": false, 16 | "offsetX": 0, 17 | "offsetY": 0, 18 | "trimX": 0, 19 | "trimY": 0, 20 | "width": 90, 21 | "height": 130, 22 | "rawWidth": 90, 23 | "rawHeight": 130, 24 | "borderTop": 0, 25 | "borderBottom": 0, 26 | "borderLeft": 0, 27 | "borderRight": 0, 28 | "subMetas": {} 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /assets/resources/Cards/Cards052.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zPiggy/cccPeekCard/dce4a4059b5fdc888cf2062272c6657e4e1d9410/assets/resources/Cards/Cards052.png -------------------------------------------------------------------------------- /assets/resources/Cards/Cards052.png.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "2.2.0", 3 | "uuid": "6430e3f9-523d-4c47-a48d-f2e66c468be4", 4 | "type": "sprite", 5 | "wrapMode": "clamp", 6 | "filterMode": "bilinear", 7 | "premultiplyAlpha": false, 8 | "subMetas": { 9 | "Cards052": { 10 | "ver": "1.0.3", 11 | "uuid": "28003b86-82ee-4dd5-82fa-e4c849f50440", 12 | "rawTextureUuid": "6430e3f9-523d-4c47-a48d-f2e66c468be4", 13 | "trimType": "auto", 14 | "trimThreshold": 1, 15 | "rotated": false, 16 | "offsetX": 0, 17 | "offsetY": 0, 18 | "trimX": 0, 19 | "trimY": 0, 20 | "width": 90, 21 | "height": 130, 22 | "rawWidth": 90, 23 | "rawHeight": 130, 24 | "borderTop": 0, 25 | "borderBottom": 0, 26 | "borderLeft": 0, 27 | "borderRight": 0, 28 | "subMetas": {} 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /assets/resources/HelloWorld.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zPiggy/cccPeekCard/dce4a4059b5fdc888cf2062272c6657e4e1d9410/assets/resources/HelloWorld.png -------------------------------------------------------------------------------- /assets/resources/HelloWorld.png.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "2.2.0", 3 | "uuid": "6aa0aa6a-ebee-4155-a088-a687a6aadec4", 4 | "type": "sprite", 5 | "wrapMode": "clamp", 6 | "filterMode": "bilinear", 7 | "premultiplyAlpha": false, 8 | "subMetas": { 9 | "HelloWorld": { 10 | "ver": "1.0.3", 11 | "uuid": "31bc895a-c003-4566-a9f3-2e54ae1c17dc", 12 | "rawTextureUuid": "6aa0aa6a-ebee-4155-a088-a687a6aadec4", 13 | "trimType": "auto", 14 | "trimThreshold": 1, 15 | "rotated": false, 16 | "offsetX": 0, 17 | "offsetY": 0, 18 | "trimX": 0, 19 | "trimY": 0, 20 | "width": 195, 21 | "height": 270, 22 | "rawWidth": 195, 23 | "rawHeight": 270, 24 | "borderTop": 0, 25 | "borderBottom": 0, 26 | "borderLeft": 0, 27 | "borderRight": 0, 28 | "subMetas": {} 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /assets/resources/shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zPiggy/cccPeekCard/dce4a4059b5fdc888cf2062272c6657e4e1d9410/assets/resources/shadow.png -------------------------------------------------------------------------------- /assets/resources/shadow.png.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "2.2.0", 3 | "uuid": "cefe72e8-608d-4212-92cf-677e5b182778", 4 | "type": "sprite", 5 | "wrapMode": "clamp", 6 | "filterMode": "bilinear", 7 | "premultiplyAlpha": false, 8 | "subMetas": { 9 | "shadow": { 10 | "ver": "1.0.3", 11 | "uuid": "d86dc2bc-b202-4c8a-bbf3-1332bebcf00b", 12 | "rawTextureUuid": "cefe72e8-608d-4212-92cf-677e5b182778", 13 | "trimType": "auto", 14 | "trimThreshold": 1, 15 | "rotated": false, 16 | "offsetX": 0, 17 | "offsetY": 0, 18 | "trimX": 0, 19 | "trimY": 0, 20 | "width": 20, 21 | "height": 20, 22 | "rawWidth": 20, 23 | "rawHeight": 20, 24 | "borderTop": 0, 25 | "borderBottom": 0, 26 | "borderLeft": 0, 27 | "borderRight": 0, 28 | "subMetas": {} 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "commonjs", 5 | "experimentalDecorators": true 6 | }, 7 | "exclude": [ 8 | "node_modules", 9 | ".vscode", 10 | "library", 11 | "local", 12 | "settings", 13 | "temp" 14 | ] 15 | } -------------------------------------------------------------------------------- /project.json: -------------------------------------------------------------------------------- 1 | { 2 | "engine": "cocos2d-html5", 3 | "packages": "packages" 4 | } -------------------------------------------------------------------------------- /settings/builder.json: -------------------------------------------------------------------------------- 1 | { 2 | "excludeScenes": [], 3 | "orientation": { 4 | "landscapeLeft": true, 5 | "landscapeRight": true, 6 | "portrait": false, 7 | "upsideDown": false 8 | }, 9 | "packageName": "org.cocos2d.helloworld", 10 | "startScene": "2d2f792f-a40c-49bb-a189-ed176a246e49", 11 | "title": "hello_world", 12 | "webOrientation": "auto" 13 | } -------------------------------------------------------------------------------- /settings/builder.panel.json: -------------------------------------------------------------------------------- 1 | { 2 | "excludeScenes": [], 3 | "packageName": "org.cocos2d.helloworld", 4 | "platform": "web-mobile", 5 | "startScene": "2d2f792f-a40c-49bb-a189-ed176a246e49", 6 | "title": "HelloWorld" 7 | } -------------------------------------------------------------------------------- /settings/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "assets-sort-type": "name", 3 | "collision-matrix": [ 4 | [ 5 | true 6 | ] 7 | ], 8 | "design-resolution-height": 720, 9 | "design-resolution-width": 1280, 10 | "excluded-modules": [], 11 | "facebook": { 12 | "appID": "", 13 | "audience": { 14 | "enable": false 15 | }, 16 | "enable": false, 17 | "live": { 18 | "enable": false 19 | } 20 | }, 21 | "fit-height": true, 22 | "fit-width": false, 23 | "group-list": [ 24 | "default" 25 | ], 26 | "last-module-event-record-time": 0, 27 | "simulator-orientation": false, 28 | "simulator-resolution": { 29 | "height": 640, 30 | "width": 960 31 | }, 32 | "use-customize-simulator": true, 33 | "use-project-simulator-setting": false 34 | } -------------------------------------------------------------------------------- /settings/services.json: -------------------------------------------------------------------------------- 1 | { 2 | "services": [ 3 | { 4 | "service_id": "235", 5 | "service_name": "Cocos Analytics", 6 | "service_icon": "https://account.cocos.com/CocosUdc/client/872b94af2e/3f8f31ccf66995e183044f167c092395.png", 7 | "service_desc": "一键集成,快速定位游戏玩家。统计更准确、数据更安全、接入更简单", 8 | "service_title": "精准了解游戏的新增、活跃、留存、付费等数据", 9 | "service_guide_url": "https://n-analytics.cocos.com/docs/", 10 | "service_sample_url": "https://github.com/CocosService/cocosAnalyticsDemo", 11 | "service_dev_url": "http://analytics.cocos.com/realtime/jump_to/", 12 | "service_type": "3", 13 | "service_type_zh": "公司和个人游戏", 14 | "support_platform": [ 15 | "Android", 16 | "iOS", 17 | "HTML5" 18 | ], 19 | "package_download_url": "https://download.cocos.com/CocosServices/plugins/service-analytics/1.2.7_2.1.2.zip", 20 | "package_version_desc": "

更新日期: 2020/04/29
\n更新说明:
\n1.修复重复点击重新加载云岚插件导致 Creator 插件系统报错的问题。
\n2.修复网络重试导致的性能损耗问题。
\n3.更新 cocosanalytics.d.ts 语法提示文档。
\n4.更新 SDK 版本。
\n", 21 | "service_component_name": "service-analytics", 22 | "package_versions": [ 23 | "1.2.7_2.1.2", 24 | "1.2.6_2.1.1", 25 | "1.2.5_2.1.1", 26 | "1.2.3_2.1.1", 27 | "1.2.0_2.1.0", 28 | "1.1.7_2.0.3", 29 | "1.1.6_2.0.1_2.0.2", 30 | "1.1.5_2.0.1", 31 | "1.1.4_2.0.1", 32 | "1.1.3_2.0.1", 33 | "1.1.2_2.0.0", 34 | "1.0.0_1.0.5" 35 | ], 36 | "build_platform": [ 37 | ], 38 | "require_verify": 0, 39 | "service_price": "", 40 | "service_protocol": "游戏首次开启该服务时,Cocos会后台通知服务方为游戏开通服务并初始化参数,服务方根据需要可能会获取您的Cocos账户信息,包括账户基本资料、游戏基本资料、账户余额等,点击确认开通按钮即视为您同意该服务访问您的账户信息,详见《Cocos用户服务协议》《Cocos隐私政策》", 41 | "service_group": "", 42 | "not_service": false 43 | }, 44 | { 45 | "service_id": "241", 46 | "service_name": "Matchvs", 47 | "service_icon": "https://account.cocos.com/CocosUdc/client/872b94af2e/14406719a07eb3d714d36e5edc6e06fa.png", 48 | "service_desc": "通过SDK接入快速实现联网功能、帧同步、国内外多节点、服务器独立部署、gameServer自定义游戏服务端逻辑。", 49 | "service_title": "专业成熟的移动游戏联网与服务端解决方案", 50 | "service_guide_url": "https://docs.cocos.com/creator/manual/zh/cocos-service/matchvs.html", 51 | "service_sample_url": "http://www.matchvs.com/serviceCourse", 52 | "service_dev_url": "http://www.matchvs.com/cocosLogin", 53 | "service_type": "3", 54 | "service_type_zh": "公司和个人游戏", 55 | "support_platform": [ 56 | "Android", 57 | "iOS", 58 | "HTML5" 59 | ], 60 | "package_download_url": "https://download.cocos.com/CocosServices/plugins/service-matchvs/1.0.10_3.7.9.10.zip", 61 | "package_version_desc": "

更新日期: 2019/9/12\n更新内容:\n1.多语言支持\n2.SDK日常更新

", 62 | "service_component_name": "service-matchvs", 63 | "package_versions": [ 64 | "1.0.9_3.7.9.9", 65 | "1.0.7_3.7.9.6", 66 | "1.0.6_3.7.9.2", 67 | "1.0.5_3.7.7.3", 68 | "1.0.3_3.7.6.4", 69 | "1.0.10_3.7.9.10" 70 | ], 71 | "build_platform": [ 72 | ], 73 | "require_verify": 0, 74 | "service_price": "该服务按使用量计费,计费规则,所产生的费用将由第三方从您的 Cocos 账户余额 中扣除。", 75 | "service_protocol": "游戏首次开启该服务时,Cocos会后台通知服务方为游戏开通服务并初始化参数,服务方根据需要可能会获取您的Cocos账户信息,包括账户基本资料、游戏基本资料、账户余额等,点击确认开通按钮即视为您同意该服务访问您的账户信息,详见《Cocos用户服务协议》《Cocos隐私政策》", 76 | "service_group": "", 77 | "not_service": false 78 | }, 79 | { 80 | "service_id": "242", 81 | "service_name": "Agora Voice", 82 | "service_icon": "https://account.cocos.com/CocosUdc/client/0ed3b350b5/273952d155b4cdb72d2b1bc61de91ade.png", 83 | "service_desc": "稳定、低耗、76ms超低延时、全球200+数据中心覆盖;变声器、超高音质、听声辩位等丰富玩法极速接入;全平台支持:Android、iOS、Web。", 84 | "service_title": "游戏内置实时语音", 85 | "service_guide_url": "https://docs.agora.io/cn/Interactive Gaming/game_c?platform=Cocos Creator", 86 | "service_sample_url": "https://github.com/AgoraIO/Voice-Call-for-Mobile-Gaming/tree/master/Basic-Voice-Call-for-Gaming/Hello-CocosCreator-Voice-Agora", 87 | "service_dev_url": "https://sso.agora.io/api/oauth/cocos/login", 88 | "service_type": "3", 89 | "service_type_zh": "公司和个人游戏", 90 | "support_platform": [ 91 | "Android", 92 | "iOS", 93 | "HTML5" 94 | ], 95 | "package_download_url": "https://download.cocos.com/CocosServices/plugins/service-agora/1.1.0_2.2.3.20_2.5.2.zip", 96 | "package_version_desc": "

更新日期: 2020/03/05
\n更新说明:
\n1、适配 Cocos Creator 2.3.x
\n", 97 | "service_component_name": "service-agora", 98 | "package_versions": [ 99 | "1.1.0_2.2.3.20_2.5.2", 100 | "1.0.2_2.2.3.20_2.5.2", 101 | "1.0.1_2.2.3.20_2.5.2" 102 | ], 103 | "build_platform": [ 104 | ], 105 | "require_verify": 1, 106 | "service_price": "该服务按使用量计费,计费规则,所产生的费用将由第三方从您的 Cocos 账户余额 中扣除。", 107 | "service_protocol": "游戏首次开启该服务时,Cocos会后台通知服务方为游戏开通服务并初始化参数,服务方根据需要可能会获取您的Cocos账户信息,包括账户基本资料、游戏基本资料、账户余额等,点击确认开通按钮即视为您同意该服务访问您的账户信息,详见《Cocos用户服务协议》《Cocos隐私政策》", 108 | "service_group": "", 109 | "not_service": false 110 | } 111 | ] 112 | } 113 | -------------------------------------------------------------------------------- /template-banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zPiggy/cccPeekCard/dce4a4059b5fdc888cf2062272c6657e4e1d9410/template-banner.png -------------------------------------------------------------------------------- /template.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "TEMPLATES.helloworld-ts.name", 3 | "desc": "TEMPLATES.helloworld-ts.desc", 4 | "banner": "template-banner.png" 5 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "lib": [ "dom", "es5", "es2015.promise" ], 5 | "target": "es5", 6 | "allowJs": true, 7 | "experimentalDecorators": true, 8 | "skipLibCheck": true 9 | }, 10 | "exclude": [ 11 | "node_modules", 12 | "library", 13 | "local", 14 | "temp", 15 | "build", 16 | "settings" 17 | ] 18 | } 19 | --------------------------------------------------------------------------------