IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> 【Cocos Creator游戏开发教程】仿微信趣味画赛车小游戏(三)代码实现 -> 正文阅读

[游戏开发]【Cocos Creator游戏开发教程】仿微信趣味画赛车小游戏(三)代码实现

【Cocos Creator游戏开发教程】仿微信趣味画赛车小游戏(一)前言,界面UI
【Cocos Creator游戏开发教程】仿微信趣味画赛车小游戏(二)物理刚体关节

项目地址已放到 github 上,需要的小伙伴可自行下载。
这节我们讲一下游戏代码实现

1.开启物理世界

// GameMain.ts
protected onLoad(): void {
    cc.director.getPhysicsManager().enabled = true; // 开启物理引擎需要写在 onLoad 中
}

protected start(): void {
    cc.debug.setDisplayStats(false);
	this.openPhysics();
	this.node.on(DrawArea.DRAW_VEHICLE, this.onDrawVehicle, this);
}

private openPhysics(): void {
    let manager: cc.PhysicsManager = cc.director.getPhysicsManager();
	manager.enabledAccumulator = true;
	manager.debugDrawFlags = 1;     // 设置调试绘制标志
	cc.PhysicsManager.FIXED_TIME_STEP = 1 / 30;
	cc.PhysicsManager.VELOCITY_ITERATIONS = 8;
	cc.PhysicsManager.POSITION_ITERATIONS = 8;
}

2.画车

监听触摸DrawArea开始事件,将绘画节点移到触摸点,记录存储当前触摸点

// DrawArea.ts
private onTouchStart(event: cc.Event.EventTouch): void {
    // 转换到局部坐标
    let pos = this.node.convertToNodeSpaceAR(event.getLocation());
    this.drawLine.moveTo(pos.x, pos.y);
    this.recordPos = cc.v2(pos.x, pos.y);
    this.drawPoints.push(cc.v2(pos.x, pos.y));
}

监听触摸DrawArea移动事件

// DrawArea.ts
private onTouchMove(event: cc.Event.EventTouch): void {
    let pos: cc.Vec2 = this.node.convertToNodeSpaceAR(event.getLocation());

    let widthLimit: number = (this.node.width + DrawArea.DRAW_CIRCLE_R) / 2;
    let heightLimit: number = (this.node.height + DrawArea.DRAW_CIRCLE_R) / 2;

    // 检查当前触摸点是否超出绘画区域
    if (pos.x < -widthLimit || pos.x > widthLimit) {
        return;
    }
    if (pos.y < -heightLimit || pos.y > heightLimit) {
        return;
    }
    // 绘画
    this.drawLine.lineTo(pos.x, pos.y);
    this.drawLine.stroke();
    this.drawLine.moveTo(pos.x, pos.y);

    // 记录当前手移动到的点
    this.currentPos = cc.v2(pos.x, pos.y);
    //求两点之间的距离
    let subVec: cc.Vec2 = this.currentPos.sub(this.recordPos);
    let distance: number = subVec.mag() + 5;    // 防止线段间出现空隙,所以+5长度

    // 为了减少触摸点数量,如果距离大于等于预制体的width,记录存储该触摸点
    if (distance >= 25) {
        // 将此时的触摸点设为记录点
        this.recordPos = cc.v2(pos.x, pos.y);

        this.drawPoints.push(cc.v2(pos.x, pos.y));
    }
}

监听触摸DrawArea结束事件,发送自定义画车事件,将触摸点数组发送出去

// DrawArea.ts
private onTouchEnd(event: cc.Event.EventTouch): void {
    // 判断触摸点数量是否小于2,不是才发送画车事件
    if (this.drawPoints.length <= 1) {
        this.drawPoints = [];
        return;
    }
    // 发送自定义画车事件 DrawArea.DRAW_VEHICLE
    let customEvent: cc.Event.EventCustom = new cc.Event.EventCustom(DrawArea.DRAW_VEHICLE, true);
    customEvent.setUserData(this.drawPoints);
    this.node.dispatchEvent(customEvent);

    // 清空绘画区域,存储的触摸点
    this.drawLine.clear();
    this.drawPoints = [];
}

3.创建小车

监听自定义画车事件,获取绘画节点数组,调用Vehicle.ts脚本刷新小车

// GameMain.ts
private onDrawVehicle(event: cc.Event.EventCustom): void {
    event.stopPropagation();
    (this.vehicle.getComponent('Vehicle') as Vehicle).updateVehicle(event.getUserData());
}

收到监听,调用刷新车方法

// Vehicle.ts
public updateVehicle(drawPoints: Array<cc.Vec2>): void {
    if (drawPoints.length <= 0) {
        return;
    }
    let _self = this;

    // 重置车位置
    _self.node.x = 0;
    _self.node.y = 200;

    // 重置车
    _self.resetVehicle();
    // 画车身
    _self.drawVehicleBody(drawPoints);
    // 画轮子
    _self.drawWheel(drawPoints);

    // 激活车节点
    if (!_self.node.active) {
        _self.node.active = true;
    }
}

重置车,清空子节点

// Vehicle.ts
private resetVehicle(): void {
    let _self = this;
    let vehicleNode: cc.Node = _self.vehicle.node;   // 获取车节点

    vehicleNode.removeAllChildren();
    _self.vehicleBodys = [];

    _self.wheelRear = null;
    _self.wheelFront = null;
}

画车身

// Vehicle.ts
private drawVehicleBody(drawPoints: Array<cc.Vec2>): void {
    let _self = this;
    let vehicleNode: cc.Node = _self.vehicle.node;   // 获取车节点

    let beforePos: cc.Vec2 = drawPoints[0];
    for (let i = 1; i < drawPoints.length; i++) {
        let curPos: cc.Vec2 = drawPoints[i];
        let subVec: cc.Vec2 = curPos.sub(beforePos);
        let distance: number = subVec.mag() + 5;    // 防止线段间出现空隙,所以+5长度

        // 给定方向向量
        let tempVec: cc.Vec2 = cc.v2(0, 10);

        // 求两点的方向角度
        let rotateVec: number = subVec.signAngle(tempVec) / Math.PI * 180 - 90;

        // 创建车刚体小部件
        let lineItem: cc.Node = cc.instantiate(_self.linePrefab);
        lineItem.angle = -rotateVec;
        lineItem.setPosition(beforePos);
        lineItem.setParent(vehicleNode);

        // 这一步是为了防止两个线段之间出现空隙,动态改变预制体的长度
        lineItem.width = distance;

        // 设置刚体属性
        lineItem.getComponent(cc.PhysicsBoxCollider).offset.x = lineItem.width / 2;
        lineItem.getComponent(cc.PhysicsBoxCollider).size.width = lineItem.width;
        lineItem.getComponent(cc.PhysicsBoxCollider).sensor = true;
        lineItem.getComponent(cc.PhysicsBoxCollider).restitution = 100;
        lineItem.getComponent(cc.PhysicsBoxCollider).apply();

        // 首刚体不需要创建刚体焊接组件
        if (_self.vehicleBodys.length > 0) {
            let beforeLine: cc.Node = _self.vehicleBodys[_self.vehicleBodys.length - 1];

            // 焊接车刚体小部件
            let weldJoint: cc.WeldJoint = lineItem.addComponent(cc.WeldJoint);
            weldJoint.referenceAngle = -rotateVec - beforeLine.angle;

            weldJoint.connectedBody = beforeLine.getComponent(cc.RigidBody);
            weldJoint.connectedAnchor = cc.v2(beforeLine.width - 5, 0);
        }
        _self.vehicleBodys.push(lineItem);

        beforePos = cc.v2(curPos.x, curPos.y);
    }
}

画轮子

// Vehicle.ts
private drawWheel(drawPoints: Array<cc.Vec2>): void {
    let _self = this;

    let vehicleNode: cc.Node = _self.vehicle.node;
    // 首尾车身刚体
    let lineRear: cc.Node = _self.vehicleBodys[0];
    let lineFront: cc.Node = _self.vehicleBodys[_self.vehicleBodys.length - 1];

    let wheelSF: cc.SpriteFrame = new cc.SpriteFrame("HelloWorld");     // 轮胎精灵帧
    // 首尾触摸点
    let rearPos: cc.Vec2 = drawPoints[0];
    let frontPos: cc.Vec2 = drawPoints[drawPoints.length - 1];

    // 通过预制节点,创建后轮
    let wheelRear: cc.Node = cc.instantiate(_self.wheelPrefab);
    wheelRear.getComponent(cc.Sprite).spriteFrame = wheelSF;
    wheelRear.setPosition(rearPos);
    vehicleNode.addChild(wheelRear);

    // 通过预制节点,创建前轮
    let wheelFront: cc.Node = cc.instantiate(_self.wheelPrefab);
    wheelRear.getComponent(cc.Sprite).spriteFrame = wheelSF;
    wheelFront.setPosition(frontPos);
    vehicleNode.addChild(wheelFront);

    // 添加轮子刚体标识
    wheelRear.getComponent(cc.PhysicsCircleCollider).tag = VehicleEnum.COLLIDER_TAG.REAR_TAG;       // 后轮
    wheelFront.getComponent(cc.PhysicsCircleCollider).tag = VehicleEnum.COLLIDER_TAG.FRONT_TAG;      // 前轮

    wheelRear.getComponent(cc.PhysicsCircleCollider).apply();
    wheelFront.getComponent(cc.PhysicsCircleCollider).apply();

    // 加入轮子关节
    // 后轮
    let wheelJointRear: cc.WheelJoint = ComponentUtil.addWheelJointToObj(lineRear, {
        connectedNode: wheelRear,
        anchor: cc.v2(0, 0)
    });

    // 前轮
    let wheelJointFront: cc.WheelJoint = ComponentUtil.addWheelJointToObj(lineFront, {
        connectedNode: wheelFront,
        anchor: cc.v2(lineFront.width - 5, 0)
    });

    // 添加距离关节,约束两个轮子
    let distanceJoint: cc.DistanceJoint = wheelRear.addComponent(cc.DistanceJoint);
    distanceJoint.connectedBody = wheelFront.getComponent(cc.RigidBody);
    distanceJoint.distance = frontPos.sub(rearPos).mag();

    _self.wheelRear = wheelRear;
    _self.wheelFront = wheelFront;
}
  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-07-31 16:57:47  更:2021-07-31 16:58:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/21 20:16:44-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码