飞机打方块(二)游戏界面制作
一、背景
1.新建bg节点
二、飞机节点功能实现
1.移动
1.新建plane节点
2.新建脚本GameController.ts,并绑定Canvas
GameControll.ts
const { ccclass, property } = cc._decorator;@ccclass
export default class NewClass extends cc.Component {@property(cc.Node)canvas: cc.Node = null;@property({ type: cc.Node, displayName: "飞机(主角)", tooltip: "主角,也就是飞机节点" })plane: cc.Node = null;@property({ displayName: "飞机和炮弹是否能移动", tooltip: "飞机和炮弹是否能移动" })is_plane_move: boolean = true;onLoad() {//给Canvas绑定事件this.canvas.on(cc.Node.EventType.TOUCH_MOVE, this.onMove, this)}//移动飞机函数,当手指在屏幕上移动时将执行这个函数onMove(event: cc.Event.EventTouch) {//打印logconsole.log("手指在屏幕上移动了");/* //触摸点的坐标var pos = new cc.Vec2(event.getLocationX(), event.getLocationY())//转换坐标//将一个点转换到节点(局部)空间坐标系,这个坐标系以锚点为位置pos = this.canvas.convertToNodeSpaceAR(pos)//给飞机赋值this.plane.position = cc.v3(pos) *///获取触点在上一次事件时的位置对象,对象包含x和y属性if (this.is_plane_move == true) {let last_pos = event.getPreviousLocation();//获取触点位置let pos = event.getLocation()//做向量减法var dir = last_pos.sub(pos)//移动飞机的坐标this.plane.x -= dir.x;this.plane.y -= dir.y;}}update(dt: number): void{//屏幕上下左右,用来防止飞机飞出屏幕let l = (this.canvas.width / 2) + (this.plane.width / 2);let r = (this.canvas.width / 2) - (this.plane.width / 2);let t = (this.canvas.height / 2) - (this.plane.height / 2);let b = (this.canvas.height / 2) + (this.plane.height / 2);//超过边界检测if (this.plane.x > r) {this.plane.x = r;}if (this.plane.x < l) {this.plane.x = l;}if (this.plane.y > t) {this.plane.y = t;}if (this.plane.y < b) {this.plane.y = b;}}
}
三.子弹
1.新建粒子
2.新建Bullet脚本,新建bullet预制体
Game.ts
@property({ type: cc.Prefab, displayName: "炮弹预制体", tooltip: "炮弹的预制体,飞机每时每刻都在发射子弹" })bullet: cc.Prefab = null;@property({ displayName: "炮弹生成左侧坐标", tooltip: "炮弹生成左侧坐标,以飞机锚点为原点建立坐标系时炮弹的位置" })bullet_left_pos: cc.Vec2 = null;@property({ displayName: "炮弹生成右侧坐标", tooltip: "炮弹生成右侧坐标,以飞机锚点为原点建立坐标系时炮弹的位置" })bullet_right_pos: cc.Vec2 = null;@property({ type: cc.Float, displayName: "每秒发射几个炮弹", tooltip: "每秒发射几个炮弹,这个值是始终不变的,当这个值过大时,设备会明显卡顿" })bullet_num: number = 10;@property({ type: cc.Float, displayName: "炮弹发射速度", tooltip: "子弹发射速度,单位是每秒发射多少个像素,吃到buff会提高" })bullet_speed: number = 100;@property({ type: cc.Float, displayName: "炮弹攻击力", tooltip: "攻击力,炮弹打到障碍物时减少的生命值,吃到buff会提高" })ATK: number = 2;@property({ displayName: "是否可以发射炮弹", tooltip: "是否可以发射炮弹,为false时飞机将不再发射炮弹" })is_fire: boolean = true@property({ displayName: "飞机和炮弹是否能移动", tooltip: "飞机和炮弹是否能移动" })is_plane_move: boolean = true;//生成飞机左侧炮弹用的变量l: number = 0;//生成飞机右侧炮弹用的变量r: number = 0update(dt: number): void {//炮弹生成let time = 1 / this.bullet_num;//飞机左侧炮弹生成this.l += dt;if (this.l > time && this.is_fire == true) {//打印logconsole.log("生成左侧炮弹");//清零this.l = 0;//创建炮弹this.create_bullet(cc.v3(this.bullet_left_pos))}//飞机右侧炮弹生成this.r += dtif (this.r > time && this.is_fire == true) {console.log("飞机右侧炮弹生成");this.r = 0;this.create_bullet(cc.v3(this.bullet_right_pos))}}//生成炮弹函数,pos以飞机锚点为原点建立坐标系时炮弹的位置create_bullet(pos: cc.Vec3) {//实例化新节点let node = cc.instantiate(this.bullet);//父节点为canvasnode.parent = this.canvas;//获取xlet x = pos.x + this.plane.x;//获取ylet y = pos.y + this.plane.y;//将坐标转换let p = this.canvas.convertToNodeSpaceAR(cc.v3(x, y))//求出最终坐标let position: cc.Vec3 = cc.v3(p.x + (this.canvas.width / 2), p.y + (this.canvas.height / 2))//赋值node.position = cc.v3(position);}
Bullet.ts:
const { ccclass, property } = cc._decorator;@ccclass
export default class NewClass extends cc.Component {//子弹速度speed: number = 100;//子弹攻击力ATK: number = 2;onLoad(): void {//获取GameController脚本let gc = cc.find("Canvas").getComponent("GameController");//获取速度和攻击力并赋值let speed: number = gc.bullet_speed;let ATK: number = gc.ATK;this.speed = speed;this.ATK = ATK;}update(dt: number) {//获取GameController脚本let gc = cc.find("Canvas").getComponent("GameController");//自身移动if (gc.is_plane_move == true) {this.node.y += dt * this.speed;}//获取canvas节点let canvas = cc.find("Canvas");//如果自身到了屏幕最上方if (this.node.y >= (canvas.height / 2) + (this.node.height / 2)) {this.node.destroy();console.log("子弹超出了屏幕,自动销毁");}}
}
3.子弹信息显示:
1.新建state_lb_parent节点:
2.新建Label节点
绑定Canvas
GameController.ts
@property({ type: cc.Label, displayName: "显示状态的文字", tooltip: "显示状态的文字,显示射速,攻击力,两个label前后位置无所谓" })state_lb: cc.Label[] = [];update(dt: number): void {//炮弹生成let time = 1 / this.bullet_num;//飞机左侧炮弹生成this.l += dt;if (this.l > time && this.is_fire == true) {//打印logconsole.log("生成左侧炮弹");//清零this.l = 0;//创建炮弹this.create_bullet(cc.v3(this.bullet_left_pos))}//飞机右侧炮弹生成this.r += dtif (this.r > time && this.is_fire == true) {console.log("飞机右侧炮弹生成");this.r = 0;this.create_bullet(cc.v3(this.bullet_right_pos))}//显示状态//子弹射速let speed = Math.floor(this.bullet_speed);//子弹攻击力let ATK = Math.floor(this.ATK)//如果速度不为满级正常显示if (this.bullet_speed < 10000) {this.state_lb[0].string = "子弹射速:" + speed;}//如果速度不为满级正常显示else {this.state_lb[0].string = "子弹射速:Max";}this.state_lb[1].string = "子弹攻击力:" + ATK;}
四、显示分数
1.新建摄像机
2.新建节点
GameController.ts
@property({ type: cc.Label, displayName: "显示分数文字", tooltip: "显示分数的文字" })score_lb: cc.Label = null;//分数score: number = 0;update(dt: number): void {//炮弹生成let time = 1 / this.bullet_num;//飞机左侧炮弹生成this.l += dt;if (this.l > time && this.is_fire == true) {//打印logconsole.log("生成左侧炮弹");//清零this.l = 0;//创建炮弹this.create_bullet(cc.v3(this.bullet_left_pos))}//飞机右侧炮弹生成this.r += dtif (this.r > time && this.is_fire == true) {console.log("飞机右侧炮弹生成");this.r = 0;this.create_bullet(cc.v3(this.bullet_right_pos))}//显示状态//子弹射速let speed = Math.floor(this.bullet_speed);//子弹攻击力let ATK = Math.floor(this.ATK)//如果速度不为满级正常显示if (this.bullet_speed < 10000) {this.state_lb[0].string = "子弹射速:" + speed;}//如果速度不为满级正常显示else {this.state_lb[0].string = "子弹射速:Max";}this.state_lb[1].string = "子弹攻击力:" + ATK;//显示分数//如果分数小于1000正常显示if (this.score < 1000) {this.score_lb.string = "分数:" + Math.floor(this.score);}//如果分数大于1000小于10000就用k表示else if (this.score < 10000) {let s = (Math.floor(this.score) / 1000).toFixed(2);this.score_lb.string = "分数:" + s + "K";}//如果分数大于10000就用w表示else {let s = (Math.floor(this.score) / 10000).toFixed(2);this.score_lb.string = "分数:" + s + "W";}}
五、障碍
1.生成障碍
1.新建所有障碍父节点
2.新建预制体barrier ,新建Barrier脚本
3.新建子节点
GameController.ts
@property({ type: cc.Node, displayName: "所有障碍父节点", tooltip: "所有障碍父节点,这个节点用来消除所有障碍" })barrier_parent: cc.Node = null;@property({ type: cc.Prefab, displayName: "障碍物预制体", tooltip: "障碍物预制体" })barrier: cc.Prefab = null;@property({ displayName: "每个障碍物间距范围", tooltip: "每个障碍物间距范围,最小多少,最大多少" })barrier_spacing: cc.Vec2 = cc.v2(10, 50)@property({ displayName: "障碍物宽度(必填)", tooltip: "障碍物宽度(必填),代码将根据这个值来计算出障碍物生成的最佳位置" })barrier_width: number = 100;@property({ displayName: "障碍我高度(必填)", tooltip: "障碍物高度(必填),代码将根据这个值来计算出障碍物生成的最佳位置" })barrier_height: number = 100;@property({ displayName: "障碍物初始生命值", tooltip: "障碍物初始生命值,其实就是障碍物上面文字的数值,当值为0时障碍物销毁,但是这个值并不是障碍物初始的生命值,因为最终障碍物还加上了随机数" })barrier_health: number = 100;@property({ type: cc.Float, displayName: "障碍物移动速度", tooltip: "障碍物移动速度,单位是每秒多少个像素" })barrier_speed: number = 100;@property({ type: cc.Float, displayName: "障碍物生成时间间隔", tooltip: "障碍物生成时间间隔,通过控制这个来调整生成频率,最终的频率为(这个变量*Math.random())+(障碍物高/障碍物移动速度)" })generation_interval: number = 0.8;@property({ type: cc.Float, displayName: "每生成一次障碍物,障碍物锁增加的生命值", tooltip: "每生成一次障碍物,障碍物锁增加的生命值,最终结果是(这个变量*Math.random())" })increase: number = 2;@property({ displayName: "是否生成障碍物", tooltip: "是否生成障碍物" })is_barrier_create: boolean = true;@property({ displayName: "障碍物和buff是否可以移动", tooltip: "障碍物和buff是否可以移动" })is_barrier_move: boolean = true;//创建障碍物用的变量(当前)cre_bar: number = 0;//创建障碍物用的变量(满的)cre_bar_f: number = 0;onLoad() {cc.game.setFrameRate(90)//恢复游戏,避免游戏暂停导致无法继续cc.director.resume();//给Canvas绑定事件this.canvas.on(cc.Node.EventType.TOUCH_MOVE, this.onMove, this)//创建障碍物this.create_barrier();this.cre_bar_f = (this.barrier_height / this.barrier_speed) + Math.random() * this.generation_interval;}update(dt: number): void {//炮弹生成let time = 1 / this.bullet_num;//飞机左侧炮弹生成this.l += dt;if (this.l > time && this.is_fire == true) {//打印logconsole.log("生成左侧炮弹");//清零this.l = 0;//创建炮弹this.create_bullet(cc.v3(this.bullet_left_pos))}//飞机右侧炮弹生成this.r += dtif (this.r > time && this.is_fire == true) {console.log("飞机右侧炮弹生成");this.r = 0;this.create_bullet(cc.v3(this.bullet_right_pos))}//生成障碍物//如果能生成障碍物就加if (this.is_barrier_create == true) {this.cre_bar = this.cre_bar + dt;}//可以生成障碍物时if (this.cre_bar >= this.cre_bar_f) {this.cre_bar = 0;this.cre_bar_f = (this.barrier_height / this.barrier_speed) + (Math.random() * this.generation_interval);this.create_barrier();}//显示状态//子弹射速let speed = Math.floor(this.bullet_speed);//子弹攻击力let ATK = Math.floor(this.ATK)//如果速度不为满级正常显示if (this.bullet_speed < 10000) {this.state_lb[0].string = "子弹射速:" + speed;}//如果速度不为满级正常显示else {this.state_lb[0].string = "子弹射速:Max";}this.state_lb[1].string = "子弹攻击力:" + ATK;//显示分数//如果分数小于1000正常显示if (this.score < 1000) {this.score_lb.string = "分数:" + Math.floor(this.score);}//如果分数大于1000小于10000就用k表示else if (this.score < 10000) {let s = (Math.floor(this.score) / 1000).toFixed(2);this.score_lb.string = "分数:" + s + "K";}//如果分数大于10000就用w表示else {let s = (Math.floor(this.score) / 10000).toFixed(2);this.score_lb.string = "分数:" + s + "W";}}//创建障碍物函数create_barrier(): void {//l为最左边,也就是从哪里生成,就是屏幕最左边加上一个随机数let l = ((-this.canvas.width / 2) + (this.barrier_width / 2)) + Math.random() * 100;//r为最右边,也就是从哪里结束生成,就是屏幕最右边减去一个随机数let r = (this.canvas.width / 2) - (this.barrier_width / 2) - Math.random() * 50;//获取屏幕最上面的Y坐标let top = (this.canvas.height / 2) + (this.barrier_height / 2);//获取障碍物之间的间距,值是随机的let barrier_spacing = this.randomNumber(this.barrier_spacing.x, this.barrier_spacing.y);//while循环生成障碍物//如果左边小于右边while (l < r) {let barrier = cc.instantiate(this.barrier);barrier.parent = this.barrier_parent;barrier.position = cc.v3(l, top)//随机数生成障碍物的间距barrier_spacing = this.randomNumber(this.barrier_spacing.x, this.barrier_spacing.y);//打印logconsole.log("生成障碍物,目前值为:" + l.toString());//左边的值加上障碍物宽和障碍物的间距l = l + this.barrier_width + barrier_spacing;}
//障碍物的生命值加上障碍物的宽和障碍物的间距this.barrier_health += Math.floor(Math.random() * this.increase)}//随机函数 min为最小值,max为最大值,将返回一个number,值大小的范围为min-maxrandomNumber(min: number, max: number) {return (Math.round(Math.random() * (min - max) + max))}
Barrier.ts
const { ccclass, property } = cc._decorator;@ccclass
export default class Barrier extends cc.Component {@property({ type: cc.Label, displayName: "显示数值的文字", tooltip: "显示数值的文字" })num_lb: cc.Label = null;//@property({type: cc.Float, displayName: "自身数值", tooltip: "自身数值,当数值为0时当前节点销毁"})num: number = 20;//自身速度speed: number = 2;onLoad(): void {//自身和文字随机颜色 this.node.color = cc.color(this.random_color().x, this.random_color().y, this.random_color().z, 255);this.num_lb.node.color = cc.color(this.random_color().x, this.random_color().y, this.random_color().z, 255);//防止颜色一样//如果自身和文字颜色一样if (this.num_lb.node.color == this.node.color) {//文字如果不为红色if (this.num_lb.node.color != cc.color(255, 0, 0, 255)) {//文字变为红色this.num_lb.node.color = cc.color(255, 0, 0, 255);} else {//如果不,则变成黑色this.num_lb.node.color = cc.color(0, 0, 0, 255);}}//获取GameController脚本let gc = cc.find("Canvas").getComponent("GameController");//获取脚本下障碍物的生命值并加上随机数let h = (gc.barrier_health) + Math.floor(Math.random() * 10);//获取脚本下障碍物的速度let s = gc.barrier_speed;//赋值this.num = h;this.speed = s;}//随机颜色函数random_color(): cc.Vec3 {let r = this.randomNumber(0, 255);let g = this.randomNumber(0, 255);let b = this.randomNumber(0, 255);return (cc.v3(r, g, b))}update(dt: number) {//将自身生命值取整let num = Math.floor(this.num);//在Label上显示this.num_lb.string = num.toString();//获取GameController脚本let gc = cc.find("Canvas").getComponent("GameController");//自身移动if (gc.is_barrier_move == true) {this.node.y -= dt * this.speed;}//获取canvas节点let canvas = cc.find("Canvas");//如果自身到了屏幕最下方if (this.node.y <= -(canvas.height / 2)) {//获取GameController脚本let gc = cc.find("Canvas").getComponent("GameController");//调用游戏结束函数/* gc.gameOver() */}}// 随机数函数 min为最小值 max为最大值 将返回一个number,值大小的范围为min-maxrandomNumber(min: number, max: number): number {return (Math.round(Math.random() * (min - max) + max));}
}
4.绑定Canvas
2.消除障碍
GameController.ts
onLoad() {cc.game.setFrameRate(90)//恢复游戏,避免游戏暂停导致无法继续cc.director.resume();//给Canvas绑定事件this.canvas.on(cc.Node.EventType.TOUCH_MOVE, this.onMove, this)//开启碰撞引擎let manager = cc.director.getCollisionManager();manager.enabled = true;//如果要调试if (this.is_debug == true) {// 是否绘制碰撞组件的形状,默认为不绘制manager.enabledDebugDraw = true;//是否绘制碰撞组件的包围盒,默认为不绘制manager.enabledDrawBoundingBox = true;}//创建障碍物this.create_barrier();this.cre_bar_f = (this.barrier_height / this.barrier_speed) + Math.random() * this.generation_interval;}
Brrier.ts
//碰撞回调//当碰撞产生的时候调用other产生碰撞的另一个组件 self产生碰撞的自身的碰撞组件onCollisionEnter(other, self) {if (other.node.group == "bullet") {//获取GameController脚本let gc = cc.find("/Canvas").getComponent("GameController");//获取Bullet脚本let c = other.getComponent("Bullet");//从脚本获取攻击力较少自身生命值this.reduce_num(c.ATK);//销毁子弹other.node.destroy();}//如果自身生命值小于0if (this.num <= 0) {//自身销毁this.node.destroy();}}
六、Buff
1.生成buff
1.新建显示获得buff类型节点
2.新建Buff脚本,新建buff预制资源
3.新建buff子节点
GameController.ts
@property({ type: cc.Prefab, displayName: "buff预制体", tooltip: "buff预制体" })buff: cc.Prefab = null;//创建障碍物函数create_barrier(): void {//l为最左边,也就是从哪里生成,就是屏幕最左边加上一个随机数let l = ((-this.canvas.width / 2) + (this.barrier_width / 2)) + Math.random() * 100;//r为最右边,也就是从哪里结束生成,就是屏幕最右边减去一个随机数let r = (this.canvas.width / 2) - (this.barrier_width / 2) - Math.random() * 50;//获取屏幕最上面的Y坐标let top = (this.canvas.height / 2) + (this.barrier_height / 2);//获取障碍物之间的间距,值是随机的let barrier_spacing = this.randomNumber(this.barrier_spacing.x, this.barrier_spacing.y);//while循环生成障碍物//如果左边小于右边while (l < r) {//利用随机数,有概率生成buff球let n = Math.random() * 100;if (n > this.probability) {let barrier = cc.instantiate(this.barrier);barrier.parent = this.barrier_parent;barrier.position = cc.v3(l, top)} else if (n < this.probability) {//生成buff球,Y坐标是屏幕上方let buff = cc.instantiate(this.buff);buff.parent = this.barrier_parent;buff.position = cc.v3(1, top);}//随机数生成障碍物的间距barrier_spacing = this.randomNumber(this.barrier_spacing.x, this.barrier_spacing.y);//打印log/* console.log("生成障碍物,目前值为:" + l.toString()); *///左边的值加上障碍物宽和障碍物的间距l = l + this.barrier_width + barrier_spacing;}//障碍物的生命值加上障碍物的宽和障碍物的间距this.barrier_health += Math.floor(Math.random() * this.increase)}
Buff.ts
const { ccclass, property } = cc._decorator;@ccclass
export default class NewClass extends cc.Component {//自身移动速度speed: number = 2;onLoad(): void {//获取GameController脚本let gc = cc.find("Canvas").getComponent("GameController");//获取障碍物移动速度let s = gc.barrier_speed;this.speed = s;}update(dt: number) {//获取GameController脚本let gc = cc.find("Canvas").getComponent("GameController");//自身移动if (gc.is_barrier_move == true) {this.node.y -= dt * this.speed;}}}
4.绑定Canvas
2.buff碰撞
1.新建double_lb节点
Buff.ts
//碰撞回调onCollisionEnter(other,self){//获取GameController脚本let gc = cc.find("Canvas").getComponent("GameController");//如果子弹射速满了,就不增加射速了if(gc.bullet_speed<10000){//随机数0-10let n = this.randomNumber(0,10);//有一半几率执行子弹加速函数//也有一半几率执行子弹加攻击函数if(n>5){//加速buffgc.enhance_speed();}else{//加攻击buffgc.enhance_ATK();}}else{gc.enhance_ATK()}//自身销毁this.node.destroy()}// 随机数函数 min为最小值 max为最大值 将返回一个number,值大小的范围为min-maxrandomNumber (min: number, max: number): number {return(Math.round(Math.random() * (min - max) + max));}
GameController.ts
@property({ type: cc.Node, displayName: "显示获得buff类型的label", tooltip: "显示获得buff类型的label" })label_parent: cc.Node = null;@property({ type: cc.Node, displayName: "显示双倍分数的label", tooltip: "显示双倍分数的label" })double_lb: cc.Node = null;@property({ type: cc.Prefab, displayName: "buff预制体", tooltip: "buff预制体" })buff: cc.Prefab = null;@property({ displayName: "是否双倍分数", tooltip: "是否双倍分数" })is_double: boolean = false;//增加子弹射速enhance_speed() {//增加射速this.bullet_speed = this.bullet_speed + this.add_buff_num[0];//射速加的越来越多this.add_buff_num[0] = this.add_buff_num[0] * 1.1;//新建一个label来显示吃到的buff//新建节点let node = new cc.Node//父节点是label_parent,这个节点上有Layout组件node.parent = this.label_parent;//添加cc.Labelnode.getComponent(cc.Label);//显示内容node.getComponent(cc.Label).string = "子弹射速提升";//定时器1秒后销毁this.scheduleOnce(function () {node.destroy();}, 1);//双倍分数this.double_score(8);}//增强子弹攻击力enhance_ATK() {//增加攻击力this.ATK = this.ATK + this.add_buff_num[1];//攻击力加的越来越多this.add_buff_num[1] = this.add_buff_num[1] * 1.1;// 新建一个label来显示吃到的buff// 新建节点let node = new cc.Node;// 父节点是label_parent,这个节点上有Layout组件node.parent = this.label_parent;// 添加cc.Labelnode.addComponent(cc.Label);// 显示内容node.getComponent(cc.Label).string = "子弹攻击力提升";// 定时器 1秒后销毁this.scheduleOnce(function () {node.destroy();}, 1);// 双倍分数this.double_score(8);}//双倍分数函数,执行后得分翻倍,time为多少秒后恢复double_score(time: number) {let self = this;//开启双倍分数并且显示文字this.is_double = true;this.double_lb.active = true;//定时器关闭双倍分数并且隐藏文字this.scheduleOnce(function () {self.is_double = false;self.double_lb.active = false;}, time);}
2.绑定Canvas
七、加分
Barrier.ts
//碰撞回调//当碰撞产生的时候调用other产生碰撞的另一个组件 self产生碰撞的自身的碰撞组件onCollisionEnter(other, self) {if (other.node.group == "bullet") {//获取GameController脚本let gc = cc.find("/Canvas").getComponent("GameController");//获取Bullet脚本let c = other.getComponent("Bullet");//从脚本获取攻击力较少自身生命值this.reduce_num(c.ATK);// 如果可以加双倍分数if(gc.is_double==true){//加分gc.add_score((c.ATK)*2)}//如果不可以加双倍分数if(gc.is_double == false){gc.add_score(c.ATK);}//销毁子弹other.node.destroy();}//如果自身生命值小于0if (this.num <= 0) {//自身销毁this.node.destroy();}}
GameController.ts
update(dt: number): void {//炮弹生成let time = 1 / this.bullet_num;//飞机左侧炮弹生成this.l += dt;if (this.l > time && this.is_fire == true) {//打印log/* console.log("生成左侧炮弹"); *///清零this.l = 0;//创建炮弹this.create_bullet(cc.v3(this.bullet_left_pos))}//飞机右侧炮弹生成this.r += dtif (this.r > time && this.is_fire == true) {/* console.log("飞机右侧炮弹生成"); */this.r = 0;this.create_bullet(cc.v3(this.bullet_right_pos))}//生成障碍物//如果能生成障碍物就加if (this.is_barrier_create == true) {this.cre_bar = this.cre_bar + dt;}//可以生成障碍物时if (this.cre_bar >= this.cre_bar_f) {this.cre_bar = 0;this.cre_bar_f = (this.barrier_height / this.barrier_speed) + (Math.random() * this.generation_interval);this.create_barrier();}//显示状态//子弹射速let speed = Math.floor(this.bullet_speed);//子弹攻击力let ATK = Math.floor(this.ATK)//如果速度不为满级正常显示if (this.bullet_speed < 10000) {this.state_lb[0].string = "子弹射速:" + speed;}//如果速度不为满级正常显示else {this.state_lb[0].string = "子弹射速:Max";}this.state_lb[1].string = "子弹攻击力:" + ATK;//显示分数//如果分数小于1000正常显示if (this.score < 1000) {this.score_lb.string = "分数:" + Math.floor(this.score);}//如果分数大于1000小于10000就用k表示else if (this.score < 10000) {let s = (Math.floor(this.score) / 1000).toFixed(2);this.score_lb.string = "分数:" + s + "K";}//如果分数大于10000就用w表示else {let s = (Math.floor(this.score) / 10000).toFixed(2);this.score_lb.string = "分数:" + s + "W";}//加分函数add_score(num: number) {this.score = this.score + num;}
相关文章:

飞机打方块(二)游戏界面制作
一、背景 1.新建bg节点 二、飞机节点功能实现 1.移动 1.新建plane节点 2.新建脚本GameController.ts,并绑定Canvas GameControll.ts const { ccclass, property } cc._decorator;ccclass export default class NewClass extends cc.Component {property(cc.Node)canvas:…...
自我理解:精度(precision)和召回(recall)
1、精度(precision) 精度是用于评估分类模型的一个重要指标。它反映了模型预测为正例的样本中,实际真正为正例样本的比例。 【注】正例样本指在二分类问题中,被标注为正类的样本。 例如:在垃圾邮件分类任务中,正例样本就是真实的…...
Nginx 使用 HTTPS(准备证书和私钥)
文章目录 Nginx生成自签名证书和配置Nginx HTTPS(准备证书和私钥)准备证书和私钥 Nginx生成自签名证书和配置Nginx HTTPS(准备证书和私钥) 准备证书和私钥 生成私钥 openssl genrsa -des3 -out server.key 2048这会生成一个加密…...

Java:集合框架:Set集合、LinkedSet集合、TreeSet集合、哈希值、HashSet的底层原理
Set集合 创建一个Set集合对象,因为Set是一个接口不能直接new一个对象,所以要用一个实现类来接 HashSet来接 无序性只有一次,只要第一次运行出来后,之后再运行的顺序还是第一次的顺序。 用LinkedSet来接 有序 不重复 无索引 用Tree…...
自定义Taro的navBar的宽度和高度
本方法是计算自定义navbar的宽度和高度,输出的参数有 navBarHeight, menuBottom,menuHeight, menuRectWidth,windowWidth, windowHeight,具体代码如下: export function getCustomNavBarRect():| {navBarHeight: number;menuBottom: number;menuHeight:…...
用Python编程实现百度自然语言处理接口的对接,助力你开发智能化处理程序
用Python编程实现百度自然语言处理接口的对接,助力你开发智能化处理程序 随着人工智能的不断进步,自然语言处理(Natural Language Processing,NLP)成为了解决文本处理问题的重要工具。百度自然语言处理接口提供了一系…...

系统架构设计专业技能 · 系统工程与系统性能
系列文章目录 系统架构设计专业技能 网络技术(三) 系统架构设计专业技能 系统安全分析与设计(四)【系统架构设计师】 系统架构设计高级技能 软件架构设计(一)【系统架构设计师】 系统架构设计高级技能 …...

初识网络原理(笔记)
目录 编辑局域网 网络通信基础 IP 地址 端口号 协议 协议分层 TCP / IP 五层网络模型 网络数据传输的基本流程 发送方的情况: 接收方的情况 局域网 搭建网络的时候,需要用到 交换机 和 路由器 路由器上,有 lan 口 和 wan 口 虽…...

嵌入式C语言基本操作方法之经典
C语言一经出现就以其功能丰富、表达能力强、灵活方便、应用面广等特点迅速在全世界普及和推广。 C语言不但执行效率高而且可移植性好,可以用来开发应用软件、驱动、操作系统等。 C语言也是其它众多高级语言的鼻祖语言,所以说学习C语言是进入编程世界的必…...
postgresql \watch实用的使用方法
文章目录 1.介绍2.语法3.实用的使用方法3.1 慢sql监控3.2 长wait事件3.3 日志输出量3.3结合pg_stat_database使用3.4 结合pg_stat_bgwriter使用3.5 其他 1.介绍 \watch Postgres 9.3 版带来的一个有用的命令,与linux watch指令类似,可以帮我们在指定间隔…...
Cocos2d 项目问题记录
环境搭建 正常运行 Android 端的 Cocos2d 项目,本机至少需要 Android SDK、NDK 环境、Android Studio 项目报错总结 CMake Error: CMake was unable to find a build program corresponding to "Ninja" 默认创建工程的 gradle.tools 版本为 3.1.0&…...

系统架构合理性的思考 | 京东云技术团队
最近牵头在梳理部门的系统架构合理性,开始工作之前,我首先想到的是如何定义架构合理性? 从研发的角度来看如果系统上下文清晰、应用架构设计简单、应用拆分合理应该称之为架构合理。 基于以上的定义可以从以下三个方面来梳理评估࿱…...

Amelia预订插件:WordPress企业级预约系统
并非所有WordPress预订插件都像他们所设计的那样。其中一些缺乏运行高效预约操作所需的功能,而其他一些则看起来陈旧过时。您不需要其中任何一个,但Amelia预订插件似乎希望确保所有用户都对功能和风格感到满意。 在这篇Amelia企业级预约系统插件评测中&…...
共享门店模式:线下门店的商家如何利用它增加客户
随着数字化时代的到来,商业模式正在不断创新与演变,而共享经济正成为引领这一变革的重要力量。在这个大背景下,共享门店模式作为共享经济的一种体现,正在逐渐走进人们的生活,并为商家和消费者带来了新的商机和体验。 共…...
实现矩阵地图与rviz地图重合
文章目录 一、rviz地图转换矩形地图(只能用于全局规划)二、在rviz上显示地图边界信息,可视化调整,实现重合(只能用于局部规划)一、rviz地图转换矩形地图(只能用于全局规划) 此方法矩形地图可能会与rviz地图不重合,通过改变偏移量x_offset,y_offset接近地图 可以将矩…...
设计模式十九:备忘录模式(Memento Pattern)
备忘录模式是一种行为型设计模式,它允许对象在不暴露其内部状态的情况下捕获和恢复其状态。该模式的主要目标是在不破坏封装性的前提下,实现对象状态的备份和恢复。备忘录模式常用于需要保存对象历史状态、撤销操作或者实现快照功能的情况。 备忘录模式…...
【题解】二叉搜索树与双向链表
二叉搜索树与双向链表 题目链接:二叉搜索树与双向链表 解题思路1:递归中序遍历 首先题目最后要求的是一个的递增的双向链表,而二叉搜索树也是一类非常有特色的树,它的根节点大于所有左侧的节点,同时又小于所有右侧的…...
【真实案例】解决后端接口调用偶尔超时问题
文章目录 背景分析代码分析二次日志分析排查Gateway服务解决解决办法1:添加重试机制解决办法2:优化网关内存分配解决办法3:调整OOM策略背景 项目从虚拟机迁移到k8s云原生平台(RainBond)后,发现偶尔会出现接口调用超时的问题。 统计了一下从上线到现在近一个月的调用失败…...

操作符详解(1)
1. 操作符分类: 算术操作符 移位操作符 位操作符 赋值操作符 单目操作符 关系操作符 逻辑操作符 条件操作符 逗号表达式 下标引用、函数调用和结构成员 2. 算术操作符 - * / % 1. 除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数。 2. 对…...

<指针进阶>指针数组和数组指针傻傻分不清?
✨Blog:🥰不会敲代码的小张:)🥰 🉑推荐专栏:C语言🤪、Cpp😶🌫️、数据结构初阶💀 💽座右铭:“記住,每一天都是一個新的開始…...

React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

SpringTask-03.入门案例
一.入门案例 启动类: package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...

短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...
第7篇:中间件全链路监控与 SQL 性能分析实践
7.1 章节导读 在构建数据库中间件的过程中,可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中,必须做到: 🔍 追踪每一条 SQL 的生命周期(从入口到数据库执行)&#…...
Spring Security 认证流程——补充
一、认证流程概述 Spring Security 的认证流程基于 过滤器链(Filter Chain),核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤: 用户提交登录请求拦…...

C++_哈希表
本篇文章是对C学习的哈希表部分的学习分享 相信一定会对你有所帮助~ 那咱们废话不多说,直接开始吧! 一、基础概念 1. 哈希核心思想: 哈希函数的作用:通过此函数建立一个Key与存储位置之间的映射关系。理想目标:实现…...