猫狗大战

  • 游戏类型:塔防游戏
  • 标签:卡通、休闲、2D、塔防、闯关
  • 引擎:Cocos Creator
  • 语言:JS
  • 作者:未生畏死
  • 注:美术资源来源于网络

游戏玩法:

  一共有两种玩法。其一:在怪物到达堡垒前杀死它,否则堡垒会扣一点血。怪物消失。其二:怪物会沿着路循环移动,请在规定时间内杀死所有怪物。

场景描述

一共三个场景。

  • Main:主场景,可开始、退出游戏。
  • Opt:选择场景。可进行选关操作,返回Main场景。
  • Pass1:游戏场景。加载对应关卡数据,生成对应物体,开始PLAY。

功能描述:

  • 猫:堡垒。10hp。每有一只AI到达猫的位置时,hp-1。hp<=0时。游戏失败。循环关卡则hp恒定。技能:尖叫。消灭自身一定范围内的AI。
  • 狗:出生点。所有AI的生成位置。
  • AI:沿着路径移动,到达猫的位置时如果是普通关卡。猫hp-1,AI销毁。如果是循环关卡,则沿着路径继续移动。
  • 炮台:炮台最高三级,每升一级会获得一定的属性提升。炮台会自动攻击在自己攻击范围内的敌人。可进行操作:创建、升级、售卖。
  • 障碍物:占据地图位置的东西,拥有一定hp。只有将其清除后,才能使用其对应的格子进行炮台的创建等操作。消灭后,你会获得一定金币。
  • 金币:你会获得一定的初始金币来进行炮台的创建、升级。消灭AI和障碍物是金币的来源。
  • 标志物。你可以标记障碍物、使AI优先攻击他们。
  • 等等…

具体功能实现:

地图生成。加载关卡数据,生成对应地图、猫、狗等。


this.PlayPass = cc.sys.localStorage.getItem("PlayPass")
this.PlayPass = 1
window.stageMission = window.mission[this.PlayPass]
// cc.log(this.PlayPass)
this.missionLoad()//任务信息加载
cc.loader.loadRes("tilemaps/stage-" + this.PlayPass, (err, tiled) => {
if (!err) {
cc.director.emit("levelUi", this.PlayPass)
this.titledMap.getComponent(cc.TiledMap).tmxAsset = tiled
// cc.log(tiled)
// cc.log(this.titledMap.getComponent(cc.TiledMap))
this.init()
}
})
  • TiledMap数据解析

initData() {
this.mapSize = this.titledMap.getMapSize();
this.tileSize = this.titledMap.getTileSize();
this.road = this.titledMap.getLayer("road");
this.object = this.titledMap.getLayer("object");
this.tower = this.titledMap.getLayer("tower");
this.path = this.titledMap.getLayer("path");
this.obj = this.titledMap.getObjectGroup("obj");
this.tiledLayer = this.path
this.path.node.opacity = 0
this.life = this.obj.getObject("life");//线段路径层处理
this.chestpath = this.obj.getObject("chestpath");
this.pathline = this.obj.getObject("pathline");
this.end = this.obj.getObject("end");
this.aistart = this.obj.getObject("start");
// cc.log(this.life)
// cc.log(this.pathline)
this.pointArr = this.pathline.polylinePoints
for (let i = 0; i < this.pointArr.length; i++) {
this.pointArr[i] = cc.v2(this.pathline.x + this.pointArr[i].x, this.pathline.y - this.pointArr[i].y)
}
// uiBase: cc.Node,//猫、狗、生命值
// cc.director.emit("uibase", this.aistart, this.end, this.life)
cc.log("uibase")
this.uiBase.getComponent("Life").init(this.aistart, this.end, this.pointArr[0], this.life, window.stageMission.Hp)
cc.director.emit("coinDeal", window.stageMission.Money)
// this.scheduleOnce(()=>{
// cc.director.emit("settleSysyem")
// },6)
},
  • TiledMap数据处理

initKu() {
// cc.log(it)
// cc.log(this.pointArr)
for (let i = 0; i < this.mapSize.width; i++) {
this.ku[i] = {}
for (let j = 0; j < this.mapSize.height; j++) {
this.ku[i][j] = {}
let gidPath = this.path.getTileGIDAt(i, j);//可走路径处理
// let tilePath = this.path.getTiledTileAt(i, j, true);
let cfgPath = this.titledMap.getPropertiesForGID(gidPath)
// cc.log(cfgPath)
if (cfgPath) {
this.ku[i][j].path = cfgPath.touchable//0红 1 绿2黄
}
// cc.log(this.object)
let gidObject = this.object.getTileGIDAt(i, j);//道具处理
if (gidObject) {
let tileObject = this.object.getTiledTileAt(i, j, true);
let cfgObject = this.titledMap.getPropertiesForGID(gidObject)
if (cfgObject) {
this.ku[i][j].tileObject = tileObject
this.ku[i][j].tileObject.node.tipsPos = cc.v2()
this.ku[i][j].tileObject.object = cfgObject
this.ku[i][j].tileObject.node.row = i
this.ku[i][j].tileObject.node.col = j
this.ku[i][j].tileObject.addComponent("Hinder")
}
}
// cc.log(this.tower)
if (this.tower == null) {
continue
}
let gidTower = this.tower.getTileGIDAt(i, j);//炮台处理
if (gidTower) {
let tileTower = this.tower.getTiledTileAt(i, j, true);
let cfgTower = this.titledMap.getPropertiesForGID(gidTower)
// cc.log("log:", cfgTower)
if (cfgTower) {
let it = cc.instantiate(this.towerPrefab)
it.x = tileTower.node.x + this.tileSize.width / 2
it.y = tileTower.node.y + this.tileSize.height / 2
it.parent = this.towerParent
it.cfg = cfgTower
// cc.log("cfgTower", cfgTower)
it.addComponent("TowerSet").init()
this.ku[i][j].tileTower = it
if (this.ku[i][j] == 1) {
this.ku[i][j].path = 5//是炮台 和障碍物的重合
}
else {
this.ku[i][j].path = 3//是炮台
}
}
}
}
}
if (this.tower == null) {
return
}
this.tower.node.destroy()
},

炮台。 根据具体id生成指定类型炮台


// Learn cc.Class:
// - [Chinese] https://docs.cocos.com/creator/manual/zh/scripting/class.html
// - [English] http://docs.cocos2d-x.org/creator/manual/en/scripting/class.html
// Learn Attribute:
// - [Chinese] https://docs.cocos.com/creator/manual/zh/scripting/reference/attributes.html
// - [English] http://docs.cocos2d-x.org/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
// - [Chinese] https://docs.cocos.com/creator/manual/zh/scripting/life-cycle-callbacks.html
// - [English] https://www.cocos2d-x.org/docs/creator/manual/en/scripting/life-cycle-callbacks.html
cc.Class({
extends: cc.Component,
properties: {
},
start() {
// this.myTower = null//炮台节点
// this.towerMold = 1//炮台模型
// this.loadTower() //加载炮台
// this.towerCreste()//生成炮台
// cc.log()
},
init(buildType) {//有参数的指定炮台
if (buildType) {
this.buildType = window.towerBuildTypeJson[buildType]
for (let i = 0; i < window.towerJson.length; i++) {
if (window.towerJson[i].Index == this.buildType.TowerBaseIndex) {
// this.towerData = window.towerJson[i]
this.towerIndex = i
this.Level = 1
cc.log(11)
}
}
this.towerCreste()//生成炮台
}
else {
cc.log("我没有")
this.loadTower() //加载炮台
// this.towerCreste()//生成炮台
}
},
loadTower() {//加载炮台数据
this.json = window.towerJson
// cc.log(this.json)
for (let i = 0; i < this.json.length; i++) {
let cfg = this.json[i]
if (cfg.Type == this.node.cfg.towertype && cfg.Level == this.node.cfg.towerlevel) {
// this.towerData = cfg//炮台数据
this.towerIndex = i
this.Level = cfg.Level
this.mapTowerCreate()//地图固定炮台生成
return
}
}
},
mapTowerCreate() {//地图固定炮台生成
let index = window.towerJson[this.towerIndex].Index - this.Level + 1
cc.log("inde:", index)
let buildTypeCfg = window.towerBuildTypeJson
for (let i = 0; i < buildTypeCfg.length; i++) {
this.buildType = buildTypeCfg[i]
if (this.buildType.TowerBaseIndex == index) {
let node = new cc.Node("myTower")
node.parent = this.node
node.group = "tower"//炮台
let it
if (this.buildType.ScriptName == "") {
it = node.addComponent("BottleTower")
} else {
it = node.addComponent(this.buildType.ScriptName)
}
it.towerData = window.towerJson[this.towerIndex]
it.init()
this.myTower = node
cc.log(it)
cc.log("我over")
return
}
}
},
towerCreste() {//更据图标生成炮台
let node = new cc.Node("myTower")
node.parent = this.node
node.group = "tower"//炮台
let it
if (this.buildType.ScriptName == "") {
it = node.addComponent("BottleTower")
} else {
it = node.addComponent(this.buildType.ScriptName)
}
it.towerData = window.towerJson[this.towerIndex]
it.init()
this.myTower = node
},
upGradeTower() {//升级炮台
this.towerIndex = this.towerIndex + 1
this.Level = this.Level + 1
// for (let i = 0; i < this.json.length; i++) {
// let cfg = this.json[i]
// if (cfg.Index == this.towerMold) {
// this.towerData = cfg
// // cc.log("hah")
// // cc.log(this.towerData)
// break
// }
// }
this.myTower.destroy()
this.myTower = null
this.towerCreste()//生成炮台
}
});

炮台的攻击列表

  • 进入可攻击列表
onCollisionEnter: function (other, self) {
if (other.node.group == "ai") { //可攻击列表
this.attList[this.attList.length] = other.node
// cc.log(this.attList)
}
},
  • 退出可攻击列表
onCollisionExit: function (other, self) {
for (let i = 0; i < this.attList.length; i++) {
if (this.attList[i] == other.node) {
this.attList.splice(i, 1)
// cc.log(this.attList)
return
}
}
},
  • 攻击逻辑
lateUpdate() {
if (this.isInit) {
this.haveTarget() //查询是否有攻击物
}
this.waitTime = this.waitTime - 1 / 60
if (this.myTarget) {//有攻击目标
this.attackDeal() //攻击处理
// cc.log("旋转")
}
},

AI

  • AI逻辑

update() {
if (this.isInit == true) {
if (this.isWait == false) {
this.moveAi() //ai移动
}
this.barLength.progress = this.node.hp / this.hpMax
if (this.node.hp < this.hpMax) {
this.hpBar.active = true
}
}
if (this.node.hp <= 0) {
this.scheduleOnce(() => {
cc.director.emit("aiOver")
cc.director.emit("coinDeal", 1)
cc.director.emit("TheExplode", this.node, "monsterexplode-", 4)
this.node.destroy()
}, 0)
}
},
  • 加载AI信息

loadAni() {//加载ai信息
for (let i = 0; i < window.monsterJson.length; i++) {
// cc.log(i)
if (window.monsterJson[i].Index == this.index) {
this.aiData = window.monsterJson[i]
// cc.log(this.aiData)
this.addAni()
// this.moveAi() //ai移动
return
}
}
},
  • AI移动

moveAi() {//ai移动
// cc.log(this.node.position, this.pointArr[this.moveIndex])
if (this.moveIndex == this.pointArr.length) {
// cc.log(this.life)
if (this.life == null) {
this.moveIndex = 0
}
else {
cc.director.emit("catHp")
this.node.destroy()
}
return
}
let pointB = this.pointArr[this.moveIndex]
// cc.log(pointB)
let fixedX = pointB.x - this.pointA.x
let fixedY = pointB.y - this.pointA.y
let fixedDis = cc.v2(fixedX, fixedY).mag()
let isx = this.pointA.x - this.node.x
let isy = this.pointA.y - this.node.y
let dis = cc.v2(isx, isy).mag()
// cc.log(this)
// cc.log("fixedDis", fixedDis)
if (dis < fixedDis) {
// cc.log(this.node.x, this.node.y)
let unit = cc.v2(fixedX, fixedY).normalizeSelf()
// cc.log("unit", unit)
this.node.x = this.node.x + unit.x * this.speed
this.node.y = this.node.y + unit.y * this.speed
// cc.log("==",this.x, this.y)
}
else {
this.moveIndex++
this.pointA = JSON.parse(JSON.stringify(this.node.position))
// this.pointA.x = this.x
// this.pointA.y = this.y
}
},
  • 加载AI血条

loadHpBar() {//加载血条
this.hpBar = cc.instantiate(window.hpPrefab)
this.barLength = this.hpBar.getComponent(cc.ProgressBar)
// cc.log(this.barLength)
this.hpBar.parent = this.node
this.hpBar.active = true
this.hpBar.width = this.node.width
this.hpBar.x = 0
this.hpBar.y = -this.node.height / 2
this.hpBar.getComponent(cc.ProgressBar).totalLength = this.node.width
this.hpBar.getChildByName("bar").x = -this.node.width / 2
// cc.log(this)
},
  • 加载AI动画。碰撞体等信息

addAni() {
let sp = this.node.addComponent(cc.Sprite);
let animation = this.node.addComponent(cc.Animation);
let collider = this.node.addComponent(cc.BoxCollider)
this.node.group = "ai"
let frames = [];
let name = this.aiData.Name
for (let i = 1; i < this.aiData.Frames + 1; i++) {
let itname = name + "-" + i
// cc.log(itname)
frames[i - 1] = sp.spriteFrame = window.monsterPic.getSpriteFrame(itname)
collider.size.width = this.node.width
collider.size.height = this.node.height
}
this.loadHpBar()//加载血条
let clip = cc.AnimationClip.createWithSpriteFrames(frames, 5);
clip.name = this.aiData.Name;
clip.wrapMode = cc.WrapMode.Loop;
// cc.log(clip)
animation.addClip(clip);
animation.play(clip.name)
},

源码

码云源码

基于Cocos的猫狗大战相关推荐

  1. cocos creator 方法数组_基于 Cocos 游戏引擎的音视频研发探索

    本文转载自公众号:流利说技术团队(lls_tech) 版权归原作者所有 本文主要介绍了流利说团队基于 Cocos 游戏引擎进行音视频相关需求开发过程中所遇到的问题和解决方案.文章中将依次阐述 Coco ...

  2. 基于Cocos Creator的水果忍者游戏

    基于cocos creater的水果忍者游戏 项目介绍 主界面 游戏界面 游戏详情界面 水果运动界面 刀片切割界面 游戏结束界面 下载方式 项目介绍 互联网技术不断革新,用户对于应用的要求在不断提高, ...

  3. 一款非常好玩的小程序游戏推荐给大家,基于cocos creator引擎开发的

    一款非常好玩的小程序游戏推荐给大家,基于cocos creator引擎开发的,排名包含微信好友排行榜,全球榜,快邀请好友,一起来玩吧.

  4. 基于Cocos Studio和BMfont制作艺术字体

    通常在游戏开发制作的过程中,我们常常要用到各式各样的艺术字体,适合游戏风格的.独特的艺术字体能让游戏看起来更加美观.更加生动活泼.但问题是很多新手并不知道这些字体是怎么来的,这篇文章主要讲一下如何基于 ...

  5. 基于Keras实现猫狗大战,25000张猫狗图像的精准分类

    文章目录 1. 建立简单版CNN网络模型 1.1 将下载好的文件分为训练集.测试集.验证集. 1.2 构建神经网络 1.3 数据预处理 1.4 绘制训练过程中的损失曲线和精度曲线 2. 使用数据增强 ...

  6. Cocos 篇:基于 Cocos Creator v1.9,开始 Hello World 。。。

    前言 身体好,才是真的好~ 从此之后,要会生活,努力活出自己想要的样子~!!! Enmmm,LZ 也是小白一枚,初入贵行,还望手下留情~ 本篇主要作用,或者说定位在于和 LZ 一样得小白,希望多多交流 ...

  7. 基于Cocos creator 实现坦克大战小游戏【100010131】

    疯狂坦克 引言 坦克大战是一款曾经风靡一时的小游戏,本次的实训,就是要力图让经典历久弥新.因此在老师的帮助下,我们将尽力开发一款在原有基础上有突破的"疯狂坦克2",加入新的元素,融 ...

  8. 深度学习之基于AlexNet实现猫狗大战

    这次实验的主角并不是猫狗大战,而是AlexNet网络,只不过数据集为猫狗大战数据集.本次实验利用自己搭建的AlexNet网络实现猫狗大战,测试一下AlexNet网络的性能. AlexNet网络作为Le ...

  9. 03_基于CNN的猫狗大战实现

    文章目录 猫狗大战背景介绍 代码示例 step1 对模型的修改 step2 数据的输入 step3 模型的重新训练与存储 step4 模型的复用 猫狗大战背景介绍 猫狗大战数据集来源于Kaggle上的 ...

最新文章

  1. DNS 到底怎么工作的? (How does dns work?)
  2. VBA学习笔记(一):自动添加代码VBA修改注册表
  3. 【C语言简单说】十二:逻辑运算符
  4. Java并发编程实战~Copy-on-Write模式
  5. 字节数组和字符串的相互转化……
  6. 云栖独栋别墅_云栖没有玫瑰
  7. 剑指offer(C++)-JZ52:两个链表的第一个公共结点(数据结构-链表)
  8. 正确理解TensorFlow中的logits
  9. 客户答谢晚宴策划案例合集(共20份)
  10. Photon与Unity核心技术之角色更换武器
  11. android简单视频播放器,推荐用于Android超简单视频播放器的ArtPlayer
  12. iOS苹方字体使用说明
  13. python调用小票打印机_PyQt5中使用Qprinter打印热敏小票
  14. 税务总局:今年预计减税1.8万亿元!个体户能享受哪些税收优惠?
  15. 老卫带你学---使用cv2.imwrite保存的图像是全黑的
  16. Dart —— 函数 函数参数 匿名函数
  17. 鸿蒙系统暗黑2,《暗黑破坏神-不朽》究竟有那些改变?手游堪比3A大作
  18. 设置MySQL复制时,replicate-ignore-db模式下如何正常工作
  19. 数据库:简述对关系型数据库(RDBMS)的认识
  20. __attribute__的使用

热门文章

  1. 练习八:利用有限状态机进行时序逻辑的设计
  2. 每日一题之Vue数据劫持原理是什么?
  3. 通过BACnet物联网关实现楼宇自动化的物联网解决方案
  4. 深度剖析互联网金融的系统逻辑
  5. 充电池中热敏电阻作用
  6. 多媒体计算机室管理制度,教室多媒体使用管理制度
  7. 集合竞价如何买入_如何在集合竞价买卖股票
  8. 对某班学生成绩排序。从键盘依次输入某班学生的姓名和成绩(一个班级人数最多不超过50人)并保存,然后分别按学生成绩由高到低顺序输出学生姓名和成绩,成绩相同时,则按输入次序排序。
  9. html 源码_HTML实例之搜索栏(附源码)
  10. 2022-2028年中国循环经济产业深度调研及投资前景预测报告