返回顶部
首页 > 资讯 > 前端开发 > JavaScript >详解CocosCreator制作射击游戏
  • 555
分享到

详解CocosCreator制作射击游戏

2024-04-02 19:04:59 555人浏览 泡泡鱼
摘要

目录场景布置游戏资源炮塔旋转动态生成子弹碰撞计算增加效果靶子移动增加弹药库的显示Common公共类ResultDialog脚本(控制分数提示框)Common脚本游戏重开更改Commo

场景布置

游戏资源

炮塔旋转

机制与之前手柄实例的小车相同,使用touchmove监听触摸事件,

  1. 获取触摸位置
  2. 通过位置用signAngle方法将该位置与cc.v2(1,0)位置的角度差求出(记得要加负号,比较所得逆时针为负,赋值angle逆指针为正)。
  3. 所求的的角度即为最终角度。


 onLoad(){
        //初始化为90度
        this.node.angle=90;
        this.node.on('touchstart',this.onTouchStart,this);
        this.node.on('touchmove',this.onTouchMove,this);
        this.node.on('touchend',this.onTouchEnd,this);
        this.node.on('touchconcel',this.onTouchConcel,this);
    }
   
    onTouchStart(e:cc.Event.EventTouch){
        //获取开始的位置
        this.starPos=this.node.parent.convertToNodeSpace(e.getLocation());
        //获取炮口的初始角度
        this.starAngle=this.node.angle;

    }
    onTouchEnd(e:cc.Event.EventTouch){

    }
    onTouchMove(e:cc.Event.EventTouch){
        //获取触点当前的位置
        let pos:cc.Vec2=this.node.parent.convertToNodeSpace(e.getLocation());

        //获取角度
        //angle顺时针为负逆时针为正
        let sweep_radian=pos.signAngle(this.starPos);//pos相对于starPose的角度p相对s顺时针为正
        let sweep_angle=sweep_radian*180/Math.PI;//弧度制换算角度
        
        //让炮塔的角度指向最终的角度
        let angle=this.starAngle-sweep_angle;
      
        //将角度限制在45~135之间
        if(angle<45)angle=45;
        if(angle>135)angle=135;

        cc.log("炮口摆动:"+sweep_angle+"最终角度位置:"+angle);
        this.node.angle=angle;
    }

动态生成子弹

  1. 生成节点cc.Node,并增加组件addComponent(cc.Sprite)
  2. 为组件的属性赋值,将图片的spriteFrame赋值
  3. 将组件挂载在一个父节点下
  4. 设置位置、角度等
  5. 控制其运动可以导入新建的脚本,并将该脚本增加到动态生成节点的组件中

 onTouchEnd(e:cc.Event.EventTouch){
        this.fire();
    }
    onTouchConcel(e:cc.Event.EventTouch){

    }

    fire(){

        if(this.bulleteicon==null)return;
        let bullet:cc.Node=new cc.Node();
        let sprite:cc.Sprite=bullet.addComponent(cc.Sprite);
        sprite.spriteFrame=this.bulleteicon;
        

        //挂载到射击系统节点下
        bullet.parent=this.node.parent;

        //设置相对父节点位置
        let ration=this.node.angle*Math.PI/180;
        let direction=cc.v2(Math.cos(ration),Math.sin(ration));
        bullet.angle=this.node.angle;
        let r=100;
        bullet.setPosition(cc.v3(r*direction.x,r*direction.y,0));
       
        //附加脚本组件
         let script=bullet.addComponent(Buletet);
         script.explodeImg=this.explodeImg;
         script.direction=direction;

    }

 start () {
         this.schedule(this.onTimer,0.01);
    }

    onTimer(){
        if(this.node.y>300){
            this.unschedule(this.onTimer);
            this.explode();
           
            return;
        }
        let dx=this.direction.x*5;
        let dy=this.direction.y*5;
        this.node.y+=dy;
        this.node.x+=dx;
    }

    explode(){

        let sp:cc.Sprite=this.getComponent(cc.Sprite);
        sp.spriteFrame=this.explodeImg;
      
        //将子弹缩小
        this.node.scale=0.1;
        //爆炸动画效果缓动系统
        let self=this;
        cc.tween(this.node)
            .to(0.5,{scale:1,opacity:0})
            .call(function(){
                self.afterExplode();
            })
            .start();

            
    }

    afterExplode(){
        this.node.destroy();
    }

本次bug:

  1. 导入的类名与文件名不同, 注意重命名文件不会自动修改代码中的类名,需要修改两次
  2. setposition()方法使用时参数写在了cc.v3的构造函数内,一定注意参数的位置

碰撞计算

计算子弹和靶标的相对位置,若小于范围,则判断为命中靶,执行命中的操作,否则判断为没有命中,执行没有命中的操作。

脚本需传入靶子节点,增加target属性


   @property(cc.SpriteFrame)
    explodeImg: cc.SpriteFrame = null;
    
    direction: cc.Vec2 = null;

    target: cc.Node = null;
    onLoad() {

    }

    start() {
        this.schedule(this.onTimer, 0.01);
    }

    onTimer() {
        if (this.node.y > 350) {
            if (this.isHit()) {
                //播放爆炸效果
                this.explode();
                console.log("命中靶");
            }
            else {
                console.log("脱靶");
                this.disMiss();
            }
            this.unschedule(this.onTimer);
            return;
        }
        let dx = this.direction.x * 5;
        let dy = this.direction.y * 5;
        this.node.y += dy;
        this.node.x += dx;
    }

    //判断是否命中
    isHit(): boolean {
        let targetPos: cc.Vec2 = this.geWorldLocation(this.target);
        let selfPos: cc.Vec2 = this.geWorldLocation(this.node);
        let distance = Math.abs(targetPos.x - selfPos.x);
        console.log("靶标x=" + targetPos.x + " , 子弹x=" + selfPos.x);

        if (distance < 50) {
            return true;

        }
        else {
            return false;
        }

    }
    explode() {

        let sp: cc.Sprite = this.getComponent(cc.Sprite);
        sp.spriteFrame = this.explodeImg;

        //将子弹缩小
        this.node.scale = 0.1;
        //爆炸动画效果缓动系统
        let self = this;
        cc.tween(this.node)
            .to(0.5, { scale: 1, opacity: 0 })
            .call(function () {
                self.disMiss();
            })
            .start();


    }

    geWorldLocation(node: cc.Node): cc.Vec2 {
        let pos = node.getPosition();
        //注意这里是node.parent。方法的调用者要是当前节点的坐标系
        return node.parent.convertToWorldSpaceAR(pos);

    }

    disMiss() {
        this.node.destroy();
    }

本次bug:

获取世界坐标时,没有调用其父节点的坐标系,用了当前节点的坐标系,所以返回的依然是自身当前坐标系的值。记得转换世界坐标的方法调用者是当前节点的坐标系,一般为其父节点 return node.parent.convertToWorldSpaceAR(pos);(以锚点为原点)

增加效果

在靶子的节点下增加脚本,控制移动,左右来回移动
同时,当子弹命中后增加文字提示效果。

文字提示:


 cheer() {
        //创建节点并挂载
        let node: cc.Node = new cc.Node();
        node.parent = this.node.parent;//两者同一级,同一个父对象
        let label: cc.Label = node.addComponent(cc.Label);
        label.string = "+10分";

        //设置位置、透明度等
        node.setPosition(cc.v3(0, 250, 0));
        node.opacity = 200;
        node.color = new cc.Color(255, 0, 0);

        //动效
        cc.tween(node)
            .to(0.5, { scale: 1.5 })
            .to(0.2, { opacity: 0 })
            .call(function () {
                node.destroy();
            })
            .start();

    }

靶子移动


 update (dt) {
         let speed=3;
         if(this.isLeft){
             speed=-speed;
         }
         this.node.x+=speed;
         if(this.isLeft&&this.node.x<-350){
             this.isLeft=false;
         }
         if(!this.isLeft&&this.node.x>350){
            this.isLeft=true;
        }
    }

增加弹药库的显示

  1. 增加弹药库节点,批量生成子弹图片(可用widget组件设置位置)
  2. 增加减少子弹方法,并通过设置子弹图片的active属性来减少子弹。
  3. 在炮塔的fire方法中调用减少子弹的方法

调用方法有两种,一种为在炮塔脚本中获取弹药库节点在调用,另一种为设置公共类,(静态变量),在onLoad()方法中就初始化该节点,然后直接调用。用后者。


 @property(cc.SpriteFrame)
    bulleteIcon: cc.SpriteFrame = null;
    capacity: number = 10;
    stockNumber: number = 10;


    onLoad() {

        let space: number = this.node.width / this.capacity;
        for (let i = 0; i < this.capacity; i++) {
            //生成图片
            let bulleteNode: cc.Node = new cc.Node();
            let bulleteSprite: cc.Sprite = bulleteNode.addComponent(cc.Sprite);
            bulleteSprite.spriteFrame = this.bulleteIcon;
            this.node.addChild(bulleteNode);

            //设置位置
            bulleteNode.x += space * i + 10;
            bulleteNode.y = 0;

        }

    }

    start() {

    }

    consum(num: number) {
        this.stockNumber -= num;
        if (this.stockNumber < 0) {
            this.stockNumber = 0;
        }
        this.display();
    }

    display() {
        let nodes: cc.Node[] = this.node.children;
        console.log(nodes.length);
        for(let i=0;i<nodes.length;i++){
            if(i>=this.stockNumber){
                nodes[i].active=false;
            }
           
        }
    }

Common公共类


  //静态类,全局变量,将所有会公用的变量、类定义在Common类中
    static ammo:Ammo=null;

    onLoad() {
        Common.ammo=cc.find('canvas/弹药').getComponent('Ammo');
        console.log(Common.ammo);
    }

此处bug:

cc.find()方法中记得用除法的斜杠。

子弹耗尽提示分数

  1. 创建遮罩层,将脚本类导入到Common类中,设置active属性为false
  2. 在ResultDialog脚本 增加show方法,让其active属性变为true同时将分数显示在屏幕上。
  3. 在Bullete(控制子弹运动脚本)中判断子弹数量是否<=0,并调用Common中show方法显示分数提示框。

ResultDialog脚本(控制分数提示框)


 onLoad () {
         let replay:cc.Node=cc.find('Canvas/结束提示框/再玩一局');
         console.log(replay);
         replay.on('touchstart',this.dismiss,this);

         this.node.on('touchstart',this.onTouchdisable,this);
         this.node.on('touchmove',this.onTouchdisable,this);
         this.node.on('touchend',this.onTouchdisable,this);
   
     }

     //显示提示框
     show(){
        this.node.active=true;  
        let scoreNode : cc.Node = cc.find('分数框/分数', this.node);
        let scoreLabel : cc.Label = scoreNode.getComponent(cc.Label);   
        scoreLabel.string = Common.score + '分';   
       
        
     }

     //隐藏提示框
     dismiss(){
         this.node.active=false;
     }

     //遮罩显示时屏蔽
     onTouchdisable(e:cc.Event.EventTouch){
         e.stopPropagation();
     }
    start () {

    }

Common脚本


 //静态类,全局变量,将所有会公用的变量、类定义在Common类中
    static ammo:Ammo=null;
    static score : number = 0;
    static resultdialog : ResultDialog = null;
  

    onLoad() {
        Common.resultdialog=cc.find('Canvas/结束提示框').getComponent('ResultDialog');
        Common.ammo=cc.find('Canvas/弹药').getComponent('Ammo');
    }

在Bullete方法中增加分数增加


  if (this.isHit()) {
                //播放爆炸效果
                this.explode();
                //显示+10分
                this.cheer();
                //总分数+10
                Common.score += 10;
                console.log("命中靶");
            }

游戏重开

该小游戏比较简单,重开只需要重置弹药库节点即可,因此reset方法放在Ammo脚本中
在公共类中创建Ammo对象,设置静态方法,重置得分、以及调用Ammo的reset方法。

Ammo(弹药库类)脚本添加


 reset(){
        this.stockNumber=this.capacity;
        this.display();
    }

更改Common脚本


 //静态类,全局变量,将所有会公用的变量、类定义在Common类中
    static ammo:Ammo=null;
    static score : number = 0;
    static resultdialog : ResultDialog = null;
  

    onLoad() {
        Common.resultdialog=cc.find('Canvas/结束提示框').getComponent('ResultDialog');
        Common.ammo=cc.find('Canvas/弹药').getComponent('Ammo');
        console.log(Common.ammo);
    }
    static resetGame() {
        Common.score=0;
        Common.ammo.reset();
    }

增加一些细节

增加游戏声音以及炮塔激活的变化

1.炮塔脚本增加属性


 //音效
    @property(cc.Audioclip)
    audioFire: cc.AudioClip = null;
    @property(cc.AudioClip)
    audioExplode: cc.AudioClip = null;

    //炮塔图片
    @property(cc.SpriteFrame)
    iconNORMal: cc.SpriteFrame = null;
    @property(cc.SpriteFrame)
    iconActive: cc.SpriteFrame = null;

图片切换


 onTouchStart(e: cc.Event.EventTouch) {方法最后添加
	   //炮塔图片切换至激活
        this.node.getComponent(cc.Sprite).spriteFrame = this.iconActive;	

 onTouchEnd(e: cc.Event.EventTouch) {方法最后添加
          //图片恢复
        this.node.getComponent(cc.Sprite).spriteFrame = this.iconNormal;
      }

音效播放


fire(){   方法后添加

       //将子弹爆炸音频传送至子弹脚本
        script.audioExplode = this.audioExplode;
 if (this.audioFire != null) {
            cc.audioEngine.play(this.audioFire, false, 1);
        }
    }

播放音频的方法:==cc.audioEngine.play(this.audioFire, false, 1);==第二个参数为是否循环播放,第三个参数为音量大小

子弹脚本


//添加属性
@property(cc.SpriteFrame)
explodeImg: cc.SpriteFrame = null;
在判断子弹命中靶子的操作后添加
if(this.audioExplode!=null){
	cc.audioEngine.play(this.audioExplode,false,1);
}

以上就是详解CocosCreator制作射击游戏的详细内容,更多关于CocosCreator射击游戏的资料请关注编程网其它相关文章!

--结束END--

本文标题: 详解CocosCreator制作射击游戏

本文链接: https://lsjlt.com/news/123713.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 详解CocosCreator制作射击游戏
    目录场景布置游戏资源炮塔旋转动态生成子弹碰撞计算增加效果靶子移动增加弹药库的显示Common公共类ResultDialog脚本(控制分数提示框)Common脚本游戏重开更改Commo...
    99+
    2024-04-02
  • CocosCreator制作射击游戏的方法
    这篇文章给大家分享的是有关CocosCreator制作射击游戏的方法的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。场景布置游戏资源炮塔旋转机制与之前手柄实例的小车相同,使用touchmove监听触摸事件,获取触摸...
    99+
    2023-06-14
  • 如何用CocosCreator实现射击小游戏
    分析下制作步骤: 1. 准备好资源,搭建场景 资源的话可以自己到网上找,也可以直接用我的也行;创建好相应文件夹,把资源放到res文件夹下; 搭建场景: 第一步:创建一个单色精灵(Sc...
    99+
    2024-04-02
  • 怎么使用CocosCreator实现射击小游戏
    这篇文章主要介绍怎么使用CocosCreator实现射击小游戏,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!分析下制作步骤:1. 准备好资源,搭建场景资源的话可以自己到网上找,也可以直接用我的也行;创建好相应文件夹,...
    99+
    2023-06-14
  • 如何用CocosCreator制作微信小游戏
    目录1、在微信公众平台下载微信开发者工具2、cocoscreator设置3、配置构建发布4、打开小程序项目5、进入微信开发工具 6、编译7、预览8、预览成功CocosCre...
    99+
    2024-04-02
  • 基于Python实现射击小游戏的制作
    目录1.游戏画面1.1开始1.2射击怪物2.涉及知识点3.代码3.1发射声3.2背景3.3射击效果4.经验总结1.游戏画面 1.1开始 1.2射击怪物 2.涉及知识点 1.spr...
    99+
    2024-04-02
  • 详解CocosCreator游戏之鱼群算法
    前言 最近想学一下CocosCreator,于是,编辑器下载,启动。 众所周知,边写边学才是最快的学习方法,得写个Demo练练手,那么写什么呢?听说现在《墨虾探蝌》挺火的,那就抄(学...
    99+
    2024-04-02
  • 使用CocosCreator怎么制作一个微信小游戏
    使用CocosCreator怎么制作一个微信小游戏?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。1、在微信公众平台下载微信开发者工具 地址: http...
    99+
    2023-06-14
  • CocosCreator入门教程之用TS制作第一个游戏
    目录前提TypeScript VS JavaScript代码编辑器选择学习 TypeScriptTypeScript 环境配置配置自己的声明文件属性类型声明用 TypeScript ...
    99+
    2024-04-02
  • Unity游戏开发之射击小游戏的实现
    目录前言游戏画面展示游戏代码解析游戏打包总结前言 人们一直都说学习和玩游戏不能兼顾,那我们就来边学习怎样制作游戏,边玩游戏 不就兼得了嘛~ 我可真是一个小天才呢~ 所以本篇文章为大家...
    99+
    2024-04-02
  • python射击游戏代码怎么写
    以下是一个简单的Python射击游戏代码示例:```pythonimport pygameimport random# 初始化pyg...
    99+
    2023-09-27
    python
  • Unity如何实现射击小游戏
    这篇文章主要为大家展示了“Unity如何实现射击小游戏”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Unity如何实现射击小游戏”这篇文章吧。游戏画面展示这款小游戏只用了两个UI界面,一个是菜单...
    99+
    2023-06-29
  • Unity制作游戏自定义按键详解
    目录一、效果图二、布局1.场景布局2.设置面板布局三、脚本思路1.KeyItem脚本2.SetKeyPanle脚本3.player移动脚本一、效果图 二、布局 1.场景布局 创建一...
    99+
    2024-04-02
  • Python如何实现射击闯关游戏
    本文小编为大家详细介绍“Python如何实现射击闯关游戏”,内容详细,步骤清晰,细节处理妥当,希望这篇“Python如何实现射击闯关游戏”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。项目功能地图编辑器:可以实现玩...
    99+
    2023-07-04
  • Python+Pygame实现简单的射击小游戏
    目录前言一、运行环境二、代码展示​三、效果展示1)游戏界面2)击中效果3)+3分前言 哈喽!哈喽。栗子上线啦~ 要说什么游戏能够获得大家的喜爱? 唯射击游戏莫属。此前大火手游的《刺激...
    99+
    2024-04-02
  • Python3+Pygame实现射击游戏完整代码
    目录一、游戏特点二、运行效果展示三、完整代码四、运行方式之前看到过很多人写的飞机大战,当然了之前我也写过多个版本,总体来说功能是实现了,但总感觉不够“炫” 今天浏览Python资料的...
    99+
    2024-04-02
  • 基于Python怎么实现射击小游戏
    本文小编为大家详细介绍“基于Python怎么实现射击小游戏”,内容详细,步骤清晰,细节处理妥当,希望这篇“基于Python怎么实现射击小游戏”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。1.游戏画面1.1开始1....
    99+
    2023-06-29
  • 详解如何利用Python制作24点小游戏
    目录先睹为快游戏规则(改编自维基百科)逐步实现Step1:制作24点生成器Step2:定义游戏精灵类Step3:实现游戏主循环先睹为快 24点 游戏规则(改编自维基百科) 从1~10...
    99+
    2024-04-02
  • 使用Python3怎么实现一个射击游戏
    今天就跟大家聊聊有关使用Python3怎么实现一个射击游戏,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。from __future__ import d...
    99+
    2023-06-14
  • Python开发之射击闯关游戏的实现
    目录项目功能地图编辑器游戏主运行程序部分游戏截图项目功能 地图编辑器:可以实现玩家自己定义每一关卡的样式和难易程度 运行界面:实现了玩家的移动,跳跃,发射子弹,投掷手雷,以及敌人的A...
    99+
    2023-01-14
    Python实现射击闯关游戏 Python射击闯关游戏 Python射击游戏
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作