Cocos Creator 滑动小方块,一笔画

发布时间:2026/7/12 2:45:55
Cocos Creator 滑动小方块,一笔画 前几天玩了个微信小游戏一笔画玩的挺起劲的就弄了个Demo弄一个二位数组const layout1: number[][] [[1, 1, 1, 1], [2, 1, 1, 1], [-1, 1, 1, -1], [1, 1, 1, -1]];1表示有方块-1表示没有方块2表示起始的方块随别啦用0代表也行只要能区分出来就行咱先把方块放到界面上generateBoard(){ const gridSize layout.length; const maxCols Math.max(...layout.map((row: string | any[]) row.length)); let tileWidth 0, tileHeight 0; for (let row 0; row gridSize; row) { for (let col 0; col layout[row].length; col) { const cellValue layout[row][col]; if (cellValue -1) { continue; } const tile instantiate(this.tilePrefab); tileWidth tile.getComponent(UITransform).contentSize.width; tileHeight tile.getComponent(UITransform).contentSize.height; tile.setParent(this.node); const x col * this.spacing - (maxCols - 1) * this.spacing / 2; const y row * this.spacing - (gridSize - 1) * this.spacing / 2; tile.setPosition(x, y, 0); const tileInfo: TileInfo { node: tile, row: row, col: col }; this.tiles.push(tileInfo); const sprite tile.getComponent(Sprite); if (sprite) { if (cellValue 2) { sprite.color this.nodeColor; this.originalColors.set(tile, this.nodeColor); this.pathTiles.push(tileInfo); this.startTile tileInfo; } else { this.originalColors.set(tile, sprite.color.clone()); } } } } this.calculateBoundingBox(tileWidth, tileHeight, layout[0].length, gridSize); }originalColors是一个map保存一下方块信息以及颜色值nodeColor:随别给个颜色值pathTiles: TileInfo[] []; // 路径上的节点信息interface TileInfo { node: Node; row: number; col: number; }好吧这个方法也不知道当初咋想的没啥用calculateBoundingBox(tileWidth: number, tileHeight: number, layoutSize: number, gridSize: number) { const uiTransform this.node.getComponent(UITransform); if (uiTransform) { uiTransform.setContentSize((this.spacing - tileWidth) * (layoutSize - 1) tileWidth * layoutSize, (this.spacing - tileHeight) * (gridSize - 1) tileHeight * gridSize); } }不是还要画线条吗this.createLineNode(); 我就用一个白色线条了 createLineNode() { this.lineNode new Node(Line); this.lineNode.setParent(this.node); this.lineNode.setPosition(0, 0, 0); this.lineNode.layer this.node.layer; this.lineNode.zIndex -1; this.graphics this.lineNode.addComponent(Graphics); this.graphics.strokeColor new Color(255, 255, 255, 255); this.graphics.lineWidth 15; this.graphics.lineCap Graphics.LineCap.ROUND; this.graphics.lineJoin Graphics.LineJoin.ROUND; }事件监听这个是必须的setupTouchEvents() { this.node.on(Node.EventType.TOUCH_START, this.onTouchStart, this); this.node.on(Node.EventType.TOUCH_MOVE, this.onTouchMove, this); this.node.on(Node.EventType.TOUCH_END, this.onTouchEnd, this); this.node.on(Node.EventType.TOUCH_CANCEL, this.onTouchEnd, this); }下面就是主要逻辑了onTouchStart(event: EventTouch) { const touchPos event.getUILocation(); const tileInfo this.getTileAtPosition(touchPos); if (tileInfo this.startTile tileInfo.node this.startTile.node) { this.isSliding true; } } onTouchStart(event: EventTouch) { const touchPos event.getUILocation(); const tileInfo this.getTileAtPosition(touchPos); if (tileInfo this.startTile tileInfo.node this.startTile.node) { this.isSliding true; } } onTouchMove(event: EventTouch) { if (!this.isSliding) return; const touchPos event.getUILocation(); const tileInfo this.getTileAtPosition(touchPos); if (tileInfo) { if (this.pathTiles.indexOf(tileInfo) ! -1) { if (tileInfo this.pathTiles[this.pathTiles.length - 2]) { const tile this.pathTiles[this.pathTiles.length - 1]; const sprite tile.node.getComponent(Sprite); if (sprite) { sprite.color this.originalColors.get(tile.node)!; } this.pathTiles.pop(); this.drawPath(); } return; }; const lastTile this.pathTiles[this.pathTiles.length - 1]; if (!this.isAdjacent(lastTile, tileInfo)) { this.resetAllTiles(); this.isSliding false; return; } AudioPreloadManager.getInstance().playEffect(sound/Drop); const sprite tileInfo.node.getComponent(Sprite); if (sprite) { sprite.color this.nodeColor; this.pathTiles.push(tileInfo); } this.drawPath(); tween(tileInfo.node) .to(0.1, { scale: new Vec3(.9, .9, .9) }) .delay(0.1) .to(0.1, { scale: new Vec3(1, 1, 1) }) .start(); } this.checkWin(); } onTouchEnd(event: EventTouch) { // if (this.pathTiles.length ! this.tiles.length) { //this.resetAllTiles(); //this.isSliding false; // } } isAdjacent(tile1: TileInfo, tile2: TileInfo): boolean { if (!tile1 || !tile2) return false; const rowDiff Math.abs(tile1.row - tile2.row); const colDiff Math.abs(tile1.col - tile2.col); return (rowDiff 1 colDiff 0) || (rowDiff 0 colDiff 1); } resetTileColor(node: Node) { const sprite node.getComponent(Sprite); if (sprite this.originalColors.has(node)) { if (node ! this.startTile?.node) { sprite.color this.originalColors.get(node)!; } } } resetAllTiles() { for (let i 1; i this.pathTiles.length; i) { const tile this.pathTiles[i]; const sprite tile.node.getComponent(Sprite); if (sprite) { sprite.color this.originalColors.get(tile.node)!; } } this.pathTiles this.startTile ? [this.startTile] : []; this.drawPath(); } getTileAtPosition(pos: Vec2): TileInfo | null { for (const tile of this.tiles) { const tileTransform tile.node.getComponent(UITransform); if (tileTransform) { const targetRect tileTransform.getBoundingBoxToWorld(); const isInRange targetRect.contains(pos); if (isInRange) { return tile; } } } return null; } checkWin() { // console.log(checkWin------, this.pathTiles.length, this.tiles.length); if (this.pathTiles.length this.tiles.length) { AudioPreloadManager.getInstance().playEffect(sound/Success); this.node.off(Node.EventType.TOUCH_START, this.onTouchStart, this); this.node.off(Node.EventType.TOUCH_MOVE, this.onTouchMove, this); this.node.off(Node.EventType.TOUCH_END, this.onTouchEnd, this); this.node.off(Node.EventType.TOUCH_CANCEL, this.onTouchEnd, this); for (const tile of this.pathTiles) { tween(tile.node) .to(0.1, { scale: new Vec3(1.1, 1.1, 1.1) }) .delay(0.1) .to(0.1, { scale: new Vec3(1, 1, 1) }) .start(); } this.currentLevelIndex; if (this.currentLevelIndex 30) { this.currentLevelIndex 1; } this.scheduleOnce(() { this.winPopup.active true; }, 1.2); } }