cocos creator实例--3D 足球

体育类游戏,3D 足球射门 ,Cocos Creator 3D 实现,附源码!

效果预览

游戏介绍

点击屏幕,松开手指,足球就会被踢出去,还缺少力度和方向控制,同时也缺少力度和方向的界面展现,后期会继续完善。

工程结构介绍

  • 游戏就 1 个场景 game ,所有游戏的元素都放在这个场景上,场景内 3D 元素主要 3 个,球场(使用 3D 平面实现)、足球(使用 3D 球体实现)、球门(柱子使用 3D 圆柱体实现,网使用 3D 四边形实现)。足球和球场,和之前的篮球类似,就是调整放大倍数,设置图片材质就行,主要的是球门。游戏中球门一个圆柱体都赋予碰撞,网的设置有些特殊,下面介绍。

  • 球门网,由多个 3D 对象构成,球门柱子都是 3D 圆柱体,球网使用了上、后、左、右四个 3D 四边形构成,是通过一点点的网图片平铺设置的。

●  球门网,以 后表面的设置设置为例,除了设置材质,需要注意两点:1. 平铺的设置,如下图的①所示,设置以后会根据比例数量进行缩放,注意原图是个方形,拉伸的时候注意长宽比,设置的时候注意比例,网才不会变形,设置的数值越大,网的空越小,反之类似;2.透明度的设置,如下图②所示,默认的设置,透明的位置会显示黑色,改成透明以后,透明位置显示的就是透明的。

球门网组织结构

组装网的原图

● 游戏核心在足球里,足球内添加了刚体,因为需要模拟重力效果,添加碰撞体,还有主要的游戏逻辑核心 Ball ,游戏里的所有核心功能,都在 Ball 内,场景内所有需要添加弹力和摩擦力的,参考之前的 3D 篮球那篇,具体参数见代码。
 

足球相关组件关联

给3D对象添加材质

足球场的材质就是一张足球图片,网络上可以找一张类似的,根据足球场的长宽比,对 3D 平面进行缩放,然后在资源目录里创建材质,把对应的图片拖拉到材质内即可,注意,材质需要选择图片类型。

足球场材质设置

足球场

● 足球的实现,和球场类似,不过我找的图有些不匹配,所以足球看起来不太和谐。

足球材质设置

  • 球门的网材质设置类似平铺设置和透明设置就行了,主要是注意下球门的柱子和网,摩擦力和阻力设置,区别一下,让球柱子容易碰撞,球网碰撞反应小点。

网的设置

球门柱的设置

● 后期计划,把力度和方向控制加上,同时在球场上以箭头的方式显示出来,力度越大,箭头伸的越长,力度越小,箭头伸的越短,箭头指向的位置就是足球发射发射出的位置

/* Ball.ts
 * @Copyright: Copyright (c) 2019
 * @Author: tony
 * @Version: 1.0
 * @Date: 2019-12-01 23:12:54
 */
import { _decorator, Component, Node, systemEvent, SystemEvent, SphereColliderComponent, RigidBodyComponent, Vec3, math, EventTouch,Touch,Vec2 } from "cc";
import { Direct } from "./Direct";
const { ccclass, property } = _decorator;

@ccclass("Ball")
export class Ball extends Component {
    @property(Direct)
    private diect: Direct = null;

    private ballRigid: RigidBodyComponent = null; // 球刚体
    private force: number = 5;
    private angle: number = Math.PI / 4;

    /* class member could be defined like this */
    // dummy = '';

    /* use `property` decorator if your want the member to be serializable */
    // @property
    // serializableDummy = 0;

    onLoad(): void{
        this.ballRigid = this.node.getComponent(RigidBodyComponent);
        systemEvent.on(SystemEvent.EventType.TOUCH_START, this.onTouchStart, this);
        systemEvent.on(SystemEvent.EventType.TOUCH_MOVE, this.onTouchMove, this);
        systemEvent.on(SystemEvent.EventType.TOUCH_END, this.onTouchEnd, this)
    }

    onTouchStart(touch:Touch, event: EventTouch): void{
        
    }

    onTouchMove(touch:Touch, event: EventTouch): void{
        let start: Vec2 = touch.getStartLocation();
        let move: Vec2 = touch.getLocation();
        let delta = move.subtract(start);
        cc.log(delta);
        let tan: number = delta.y / delta.x;
        let angle: number = Math.atan(-tan);
        cc.log(angle);
        angle = -(180 / Math.PI * angle);
        cc.log(angle);
        angle += 90;
        cc.log('d', angle);
        // this.diect.setDirect(angle);
    }

    onTouchEnd(touch:Touch, event: EventTouch):void{
        cc.log('end');
        let v: Vec3 = cc.v3();
        v.x = 0;
        v.y = this.force * Math.sin(this.angle);
        v.z = -this.force * Math.cos(this.angle);
        this.ballRigid.setLinearVelocity(v);
    }

    start () {
        // Your initialization goes here.
    }

    // update (deltaTime: number) {
    //     // Your update function goes here.
    // }
}

//Direct.ts
import { _decorator, Component, Node, Vec3, v2, Quat } from "cc";
const { ccclass, property } = _decorator;

@ccclass("Direct")
export class Direct extends Component {
    @property(Node)
    private mid: Node = null;

    @property(Node)
    private top: Node = null;

    @property(Node)
    private ball: Node = null;

    private ratio: number = 0.5;
    /* class member could be defined like this */
    // dummy = '';

    /* use `property` decorator if your want the member to be serializable */
    // @property
    // serializableDummy = 0;

    onLoad():void{
        this.setLen(0.2);
    }

    start () {
        // Your initialization goes here.
    }

    // update (deltaTime: number) {
    //     // Your update function goes here.
    // }

    setLen(len: number): void{
        len = this.ratio * len;        
        let v3: Vec3 = cc.v3();

        v3 = this.mid.getScale();
        v3.y = len;
        this.mid.setScale(v3);

        v3 = this.mid.position;
        cc.log(v3);
        v3.z = - len / 2;
        cc.log(v3);
        this.mid.setPosition(v3);

        v3 = this.top.position;
        v3.z = -len;
        this.top.setPosition(v3);
    }

    setDirect(angle: number): void{
        let quat: Quat = new Quat();
        quat = this.node.getRotation();
        quat.y = angle;
        this.node.setRotation(quat);

    }
}

/* PhyMat.ts
 * @Copyright: Copyright (c) 2019
 * @Author: tony
 * @Version: 1.0
 * @Date: 2019-12-01 23:19:02
 */
import { _decorator, Component, Node,ColliderComponent,PhysicMaterial } from "cc";
const { ccclass, property } = _decorator;

@ccclass("PhyMat")
export class PhyMat extends Component {
    @property
    private friction: number = 0; // 摩擦力

    @property
    private restitution: number = 0; // 弹力

    onLoad():void{
        let comps: Array<ColliderComponent> = this.node.getComponents(ColliderComponent) as Array<ColliderComponent>;

        let mat = new PhysicMaterial();
        mat.friction = this.friction;
        mat.restitution = this.restitution;

        for(let i = 0; i < comps.length; i++){
            comps[i].material = mat;
        }
    }

    start () {
        // Your initialization goes here.
    }

    // update (deltaTime: number) {
    //     // Your update function goes here.
    // }
}


感谢:

本文转载自 https://mp.weixin.qq.com/s/1ZXQS9ok-FyEMb6MbsR1Hg 这篇文章,这里感谢原作者对于技术的分享。

下载:

本文章源码和资源下载地址

发布了265 篇原创文章 · 获赞 20 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/ccnu027cs/article/details/103519832
今日推荐