├── .gitignore ├── README.md ├── assets ├── data.meta ├── data │ ├── levelData.json │ └── levelData.json.meta ├── game.fire ├── game.fire.meta ├── res.meta ├── res │ ├── prefab.meta │ ├── prefab │ │ ├── bubble.prefab │ │ └── bubble.prefab.meta │ ├── textures.meta │ └── textures │ │ ├── bg.png │ │ ├── bg.png.meta │ │ ├── bubbles.meta │ │ ├── bubbles │ │ ├── bubble1.png │ │ ├── bubble1.png.meta │ │ ├── bubble2.png │ │ ├── bubble2.png.meta │ │ ├── bubble3.png │ │ ├── bubble3.png.meta │ │ ├── bubble4.png │ │ └── bubble4.png.meta │ │ ├── shoot.meta │ │ └── shoot │ │ ├── shooter.png │ │ └── shooter.png.meta ├── script.meta └── script │ ├── Bubble.ts │ ├── Bubble.ts.meta │ ├── BubbleMgr.ts │ ├── BubbleMgr.ts.meta │ ├── Interface.ts │ ├── Interface.ts.meta │ ├── TouchMgr.ts │ ├── TouchMgr.ts.meta │ ├── Util.ts │ └── Util.ts.meta ├── creator.d.ts ├── jsconfig.json ├── project.json └── settings ├── project.json └── services.json /.gitignore: -------------------------------------------------------------------------------- 1 | #///////////////////////////////////////////////////////////////////////////// 2 | # Fireball Projects 3 | #///////////////////////////////////////////////////////////////////////////// 4 | 5 | /library/ 6 | /temp/ 7 | /local/ 8 | /build/ 9 | 10 | #///////////////////////////////////////////////////////////////////////////// 11 | # npm files 12 | #///////////////////////////////////////////////////////////////////////////// 13 | 14 | npm-debug.log 15 | node_modules/ 16 | 17 | #///////////////////////////////////////////////////////////////////////////// 18 | # Logs and databases 19 | #///////////////////////////////////////////////////////////////////////////// 20 | 21 | *.log 22 | *.sql 23 | *.sqlite 24 | 25 | #///////////////////////////////////////////////////////////////////////////// 26 | # files for debugger 27 | #///////////////////////////////////////////////////////////////////////////// 28 | 29 | *.sln 30 | *.csproj 31 | *.pidb 32 | *.unityproj 33 | *.suo 34 | 35 | #///////////////////////////////////////////////////////////////////////////// 36 | # OS generated files 37 | #///////////////////////////////////////////////////////////////////////////// 38 | 39 | .DS_Store 40 | ehthumbs.db 41 | Thumbs.db 42 | 43 | #///////////////////////////////////////////////////////////////////////////// 44 | # WebStorm files 45 | #///////////////////////////////////////////////////////////////////////////// 46 | 47 | .idea/ 48 | 49 | #////////////////////////// 50 | # VS Code files 51 | #////////////////////////// 52 | 53 | .vscode/ 54 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CocosCreator-Bubble 2 | 基于CocosCreator引擎2.1.2版本制作的《泡泡龙》游戏项目,注释很全新手无压力。 3 | 4 | 5 | Made by CocosCreator 2.1.2 . 6 | Convenient for beginners to learn. 7 | 8 | **内容**: 9 | - 使用JSON配置关卡 10 | - 有好的注释 11 | - 泡泡碰撞优化算法 12 | - 悬空检测 13 | - 一个可以参考的编程模式 14 | 15 | **Free配套讲解视频** 16 | 在Bilibili视频站搜索“**KUOKUO众享**”即可 17 | 18 | **O(∩_∩)O 下载时别忘了顺手点个星星哦** 19 | -------------------------------------------------------------------------------- /assets/data.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.1", 3 | "uuid": "5fab39bd-6792-493d-8f43-d3f6cabf548a", 4 | "isSubpackage": false, 5 | "subpackageName": "", 6 | "subMetas": {} 7 | } -------------------------------------------------------------------------------- /assets/data/levelData.json: -------------------------------------------------------------------------------- 1 | { 2 | "lv1": [ 3 | [2,2,2,3,3,3,4,4,4], 4 | [2,2,0,3,3,0,4,4], 5 | [0,2,0,0,3,0,0,4,0], 6 | [0,1,1,1,1,1,1,0], 7 | [0,0,1,1,0,1,1,0,0], 8 | [0,0,1,0,0,1,0,0], 9 | [0,0,0,0,0,0,0,0,0], 10 | [0,0,0,0,0,0,0,0], 11 | [0,0,0,0,0,0,0,0,0], 12 | [0,0,0,0,0,0,0,0], 13 | [0,0,0,0,0,0,0,0,0], 14 | [0,0,0,0,0,0,0,0] 15 | ] 16 | } -------------------------------------------------------------------------------- /assets/data/levelData.json.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.0", 3 | "uuid": "917b9546-68b8-479e-ad5f-5cb1e32ef234", 4 | "subMetas": {} 5 | } -------------------------------------------------------------------------------- /assets/game.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 | "__id__": 11 21 | } 22 | ], 23 | "_active": false, 24 | "_level": 0, 25 | "_components": [], 26 | "_prefab": null, 27 | "_opacity": 255, 28 | "_color": { 29 | "__type__": "cc.Color", 30 | "r": 255, 31 | "g": 255, 32 | "b": 255, 33 | "a": 255 34 | }, 35 | "_contentSize": { 36 | "__type__": "cc.Size", 37 | "width": 0, 38 | "height": 0 39 | }, 40 | "_anchorPoint": { 41 | "__type__": "cc.Vec2", 42 | "x": 0, 43 | "y": 0 44 | }, 45 | "_scale": { 46 | "__type__": "cc.Vec3", 47 | "x": 1, 48 | "y": 1, 49 | "z": 1 50 | }, 51 | "_eulerAngles": { 52 | "__type__": "cc.Vec3", 53 | "x": 0, 54 | "y": 0, 55 | "z": 0 56 | }, 57 | "_is3DNode": true, 58 | "groupIndex": 0, 59 | "autoReleaseAssets": false, 60 | "_id": "8a7db86e-40ea-4005-ad31-ef806fec11ee" 61 | }, 62 | { 63 | "__type__": "cc.Node", 64 | "_name": "Canvas", 65 | "_objFlags": 0, 66 | "_parent": { 67 | "__id__": 1 68 | }, 69 | "_children": [ 70 | { 71 | "__id__": 3 72 | }, 73 | { 74 | "__id__": 5 75 | } 76 | ], 77 | "_active": true, 78 | "_level": 1, 79 | "_components": [ 80 | { 81 | "__id__": 7 82 | }, 83 | { 84 | "__id__": 8 85 | } 86 | ], 87 | "_prefab": null, 88 | "_opacity": 255, 89 | "_color": { 90 | "__type__": "cc.Color", 91 | "r": 255, 92 | "g": 255, 93 | "b": 255, 94 | "a": 255 95 | }, 96 | "_contentSize": { 97 | "__type__": "cc.Size", 98 | "width": 720, 99 | "height": 1280 100 | }, 101 | "_anchorPoint": { 102 | "__type__": "cc.Vec2", 103 | "x": 0.5, 104 | "y": 0.5 105 | }, 106 | "_position": { 107 | "__type__": "cc.Vec3", 108 | "x": 360, 109 | "y": 640, 110 | "z": 0 111 | }, 112 | "_scale": { 113 | "__type__": "cc.Vec3", 114 | "x": 1, 115 | "y": 1, 116 | "z": 1 117 | }, 118 | "_eulerAngles": { 119 | "__type__": "cc.Vec3", 120 | "x": 0, 121 | "y": 0, 122 | "z": 0 123 | }, 124 | "_skewX": 0, 125 | "_skewY": 0, 126 | "_is3DNode": false, 127 | "groupIndex": 0, 128 | "_id": "53UUydPLZOpa+h6FhzKizp" 129 | }, 130 | { 131 | "__type__": "cc.Node", 132 | "_name": "Main Camera", 133 | "_objFlags": 0, 134 | "_parent": { 135 | "__id__": 2 136 | }, 137 | "_children": [], 138 | "_active": true, 139 | "_level": 1, 140 | "_components": [ 141 | { 142 | "__id__": 4 143 | } 144 | ], 145 | "_prefab": null, 146 | "_opacity": 255, 147 | "_color": { 148 | "__type__": "cc.Color", 149 | "r": 255, 150 | "g": 255, 151 | "b": 255, 152 | "a": 255 153 | }, 154 | "_contentSize": { 155 | "__type__": "cc.Size", 156 | "width": 0, 157 | "height": 0 158 | }, 159 | "_anchorPoint": { 160 | "__type__": "cc.Vec2", 161 | "x": 0.5, 162 | "y": 0.5 163 | }, 164 | "_position": { 165 | "__type__": "cc.Vec3", 166 | "x": 0, 167 | "y": 0, 168 | "z": 1108.5125168440816 169 | }, 170 | "_scale": { 171 | "__type__": "cc.Vec3", 172 | "x": 1, 173 | "y": 1, 174 | "z": 1 175 | }, 176 | "_eulerAngles": { 177 | "__type__": "cc.Vec3", 178 | "x": 0, 179 | "y": 0, 180 | "z": 0 181 | }, 182 | "_skewX": 0, 183 | "_skewY": 0, 184 | "_is3DNode": false, 185 | "groupIndex": 0, 186 | "_id": "b7I7i0ythBQZfDkmS3w3cr" 187 | }, 188 | { 189 | "__type__": "cc.Camera", 190 | "_name": "", 191 | "_objFlags": 0, 192 | "node": { 193 | "__id__": 3 194 | }, 195 | "_enabled": true, 196 | "_cullingMask": 4294967295, 197 | "_clearFlags": 7, 198 | "_backgroundColor": { 199 | "__type__": "cc.Color", 200 | "r": 0, 201 | "g": 0, 202 | "b": 0, 203 | "a": 255 204 | }, 205 | "_depth": -1, 206 | "_zoomRatio": 1, 207 | "_targetTexture": null, 208 | "_fov": 60, 209 | "_orthoSize": 10, 210 | "_nearClip": 1, 211 | "_farClip": 4096, 212 | "_ortho": true, 213 | "_rect": { 214 | "__type__": "cc.Rect", 215 | "x": 0, 216 | "y": 0, 217 | "width": 1, 218 | "height": 1 219 | }, 220 | "_renderStages": 1, 221 | "_id": "07PAe1g3hEW5SsoMKWyCiW" 222 | }, 223 | { 224 | "__type__": "cc.Node", 225 | "_name": "bg", 226 | "_objFlags": 0, 227 | "_parent": { 228 | "__id__": 2 229 | }, 230 | "_children": [], 231 | "_active": true, 232 | "_level": 1, 233 | "_components": [ 234 | { 235 | "__id__": 6 236 | } 237 | ], 238 | "_prefab": null, 239 | "_opacity": 255, 240 | "_color": { 241 | "__type__": "cc.Color", 242 | "r": 255, 243 | "g": 255, 244 | "b": 255, 245 | "a": 255 246 | }, 247 | "_contentSize": { 248 | "__type__": "cc.Size", 249 | "width": 720, 250 | "height": 1280 251 | }, 252 | "_anchorPoint": { 253 | "__type__": "cc.Vec2", 254 | "x": 0.5, 255 | "y": 0.5 256 | }, 257 | "_position": { 258 | "__type__": "cc.Vec3", 259 | "x": 0, 260 | "y": 0, 261 | "z": 0 262 | }, 263 | "_scale": { 264 | "__type__": "cc.Vec3", 265 | "x": 1, 266 | "y": 1, 267 | "z": 1 268 | }, 269 | "_eulerAngles": { 270 | "__type__": "cc.Vec3", 271 | "x": 0, 272 | "y": 0, 273 | "z": 0 274 | }, 275 | "_skewX": 0, 276 | "_skewY": 0, 277 | "_is3DNode": false, 278 | "groupIndex": 0, 279 | "_id": "8a0Gat9EVFr4dta5pNEo2L" 280 | }, 281 | { 282 | "__type__": "cc.Sprite", 283 | "_name": "", 284 | "_objFlags": 0, 285 | "node": { 286 | "__id__": 5 287 | }, 288 | "_enabled": true, 289 | "_materials": [ 290 | { 291 | "__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432" 292 | } 293 | ], 294 | "_srcBlendFactor": 770, 295 | "_dstBlendFactor": 771, 296 | "_spriteFrame": { 297 | "__uuid__": "e8904d7e-e46a-45f3-a319-150119858587" 298 | }, 299 | "_type": 0, 300 | "_sizeMode": 1, 301 | "_fillType": 0, 302 | "_fillCenter": { 303 | "__type__": "cc.Vec2", 304 | "x": 0, 305 | "y": 0 306 | }, 307 | "_fillStart": 0, 308 | "_fillRange": 0, 309 | "_isTrimmedMode": true, 310 | "_atlas": null, 311 | "_id": "baMzXQDt9PK7BdpMsbZIx1" 312 | }, 313 | { 314 | "__type__": "cc.Canvas", 315 | "_name": "", 316 | "_objFlags": 0, 317 | "node": { 318 | "__id__": 2 319 | }, 320 | "_enabled": true, 321 | "_designResolution": { 322 | "__type__": "cc.Size", 323 | "width": 720, 324 | "height": 1280 325 | }, 326 | "_fitWidth": true, 327 | "_fitHeight": false, 328 | "_id": "66rNXTRbdIf4zQpjtxeC03" 329 | }, 330 | { 331 | "__type__": "6e8f2bpKJRLLJnPCx8f3vFZ", 332 | "_name": "", 333 | "_objFlags": 0, 334 | "node": { 335 | "__id__": 2 336 | }, 337 | "_enabled": true, 338 | "shooter": { 339 | "__id__": 9 340 | }, 341 | "_id": "d6EiZd6VpG36qcNqNdCSuI" 342 | }, 343 | { 344 | "__type__": "cc.Node", 345 | "_name": "shooter", 346 | "_objFlags": 0, 347 | "_parent": { 348 | "__id__": 10 349 | }, 350 | "_children": [], 351 | "_active": true, 352 | "_level": 3, 353 | "_components": [ 354 | { 355 | "__id__": 14 356 | } 357 | ], 358 | "_prefab": null, 359 | "_opacity": 255, 360 | "_color": { 361 | "__type__": "cc.Color", 362 | "r": 255, 363 | "g": 255, 364 | "b": 255, 365 | "a": 255 366 | }, 367 | "_contentSize": { 368 | "__type__": "cc.Size", 369 | "width": 40, 370 | "height": 131 371 | }, 372 | "_anchorPoint": { 373 | "__type__": "cc.Vec2", 374 | "x": 0.5, 375 | "y": -0.5 376 | }, 377 | "_position": { 378 | "__type__": "cc.Vec3", 379 | "x": 360, 380 | "y": 180, 381 | "z": 0 382 | }, 383 | "_scale": { 384 | "__type__": "cc.Vec3", 385 | "x": 1, 386 | "y": 1, 387 | "z": 1 388 | }, 389 | "_eulerAngles": { 390 | "__type__": "cc.Vec3", 391 | "x": 0, 392 | "y": 0, 393 | "z": 0 394 | }, 395 | "_skewX": 0, 396 | "_skewY": 0, 397 | "_is3DNode": false, 398 | "groupIndex": 0, 399 | "_id": "e1SOEVDRlPd680IvW73b5t" 400 | }, 401 | { 402 | "__type__": "cc.Node", 403 | "_name": "ShootLayer", 404 | "_objFlags": 0, 405 | "_parent": { 406 | "__id__": 11 407 | }, 408 | "_children": [ 409 | { 410 | "__id__": 9 411 | } 412 | ], 413 | "_active": true, 414 | "_level": 2, 415 | "_components": [], 416 | "_prefab": null, 417 | "_opacity": 255, 418 | "_color": { 419 | "__type__": "cc.Color", 420 | "r": 255, 421 | "g": 255, 422 | "b": 255, 423 | "a": 255 424 | }, 425 | "_contentSize": { 426 | "__type__": "cc.Size", 427 | "width": 0, 428 | "height": 0 429 | }, 430 | "_anchorPoint": { 431 | "__type__": "cc.Vec2", 432 | "x": 0.5, 433 | "y": 0.5 434 | }, 435 | "_position": { 436 | "__type__": "cc.Vec3", 437 | "x": 0, 438 | "y": 0, 439 | "z": 0 440 | }, 441 | "_scale": { 442 | "__type__": "cc.Vec3", 443 | "x": 1, 444 | "y": 1, 445 | "z": 1 446 | }, 447 | "_eulerAngles": { 448 | "__type__": "cc.Vec3", 449 | "x": 0, 450 | "y": 0, 451 | "z": 0 452 | }, 453 | "_skewX": 0, 454 | "_skewY": 0, 455 | "_is3DNode": false, 456 | "groupIndex": 0, 457 | "_id": "43uXlv+8JHX7gxKFlcjej1" 458 | }, 459 | { 460 | "__type__": "cc.Node", 461 | "_name": "GameLayer", 462 | "_objFlags": 0, 463 | "_parent": { 464 | "__id__": 1 465 | }, 466 | "_children": [ 467 | { 468 | "__id__": 10 469 | }, 470 | { 471 | "__id__": 12 472 | } 473 | ], 474 | "_active": true, 475 | "_level": 1, 476 | "_components": [], 477 | "_prefab": null, 478 | "_opacity": 255, 479 | "_color": { 480 | "__type__": "cc.Color", 481 | "r": 255, 482 | "g": 255, 483 | "b": 255, 484 | "a": 255 485 | }, 486 | "_contentSize": { 487 | "__type__": "cc.Size", 488 | "width": 0, 489 | "height": 0 490 | }, 491 | "_anchorPoint": { 492 | "__type__": "cc.Vec2", 493 | "x": 0.5, 494 | "y": 0.5 495 | }, 496 | "_position": { 497 | "__type__": "cc.Vec3", 498 | "x": 0, 499 | "y": 0, 500 | "z": 0 501 | }, 502 | "_scale": { 503 | "__type__": "cc.Vec3", 504 | "x": 1, 505 | "y": 1, 506 | "z": 1 507 | }, 508 | "_eulerAngles": { 509 | "__type__": "cc.Vec3", 510 | "x": 0, 511 | "y": 0, 512 | "z": 0 513 | }, 514 | "_skewX": 0, 515 | "_skewY": 0, 516 | "_is3DNode": false, 517 | "groupIndex": 0, 518 | "_id": "a01MPeoe1Iupu6gyILn6e6" 519 | }, 520 | { 521 | "__type__": "cc.Node", 522 | "_name": "BubbleLayer", 523 | "_objFlags": 0, 524 | "_parent": { 525 | "__id__": 11 526 | }, 527 | "_children": [], 528 | "_active": true, 529 | "_level": 2, 530 | "_components": [ 531 | { 532 | "__id__": 13 533 | } 534 | ], 535 | "_prefab": null, 536 | "_opacity": 255, 537 | "_color": { 538 | "__type__": "cc.Color", 539 | "r": 255, 540 | "g": 255, 541 | "b": 255, 542 | "a": 255 543 | }, 544 | "_contentSize": { 545 | "__type__": "cc.Size", 546 | "width": 0, 547 | "height": 0 548 | }, 549 | "_anchorPoint": { 550 | "__type__": "cc.Vec2", 551 | "x": 0.5, 552 | "y": 0.5 553 | }, 554 | "_position": { 555 | "__type__": "cc.Vec3", 556 | "x": 0, 557 | "y": 0, 558 | "z": 0 559 | }, 560 | "_scale": { 561 | "__type__": "cc.Vec3", 562 | "x": 1, 563 | "y": 1, 564 | "z": 1 565 | }, 566 | "_eulerAngles": { 567 | "__type__": "cc.Vec3", 568 | "x": 0, 569 | "y": 0, 570 | "z": 0 571 | }, 572 | "_skewX": 0, 573 | "_skewY": 0, 574 | "_is3DNode": false, 575 | "groupIndex": 0, 576 | "_id": "c3nPtTsMhJqoN36wh7hDzA" 577 | }, 578 | { 579 | "__type__": "c3c35Rv27JBRIOSDzrh7MRZ", 580 | "_name": "", 581 | "_objFlags": 0, 582 | "node": { 583 | "__id__": 12 584 | }, 585 | "_enabled": true, 586 | "bubbleSpriteFrame": [ 587 | { 588 | "__uuid__": "f8ebb73e-6f80-4166-a352-8e043ae708df" 589 | }, 590 | { 591 | "__uuid__": "2ff6dd8e-6890-4950-8bb3-b0b2978ca97d" 592 | }, 593 | { 594 | "__uuid__": "7fe1a0d4-37d0-4c6e-956b-19d09a99fb0e" 595 | }, 596 | { 597 | "__uuid__": "3c26acf7-0d23-4b6a-b56b-3b5ad1f3519b" 598 | } 599 | ], 600 | "bubblePrefab": { 601 | "__uuid__": "91c2ccd6-0bd3-4da2-b4cc-58797a202360" 602 | }, 603 | "shooter": { 604 | "__id__": 9 605 | }, 606 | "levelData": { 607 | "__uuid__": "917b9546-68b8-479e-ad5f-5cb1e32ef234" 608 | }, 609 | "_id": "eamkUHYPpOGp5dAeumBIoQ" 610 | }, 611 | { 612 | "__type__": "cc.Sprite", 613 | "_name": "", 614 | "_objFlags": 0, 615 | "node": { 616 | "__id__": 9 617 | }, 618 | "_enabled": true, 619 | "_materials": [ 620 | { 621 | "__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432" 622 | } 623 | ], 624 | "_srcBlendFactor": 770, 625 | "_dstBlendFactor": 771, 626 | "_spriteFrame": { 627 | "__uuid__": "7bc48a43-36c4-4ed2-a4df-a50bf76e462f" 628 | }, 629 | "_type": 0, 630 | "_sizeMode": 1, 631 | "_fillType": 0, 632 | "_fillCenter": { 633 | "__type__": "cc.Vec2", 634 | "x": 0, 635 | "y": 0 636 | }, 637 | "_fillStart": 0, 638 | "_fillRange": 0, 639 | "_isTrimmedMode": true, 640 | "_atlas": null, 641 | "_id": "32gt9M6IVGz6oID0QzTVWC" 642 | } 643 | ] -------------------------------------------------------------------------------- /assets/game.fire.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.2.0", 3 | "uuid": "8a7db86e-40ea-4005-ad31-ef806fec11ee", 4 | "asyncLoadAssets": false, 5 | "autoReleaseAssets": false, 6 | "subMetas": {} 7 | } -------------------------------------------------------------------------------- /assets/res.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.1", 3 | "uuid": "cf91833e-a427-42e8-89ce-64a6223805e7", 4 | "isSubpackage": false, 5 | "subpackageName": "", 6 | "subMetas": {} 7 | } -------------------------------------------------------------------------------- /assets/res/prefab.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.1", 3 | "uuid": "01583de9-f3c1-4ad2-866a-bab38b987937", 4 | "isSubpackage": false, 5 | "subpackageName": "", 6 | "subMetas": {} 7 | } -------------------------------------------------------------------------------- /assets/res/prefab/bubble.prefab: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "__type__": "cc.Prefab", 4 | "_name": "", 5 | "_objFlags": 0, 6 | "_native": "", 7 | "data": { 8 | "__id__": 1 9 | }, 10 | "optimizationPolicy": 0, 11 | "asyncLoadAssets": false, 12 | "readonly": false 13 | }, 14 | { 15 | "__type__": "cc.Node", 16 | "_name": "bubble", 17 | "_objFlags": 0, 18 | "_parent": null, 19 | "_children": [], 20 | "_active": true, 21 | "_level": 1, 22 | "_components": [ 23 | { 24 | "__id__": 2 25 | }, 26 | { 27 | "__id__": 3 28 | } 29 | ], 30 | "_prefab": { 31 | "__id__": 4 32 | }, 33 | "_opacity": 255, 34 | "_color": { 35 | "__type__": "cc.Color", 36 | "r": 255, 37 | "g": 255, 38 | "b": 255, 39 | "a": 255 40 | }, 41 | "_contentSize": { 42 | "__type__": "cc.Size", 43 | "width": 80, 44 | "height": 80 45 | }, 46 | "_anchorPoint": { 47 | "__type__": "cc.Vec2", 48 | "x": 0.5, 49 | "y": 0.5 50 | }, 51 | "_position": { 52 | "__type__": "cc.Vec3", 53 | "x": 0, 54 | "y": 0, 55 | "z": 0 56 | }, 57 | "_scale": { 58 | "__type__": "cc.Vec3", 59 | "x": 1, 60 | "y": 1, 61 | "z": 1 62 | }, 63 | "_eulerAngles": { 64 | "__type__": "cc.Vec3", 65 | "x": 0, 66 | "y": 0, 67 | "z": 0 68 | }, 69 | "_skewX": 0, 70 | "_skewY": 0, 71 | "_is3DNode": false, 72 | "groupIndex": 0, 73 | "_id": "" 74 | }, 75 | { 76 | "__type__": "cc.Sprite", 77 | "_name": "", 78 | "_objFlags": 0, 79 | "node": { 80 | "__id__": 1 81 | }, 82 | "_enabled": true, 83 | "_materials": [ 84 | { 85 | "__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432" 86 | } 87 | ], 88 | "_srcBlendFactor": 770, 89 | "_dstBlendFactor": 771, 90 | "_spriteFrame": { 91 | "__uuid__": "f8ebb73e-6f80-4166-a352-8e043ae708df" 92 | }, 93 | "_type": 0, 94 | "_sizeMode": 1, 95 | "_fillType": 0, 96 | "_fillCenter": { 97 | "__type__": "cc.Vec2", 98 | "x": 0, 99 | "y": 0 100 | }, 101 | "_fillStart": 0, 102 | "_fillRange": 0, 103 | "_isTrimmedMode": true, 104 | "_atlas": null, 105 | "_id": "" 106 | }, 107 | { 108 | "__type__": "2620bjKKJhPi6b/2EnkJDAa", 109 | "_name": "", 110 | "_objFlags": 0, 111 | "node": { 112 | "__id__": 1 113 | }, 114 | "_enabled": true, 115 | "_id": "" 116 | }, 117 | { 118 | "__type__": "cc.PrefabInfo", 119 | "root": { 120 | "__id__": 1 121 | }, 122 | "asset": { 123 | "__uuid__": "91c2ccd6-0bd3-4da2-b4cc-58797a202360" 124 | }, 125 | "fileId": "3d4jKgOJlEnJTpQvENhkWO", 126 | "sync": false 127 | } 128 | ] -------------------------------------------------------------------------------- /assets/res/prefab/bubble.prefab.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.2.0", 3 | "uuid": "91c2ccd6-0bd3-4da2-b4cc-58797a202360", 4 | "optimizationPolicy": "AUTO", 5 | "asyncLoadAssets": false, 6 | "readonly": false, 7 | "subMetas": {} 8 | } -------------------------------------------------------------------------------- /assets/res/textures.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.1", 3 | "uuid": "e18b149f-6e9e-49d0-89ed-f3b871b0f45d", 4 | "isSubpackage": false, 5 | "subpackageName": "", 6 | "subMetas": {} 7 | } -------------------------------------------------------------------------------- /assets/res/textures/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KuoKuo666/CocosCreator-Bubble/4e597d5440941b84df12e65fe3d098cb97df647a/assets/res/textures/bg.png -------------------------------------------------------------------------------- /assets/res/textures/bg.png.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "2.3.1", 3 | "uuid": "7bb0f575-dfe8-45af-ab1e-e9cf63c610a9", 4 | "type": "sprite", 5 | "wrapMode": "clamp", 6 | "filterMode": "bilinear", 7 | "premultiplyAlpha": false, 8 | "platformSettings": {}, 9 | "subMetas": { 10 | "bg": { 11 | "ver": "1.0.4", 12 | "uuid": "e8904d7e-e46a-45f3-a319-150119858587", 13 | "rawTextureUuid": "7bb0f575-dfe8-45af-ab1e-e9cf63c610a9", 14 | "trimType": "custom", 15 | "trimThreshold": 1, 16 | "rotated": false, 17 | "offsetX": 0, 18 | "offsetY": 0, 19 | "trimX": 0, 20 | "trimY": 0, 21 | "width": 720, 22 | "height": 1280, 23 | "rawWidth": 720, 24 | "rawHeight": 1280, 25 | "borderTop": 0, 26 | "borderBottom": 0, 27 | "borderLeft": 0, 28 | "borderRight": 0, 29 | "subMetas": {} 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /assets/res/textures/bubbles.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.1", 3 | "uuid": "910de0c5-4449-43dd-9a86-86739f810cd3", 4 | "isSubpackage": false, 5 | "subpackageName": "", 6 | "subMetas": {} 7 | } -------------------------------------------------------------------------------- /assets/res/textures/bubbles/bubble1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KuoKuo666/CocosCreator-Bubble/4e597d5440941b84df12e65fe3d098cb97df647a/assets/res/textures/bubbles/bubble1.png -------------------------------------------------------------------------------- /assets/res/textures/bubbles/bubble1.png.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "2.3.1", 3 | "uuid": "c24f9b07-2e19-488f-affe-945da3e86b2b", 4 | "type": "sprite", 5 | "wrapMode": "clamp", 6 | "filterMode": "bilinear", 7 | "premultiplyAlpha": false, 8 | "platformSettings": {}, 9 | "subMetas": { 10 | "bubble1": { 11 | "ver": "1.0.4", 12 | "uuid": "f8ebb73e-6f80-4166-a352-8e043ae708df", 13 | "rawTextureUuid": "c24f9b07-2e19-488f-affe-945da3e86b2b", 14 | "trimType": "custom", 15 | "trimThreshold": 1, 16 | "rotated": false, 17 | "offsetX": 0, 18 | "offsetY": 0, 19 | "trimX": 0, 20 | "trimY": 0, 21 | "width": 80, 22 | "height": 80, 23 | "rawWidth": 80, 24 | "rawHeight": 80, 25 | "borderTop": 0, 26 | "borderBottom": 0, 27 | "borderLeft": 0, 28 | "borderRight": 0, 29 | "subMetas": {} 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /assets/res/textures/bubbles/bubble2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KuoKuo666/CocosCreator-Bubble/4e597d5440941b84df12e65fe3d098cb97df647a/assets/res/textures/bubbles/bubble2.png -------------------------------------------------------------------------------- /assets/res/textures/bubbles/bubble2.png.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "2.3.1", 3 | "uuid": "ec8937fa-55f5-4d97-b41d-73d44225ff50", 4 | "type": "sprite", 5 | "wrapMode": "clamp", 6 | "filterMode": "bilinear", 7 | "premultiplyAlpha": false, 8 | "platformSettings": {}, 9 | "subMetas": { 10 | "bubble2": { 11 | "ver": "1.0.4", 12 | "uuid": "2ff6dd8e-6890-4950-8bb3-b0b2978ca97d", 13 | "rawTextureUuid": "ec8937fa-55f5-4d97-b41d-73d44225ff50", 14 | "trimType": "custom", 15 | "trimThreshold": 1, 16 | "rotated": false, 17 | "offsetX": 0, 18 | "offsetY": 0, 19 | "trimX": 0, 20 | "trimY": 0, 21 | "width": 80, 22 | "height": 80, 23 | "rawWidth": 80, 24 | "rawHeight": 80, 25 | "borderTop": 0, 26 | "borderBottom": 0, 27 | "borderLeft": 0, 28 | "borderRight": 0, 29 | "subMetas": {} 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /assets/res/textures/bubbles/bubble3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KuoKuo666/CocosCreator-Bubble/4e597d5440941b84df12e65fe3d098cb97df647a/assets/res/textures/bubbles/bubble3.png -------------------------------------------------------------------------------- /assets/res/textures/bubbles/bubble3.png.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "2.3.1", 3 | "uuid": "7504a837-22f3-48ed-9cdd-5f5318cff6c7", 4 | "type": "sprite", 5 | "wrapMode": "clamp", 6 | "filterMode": "bilinear", 7 | "premultiplyAlpha": false, 8 | "platformSettings": {}, 9 | "subMetas": { 10 | "bubble3": { 11 | "ver": "1.0.4", 12 | "uuid": "7fe1a0d4-37d0-4c6e-956b-19d09a99fb0e", 13 | "rawTextureUuid": "7504a837-22f3-48ed-9cdd-5f5318cff6c7", 14 | "trimType": "custom", 15 | "trimThreshold": 1, 16 | "rotated": false, 17 | "offsetX": 0, 18 | "offsetY": 0, 19 | "trimX": 0, 20 | "trimY": 0, 21 | "width": 80, 22 | "height": 80, 23 | "rawWidth": 80, 24 | "rawHeight": 80, 25 | "borderTop": 0, 26 | "borderBottom": 0, 27 | "borderLeft": 0, 28 | "borderRight": 0, 29 | "subMetas": {} 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /assets/res/textures/bubbles/bubble4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KuoKuo666/CocosCreator-Bubble/4e597d5440941b84df12e65fe3d098cb97df647a/assets/res/textures/bubbles/bubble4.png -------------------------------------------------------------------------------- /assets/res/textures/bubbles/bubble4.png.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "2.3.1", 3 | "uuid": "68dd0831-75a9-41ea-8112-5159283f9b5e", 4 | "type": "sprite", 5 | "wrapMode": "clamp", 6 | "filterMode": "bilinear", 7 | "premultiplyAlpha": false, 8 | "platformSettings": {}, 9 | "subMetas": { 10 | "bubble4": { 11 | "ver": "1.0.4", 12 | "uuid": "3c26acf7-0d23-4b6a-b56b-3b5ad1f3519b", 13 | "rawTextureUuid": "68dd0831-75a9-41ea-8112-5159283f9b5e", 14 | "trimType": "custom", 15 | "trimThreshold": 1, 16 | "rotated": false, 17 | "offsetX": 0, 18 | "offsetY": 0, 19 | "trimX": 0, 20 | "trimY": 0, 21 | "width": 80, 22 | "height": 80, 23 | "rawWidth": 80, 24 | "rawHeight": 80, 25 | "borderTop": 0, 26 | "borderBottom": 0, 27 | "borderLeft": 0, 28 | "borderRight": 0, 29 | "subMetas": {} 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /assets/res/textures/shoot.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.1", 3 | "uuid": "d51177ac-c6b0-45ae-bc0a-85a9080086e5", 4 | "isSubpackage": false, 5 | "subpackageName": "", 6 | "subMetas": {} 7 | } -------------------------------------------------------------------------------- /assets/res/textures/shoot/shooter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KuoKuo666/CocosCreator-Bubble/4e597d5440941b84df12e65fe3d098cb97df647a/assets/res/textures/shoot/shooter.png -------------------------------------------------------------------------------- /assets/res/textures/shoot/shooter.png.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "2.3.1", 3 | "uuid": "f3a97a43-32c8-41b7-b672-c9143186b8bb", 4 | "type": "sprite", 5 | "wrapMode": "clamp", 6 | "filterMode": "bilinear", 7 | "premultiplyAlpha": false, 8 | "platformSettings": {}, 9 | "subMetas": { 10 | "shooter": { 11 | "ver": "1.0.4", 12 | "uuid": "7bc48a43-36c4-4ed2-a4df-a50bf76e462f", 13 | "rawTextureUuid": "f3a97a43-32c8-41b7-b672-c9143186b8bb", 14 | "trimType": "custom", 15 | "trimThreshold": 1, 16 | "rotated": false, 17 | "offsetX": 0, 18 | "offsetY": 0, 19 | "trimX": 0, 20 | "trimY": 0, 21 | "width": 40, 22 | "height": 131, 23 | "rawWidth": 40, 24 | "rawHeight": 131, 25 | "borderTop": 0, 26 | "borderBottom": 0, 27 | "borderLeft": 0, 28 | "borderRight": 0, 29 | "subMetas": {} 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /assets/script.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.1", 3 | "uuid": "504c2b9b-61e3-49e9-9f2f-87af8471aa67", 4 | "isSubpackage": false, 5 | "subpackageName": "", 6 | "subMetas": {} 7 | } -------------------------------------------------------------------------------- /assets/script/Bubble.ts: -------------------------------------------------------------------------------- 1 | import BubbleMgr from "./BubbleMgr"; 2 | 3 | const {ccclass, property} = cc._decorator; 4 | 5 | @ccclass 6 | export default class Bubble extends cc.Component { 7 | 8 | // 父节点类 9 | private parent: BubbleMgr; 10 | 11 | /** 初始化 */ 12 | public init (parent: BubbleMgr, position: cc.Vec2, spriteFrame: cc.SpriteFrame): void { 13 | parent.node.addChild(this.node); 14 | this.parent = parent; 15 | this.node.position = position; 16 | this.setSpriteFrame(spriteFrame); 17 | } 18 | 19 | /** 设置纹理 */ 20 | public setSpriteFrame (spriteFrame: cc.SpriteFrame): void { 21 | this.getComponent(cc.Sprite).spriteFrame = spriteFrame; 22 | } 23 | 24 | /** 死亡动画 */ 25 | public playDeathAnimation (index: cc.Vec2): void { 26 | this.node.runAction( 27 | cc.sequence( 28 | // 膨胀后消除自己 29 | cc.scaleTo(0.1, 1.2), 30 | cc.scaleTo(0.1, 1.0), 31 | cc.callFunc(() => { 32 | // 将位置空出 33 | this.parent.bubblesArray[index.x][index.y] = undefined; 34 | }, this), 35 | cc.removeSelf() 36 | ) 37 | ); 38 | } 39 | 40 | /** 下落动画 */ 41 | public playDownAnimation (index: cc.Vec2): void { 42 | this.node.runAction( 43 | // 渐隐下落 44 | cc.sequence( 45 | cc.spawn( 46 | cc.moveBy(0.5, 0, -300), 47 | cc.fadeOut(0.5) 48 | ), 49 | cc.callFunc(() => { 50 | this.parent.bubblesArray[index.x][index.y] = undefined; 51 | }, this), 52 | cc.removeSelf() 53 | ) 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /assets/script/Bubble.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.5", 3 | "uuid": "2620b8ca-2898-4f8b-a6ff-d849e424301a", 4 | "isPlugin": false, 5 | "loadPluginInWeb": true, 6 | "loadPluginInNative": true, 7 | "loadPluginInEditor": false, 8 | "subMetas": {} 9 | } -------------------------------------------------------------------------------- /assets/script/BubbleMgr.ts: -------------------------------------------------------------------------------- 1 | import { bubbleData, EVENT } from "./Interface"; 2 | import Bubble from "./Bubble"; 3 | import Util from "./Util"; 4 | 5 | const {ccclass, property} = cc._decorator; 6 | 7 | @ccclass 8 | export default class BubbleMgr extends cc.Component { 9 | 10 | /** 泡泡纹理 */ 11 | @property([cc.SpriteFrame]) bubbleSpriteFrame: cc.SpriteFrame[] = []; 12 | /** 预制体 */ 13 | @property(cc.Prefab) bubblePrefab: cc.Prefab = null; 14 | /** 确认发射点 */ 15 | @property(cc.Node) shooter: cc.Node = null; 16 | /** 关卡数据 */ 17 | @property(cc.JsonAsset) levelData: cc.JsonAsset = null; 18 | 19 | /** 装载场景中所有泡泡,注意 s 这是二维数组 */ 20 | public bubblesArray: bubbleData[][] = []; 21 | /** 当前待发射球 */ 22 | public shootBubble: bubbleData; 23 | /** 是否正在射击的标志 */ 24 | public isShooting: boolean = false; 25 | /** 射出方向 */ 26 | public shootDir: cc.Vec2 = null; 27 | 28 | public onLoad (): void { 29 | this.init("lv1"); 30 | // 监听触摸结束 31 | cc.director.on(EVENT.TOUCHEND_SHOOT, (data) => { 32 | console.log('BubbleMgr -on -touchend'); 33 | // console.log(data); 34 | // FIX: 小球飞行时不应触发点击事件 35 | if (this.isShooting) { return } 36 | // 转为弧度 37 | let r = cc.misc.degreesToRadians(data); 38 | // 分量 x - sin y - cos 39 | this.shootDir = cc.v2(-Math.sin(r), Math.cos(r)); 40 | console.log(this.shootDir); 41 | // 开启射击 42 | this.isShooting = true; 43 | }, this); 44 | 45 | this._createOneShooter(); 46 | } 47 | 48 | public update (dt: number) { 49 | if (this.isShooting) { 50 | // 小球移动 51 | this._bubbleMove(dt); 52 | this._isCollided(); 53 | } 54 | } 55 | 56 | /** 检测碰撞 */ 57 | private _isCollided (): void { 58 | for (let row = 0; row < this.bubblesArray.length; row++) { 59 | for (let col = 0; col < this.bubblesArray[row].length; col++) { 60 | // 是否存在小球 61 | if (!this.bubblesArray[row][col]) continue; 62 | let n: cc.Node = this.bubblesArray[row][col].node; 63 | // 先看 y 轴 64 | let offsetY = Math.abs(n.y - this.shootBubble.node.y); 65 | if (offsetY > Util.BUBBLE_R * 2) continue; 66 | // 再看 x 轴 67 | let offsetX = Math.abs(n.x - this.shootBubble.node.x); 68 | if (offsetX > Util.BUBBLE_R * 2) continue; 69 | // 再做乘法 70 | let dis = offsetX * offsetX + offsetY * offsetY; 71 | if (dis > Util.BUBBLE_R * 2 * Util.BUBBLE_R * 2) continue; 72 | // 在范围内,触发碰撞,停止射击移动 73 | this.isShooting = false; 74 | // 位置修正 75 | this._setBubblePos(); 76 | // 如果有小球符合条件,return 77 | return; 78 | } 79 | } 80 | // 没触发碰撞且碰到最上方 81 | if (this.shootBubble.node.y > Util.SCREEN_H - Util.BUBBLE_R) { 82 | this.isShooting = false; 83 | // 位置修正 84 | this._setBubblePos(); 85 | } 86 | } 87 | 88 | /** 根据停止位置,修正 */ 89 | private _setBubblePos (): void { 90 | let index: cc.Vec2 = Util.convertPosToRowCol(this.shootBubble.node.x, this.shootBubble.node.y); 91 | this.shootBubble.node.position = Util.convertRowColToPos(index.x, index.y); 92 | // 设置对应数据 93 | let obj: bubbleData = Object.create(null); 94 | obj.node = this.shootBubble.node; 95 | obj.color = this.shootBubble.color; 96 | obj.isLinked = false; 97 | obj.isVisited = false; 98 | this.bubblesArray[index.x][index.y] = obj; 99 | // 应该遍历相同颜色的泡泡了 100 | this._mapColor(index); 101 | } 102 | 103 | /** 相同颜色检测,传入当前小球位置 */ 104 | private _mapColor (index: cc.Vec2): void { 105 | // 检测消除方法 106 | let test: Function = (row: number, col: number, color: number) => { 107 | // 非空检测 108 | if (!this.bubblesArray[row] || !this.bubblesArray[row][col]) return; 109 | // 获取泡泡数据 110 | let b: bubbleData = this.bubblesArray[row][col]; 111 | // 如果被访问过 112 | if (b.isVisited) return; 113 | // 如果颜色不同 114 | if (b.color !== color) return; 115 | // 符合条件 116 | b.isVisited = true; 117 | let leftTop = col; 118 | // 根据不同的行做偏移 119 | if (row % 2 === 0) { 120 | leftTop = col - 1; 121 | } 122 | // 每个泡泡周围有6个,依次检测 123 | // 左上 124 | test(row - 1, leftTop, color); 125 | //右上 126 | test(row - 1, leftTop + 1, color); 127 | //左 128 | test(row, col - 1, color); 129 | //右 130 | test(row, col + 1, color); 131 | //左下 132 | test(row + 1, leftTop, color); 133 | //右下 134 | test(row + 1, leftTop + 1, color); 135 | } 136 | 137 | // 执行 138 | test(index.x, index.y, this.bubblesArray[index.x][index.y].color); 139 | // 看有几个相同的 140 | let count: number = 0; 141 | // 记录消除行列值 142 | let record: cc.Vec2[] = []; 143 | for (let row = 0; row < this.bubblesArray.length; row++) { 144 | for (let col = 0; col < this.bubblesArray[row].length; col++) { 145 | if (!this.bubblesArray[row][col]) continue; 146 | if (this.bubblesArray[row][col].isVisited) { 147 | this.bubblesArray[row][col].isVisited = false; 148 | count ++; 149 | // 记录要进行消除的泡泡行列值 150 | record.push(cc.v2(row, col)); 151 | } 152 | } 153 | } 154 | if (count >= 3) { 155 | // 执行消除 156 | for (let i in record) { 157 | // 获取到该位置泡泡,执行消除 158 | let b = this.bubblesArray[record[i].x][record[i].y].node; 159 | b.getComponent(Bubble).playDeathAnimation(record[i]); 160 | } 161 | this.scheduleOnce(this._testUnLinked, 0.3); 162 | // this.scheduleOnce(this._nextBubble, 0.3); 163 | } else { 164 | this._nextBubble(); 165 | } 166 | } 167 | 168 | /** 悬空检测 同理 */ 169 | private _testUnLinked (): void { 170 | // 检测方法 171 | let test: Function = (row: number, col: number) => { 172 | //从刚刚加入的泡泡为起点,递归寻找相连的 173 | if (!this.bubblesArray[row] || !this.bubblesArray[row][col]) return; 174 | let b = this.bubblesArray[row][col]; 175 | if (b.isVisited) return; 176 | // 符合条件 177 | b.isVisited = true; 178 | b.isLinked = true; 179 | let leftTop = col; 180 | if (row % 2 === 0) { 181 | leftTop = col - 1; 182 | } 183 | // 每个泡泡周围有6个,依次检测 184 | // 左上 185 | test(row - 1, leftTop); 186 | //右上 187 | test(row - 1, leftTop + 1); 188 | //左 189 | test(row, col - 1); 190 | //右 191 | test(row, col + 1); 192 | //左下 193 | test(row + 1, leftTop); 194 | //右下 195 | test(row + 1, leftTop + 1); 196 | } 197 | // 执行 198 | for (let i = 0; i < this.bubblesArray[0].length; i++) { 199 | // 执行最上的一排泡泡 200 | if (!this.bubblesArray[0][i]) continue; 201 | test(0, i); 202 | } 203 | 204 | // 局部标志,是否执行过下落 205 | let flag: boolean = true; 206 | for (let row = 0; row < this.bubblesArray.length; row++) { 207 | for (let col = 0; col < this.bubblesArray[row].length; col++) { 208 | if (!this.bubblesArray[row][col]) continue; 209 | if (!this.bubblesArray[row][col].isLinked) { 210 | flag = false; 211 | let b = this.bubblesArray[row][col].node; 212 | b.getComponent(Bubble).playDownAnimation(cc.v2(row, col)); 213 | } else { 214 | this.bubblesArray[row][col].isVisited = false; 215 | this.bubblesArray[row][col].isLinked = false; 216 | } 217 | } 218 | } 219 | if (flag) { 220 | this._nextBubble(); 221 | } else { 222 | this.scheduleOnce(this._nextBubble, 0.6); 223 | } 224 | } 225 | 226 | private _nextBubble (): void { 227 | // 继续游戏 228 | this._createOneShooter(); 229 | } 230 | 231 | private _bubbleMove (dt: number): void { 232 | // 移动速度 233 | let speed = 1000; 234 | let n: cc.Node = this.shootBubble.node; 235 | // 左右出区域要改向 因为不知正负,先求绝对值 236 | if (n.x < Util.BUBBLE_R) this.shootDir.x = Math.abs(this.shootDir.x); 237 | if (n.x > Util.SCREEN_W - Util.BUBBLE_R) this.shootDir.x = -Math.abs(this.shootDir.x); 238 | n.x += this.shootDir.x * speed * dt; 239 | n.y += this.shootDir.y * speed * dt; 240 | } 241 | 242 | // 根据数据初始化 243 | public init (str: string): void { 244 | // 获取到关卡数据 245 | let data: [][] = this.levelData.json[str]; 246 | // 将所有数据遍历,0代表空 247 | for (let row = 0; row < data.length; row++) { 248 | let colBubbleData: bubbleData[] = data[row]; 249 | // 一起初始化一下 bubblesArray 250 | this.bubblesArray[row] = []; 251 | for (let col = 0; col < colBubbleData.length; col++) { 252 | let color = data[row][col]; 253 | if (color === 0) continue; 254 | // 实例化泡泡 255 | let b = cc.instantiate(this.bubblePrefab); 256 | // 行列 -> 坐标 257 | let pos = Util.convertRowColToPos(row, col); 258 | // 调用泡泡初始化 259 | b.getComponent(Bubble).init(this, pos, this.bubbleSpriteFrame[color-1]); 260 | // 往bubblesArray 里 设置对应数据 261 | let obj: bubbleData = Object.create(null); 262 | obj.node = b; 263 | obj.color = color; 264 | obj.isLinked = false; 265 | obj.isVisited = false; 266 | this.bubblesArray[row][col] = obj; 267 | } 268 | } 269 | } 270 | 271 | /** 创造发射小球 */ 272 | private _createOneShooter (): void { 273 | let b = cc.instantiate(this.bubblePrefab); 274 | let color = Util.randNum(1, 4); 275 | b.getComponent(Bubble).init(this, this.shooter.position, this.bubbleSpriteFrame[color-1]); 276 | // 设置对应数据 277 | let obj: bubbleData = Object.create(null); 278 | obj.node = b; 279 | obj.color = color; 280 | obj.isLinked = false; 281 | obj.isVisited = false; 282 | // 指定当前 shootBubble 283 | this.shootBubble = obj; 284 | } 285 | 286 | } 287 | -------------------------------------------------------------------------------- /assets/script/BubbleMgr.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.5", 3 | "uuid": "c3c3546f-dbb2-4144-8392-0f3ae1ecc459", 4 | "isPlugin": false, 5 | "loadPluginInWeb": true, 6 | "loadPluginInNative": true, 7 | "loadPluginInEditor": false, 8 | "subMetas": {} 9 | } -------------------------------------------------------------------------------- /assets/script/Interface.ts: -------------------------------------------------------------------------------- 1 | /** 泡泡对象 */ 2 | export interface bubbleData { 3 | node: cc.Node, 4 | color: number, 5 | isVisited: boolean, 6 | isLinked: boolean 7 | } 8 | 9 | /** 导出事件名称枚举 */ 10 | export enum EVENT { 11 | /** 触摸结束后,射击事件,附带角度参数 */ 12 | TOUCHEND_SHOOT = 'shoot' 13 | } 14 | -------------------------------------------------------------------------------- /assets/script/Interface.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.5", 3 | "uuid": "022296e7-a6b0-46b0-9422-0007550c1e35", 4 | "isPlugin": false, 5 | "loadPluginInWeb": true, 6 | "loadPluginInNative": true, 7 | "loadPluginInEditor": false, 8 | "subMetas": {} 9 | } -------------------------------------------------------------------------------- /assets/script/TouchMgr.ts: -------------------------------------------------------------------------------- 1 | import { EVENT } from "./Interface"; 2 | 3 | const {ccclass, property} = cc._decorator; 4 | 5 | @ccclass 6 | export default class TouchMgr extends cc.Component { 7 | 8 | @property(cc.Node) shooter: cc.Node = null; 9 | 10 | public onLoad (): void { 11 | this.openTouch(); 12 | } 13 | 14 | public openTouch (): void { 15 | this.node.on(cc.Node.EventType.TOUCH_START, this._touchStart, this); 16 | this.node.on(cc.Node.EventType.TOUCH_MOVE, this._touchsMove, this); 17 | this.node.on(cc.Node.EventType.TOUCH_END, this._touchEnd, this); 18 | } 19 | 20 | public closeTouch (): void { 21 | this.node.off(cc.Node.EventType.TOUCH_START, this._touchStart, this); 22 | this.node.off(cc.Node.EventType.TOUCH_MOVE, this._touchsMove, this); 23 | this.node.off(cc.Node.EventType.TOUCH_END, this._touchEnd, this); 24 | } 25 | 26 | private _touchStart (e: cc.Event.EventTouch): void { 27 | let d = this.convertToDegree(e); 28 | this.shooter.angle = d; 29 | } 30 | 31 | private _touchsMove (e: cc.Event.EventTouch): void { 32 | let d = this.convertToDegree(e); 33 | this.shooter.angle = d; 34 | } 35 | 36 | private _touchEnd (e: cc.Event.EventTouch): void { 37 | let d = this.convertToDegree(e); 38 | this.shooter.angle = d; 39 | // 发送角度 40 | cc.director.emit(EVENT.TOUCHEND_SHOOT, d); 41 | } 42 | 43 | // 转化角度 44 | private convertToDegree (e: cc.Event.EventTouch): number { 45 | let pos: cc.Vec2 = e.getLocation(); 46 | let x = pos.x - this.shooter.x; 47 | let y = pos.y - this.shooter.y; 48 | let radian = Math.atan2(y, x); 49 | // 弧度转角度 0 - 2π -> 0 - 360 50 | let degree = cc.misc.radiansToDegrees(radian); 51 | // angle 与原版 rotation 差 90 52 | degree -= 90; 53 | // console.log(degree); 54 | if (degree < -80 && degree > -180) degree = -80; 55 | if (degree > 80 || degree <= -180) degree = 80; 56 | return degree; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /assets/script/TouchMgr.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.5", 3 | "uuid": "6e8f26e9-2894-4b2c-99cf-0b1f1fdef159", 4 | "isPlugin": false, 5 | "loadPluginInWeb": true, 6 | "loadPluginInNative": true, 7 | "loadPluginInEditor": false, 8 | "subMetas": {} 9 | } -------------------------------------------------------------------------------- /assets/script/Util.ts: -------------------------------------------------------------------------------- 1 | export default class Util { 2 | 3 | public static readonly SCREEN_W: number = 720; 4 | public static readonly SCREEN_H: number = 1280; 5 | public static readonly BUBBLE_R: number = 40; 6 | /** Y 方向偏差为 40 倍根号 3 */ 7 | public static readonly BUBBLE_Y: number = 40 * Math.sqrt(3); 8 | 9 | /** 随机数 min - max */ 10 | public static randNum (min: number, max: number): number { 11 | // random 0 - 1 不包括 1 12 | return min + Math.floor((max - min + 1) * Math.random()); 13 | } 14 | 15 | /** 传入二维数组行列,返回泡泡对应位置坐标 */ 16 | public static convertRowColToPos (row: number, col: number): cc.Vec2 { 17 | // 奇数行前方少一个半径宽 18 | // 如果为偶数行 row % 2 = 0; 19 | let posX: number = this.BUBBLE_R * ((row % 2) + 1) + col * this.BUBBLE_R * 2; 20 | let posY: number = this.SCREEN_H - (this.BUBBLE_R + row * this.BUBBLE_Y); 21 | return cc.v2(posX, posY); 22 | } 23 | 24 | /** 传入泡泡对应位置坐标,返回二维数组行列 */ 25 | public static convertPosToRowCol (posX: number, posY: number): cc.Vec2 { 26 | let row: number = Math.round((this.SCREEN_H - posY - this.BUBBLE_R) / this.BUBBLE_Y); 27 | let col: number = Math.round((posX - this.BUBBLE_R * ((row % 2) + 1)) / (this.BUBBLE_R * 2)); 28 | return cc.v2(row, col); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /assets/script/Util.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.0.5", 3 | "uuid": "70790414-52bd-4147-996c-3e13662d4472", 4 | "isPlugin": false, 5 | "loadPluginInWeb": true, 6 | "loadPluginInNative": true, 7 | "loadPluginInEditor": false, 8 | "subMetas": {} 9 | } -------------------------------------------------------------------------------- /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": "cocos-creator-js", 3 | "packages": "packages", 4 | "version": "2.1.2" 5 | } -------------------------------------------------------------------------------- /settings/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "start-scene": "current", 3 | "group-list": [ 4 | "default" 5 | ], 6 | "collision-matrix": [ 7 | [ 8 | true 9 | ] 10 | ], 11 | "excluded-modules": [], 12 | "last-module-event-record-time": 0, 13 | "design-resolution-width": 960, 14 | "design-resolution-height": 640, 15 | "fit-width": false, 16 | "fit-height": true, 17 | "use-project-simulator-setting": false, 18 | "simulator-orientation": false, 19 | "use-customize-simulator": false, 20 | "simulator-resolution": { 21 | "width": 960, 22 | "height": 640 23 | }, 24 | "assets-sort-type": "name", 25 | "facebook": { 26 | "enable": false, 27 | "appID": "", 28 | "live": { 29 | "enable": false 30 | }, 31 | "audience": { 32 | "enable": false 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /settings/services.json: -------------------------------------------------------------------------------- 1 | { 2 | "services": [ 3 | { 4 | "service_id": "235", 5 | "service_name": "Cocos Analytics", 6 | "service_icon": "https://account.cocos.com/client/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/cocos-creator/tutorial-dark-slash/tree/analytics", 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.0_2.1.0.zip", 20 | "package_version_desc": "更新日期:2019/6/10
\n
更新说明:
\n1、优化SDK,修复H5-SDK 与多个小游戏平台适配问题,删除和优化init事件无用接口
\n2、如有相关问题咨询或者需求, 可以联系我们技术支持邮箱 support-cocos@cocos.com", 21 | "service_component_name": "service-analytics", 22 | "package_versions": [ 23 | "1.2.1_2.1.0", 24 | "1.2.0_2.1.0", 25 | "1.1.7_2.0.3", 26 | "1.1.6_2.0.1_2.0.2", 27 | "1.1.5_2.0.1", 28 | "1.1.4_2.0.1", 29 | "1.1.3_2.0.1", 30 | "1.1.2_2.0.0", 31 | "1.0.0_1.0.5" 32 | ], 33 | "build_platform": [], 34 | "require_verify": 0, 35 | "service_price": "", 36 | "service_protocol": "游戏首次开启该服务时,Cocos会后台通知服务方为游戏开通服务并初始化参数,服务方根据需要可能会获取您的Cocos账户信息,包括账户基本资料、游戏基本资料、账户余额等,点击确认开通按钮即视为您同意该服务访问您的账户信息,详见《Cocos用户服务协议》《Cocos隐私政策》" 37 | }, 38 | { 39 | "service_id": "241", 40 | "service_name": "Matchvs", 41 | "service_icon": "https://account.cocos.com/client/14406719a07eb3d714d36e5edc6e06fa.png", 42 | "service_desc": "通过SDK接入快速实现联网功能、帧同步、国内外多节点、服务器独立部署、gameServer自定义游戏服务端逻辑。", 43 | "service_title": "专业成熟的移动游戏联网与服务端解决方案", 44 | "service_guide_url": "http://doc.matchvs.com/QuickStart/QuickStart-CocosCreator", 45 | "service_sample_url": "http://www.matchvs.com/serviceCourse", 46 | "service_dev_url": "http://www.matchvs.com/cocosLogin", 47 | "service_type": "3", 48 | "service_type_zh": "公司和个人游戏", 49 | "support_platform": [ 50 | "Android", 51 | "iOS", 52 | "HTML5" 53 | ], 54 | "package_download_url": "https://download.cocos.com/CocosServices/plugins/service-matchvs/1.0.10_3.7.9.10.zip", 55 | "package_version_desc": "

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

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