使用Cocos Creator 新建脚本模板 下载好Cocos Creator新建脚本如下
如若想更改,可修改CocosDashboard_1.2.2(Cocos Creator安装路径下)\resources\.editors\Creator\2.4.9\resources\static\template\new-script.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 const {ccclass, property} = cc._decorator ;@ccclass export default class NewClass extends cc.Component { start () { } }
Cocos项目 Cocos项目常用目录结构 1 2 3 4 5 6 ——assets ——audio ——prefab ——scene ——script ——texture
关于(TS下)Cocos使用 报错:无法重新声明块范围变量 let
声明过的变量无法再用let
或var
重新声明,全用var
不会报错
二维数组使用中错误 ERROR: Uncaught TypeError: Cannot set property ‘0’ of undefined,
错误 使用
1 2 3 4 5 for (let i=0 ;i<18 ;i++){ for (let j=0 ;j<18 ;j++){ this .arr [i][j]=0 } }
正确使用
1 2 3 4 5 6 for (let i=0 ;i<18 ;i++){ this .arr [i]=[] for (let j=0 ;j<18 ;j++){ this .arr [i][j]=0 } }
Cocos脚本开发 TS补充 取整 1 2 3 4 5 6 7 8 9 10 11 12 13 cc.log (Math .ceil (1.111 )); cc.log (Math .ceil (1.6666 )); cc.log (Math .floor (1.111 )); cc.log (Math .floor (1.666 )); cc.log (Math .round (1.111 )); cc.log (Math .round (1.666 )); cc.log (1.1111 .toFixed ()); cc.log (1.1111 .toFixed (2 )); cc.log (1.1111 .toFixed (3 ));
绝对值 (method) Math.abs(x: number): number
回调 (method) cc.Component.schedule(callback: Function, interval?: number, repeat?: number, delay?: number): void !#en Schedules a custom selector. If the selector is already scheduled, then the interval parameter will be updated without scheduling it again. !#zh 调度一个自定义的回调函数。 如果回调函数已调度,那么将不会重复调度它,只会更新时间间隔参数。 @param callback — The callback function @param interval — Tick interval in seconds. 0 means tick every frame. @param repeat — The selector will be executed (repeat + 1) times, you can use cc.macro.REPEAT_FOREVER for tick infinitely. @param delay — The amount of time that the first tick will wait before execution. Unit: s
1 2 3 4 let timeCallback = function (dt ) { cc.log ("time: " + dt); } this .schedule (timeCallback, 1 );
(method) cc.Component.scheduleOnce(callback: Function, delay?: number): void !#en Schedules a callback function that runs only once, with a delay of 0 or larger. !#zh 调度一个只运行一次的回调函数,可以指定 0 让回调函数在下一帧立即执行或者在一定的延时之后执行。 @param callback — A function wrapped as a selector @param delay — The amount of time that the first tick will wait before execution. Unit: s
1 2 3 4 let timeCallback = function (dt ) { cc.log ("time: " + dt); } this .scheduleOnce (timeCallback, 2 );
(method) cc.Component.unscheduleAllCallbacks(): void !#en unschedule all scheduled callback functions: custom callback functions, and the ‘update’ callback function. Actions are not affected by this method. !#zh 取消调度所有已调度的回调函数:定制的回调函数以及 update 回调函数。动作不受此方法影响。
1 this .unscheduleAllCallbacks ();
setTimeout() function setTimeout(handler: TimerHandler, timeout?: number, …arguments: any[]): number
1 2 3 setTimeout (function ( ) { tip.destroy () }.bind (this ), 500 )
常用代码块(代码组件化) 随机颜色 1 2 3 4 5 6 7 randomColor ( ){ let red=Math .random ()*255 let green =Math .random ()*255 let blue =Math .random ()*255 let color=cc.color (red,green,blue) this .node .color =color }
挂载资源 @property()
示例 1 2 3 4 5 6 7 8 9 10 11 12 @property (cc.Integer )num :number =0 ;@property (cc.String )text : string = 'hello' ;@property (cc.Boolean )isTrue :boolean =false ;@property (cc.SpriteFrame )picArr :cc.SpriteFrame []=[];
挂载Cocos类 有两种写法,效果是一样的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @property ({ type :cc.Class ({ name :"pic_List" , properties :{ a :{ default :null , type :cc.SpriteFrame }, b :{ default :null , type :cc.SpriteFrame }, c :{ default :null , type :cc.SpriteFrame }, }, }), displayName :"图片数组" }) pic_List=null ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 const picArr=cc.Class ({ name :"pic_List" , properties :{ a :{ default :null , type :cc.SpriteFrame }, b :{ default :null , type :cc.SpriteFrame }, c :{ default :null , type :cc.SpriteFrame }, }, }); @property ({ type :picArr, displayName :"图片数组" }) pic_List=null ;
组件 获取组件 (method) cc._BaseNode.getComponent<cc.Component>(type: { prototype: cc.Component; }): cc.Component (+1 overload) !#en Returns the component of supplied type if the node has one attached, null if it doesn’t. You can also get component in the node by passing in the name of the script. !#zh 获取节点上指定类型的组件,如果节点有附加指定类型的组件,则返回,如果没有则为空。 传入参数也可以是脚本的名称。 @param typeOrClassName — typeOrClassName
1 2 3 4 let sprite = this .node .getComponent (cc.Sprite );let test = this .node .getComponent ("Test" );
预制体 克隆指定的任意类型的对象,或者从 Prefab 实例化出新节点
1 2 3 4 5 6 7 8 @property (cc.Prefab )prefabAsset :cc.Prefab =null ;onLoad () { let scene :cc.Scene =cc.director .getScene (); let node :cc.Node =cc.instantiate (this .prefabAsset ); node.parent = scene; }
1 2 3 4 5 6 7 8 9 @property (cc.Node )targetNode :cc.Node =null ;onLoad () { let scene = cc.director .getScene (); let node = cc.instantiate (this .targetNode ); node.parent = scene; node.setPosition (0 ,0 ); }
场景 切换场景 1 cc.director .loadScene ("game" )
节点(cc.Node) 新结点 1 let bullet :cc.Node =new cc.Node ()
寻找节点 cc.find()
function cc.find(path: string, referenceNode?: cc.Node): cc.Node Finds a node by hierarchy path, the path is case-sensitive. It will traverse the hierarchy by splitting the path using ‘/‘ character. This function will still returns the node even if it is inactive. It is recommended to not use this function every frame instead cache the result at startup. @param path — path @param referenceNode — referenceNode
1 cc.find ("Canvas/startButton/Background/start" ).getComponent (cc.Label ).string ="重新开始"
getChildByName("name")
1 this .node .getChildByName ("Background" ).getChildByName ("start" ).getComponent (cc.Label ).string ="重新开始"
节点层次 拥有更高 zIndex
的节点将被排在后面
1 2 3 this .playagain = cc.find ("main/start" , this .node );this .playagain .zIndex = 100 ;this .playagain .active = false ;
坐标与距离 全局坐标转相对坐标 (method) cc.Node.convertToNodeSpaceAR<cc.Vec2>(worldPoint: cc.Vec2, out?: cc.Vec2): cc.Vec2 !#en Converts a Point to node (local) space coordinates. !#zh 将一个点转换到节点 (局部) 空间坐标系。 @param worldPoint — worldPoint @param out — out
1 let temp_position=this .node .convertToNodeSpaceAR (Point )
向量减法 (method) cc.Vec2.sub(vector: cc.Vec2, out?: cc.Vec2): cc.Vec2 !#en Subtracts one vector from this, and returns the new result. !#zh 向量减法,并返回新结果。 @param vector — vector @param out — optional, the receiving vector, you can pass the same vec2 to save result to itself, if not provided, a new vec2 will be created
1 2 3 4 let v :cc.Vec2 = cc.v2 (10 , 10 );v.sub (cc.v2 (5 , 5 )); let v1 = new cc.Vec2 ();v.sub (cc.v2 (5 , 5 ), v1);
向量长度 (method) cc.Vec2.mag(): number !#en Returns the length of this vector. !#zh 返回该向量的长度。
1 2 var v = cc.v2 (10 , 10 );v.mag ();
鼠标事件 可以使用枚举类型也可以直接使用事件名来注册事件的监听器
枚举对象定义
对应的事件名
事件触发的时机
cc.Node.EventType.MOUSE_DOWN
mousedown
当鼠标在目标节点区域按下时触发一次
cc.Node.EventType.MOUSE_ENTER
mouseenter
当鼠标移入目标节点区域时,不论是否按下
cc.Node.EventType.MOUSE_MOVE
mousemove
当鼠标在目标节点区域中移动时,不论是否按下
cc.Node.EventType.MOUSE_LEAVE
mouseleave
当鼠标移出目标节点区域时,不论是否按下
cc.Node.EventType.MOUSE_UP
mouseup
当鼠标从按下状态松开时触发一次
cc.Node.EventType.MOUSE_WHEEL
mousewheel
当鼠标滚轮滚动时
注册事件示例 1 2 3 4 this .node .on ('mousedown' ,this .playGame ,this )playGame (event ){ console .log ('Mouse down' ) }
常用API
函数名
返回值类型
意义
getScrollY
Number
获取滚轮滚动的 Y 轴距离,只有滚动时才有效
getLocation
Object
获取鼠标位置对象,对象包含 x 和 y 属性
getPreviousLocation
Object
获取鼠标事件上次触发时的位置对象,对象包含 x 和 y 属性
getDelta
Object
获取鼠标距离上一次事件移动的距离对象,对象包含 x 和 y 属性
触摸事件
枚举对象定义
对应的事件名
事件触发的时机
cc.Node.EventType.TOUCH_START
touchstart
当手指触点落在目标节点区域内时
cc.Node.EventType.TOUCH_MOVE
touchmove
当手指在屏幕上移动时
cc.Node.EventType.TOUCH_END
touchend
当手指在目标节点区域内离开屏幕时
cc.Node.EventType.TOUCH_CANCEL
touchcancel
当手指在目标节点区域外离开屏幕时
示例 1 2 3 4 this .node .on ('touchstart' ,this .playGame ,this )playGame (event ){ console .log ('touch start' ) }
常用API
函数名
返回值类型
意义
touch
cc.Touch
与当前事件关联的触点对象
getID
Number
获取触点的 ID,用于多点触摸的逻辑判断
getLocation
Object
获取触点位置对象,对象包含 x 和 y 属性
getPreviousLocation
Object
获取触点上一次触发事件时的位置对象,对象包含 x 和 y 属性
getStartLocation
Object
获取触点距离上一次事件移动的距离对象,对象包含 x 和 y 属性
getDelta
Object
获取触点距离上一次事件移动的距离对象,对象包含 x 和 y 属性
声音 挂载资源法使用声音(cc.AudioClip) method) cc.audioEngine.playEffect(clip: cc.AudioClip, loop: boolean): number !#en Play effect audio. !#zh 播放音效 @param clip — The audio clip to play. @param loop — Whether the music loop or not.
1 2 3 @property (cc.AudioClip )private bgmAudio :cc.AudioClip =null cc.audioEngine .playEffect (this .bgmAudio , false )
组件(cc.AudioSource)法使用声音 节点下需要有这个组件
1 this .node .getComponent (cc.AudioSource ).play ()
碰撞系统 碰撞系统接口 获取碰撞检测系统
1 let manager = cc.director .getCollisionManager ()
默认碰撞检测系统是禁用的
开启默认碰撞检测系统
默认碰撞检测系统的 debug
绘制是禁用的
开启碰撞系统绘制 1 manager.enabledDebugDraw = true
显示碰撞组件的包围盒 1 manager.enabledDrawBoundingBox = true
碰撞组件 碰撞组件有三种
矩形碰撞组件(cc.BoxCollider) 圆形碰撞组件(cc.CircleCollider) 多边形碰撞组件(cc.PolygonCollider) 碰撞系统回调 当碰撞系统检测到有碰撞产生时,将会以回调的方式通知使用者,如果产生碰撞的碰撞组件依附的节点下挂的脚本中有实现以下函数,则会自动调用以下函数,并传入相关的参数。
@param {Collider} other 产生碰撞的另一个碰撞组件 @param {Collider} self 产生碰撞的自身的碰撞组件
碰撞产生的时候调用 1 2 3 onCollisionEnter (other, self ) { console .log ('on collision enter' ) }
碰撞中调用 当碰撞产生后,碰撞结束前的情况下,每次计算碰撞结果后调用
1 2 3 onCollisionStay (other, self ) { console .log ('on collision stay' ) }
碰撞结束后调用 1 2 3 onCollisionExit (other, self ) { console .log ('on collision exit' ) }
角色移动 由于移动中,经常涉及到重复播放动画的问题,直接写在事件函数里,往往出现各种问题 所以,实现移动一般使用状态监听法 (比如按下A键开启左移状态)
键盘事件控制移动 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 onKeyDown (event :cc.Event .EventKeyboard ) { switch (event.keyCode ) { case cc.macro .KEY .a : this .Left = true break case cc.macro .KEY .d : this .Right = true break } } onKeyUp (event) { switch (event.keyCode ) { case cc.macro .KEY .a : this .Left = false break case cc.macro .KEY .d : this .Right = false break } } onLoad ( ) { this .Left = false this .Right = false this .xSpeed = 0 cc.systemEvent .on (cc.SystemEvent .EventType .KEY_DOWN , this .onKeyDown , this ) cc.systemEvent .on (cc.SystemEvent .EventType .KEY_UP , this .onKeyUp , this ) } onDestroy ( ){ cc.systemEvent .off (cc.SystemEvent .EventType .KEY_DOWN , this .onKeyDown , this ) cc.systemEvent .off (cc.SystemEvent .EventType .KEY_UP , this .onKeyUp , this ) }
加速度式移动 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 update (dt ) { if (this .Left ) { this .xSpeed -= this .accel * dt } else if (this .Right ) { this .xSpeed += this .accel * dt } if (Math .abs (this .xSpeed ) > this .maxMoveSpeed ) { this .xSpeed = this .maxMoveSpeed * this .xSpeed / Math .abs (this .xSpeed ) } if (this .node .x <-880 ){ this .xSpeed =20 ; } else if (this .node .x >880 ){ this .xSpeed =-20 ; } this .node .x += this .xSpeed * dt }
触摸移动 1 2 3 4 5 6 7 8 9 10 11 12 13 move (event ){ let offset = event.getDelta (); this .player .x += offset.x ; if (this .player .x <-450 ){ this .player .x =-445 }else if (this .player .x >450 ){ this .player .x =445 } } onLoad () { this .node .on (cc.Node .EventType .TOUCH_MOVE , this .move ,this ) }
Cocos Project 摘星星(PickStars) PickStars 游戏预览
1 2 3 4 5 6 ——Canvas ——background ——Main Camera ——ground ——Player ——score
Game.ts Star.ts Player.ts Start.ts 用于挂载在Canvas节点下控制游戏的进行 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 import {Global } from "./Start" ;const {ccclass, property} = cc._decorator ;@ccclass export default class Game extends cc.Component { @property (cc.Label ) scoreDisplay : cc.Label = null ; @property (cc.Prefab ) private starPrefab :cc.Prefab =null ; @property (cc.Integer ) private maxStarDuration :number =0 ; @property (cc.Integer ) private minStarDuration :number =0 ; @property (cc.Node ) private groundNode :cc.Node =null ; @property (cc.Node ) public playerNode :cc.Node =null ; @property (cc.AudioClip ) private scoreAudio :cc.AudioClip =null ; private groundY :number ; private score=0 ; timer : number ; starDuration : number ; spawnNewStar ( ) { let newStar :cc.Node = cc.instantiate (this .starPrefab ) this .node .addChild (newStar) newStar.setPosition (this .getNewStarPosition ()) newStar.getComponent ('Star' ).game = this this .starDuration = this .minStarDuration + Math .random () * (this .maxStarDuration - this .minStarDuration ) this .timer = 0 } getNewStarPosition ( ) { let randX :number = 0 let randY = this .groundY + Math .random () * this .playerNode .getComponent ('Player' ).jumpHeight + 70 let maxX = 888 randX = (Math .random () - 0.5 ) * 2 * maxX return cc.v2 (randX, randY) } gainScore ( ) { this .score += 1 this .scoreDisplay .string = 'Score: ' + this .score cc.audioEngine .playEffect (this .scoreAudio , false ) } gameOver ( ) { this .playerNode .stopAllActions () this .node .destroy () cc.director .loadScene ('play' ) Global .isRestart =true } touchStart (event ){ let x :number =event.getLocationX () if (x<=960 ){ this .playerNode .getComponent ("Player" ).accLeft =true } else { this .playerNode .getComponent ("Player" ).accRight =true } } touchEnd ( ){ this .playerNode .getComponent ("Player" ).accLeft =false this .playerNode .getComponent ("Player" ).accRight =false } onLoad () { this .node .on ("touchstart" ,this .touchStart ,this ) this .node .on ("touchend" ,this .touchEnd ,this ) cc.macro .ENABLE_MULTI_TOUCH = false this .score = 0 this .timer = 0 this .starDuration = 0 this .groundY = this .groundNode .y + this .groundNode .height /2 this .spawnNewStar () } start () { } update (dt) { if (this .timer > this .starDuration ) { this .gameOver () return } this .timer += dt } }
这里使用了其他脚本的函数
挂载于星星预制体 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 import Game from "./Game" const {ccclass, property} = cc._decorator ;@ccclass export default class Star extends cc.Component { @property (cc.Integer ) private pickRadius :number =0 ; private game :Game =null ; public init (game:Game ){ this .game =game } getPlayerDistance ( ) { let playerPos = this .game .playerNode .getPosition () let dist = this .node .getPosition ().sub (playerPos).mag () return dist } onPicked ( ) { this .game .spawnNewStar () this .game .gainScore () this .node .destroy () } onLoad () {} start () { } update (dt) { if (this .getPlayerDistance () < this .pickRadius ) { this .onPicked () return } let opacityRatio = 1 - this .game .timer /this .game .starDuration ; let minOpacity = 50 ; this .node .opacity = minOpacity + Math .floor (opacityRatio * (255 - minOpacity)) } }
用于实现角色控制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 const {ccclass, property} = cc._decorator ;@ccclass export default class Player extends cc.Component { @property (cc.Integer ) private jumpHeight :number =0 ; @property (cc.Integer ) private jumpDuration :number =0 ; @property (cc.Integer ) private maxMoveSpeed :number = 0 ; @property (cc.Integer ) private accel :number = 0 ; @property (cc.AudioClip ) private jumpAudio :cc.AudioClip =null ; private xSpeed :number =0 ; private accLeft :boolean =false ; private accRight :boolean =false ; private setJumpAction ( ){ let jumpUp = cc.tween ().by (this .jumpDuration , {y : this .jumpHeight }, {easing : 'sineOut' }) let jumpDown = cc.tween ().by (this .jumpDuration , {y : -this .jumpHeight }, {easing : 'sineIn' }) let tween = cc.tween () .sequence (jumpUp, jumpDown) .call (this .playJumpSound , this ) return cc.tween ().repeatForever (tween) } onKeyDown (event :cc.Event .EventKeyboard ) { switch (event.keyCode ) { case cc.macro .KEY .a : this .accLeft = true break case cc.macro .KEY .d : this .accRight = true break } } onKeyUp (event) { switch (event.keyCode ) { case cc.macro .KEY .a : this .accLeft = false break case cc.macro .KEY .d : this .accRight = false break } } playJumpSound ( ) { cc.audioEngine .playEffect (this .jumpAudio , false ); } onLoad ( ) { let jumpAction = this .setJumpAction () cc.tween (this .node ).then (jumpAction).start () this .accLeft = false this .accRight = false this .xSpeed = 0 cc.systemEvent .on (cc.SystemEvent .EventType .KEY_DOWN , this .onKeyDown , this ) cc.systemEvent .on (cc.SystemEvent .EventType .KEY_UP , this .onKeyUp , this ) } start () {} update (dt ) { if (this .accLeft ) { this .xSpeed -= this .accel * dt } else if (this .accRight ) { this .xSpeed += this .accel * dt } if (Math .abs (this .xSpeed ) > this .maxMoveSpeed ) { this .xSpeed = this .maxMoveSpeed * this .xSpeed / Math .abs (this .xSpeed ) } if (this .node .x <-880 ){ this .xSpeed =20 } else if (this .node .x >880 ){ this .xSpeed =-20 } this .node .x += this .xSpeed * dt } onDestroy ( ){ cc.systemEvent .off (cc.SystemEvent .EventType .KEY_DOWN , this .onKeyDown , this ) cc.systemEvent .off (cc.SystemEvent .EventType .KEY_UP , this .onKeyUp , this ) } }
用于实现菜单控制及管理全局变量 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 const {ccclass, property} = cc._decorator ;export class Global { static isRestart :boolean =false ; } @ccclass export class Start extends cc.Component { playGame ( ){ this .node .parent .destroy () cc.director .loadScene ("game" ) } onLoad () { if (Global .isRestart ){ this .node .getChildByName ("Background" ).getChildByName ("start" ).getComponent (cc.Label ).string ="重新开始" } this .node .on ("touchstart" ,this .playGame ,this ) } start () { } }
五子棋(GoBang) GoBang 游戏预览 1 2 3 4 5 ——Canvas ——Main Camera ——chess(Anchor:(0,0)) ——btn_start ——title
display 挂载于棋盘节点 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 const {ccclass, property} = cc._decorator ;@ccclass export default class ChessBoard extends cc.Component { @property (cc.Prefab ) private chessPrefab_black :cc.Prefab =null @property (cc.Prefab ) private chessPrefab_white :cc.Prefab =null @property (cc.SpriteFrame ) private restart :cc.SpriteFrame =null @property (cc.Prefab ) private start_board :cc.Prefab =null @property (cc.Prefab ) private Tip _board :cc.Prefab =null private startGame :cc.Node =null private num :number =0 ; private _board=[] private isPlayGame :boolean =false private isRestart :boolean =false initBoard ( ){ for (let i=0 ;i<18 ;i++){ this ._board [i]=[] for (let j=0 ;j<18 ;j++){ this ._board [i][j]=0 } } } playGame ( ){ if (this .isRestart ){ cc.director .loadScene ("game" ) } else { this .startGame .active =false this .isPlayGame =true } } restartGame ( ){ this .startGame .active =true this .startGame .getComponent (cc.Sprite ).spriteFrame =this .restart this .startGame .removeAllChildren (); this .startGame .scale =0.5 this .startGame .opacity =200 this .isRestart =true } isPlayChess (i:number ,j:number ){ if (this ._board [i][j]!=0 ){ cc.log ("此处已有棋子" ) return false } if (i==0 || j==0 || i==17 || j==17 ){ let tip :cc.Node = cc.instantiate (this .Tip_board ) this .node .addChild (tip) tip.setPosition (cc.v2 (425 ,500 )) setTimeout (function ( ) { tip.destroy () }.bind (this ), 500 ) return false } return true } setNewChess (event ){ cc.log (this .isPlayGame ) if (!this .isPlayGame ){ return } let startPoint :cc.Vec2 = event.getLocation () let temp_position=this .node .convertToNodeSpaceAR (startPoint) let x=Math .round (temp_position.x /50 ) let y=Math .round (temp_position.y /50 ) let position :cc.Vec2 =cc.v2 (x*50 ,y*50 ) let myPos=cc.v2 (x,y) if (this .num %2 ==0 && this .isPlayChess (myPos.x ,myPos.y )){ let newChess_black :cc.Node = cc.instantiate (this .chessPrefab_black ) this .node .addChild (newChess_black) newChess_black.setPosition (position) this ._board [myPos.x ][myPos.y ]=1 if (this .judge (1 ,myPos)){ cc.log ("黑胜" ) let newGame :cc.Node = cc.instantiate (this .start_board ) this .node .addChild (newGame) newGame.children [1 ].color =cc.Color .BLACK newGame.setPosition (cc.v2 (425 ,325 )) this .restartGame () } this .num +=1 return } if (this .num %2 ==1 && this .isPlayChess (myPos.x ,myPos.y )){ let newChess_white :cc.Node = cc.instantiate (this .chessPrefab_white ) this .node .addChild (newChess_white) newChess_white.setPosition (position) this ._board [myPos.x ][myPos.y ]=2 if (this .judge (2 ,myPos)){ cc.log ("白胜" ) let newGame :cc.Node = cc.instantiate (this .start_board ) newGame.children [1 ].getComponent (cc.Label ).string ="白棋" this .node .addChild (newGame) newGame.setPosition (cc.v2 (425 ,325 )) this .restartGame () } this .num +=1 return } } judge (flag:number ,myPos:cc.Vec2 ){ if (this .judge_row (flag,myPos) || this .judge_list (flag,myPos) || this .judge_left (flag,myPos) || this .judge_right (flag,myPos)){ this .isPlayGame =false return true } return false } judge_row (flag:number ,myPos:cc.Vec2 ){ let count=0 let i=1 while (this ._board [myPos.x +i][myPos.y ]==flag){ count+=1 i+=1 } i=1 while (this ._board [myPos.x -i][myPos.y ]==flag){ count+=1 i+=1 } if (count<4 ){ return false } return true } judge_list (flag:number ,myPos:cc.Vec2 ){ let count=0 let i=1 while (this ._board [myPos.x ][myPos.y +i]==flag){ count+=1 i+=1 } i=1 while (this ._board [myPos.x ][myPos.y -i]==flag){ count+=1 i+=1 } if (count<4 ){ return false } return true } judge_left (flag:number ,myPos:cc.Vec2 ){ let count=0 let i=1 while (this ._board [myPos.x +i][myPos.y +i]==flag){ count+=1 i+=1 } i=1 while (this ._board [myPos.x -i][myPos.y -i]==flag){ count+=1 i+=1 } if (count<4 ){ return false } return true } judge_right (flag:number ,myPos:cc.Vec2 ){ let count=0 let i=1 while (this ._board [myPos.x -i][myPos.y +i]==flag){ count+=1 i+=1 } i=1 while (this ._board [myPos.x +i][myPos.y -i]==flag){ count+=1 i+=1 } if (count<4 ){ return false } return true } onLoad () { this .startGame =cc.find ("Canvas/btn_start" ) this .node .on ("touchstart" ,this .setNewChess , this ) } start () { this .initBoard () } }
简易消消乐(Xiaoxiaole) Xiaoxiaole 游戏预览 1 2 3 ——Canvas ——Main Camera ——bg(Anchor:(0,0))
Xiaoxiaole思路 就是一个递归的思想在里面
Xiaoxiaole实现 挂载在一个方块预制体上 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 const {ccclass, property} = cc._decorator ;const picArr=cc.Class ({ name :"pic_List" , properties :{ a :{ default :null , type :cc.SpriteFrame }, b :{ default :null , type :cc.SpriteFrame }, c :{ default :null , type :cc.SpriteFrame }, d :{ default :null , type :cc.SpriteFrame }, e :{ default :null , type :cc.SpriteFrame }, f :{ default :null , type :cc.SpriteFrame }, }, }); @ccclass export default class NewBlock extends cc.Component { @property ({ type :picArr, displayName :"图片数组" }) pic_List=null ; index=this .myRandom (0 ,5 ) arr=['a' ,'b' ,'c' ,'d' ,'e' ,'f' ] xiaoxiaole ( ){ this .index =null } myRandom (min:number ,max:number ){ return Math .floor (Math .random ()*(max-min+1 )+min) } random_block ( ){ this .index =this .myRandom (0 ,5 ) } judge_block ( ){ if (this .arr [this .index ]=='a' ){ this .node .getComponent (cc.Sprite ).spriteFrame =this .pic_List .a } else if (this .arr [this .index ]=='b' ){ this .node .getComponent (cc.Sprite ).spriteFrame =this .pic_List .b } else if (this .arr [this .index ]=='c' ){ this .node .getComponent (cc.Sprite ).spriteFrame =this .pic_List .c } else if (this .arr [this .index ]=='d' ){ this .node .getComponent (cc.Sprite ).spriteFrame =this .pic_List .d } else if (this .arr [this .index ]=='e' ){ this .node .getComponent (cc.Sprite ).spriteFrame =this .pic_List .e } else if (this .arr [this .index ]=='f' ){ this .node .getComponent (cc.Sprite ).spriteFrame =this .pic_List .f } else if (this .arr [this .index ]==null ){ this .node .getComponent (cc.Sprite ).spriteFrame =null } } update (dt) { this .judge_block () } }
挂载在背景节点下控制游戏进行 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 const {ccclass, property} = cc._decorator ;@ccclass export default class NewClass extends cc.Component { @property (cc.Prefab ) pic :cc.Prefab =null ; private arr=[]; xiaoxiaole (event ){ let Point :cc.Vec2 = event.getLocation () let temp_position=this .node .convertToNodeSpaceAR (Point ) let x=Math .round ((temp_position.x +25 )/50 ) let y=Math .round ((temp_position.y +25 )/50 ) let myPos=cc.v2 (x,y) this .judge (myPos) for (let i=1 ;i<11 ;i++){ for (let j=1 ;j<11 ;j++){ if (this .arr [i][j]==null ){ let n :number =1 let a :number =1 while (this .arr [i][j+a]==null && j+a<11 ){ n++ a++ } this .scheduleOnce (()=> { for (let k=0 ;k<(11 -n-j);k++){ this .node .children [(i-1 )*10 +j-1 +k].getComponent ("NewBlock" ).index =this .node .children [(i-1 )*10 +j-1 +k+n].getComponent ("NewBlock" ).index this .arr [i][j+k]=this .arr [i][j+k+n] this .arr [i][j+k+n]=null this .node .children [(i-1 )*10 +j-1 +k+n].getComponent ("NewBlock" ).index =null } }, 0.4 ); setTimeout (function ( ) { for (let k=0 ;k<n;k++){ this .node .children [(i-1 )*10 +9 -k].getComponent ("NewBlock" ).random_block () this .arr [i][10 -k]=this .node .children [(i-1 )*10 +9 -k].getComponent ("NewBlock" ).index } }.bind (this ),950 ) break } } } } judge (myPos:cc.Vec2 ){ let temp= this .arr [myPos.x ][myPos.y ] if (temp==null || (this .arr [myPos.x -1 ][myPos.y ]!=temp && this .arr [myPos.x +1 ][myPos.y ]!=temp && this .arr [myPos.x ][myPos.y -1 ]!=temp && this .arr [myPos.x ][myPos.y +1 ]!=temp)){ return } this .node .children [(myPos.x -1 )*10 +myPos.y -1 ].getComponent ("NewBlock" ).xiaoxiaole () this .arr [myPos.x ][myPos.y ]=null if (this .arr [myPos.x -1 ][myPos.y ]==temp){ this .node .children [(myPos.x -2 )*10 +myPos.y -1 ].getComponent ("NewBlock" ).xiaoxiaole () this .judge (cc.v2 (myPos.x -1 ,myPos.y )) this .arr [myPos.x -1 ][myPos.y ]=null } if (this .arr [myPos.x +1 ][myPos.y ]==temp){ this .node .children [myPos.x *10 +myPos.y -1 ].getComponent ("NewBlock" ).xiaoxiaole () this .judge (cc.v2 (myPos.x +1 ,myPos.y )) this .arr [myPos.x +1 ][myPos.y ]=null } if (this .arr [myPos.x ][myPos.y -1 ]==temp){ this .node .children [(myPos.x -1 )*10 +myPos.y -2 ].getComponent ("NewBlock" ).xiaoxiaole () this .judge (cc.v2 (myPos.x ,myPos.y -1 )) this .arr [myPos.x ][myPos.y -1 ]=null } if (this .arr [myPos.x ][myPos.y +1 ]==temp){ this .node .children [(myPos.x -1 )*10 +myPos.y ].getComponent ("NewBlock" ).xiaoxiaole () this .judge (cc.v2 (myPos.x ,myPos.y +1 )) this .arr [myPos.x ][myPos.y +1 ]=null } } onLoad () { this .initGame () this .node .on ("mousedown" ,this .xiaoxiaole ,this ) } initGame ( ){ for (let i=0 ;i<12 ;i++){ this .arr [i]=[] for (let j=0 ;j<12 ;j++){ this .arr [i][j]=null } } for (let i=1 ;i<11 ;i++){ this .arr [i]=[] for (let j=1 ;j<11 ;j++){ let block :cc.Node = cc.instantiate (this .pic ) this .node .addChild (block) block.setPosition (cc.v2 (50 *i-25 ,50 *j-25 )) this .arr [i][j]=block.getComponent ("NewBlock" ).index } } } update (dt) { } }
打砖块(Bricks) Bricks 游戏预览 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ——Canvas ——Main Camera ——bg ——ball ——board ——wall ——left ——right ——top ——menu ——level ——score ——restart ——tip
Bricks游戏思路 主要是处理砖块碰撞问题,由于小球打在砖块的不同位置效果是不一样的,因此需要设计好不同的碰撞区域,并进行标记
Bricks实现 挂载在砖块预制体上 1 2 3 4 5 6 7 8 9 10 11 12 13 const {ccclass, property} = cc._decorator ;@ccclass export default class Brick extends cc.Component { onLoad () { let red=Math .random ()*255 let green =Math .random ()*255 let blue =Math .random ()*255 let color=cc.color (red,green,blue) this .node .color =color } }
挂载在背景节点上用于控制游戏进行 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 const {ccclass, property} = cc._decorator ;@ccclass export default class Game extends cc.Component { @property (cc.Prefab ) brick :cc.Prefab =null ; @property (cc.Node ) player :cc.Node =null ; Left :boolean =false ; Right :boolean =false ; xSpeed :number =11 ; initGame ( ){ for (let i=0 ;i<9 ;i++){ for (let j=0 ;j<15 ;j++){ let node :cc.Node =cc.instantiate (this .brick ) this .node .addChild (node) node.setPosition (cc.v2 (-480 +i*120 ,800 -j*60 )) } } } onKeyDown (event :cc.Event .EventKeyboard ) { switch (event.keyCode ) { case cc.macro .KEY .a : this .Left = true break case cc.macro .KEY .d : this .Right = true break } } onKeyUp (event) { switch (event.keyCode ) { case cc.macro .KEY .a : this .Left = false break case cc.macro .KEY .d : this .Right = false break } } move (event ){ let offset = event.getDelta (); this .player .x += offset.x ; if (this .player .x <-450 ){ this .player .x =-445 }else if (this .player .x >450 ){ this .player .x =445 } } onLoad () { cc.systemEvent .on (cc.SystemEvent .EventType .KEY_DOWN , this .onKeyDown , this ) cc.systemEvent .on (cc.SystemEvent .EventType .KEY_UP , this .onKeyUp , this ) this .node .on (cc.Node .EventType .TOUCH_MOVE , this .move ,this ) this .initGame () let node=new cc.Node () node.color =cc.Color .BLACK let label=node.addComponent (cc.Label ) label.string ="调整球位置后\n按下空格(或者点击小球)\n开始消除砖块" label.fontSize =70 label.lineHeight =70 this .node .parent .addChild (node) node.setPosition (0 ,-200 ) setTimeout (() => { node.destroy () }, 2000 ); } update (dt) { if (this .Left ) { this .player .x -= dt*this .xSpeed *100 } if (this .Right ) { this .player .x +=dt*this .xSpeed *100 } if (this .player .x <-450 ){ this .player .x =-445 }else if (this .player .x >450 ){ this .player .x =445 } } }
挂载在小球上实现碰撞 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 const {ccclass, property} = cc._decorator ;@ccclass export default class NewClass extends cc.Component { @property (cc.SpriteFrame ) win :cc.SpriteFrame =null ; @property (cc.Node ) scoreBoard :cc.Node =null ; @property (cc.Node ) levelBoard :cc.Node =null ; restart :cc.Node =null ; xSpeed :number =0 ; ySpeed :number =0 ; score :number =0 ; level :number =0 ; gameLevel :number =0 ; isLunch :boolean =false ; judge ( ){ let tempNode :cc.Node =cc.find ("Canvas/bg" ) for (let i=0 ;i<tempNode.children .length ;i++){ if (tempNode.children [i].name =="brick" ){ return false } } return true } restartGame ( ){ cc.director .loadScene ("game" ) } fire (event ){ switch (event.keyCode ) { case cc.macro .KEY .space : this .isLunch =true this .changeLevel () break } } changeLevel ( ){ if (this .score >=this .level ){ this .level +=10 +this .gameLevel *10 ; this .gameLevel +=1 ; this .levelBoard .getComponent (cc.Label ).string ="等级:" + this .gameLevel .toString () switch (this .gameLevel ){ case 1 : this .xSpeed =(this .xSpeed >=0 )?3 :-3 this .ySpeed =(this .ySpeed >=0 )?7 :-7 break case 2 : this .xSpeed =(this .xSpeed >0 )?4 :-4 this .ySpeed =(this .ySpeed >0 )?9 :-9 break case 3 : this .xSpeed =(this .xSpeed >0 )?4 :-4 this .ySpeed =(this .ySpeed >0 )?10 :-10 break case 4 : this .xSpeed =(this .xSpeed >0 )?5 :-5 this .ySpeed =(this .ySpeed >0 )?11 :-11 break case 5 : this .xSpeed =(this .xSpeed >0 )?5 :-5 this .ySpeed =(this .ySpeed >0 )?13 :-13 case 6 : this .xSpeed =(this .xSpeed >0 )?6 :-6 this .ySpeed =(this .ySpeed >0 )?15 :-15 case 7 : this .xSpeed =(this .xSpeed >0 )?6 :-6 this .ySpeed =(this .ySpeed >0 )?17 :-17 default : break } } } onLoad () { let manager = cc.director .getCollisionManager () manager.enabled =true manager.enabledDebugDraw =true this .restart =cc.find ("Canvas/restart" ) this .restart .active =false this .node .getComponent (cc.AudioSource ).preload =true this .node .on ("touchstart" ,()=> {this .isLunch =true ;this .changeLevel ()},this ) cc.systemEvent .on (cc.SystemEvent .EventType .KEY_DOWN , this .fire , this ) } onCollisionEnter (other,self:cc.PolygonCollider ){ if (other.tag ==1 ){ this .ySpeed =-Math .abs (this .ySpeed ) } else if (other.tag ==5 ){ this .ySpeed =Math .abs (this .ySpeed ) } else if (other.tag ==2 ){ this .xSpeed =-this .xSpeed } else if (other.tag ==3 ){ this .xSpeed =-this .xSpeed } else if (other.tag ==4 ){ this .ySpeed =-this .ySpeed } } onCollisionExit (other, self ) { if (other.tag ==1 || other.tag ==2 || other.tag ==5 ){ other.node .destroy () this .score +=1 this .scoreBoard .getComponent (cc.Label ).string ="得分:" + this .score .toString () this .node .getComponent (cc.AudioSource ).play () this .changeLevel () } } update (dt) { if (this .judge ()){ this .restart .getChildByName ("tip" ).getComponent (cc.Sprite ).spriteFrame =this .win this .restart .active =true } this .node .x +=this .xSpeed *dt*100 this .node .y +=this .ySpeed *dt*100 if (this .node .y <-960 ){ this .restart .active =true } if (!this .isLunch ){ this .node .x =cc.find ("Canvas/bg/board" ).x } if (this .node .x >530 ){ this .node .x =514 } else if (this .node .x <-530 ){ this .node .x =-514 } } }