Threejs系列--18游戏开发--沙漠赛车游戏【loading资源加载进度条】

序言

本章将实现loading加载资源进度条。

目录结构

资源目录里面的结构不变,点击传送门快速查看。

|__src
	|__assets
	|__js
	|	|__base		基础类文件夹
	|		|__Camera.js 相机类	
	|		|__Resources.js 资源类 
	|	|__geometries	定制的物体类文件夹
	|		|__AreaFloorBorderBufferGeometry.js 进度条几何体  【新增】
	|	|__materials	材质类文件夹
	|		|__Floor.js 地面材质
	|		|__AreaFloorBorder.js 进度条着色器  【新增】
	|	|__passes	合成器通道文件夹
	|		|__Blur.js	  模糊着色器
	|		|__Glows.js		发光着色器
	|	|__utils	工具类文件夹
	|		|__Sizes.js  画布大小控制类
	|		|__EventEmitter.js 基础事件处理器
	|		|__Time.js  动画刷新
	|		|__Loader.js 加载器 
	|	|__world	精灵类文件夹
	|		|__Area.js	区域基础类  【新增--基础实现】
	|		|__Areas.js	区域管理类  【新增--管理各个区域】
	|		|__index.js	精灵类	【新增--进度条导入与切换】
	|		|__Floor.js 地面类
	|	|__Application.js	初始化游戏的文件 
	|__index.js		入口
	|__index.css  	小项目,样式一丢丢

代码一览

AreaFloorBorderBufferGeometry.js代码

import * as THREE from "three";

/**
* 自定义进度条几何体
*/
class AreaFloorBorderBufferGeometry {
  constructor(_width, _height, _thickness) {
    this.parameters = {
      width: _width,
      height: _height,
      thickness: _thickness,
    };

    this.type = "AreaFloorBufferGeometry";

    const length = 8;

    const vertices = new Float32Array(length * 3);
    const indices = new Uint32Array(length * 6);

    const outerWidth = _width;
    const outerHeight = _height;

    const innerWidth = outerWidth - _thickness;
    const innerHeight = outerHeight - _thickness;

    // Vertices
    vertices[0 * 3 + 0] = innerWidth * 0.5;
    vertices[0 * 3 + 1] = innerHeight * 0.5;
    vertices[0 * 3 + 2] = 0;

    vertices[1 * 3 + 0] = innerWidth * 0.5;
    vertices[1 * 3 + 1] = -innerHeight * 0.5;
    vertices[1 * 3 + 2] = 0;

    vertices[2 * 3 + 0] = -innerWidth * 0.5;
    vertices[2 * 3 + 1] = -innerHeight * 0.5;
    vertices[2 * 3 + 2] = 0;

    vertices[3 * 3 + 0] = -innerWidth * 0.5;
    vertices[3 * 3 + 1] = innerHeight * 0.5;
    vertices[3 * 3 + 2] = 0;

    vertices[4 * 3 + 0] = outerWidth * 0.5;
    vertices[4 * 3 + 1] = outerHeight * 0.5;
    vertices[4 * 3 + 2] = 0;

    vertices[5 * 3 + 0] = outerWidth * 0.5;
    vertices[5 * 3 + 1] = -outerHeight * 0.5;
    vertices[5 * 3 + 2] = 0;

    vertices[6 * 3 + 0] = -outerWidth * 0.5;
    vertices[6 * 3 + 1] = -outerHeight * 0.5;
    vertices[6 * 3 + 2] = 0;

    vertices[7 * 3 + 0] = -outerWidth * 0.5;
    vertices[7 * 3 + 1] = outerHeight * 0.5;
    vertices[7 * 3 + 2] = 0;

    // Index
    indices[0 * 3 + 0] = 4;
    indices[0 * 3 + 1] = 0;
    indices[0 * 3 + 2] = 1;

    indices[1 * 3 + 0] = 1;
    indices[1 * 3 + 1] = 5;
    indices[1 * 3 + 2] = 4;

    indices[2 * 3 + 0] = 5;
    indices[2 * 3 + 1] = 1;
    indices[2 * 3 + 2] = 2;

    indices[3 * 3 + 0] = 2;
    indices[3 * 3 + 1] = 6;
    indices[3 * 3 + 2] = 5;

    indices[4 * 3 + 0] = 6;
    indices[4 * 3 + 1] = 2;
    indices[4 * 3 + 2] = 3;

    indices[5 * 3 + 0] = 3;
    indices[5 * 3 + 1] = 7;
    indices[5 * 3 + 2] = 6;

    indices[6 * 3 + 0] = 7;
    indices[6 * 3 + 1] = 3;
    indices[6 * 3 + 2] = 0;

    indices[7 * 3 + 0] = 0;
    indices[7 * 3 + 1] = 4;
    indices[7 * 3 + 2] = 7;

    const geometry = new THREE.BufferGeometry();

    geometry.setIndex(new THREE.BufferAttribute(indices, 1, false));

    geometry.setAttribute(
      "position",
      new THREE.Float32BufferAttribute(vertices, 3)
    );

    return geometry;
  }
}

export default AreaFloorBorderBufferGeometry;

AreaFloorBorder.js代码

import * as THREE from "three";

import shaderFragment from "../../assets/shaders/areaFloorBorder/fragment.glsl";
import shaderVertex from "../../assets/shaders/areaFloorBorder/vertex.glsl";

/**
* 进度条着色器
*/
export default function () {
  const uniforms = {
    uColor: { value: null },
    uAlpha: { value: null },
    uLoadProgress: { value: null },
    uProgress: { value: null },
  };

  const material = new THREE.ShaderMaterial({
    wireframe: false,
    transparent: true,
    depthTest: true,
    depthWrite: false,
    uniforms,
    vertexShader: shaderVertex,
    fragmentShader: shaderFragment,
  });

  return material;
}

Area.js代码

import * as THREE from 'three';
import EventEmitter from "../utils/EventEmitter";

import AreaFloorBorderBufferGeometry from '../geometries/AreaFloorBorderBufferGeometry';
import AreaFloorBorderMaterial from '../materials/AreaFloorBorder';

/**
* 区域类
*/
export default class Area extends EventEmitter{
    constructor(_options){
        super();

        this.position = _options.position;
        this.halfExtents = _options.halfExtents;

        this.container = new THREE.Object3D();
        this.container.position.x = this.position.x;
        this.container.position.y = this.position.y;
        this.container.matrixAutoUpdate = false;
        this.container.updateMatrix();

        this.setFloorBorder();
    }

    setFloorBorder(){
        this.floorBorder = {};
		//创建进度条
        this.floorBorder.geometry = new AreaFloorBorderBufferGeometry(
            this.halfExtents.x * 2,
            this.halfExtents.y * 2,
            0.25
        );
        this.floorBorder.material = new AreaFloorBorderMaterial();
        this.floorBorder.material.uniforms.uColor.value = new THREE.Color(0xffffff);
        this.floorBorder.material.uniforms.uAlpha.value = 1;
        this.floorBorder.material.uniforms.uLoadProgress.value = 1;
        this.floorBorder.material.uniforms.uProgress.value = 1;
        
        this.floorBorder.mesh = new THREE.Mesh(this.floorBorder.geometry, this.floorBorder.material);
        console.log(this.floorBorder.geometry)
        this.floorBorder.mesh.matrixAutoUpdate = false;
        this.container.add(this.floorBorder.mesh);
    }
}

Areas.js代码

import * as THREE from 'three';
import Area from "./Area";

/**
* 区域管理
*/
export default class Areas {
    constructor(_options) {
        this.resources = _options.resources;

        this.container = new THREE.Object3D();
        this.container.matrixAutoUpdate = false;
    }

    add(_options) {
        const area = new Area({
            resources: this.resources,
            ..._options,
        });

        this.container.add(area.container);

        return area;
    }
}

index.js代码

import * as THREE from "three";
import gsap from "gsap";
import Floor from "./Floor.js";
import Areas from "./Areas.js";

export default class {
    constructor(_options){
        ...

        //设置世界中的区域加载
        this.setAreas();

        //设置启动屏
        this.setStartingScreen();
    }

    setStartingScreen() {
        this.startingScreen = {};
        
        this.startingScreen.area = this.areas.add({
            position: new THREE.Vector2(0, 0),
            halfExtents: new THREE.Vector2(2.35, 1.5),
        });

        ...
        
        this.resources.on('progress', _progress => {
            this.startingScreen.area.floorBorder.material.uniforms.uAlpha.value = 1;
            this.startingScreen.area.floorBorder.material.uniforms.uLoadProgress.value = _progress;
        })
        
        this.resources.on('ready', () => {
            window.requestAnimationFrame(() => {
                gsap.to(this.startingScreen.area.floorBorder.material.uniforms.uAlpha, {duration: 0.3, value: 0.3 });
                ...
            })
        })
    }

   ...

    setAreas(){
        this.areas = new Areas({
            resources: this.resources
        })
        this.container.add(this.areas.container)
    }
}

代码解读

AreaFloorBorderBufferGeometry.js自定义了需要的进度条
AreaFloorBorder.js使用自定义的着色器渲染材质
Area.js合成自定义的进度条
Areas.js统一管理区块【进度条也是一个区块】
index.js导入Areas,使用进度条,根据资源加载进度,控制参数变化

运行结果

在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Phaser.js是一个用于创建HTML5游戏的开源框架,其中包含了许多功能强大的工具和库。要创建一个赛车游戏,你可以使用Phaser.js的物理引擎和精灵功能来实现。以下是一个简单的示例代码,展示了如何使用Phaser.js创建一个基本的赛车游戏: ```javascript // 创建一个Phaser游戏实例 var game = new Phaser.Game(800, 600, Phaser.AUTO, '', { preload: preload, create: create, update: update }); // 预加载资源 function preload() { game.load.image('car', 'assets/car.png'); } // 创建游戏场景 function create() { // 添加赛车精灵 var car = game.add.sprite(400, 300, 'car'); // 启用物理引擎 game.physics.startSystem(Phaser.Physics.ARCADE); game.physics.arcade.enable(car); // 设置赛车的重力和碰撞边界 car.body.collideWorldBounds = true; car.body.gravity.y = 0; // 设置赛车的控制 var cursors = game.input.keyboard.createCursorKeys(); cursors.up.onDown.add(function() { car.body.velocity.y = -200; }); cursors.down.onDown.add(function() { car.body.velocity.y = 200; }); cursors.left.onDown.add(function() { car.body.velocity.x = -200; }); cursors.right.onDown.add(function() { car.body.velocity.x = 200; }); } // 游戏更新 function update() { // 游戏逻辑更新 } ``` 请注意,这只是一个简单的示例,你可以根据自己的需求进行修改和扩展。你还可以通过添加更多的精灵、道具、关卡和游戏机制来进一步完善赛车游戏。希望对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小猴子喝牛奶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值