精华内容
下载资源
问答
  • cocosCreator小游戏

    2017-05-17 15:34:39
    用js写的cocosCreator 小游戏,有完整的游戏开发代码。
  • cocos creator 小游戏

    2018-10-08 16:58:33
    可以直接发布到微信,做成微信小游戏。打开之后完全能用,如果打开有问题,删除local目录即可。
  • cocos creator小游戏合集

    2020-05-29 10:44:18
    2048,小鸟,黄金矿工,开心消消乐,跑酷,扫雷,飞机大战等 cocos creator小游戏合集 cocos2dx
  • 使用CocosCreator,javacripts语言制作的仿小人过桥小游戏源码
  • CocosCreator小游戏框架 此项目是我使用CCC开发小游戏的一些总结,主要是一些可以复用的模块,特别是处理一些跨平台的问题,让开发者尽量少关心游戏业务逻辑以外的事。脚本使用Typescript,欢迎各路大侠补充pr。 CCC...
  • cocos creator 1.9.1版本下的小游戏排行榜,竖屏小游戏,完整工程代码。横屏游戏的可以下载另一个资源
  • 是一款益智类射击游戏
  • 这个项目文件适合初学者,如果你已经对CocosCreator很熟悉了,做过相应的游戏开发的朋友可以忽略,这个游戏内容比较简单,一个小时就可以搞定!
  • cocos creator小游戏加载跨域头像 // 玩家头像 和 名字 (防止跨域问题) cc.assetManager.downloader.downloadDomImage(avatarUrl ,null, (err, img) => { if(err){ cc.error('玩家头像错误='+err) return }...

    cocos creator小游戏加载跨域头像

    // 玩家头像 和 名字 (防止跨域问题)
    cc.assetManager.downloader.downloadDomImage(avatarUrl ,null, (err, img) => {
        if(err){
            cc.error('玩家头像错误='+err)
            return
        }
        let texture = new cc.Texture2D();
        texture.initWithElement(img);
        texture.handleLoadedTexture();
    
        this.headNodeArr[0].getComponent(Sprite).spriteFrame = new cc.SpriteFrame(texture);
    })
    
    展开全文
  • 可以直接发布到微信,做成微信小游戏。是跟着教程做的小游戏,需要来
  • cocoscreator小游戏吃鸡

    2018-08-10 11:04:19
    资源集成自带框架,项目比较完整,游戏内容是两人对战模式,一人控制一只鸡,发射火焰,看谁先被击倒,用到物理引擎,欢迎新手玩家,来下载。
  • 多个小游戏合集,内含五子棋,黑白棋,2048,跳一跳,拼图,俄罗斯,扫雷,连连看,贪吃蛇,打砖块,一个场景一个游戏,适合新手!
  • CocosCreator小游戏分包

    千次阅读 2019-07-08 16:18:30
  • 现在微信小游戏的项目资源包...所以对于CocosCreator要打包成小游戏的项目,我们都会统一把资源放在资源服务器上面。   这样,我们可以在小游戏开始运行的时候,只加载游戏的代码文件,而对于资源文件,就可以...

    现在微信小游戏的项目资源包大小已经由4M改成了8M,为的就是适应小游戏越来越丰富的玩法。

    但是,就算有8M也是不足以做大部分游戏的,因为项目中的图片资源就有很多了,绝大部分游戏的资源(除了代码)都在10M以上。

    所以对于CocosCreator要打包成小游戏的项目,我们都会统一把资源放在资源服务器上面。

     

    这样,我们可以在小游戏开始运行的时候,只加载游戏的代码文件,而对于资源文件,就可以在加载完代码文件后,慢慢来加载。

    这样做有三个好处:

    1. 避开小游戏项目资源大小不能超过8M的限制
    2. 避开不可以从远程服务器下载脚本文件的限制
    3. 可以进行动态加载,避免游戏初次运行时需要加载过多的文件而导致的卡顿

    对于以上的第3点,就算不是因为小游戏资源包大小的限制,绝大多数游戏也是需要采取这样的游戏优化策略,所以我们应当把资源放到服务器上。

     

    对于上面的总结,我之前想到一个问题:

    就是CocosCreator中对于Prefab的引用有动态加载的和静态加载(编辑界面拖拽)的这两种。

    而对于静态加载的已经在脚本中绑定,这样预制体加载(意味着脚本也加载了)的时候可能资源还没有加载,这样脚本会不会不能成功绑定资源?

     

    对于这个问题,我后来发现了Creator官网上说的一句:

    对于小游戏包内资源,小游戏环境并不是按需加载的,而是一次性加载所有包内资源,然后再启动页面。

    这样,就意味着,脚本加载了的同时,资源肯定也是加载了的,所以问题就可以解决。

     

    下面,引用官网上的一段文字,对远程资源的管理讲解得比较简洁明了:

    在小游戏环境中,我们提供了一个 wxDownloader 对象,给它设置了 REMOTE_SERVER_ROOT 属性后,引擎下载资源的逻辑就变成:

    1. 检查资源是否在小游戏包内
    2. 不存在则查询本地缓存资源
    3. 如果没有缓存就从远程服务器下载
    4. 下载后保存到小游戏应用缓存内供再次访问时使用

    同时,当开启引擎的 md5Cache 功能后,文件的 url 会随着文件内容的改变而改变,这样当游戏发布新版本后,旧版本的资源在缓存中就自然失效了,只能从服务器请求新的资源,也就达到了版本控制的效果。

    具体来说,开发者需要做的是:

    1. 构建时,勾选 md5Cache 功能。
    2. 将小游戏发布包中的 res 文件夹完整的上传到服务器。
    3. 删除发布包内的 res 文件夹。
    4. 在构建发布面板中设置 远程服务地址
    5. 对于测试阶段来说,可能你无法部署到正式服务器上,需要用本地服务器来测试,那么请在微信开发者工具中打开详情页面,勾选项目设置中的 不检验安全域名、TLS 版本以及 HTTPS 证书 选项。

    展开全文
  • )写一个类似的小游戏吧! (在《墨虾探蝌》中,鱼的位置固定,到达一定数量后玩家会升级,不会出现一大群鱼的情况,本项目其实和它不同,没有升级进化,是会有一大群鱼的,每条鱼也不是固定位置,而是有自己的运动...

    最近想学一下CocosCreator,于是,编辑器下载,启动。

    众所周知,边写边学才是最快的学习方法,得写个Demo练练手,那么写什么呢?听说现在《墨虾探蝌》挺火的,那就抄(学习的事怎么能叫抄呢?)写一个类似的小游戏吧!

    (在《墨虾探蝌》中,鱼的位置固定,到达一定数量后玩家会升级,不会出现一大群鱼的情况,本项目其实和它不同,没有升级进化,是会有一大群鱼的,每条鱼也不是固定位置,而是有自己的运动逻辑,其实和另一个游戏更像,不过我不知道叫什么。。。)

    (初学CocosCreator和TypeScript,有写的不好的地方你TM来打我啊还请大家多多包涵。)

    本文算法参考了大佬的文章:http://blog.sina.com.cn/s/blog_4a2183a60101avwt.html

    效果展示:

     

    正文开始

    首先整一个玩家player:

    图片资源用的是CocosCreator官方Demo的图片,照着官方Demo学习了一下,懒得找鱼的图片就直接把图片拿来用了,这个项目目前只用了两张图片

    有了player就得写个player控制脚本,点击一个方向,player就会一直向这个方向移动。那么我们首先需要获取玩家点击的位置,然后计算出player移动的方向,我们把这个写在GameManager里面,所以新建一个脚本GameManager,这个脚本挂在Canvas上。

    先定义两个变量,玩家节点和方向向量:

        @property(cc.Node)
    
        player: cc.Node = null;
    
        dir: cc.Vec2 = cc.Vec2.ZERO;

    获取方向的方法:

        getClickDir(event) {
            let pos: cc.Vec2 = event.getLocation();
            //转本地坐标
            let localPos = this.node.convertToNodeSpaceAR(pos);
            let playerPos: cc.Vec2 = new cc.Vec2(
                this.player.position.x,
                this.player.position.y
            );
    
            let len = localPos.sub(playerPos).mag();
    
            this.dir.x = localPos.sub(playerPos).x / len;
            this.dir.y = localPos.sub(playerPos).y / len;
        }

    这方法在onMouseDown和onMouseMove时调用:

        onMouseDown(event) {
            if (event.getButton() == cc.Event.EventMouse.BUTTON_LEFT) {
                this.getClickDir(event);
            }
        }
    
        onMouseMove(event) {
            if (event.getButton() == cc.Event.EventMouse.BUTTON_LEFT) {
                this.getClickDir(event);
            }
        }
    
        onLoad() {
            cc.director.getCollisionManager().enabled = true;
            cc.director.getPhysicsManager().enabled = true;
    
            this.node.on(cc.Node.EventType.MOUSE_DOWN, this.onMouseDown, this);
            this.node.on(cc.Node.EventType.MOUSE_MOVE, this.onMouseMove, this);
        }
    
        onDestroy() {
            this.node.off(cc.Node.EventType.MOUSE_DOWN, this.onMouseDown, this);
            this.node.off(cc.Node.EventType.MOUSE_MOVE, this.onMouseMove, this);
        }

    有了方向向量,就可以让玩家移动了,新建一个FishPlayer脚本。

    为了不让玩家乱跑,我们先 build the wall:

    墙上加上物理碰撞体:

    然后就可以开始写FishPlayer脚本了,先把要用到的变量都定义一下:

        @property(cc.Node)
        camera: cc.Node = null;
    
        @property(cc.Node)
        gameManager: cc.Node = null;
    
        game: GameManager;
        speed: number = 170;
        velocity: cc.Vec3 = cc.Vec3.ZERO;

    在onLoad()中给game赋值:

        onLoad() {
            this.game = this.gameManager.getComponent("GameManager");
        }

    通过射线来检测边界,判断玩家是否能移动的方法:

        canMove() {
            var flag: boolean = true;
            //前方有障碍物
            var pos = this.node.convertToWorldSpaceAR(cc.Vec3.ZERO);
            var endPos = pos.add(this.node.up.mul(40));
            var hit: cc.PhysicsRayCastResult[] = cc.director
                .getPhysicsManager()
                .rayCast(
                    new cc.Vec2(pos.x, pos.y),
                    new cc.Vec2(endPos.x, endPos.y),
                    cc.RayCastType.All
                );
            if (hit.length > 0) {
                flag = false;
            }
            return flag;
        }

    在update中控制玩家移动:

        update(dt) {
            if (this.game.dir.mag() < 0.5) {
                this.velocity = cc.Vec3.ZERO;
                return;
            }
    
            let vx: number = this.game.dir.x * this.speed;
            let vy: number = this.game.dir.y * this.speed;
    
            this.velocity = new cc.Vec3(vx, vy);
            //移动
            if (this.canMove()) {
                this.node.x += vx * dt;
                this.node.y += vy * dt;
            }
    
            //相机跟随
            this.camera.setPosition(this.node.position);
    
            //向运动方向旋转
            let hudu = Math.atan2(this.game.dir.y, this.game.dir.x);
            let angle = hudu * (180 / Math.PI);
            angle = 360 - angle + 90;
            this.node.angle = -angle;
        }
    

    玩家的移动逻辑写完了,接下来写鱼群。

    新建一个FishGroupManager脚本和一个FishGroup脚本,FishGroupManager挂在Canvas上,FishGroup挂在player上。

    FishGroupManager中定义一个静态fishGroups变量,用来管理所有Group(因为场景中可能有多个玩家,多个鱼群,现在只有一个玩家,这里方便之后扩展):

        static fishGroups: FishGroup[]; //所有组

    来一个把group加入groups的静态方法:

        static AddGroup(group: FishGroup) {
            if (this.fishGroups == null) this.fishGroups = new Array();
    
            if (this.fishGroups.indexOf(group) == -1) this.fishGroups.push(group);
        }

    再来一个获取group的静态方法(根据索引获取):

        static GetFishGroup(index: number) {
            for (var i = 0; i < this.fishGroups.length; i++)
                if (this.fishGroups[i].groupID == index) return this.fishGroups[i];
        }

    FishGroupManager就写完了,接下来再写FishGroup,把上面用到的groupID定义一下,还有鱼群数组:

        groupID: number = 0; //组id    
        fishArr: cc.Component[] = new Array<cc.Component>();

    在onLoad中将自身加到fishGroups里面:

        onLoad() {
            FishGroupManager.AddGroup(this);
        }

    现在鱼群有了,但是里面一条鱼都没有,所以我们还要一个抓鱼的方法:

        catchFish(fish) {
            this.fishArr.push(fish);
        }

    再定义一些要用到的参数,FishGroup就写完了:

        keepMinDistance: number = 80;
        keepMaxDistance: number = 100;
        keepWeight: number = 1; //成员保持距离和保持距离权重
        moveWeight: number = 0.8; //和成员移动权重

    接下来就到了重头戏了——鱼群中其他小鱼的运动逻辑。

    直接将player复制一下,把挂载的FishPlayer和FishGroup脚本去掉,命名为fish,这就是我们的小鱼了,把它做成预制。然后新建一个FishBehaviour脚本,这个脚本挂在player和普通小鱼身上。

    首先实现“抓鱼”功能,当player靠近小鱼后,小鱼就被捕获,成为该player鱼群中的一员。

    定义相关变量:

        @property(cc.Node)
        gameManager: cc.Node = null;
        game: GameManager;
        isPicked: boolean = false;
        pickRadius: number = 50; //抓取距离
    
        groupId: number = -1; //组 id
        myGroup: FishGroup;

    同样,在onLoad()中给game赋值:

        onLoad() {
            this.game = this.gameManager.getComponent(GameManager);
        }

    判断和player距离的方法:

        getPlayerDistance() {
            let dist = this.node.position.sub(this.game.player.position).mag();
            return dist;
        }

    加入鱼群方法:

        onPicked() {
            //设置group
            this.groupId = this.game.player.getComponent(FishGroup).groupID;
            this.myGroup = FishGroupManager.GetFishGroup(this.groupId);
    
            if (this.myGroup != null) {
                this.myGroup.catchFish(this);
                this.isPicked = true;
            }
        }

    在update中调用:

        update(dt) {
            if (this.isPicked) {
                //随着鱼群移动
            }
            else {
                if (this.getPlayerDistance() < this.pickRadius) {
                    this.onPicked();
                }
            }
        }

    OK,现在小鱼到鱼群中了,怎么随着鱼群一起移动呢?

    这里主要有两个点:

    1.小鱼会随着周围“邻居鱼”一起移动

    2.小鱼之间要保持距离,不能太过拥挤

    所以我们需要计算小鱼周围一定范围内鱼群运动向量的平均值,这样还不够,还要判断是否“拥挤”,“拥挤”的话就增加一个远离的趋势,太远的话就增加一个靠近的趋势,再分别乘以权重,加起来,就可以得到我们要的向量了,代码如下:

     

    定义变量:

        moveSpeed: number = 170;
        rotateSpeed: number = 40; //移动旋转速度
        neighborRadius: number = 500; //距离小于500算是邻居
    
        speed: number = 0;
        currentSpeed: number = 0;
        myMovement: cc.Vec3 = cc.Vec3.ZERO;

    求平均向量:

    GetGroupMovement() {
            var v1: cc.Vec3 = cc.Vec3.ZERO;
            var v2: cc.Vec3 = cc.Vec3.ZERO;
    
            for (var i = 0; i < this.myGroup.fishArr.length; i++) {
                var otherFish: FishBehaviour = this.myGroup.fishArr[i].getComponent(
                    FishBehaviour
                );
    
                var dis = this.node.position.sub(otherFish.node.position); //距离
    
                //不是邻居
                if (dis.mag() > this.neighborRadius) {
                    continue;
                }
    
                var v: cc.Vec3 = cc.Vec3.ZERO;
                //大于最大间隔,靠近
                if (dis.mag() > this.myGroup.keepMaxDistance) {
                    v = dis.normalize().mul(1 - dis.mag() / this.myGroup.keepMaxDistance);
                }
                //小于最小间隔,远离
                else if (dis.mag() < this.myGroup.keepMinDistance) {
                    v = dis.normalize().mul(1 - dis.mag() / this.myGroup.keepMinDistance);
                } else {
                    continue;
                }
    
                v1 = v1.add(v); //与周围单位的距离
                v2 = v2.add(otherFish.myMovement); //周围单位移动方向
            }
    
            //添加权重因素
            v1 = v1.normalize().mul(this.myGroup.keepWeight);
            v2 = v2.normalize().mul(this.myGroup.moveWeight);
            var ret = v1.add(v2);
            return ret;
        }
    

    现在,可以把update补全了:

    update(dt) {
            //随着鱼群移动
            if (this.isPicked) {
                var direction = cc.Vec3.ZERO;
                if (this.node.name != "player") {
                    direction = direction.add(this.GetGroupMovement());
                }
    
                this.speed = cc.misc.lerp(this.speed, this.moveSpeed, 2 * dt);
                this.Drive(direction, this.speed, dt); //移动
            }
            //捕获
            else {
                if (this.getPlayerDistance() < this.pickRadius) {
                    this.onPicked();
                }
            }
        }

    Drive()方法:

        Drive(direction: cc.Vec3, spd: number, dt) {
            var finialDirection: cc.Vec3 = direction.normalize();
            var finialSpeed: number = spd;
            var finialRotate: number = 0;
            var rotateDir: number = cc.Vec3.dot(finialDirection, this.node.right);
            var forwardDir: number = cc.Vec3.dot(finialDirection, this.node.up);
    
            if (forwardDir < 0) {
                rotateDir = Math.sign(rotateDir);
            }
    
            //防抖
            if (forwardDir < 0.98) {
                finialRotate = cc.misc.clampf(
                    rotateDir * 180,
                    -this.rotateSpeed,
                    this.rotateSpeed
                );
            }
    
            finialSpeed *= cc.misc.clamp01(direction.mag());
            finialSpeed *= cc.misc.clamp01(1 - Math.abs(rotateDir) * 0.8);
            if (Math.abs(finialSpeed) < 0.01) {
                finialSpeed = 0;
            }
    
            //移动
            if (this.canMove()) {
                this.node.x += this.node.up.x * finialSpeed * dt;
                this.node.y += this.node.up.y * finialSpeed * dt;
            }
    
            //旋转
            var angle1 = finialRotate * 8 * dt;
            var angle2 = this.node.angle - angle1;
            this.node.angle = angle2 % 360;
    
            this.currentSpeed = finialSpeed;
            this.myMovement = direction.mul(finialSpeed);
        }
    
        canMove() {
            var flag: boolean = true;
            //前方有障碍物
            var pos = this.node.convertToWorldSpaceAR(cc.Vec3.ZERO);
            var endPos = pos.add(this.node.up.mul(40));
            var hit: cc.PhysicsRayCastResult[] = cc.director
                .getPhysicsManager()
                .rayCast(
                    new cc.Vec2(pos.x, pos.y),
                    new cc.Vec2(endPos.x, endPos.y),
                    cc.RayCastType.All
                );
            if (hit.length > 0) {
                flag = false;
            }
            return flag;
        }

    最后这个Drive()方法我是拿大佬的原方法改的,里面那个“防抖”我也没弄懂啥意思,大家一起研究研究。

    好了,本篇文章就到这里。

    展开全文
  • CocosCreator小游戏排行榜

    万次阅读 2018-07-18 11:43:44
    先贴上几个链接 : ... https://www.w3cschool.cn/weixinapp/weixinapp-vibrate.html  微信程序的接口 当时查震动就是在这里找...
  • CocosCreator小游戏如何在pc端测试开发

    千次阅读 2018-10-10 16:41:44
    现在我们希望小游戏能在pc端做测试,但是这样会调用不了微信的一些接口。 所以,小游戏在pc端测试明显有两个问题: 1、如果在pc端就调用不到微信小游戏的一些接口; 2、如果每次测试都要打包成微信小游戏,这样又...
  • cocos creator 可以通过新建一个creator项目进行添加子域项目,但是有一个缺点就是占用文件大小是一个问题,所以我这里采用微信的API进行绘制排行榜, 主域就是各种发送给子域的消息,这里不再这里赘述,就是各种...
  • * description:H5小游戏主流渠道聚合SDK(微信,手Q,支付宝,OPPO,VIVO,HUAWEI,BAIDU,XIAOMI等渠道的登录及支付调用接口),持续开发中。。。。。。 * author: 白 * date: 2020.4.18 * version:1.0.0 * compiler...
  • 截图是游戏中非常常见的一个功能,在cocos中可以通过摄像机和 RenderTexture 可以快速实现一个截图功能,具体API可参考:https://docs.cocos.com/creator/manual/zh/render/camera.html?h=%E6%88%AA%E5%9B%BE,其中...
  • 在Main.js的onLoad里边预加载游戏结束场景 cc.director.preloadScene('GameOver') onCollisionStay 回调函数中切换场景: cc.director.loadScene('GameOver') // Dici.js cc . Class ( { extends : cc ....

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,845
精华内容 2,338
关键字:

cocoscreator小游戏