目录
- 创建玩家
- 玩家图片
- 玩家动画
- 玩家移动
- 子弹
- 子弹运动
- 子弹发射
- 双发模式 和 模式切换
- 子弹销毁
本笔记是学习记录
SIKI学院 视频原地址 点击跳转
创建玩家
玩家飞机 后面简称玩家
玩家图片
先创建一个空节点
把玩家飞机图片丢进空节点
系统自动生成一个 canvas 和 camera
这是不对的 再把玩家图片丢进上一个 camera 下
未创建新的,再移动到 空节点 下
最终样子
初始位置 及大小 看自己高兴,右边属性自己改
我改成0.7
玩家动画
动画添加到空节点上
- 进入动画编辑器
- 选择新建动画 ( 在玩家飞机图片上 空节点用来写飞机逻辑代码)
- 命名保存
- 添加关键帧
- 循环播放 和 加载后播放
完整差不多如下图
差不多可以试运行一下看看动画有无异常
玩家移动
玩家移动,现在我能想到的三种方式
- 遥感式
- 跟随触摸式 (手指在哪里飞机在哪里)
- 触摸增量式 (手指在任意位置飞机跟随移动增量)
老师用的就是第三种,先创建一个TS脚本,把TS脚本绑定到 空父节点 上
进行代码编辑
@ccclass('player')
export class player extends Component {protected onLoad(): void { // 打开触摸移动监听input.on(Input.EventType.TOUCH_MOVE, // 设置获取的类型this.onmove, // 赋值给onmove函数this)}protected onDestroy(): void { // 关闭input.off(Input.EventType.TOUCH_MOVE,this.onmove,this)}onmove(event:EventTouch){const p = this.node.position; // 获取坐标this.node.setPosition( // 设置位置p.x + event.getDeltaX(), // 当前X坐标 + 移动的X坐标p.y + event.getDeltaY(),p.z // 2d z轴无关,不填好像也可以)}
}
保存运行一下看是否能控制移动
这里有一个问题,飞机能移动出屏幕外,所以要加以限制
坐标我调了好久都不对,发现是我脚本挂在父空节点上,
图片是子节点,所以我们动的是父节点,查看坐标也应该是父节点坐标
import { _decorator, Component, EventTouch, Input, input, Node, Vec3 } from 'cc';
const { ccclass, property } = _decorator;@ccclass('player')
export class player extends Component {protected onLoad(): void { // 打开触摸移动监听input.on(Input.EventType.TOUCH_MOVE, // 设置获取的类型this.onmove, // 赋值给onmove函数this)}protected onDestroy(): void { // 关闭input.off(Input.EventType.TOUCH_MOVE,this.onmove,this)}onmove(event:EventTouch){const p = this.node.position; // 获取坐标let pos1 = new Vec3( // 创建一个新的变量.来存储将要变更坐标,以便于判断p.x + event.getDeltaX(), // 当前X坐标 + 移动的X坐标p.y + event.getDeltaY(),)/*坐标我调了好久都不对,发现是我脚本挂在父空节点上,图片是子节点,所以我们动的是父节点,查看坐标也应该是父节点坐标*/if (pos1.x < -476) pos1.x = -476 // 限制左边if (pos1.x > -6) pos1.x = -6 // 限制右边if (pos1.y < -500) pos1.y = -500 // 限制下边if (pos1.y > 276) pos1.y = 276 // 限制上边this.node.setPosition(pos1.x , pos1.y) // 设置新的位置}
}
子弹
子弹运动
把子弹图拖进场景2,调整位置,创建TS脚本,把TS脚本绑定到子弹上
编辑代码
@property speed : number = 250;
给这个变量加了 property 这个装饰器后,查看属性
发现多了一个 SPEED 的属性项,由此可以得出
property 装饰器 声明的变量会在属性面板中体现
再把子弹刷新代码写上
update(deltaTime: number) {const pos1 = this.node.positionthis.node.setPosition(pos1.x,pos1.y + this.speed * deltaTime,pos1.z)}
运行一下,如果发现子弹速度不理想,可以直接在属性面板修改 SPEED 属性
cocos 里 属性面板 的级别高于 代码属性
调试好 子弹1 后直接在 cocos 面板上复制 子弹1 再粘贴
修改贴图
最后这个样子就OK了
老师说这个要单独放在一个资源文件夹下,
以便后续调用
子弹发射
把子弹做好后在场景中可以删除
创建一个空节点,定位子弹 生成时(发射时) 的初始位置
子弹时自动发射,无需控制
直接对 Player 脚本进行添加一个方法
- 子弹生成速度
- 子弹生成的样子
- 子弹生成临时位置
- 已生成的子弹调整位置
import { _decorator, Component, EventTouch, Input, input, instantiate, Node, Prefab, Vec3 } from 'cc';
const { ccclass, property } = _decorator;@ccclass('player')
export class player extends Component {@property pinlv : number = 0.5 // 发色子弹频率time1 : number = 0 // 计时器@property(Prefab) zidan1 : Prefab = null // 创建一个绑定位,把子弹绑(图)定到上面@property(Node) bullet_cunfang : Node = null // 子弹生成是临时存放点@property(Node) bullet_weizhi : Node = null // 定位子弹位置protected onLoad(): void { // 打开触摸移动监听input.on(Input.EventType.TOUCH_MOVE, // 设置获取的类型this.onmove, // 赋值给onmove函数this)}protected onDestroy(): void { // 关闭input.off(Input.EventType.TOUCH_MOVE,this.onmove,this)}onmove(event:EventTouch){const p = this.node.position; // 获取坐标let pos1 = new Vec3( // 创建一个新的变量.来存储将要变更坐标,以便于判断p.x + event.getDeltaX(), // 当前X坐标 + 移动的X坐标p.y + event.getDeltaY(),)/*坐标我调了好久都不对,发现是我脚本挂在父空节点上,图片是子节点,所以我们动的是父节点,查看坐标也应该是父节点坐标*/if (pos1.x < -476) pos1.x = -476 // 限制左边if (pos1.x > -6) pos1.x = -6 // 限制右边if (pos1.y < -500) pos1.y = -500 // 限制下边if (pos1.y > 276) pos1.y = 276 // 限制上边this.node.setPosition(pos1.x , pos1.y) // 设置新的位置}protected update(dt: number): void {this.time1 += dtif (this.time1 >= this.pinlv){ // 发射时间判断this.time1 = 0 // 归零const bullet1 = instantiate (this.zidan1) this.bullet_cunfang.addChild(bullet1) // 生成一个实例bullet1.setWorldPosition(this.bullet_weizhi.worldPosition) // 把生成的子弹移动到位置上 世界坐标}}
}
下图场景列表
下图属性列表
下图资源列表
这里绑定时要特别注意上面三图,和在代码里面的关系
代码编辑完成后保存下,把三个属性绑定好
运行一下看有无问题
双发模式 和 模式切换
这里声明一下,本人也是零基础,初学者
弄了单发模式后,一葫芦画瓢,就自己写了个双发模式
我的代码可能和老师的不太一样
比如判断模式这里,我就只用了一个数字代替
老师用的是枚举 (实际情况模式种类多,用枚举更好,不容易出错)
我这里算是简化了,废话不多说,上代码
import { _decorator, Component, EventTouch, Input, input, instantiate, Node, Prefab, Vec3 } from 'cc';
const { ccclass, property } = _decorator;@ccclass('player')
export class player extends Component {@property pinlv : number = 0.5 // 发色子弹频率time1 : number = 0 // 计时器@property mode : number = 1 // 控制开火模式@property(Prefab) zidan1 : Prefab = null // 创建一个绑定位,把子弹绑(图)定到上面@property(Prefab) zidan2 : Prefab = null@property(Node) bullet_cunfang : Node = null // 子弹生成是临时存放点@property(Node) bullet_weizhi1 : Node = null // 子弹1位置定位@property(Node) bullet_weizhi2_1 : Node = null // 子弹2_1位置定位@property(Node) bullet_weizhi2_2 : Node = null // 子弹2_2位置定位protected onLoad(): void { // 打开触摸移动监听input.on(Input.EventType.TOUCH_MOVE, // 设置获取的类型this.onmove, // 赋值给onmove函数this)}protected onDestroy(): void { // 关闭input.off(Input.EventType.TOUCH_MOVE,this.onmove,this)}onmove(event:EventTouch){const p = this.node.position; // 获取坐标let pos1 = new Vec3( // 创建一个新的变量.来存储将要变更坐标,以便于判断p.x + event.getDeltaX(), // 当前X坐标 + 移动的X坐标p.y + event.getDeltaY(),)/*坐标我调了好久都不对,发现是我脚本挂在父空节点上,图片是子节点,所以我们动的是父节点,查看坐标也应该是父节点坐标*/if (pos1.x < -476) pos1.x = -476 // 限制左边if (pos1.x > -6) pos1.x = -6 // 限制右边if (pos1.y < -500) pos1.y = -500 // 限制下边if (pos1.y > 276) pos1.y = 276 // 限制上边this.node.setPosition(pos1.x , pos1.y) // 设置新的位置}protected update(dt: number): void {this.time1 += dtif (this.time1 >= this.pinlv){ // 发射时间判断this.time1 = 0 // 归零if (this.mode == 1){const bullet1 = instantiate (this.zidan1) this.bullet_cunfang.addChild(bullet1) // 生成一个实例bullet1.setWorldPosition(this.bullet_weizhi1.worldPosition) // 把生成的子弹移动到位置上 世界坐标}else if (this.mode == 2){const bullet2_1 = instantiate (this.zidan2)this.bullet_cunfang.addChild(bullet2_1)bullet2_1.setWorldPosition(this.bullet_weizhi2_1.worldPosition)const bullet2_2 = instantiate (this.zidan2)this.bullet_cunfang.addChild (bullet2_2)bullet2_2.setWorldPosition (this.bullet_weizhi2_2.worldPosition)}}}
}
注意
我这里稍微修改了一下变量名,为了整齐和区分
在cocos里也要重新绑定一下
小技巧
VScode 中重命名某个变量等等,不需要一个一个改
对着单词右键,自动修改当前页面所有一样的
英文名就不知道了,看原视频有说
上图是老师的代码
老师用是是一个switch语句 跳转讲解 if 语句 下面 switch 语法
创建单发函数 和 双发函数
再加入 switch 语句中
老师的代码,如果后续还要大范围更改的话,老师的更好,模块式开发
子弹销毁
回到子弹运行逻辑的TS脚本
加一个判断
update(deltaTime: number) {const pos1 = this.node.positionthis.node.setPosition(pos1.x,pos1.y + this.speed * deltaTime,pos1.z)if (pos1.y > 840) {this.node.destroy()} // 销毁自身}
下图这是没有加 node 时的问题
小技巧
重命名cocos属性面板上某个变量
会导致cocos上绑定在上面的东西重置