50 строк кода для 3D-симуляции настоящих золотых монет

внешний интерфейс анимация Canvas

Мы будем использовать менее 50 строк кода для реализации 3D-моделирования золотых монет. Чтобы быстро приступить к работе, вам нужно немного узнать о Egret.Если вы не знаете Egret, вот статьяСоздать привет мир за 3 минутычтобы вы начали быстро.

добиться эффекта

Исходный код и онлайн-демонстрация

подготовка ресурсов

Кадр последовательности изображений в проектеdesign/coinВниз. нам нужно использоватьTextureMergeинструмент для создания精灵图(спрайт-лист). Просмотр конкретным способомздесь. Наконец импортируйте спрайтassets/папка с именем файлаcoin.jsonа такжеcoin.png.

Примечание. Имя файла изображения кадра последовательности1.png~8.png.

ресурс загрузки

Мы загружаем эти 8 изображений кадра последовательности с помощью спрайтов. Вот полезная функция:

const loadSpriteSheet: (keys: string[]) => Promise<egret.SpriteSheet>

Мы можем получить спрайт, передав ключи спрайтаegret.SpriteSheetобъект типа, используйте код:

const keys = ['assets/coin.json', 'assets/coin.png'];
const spritesheet = await loadSpriteSheet(keys);

Примечание: если вы хотите использоватьTexturePackerТакже можно создавать спрайты, простоloadSpriteSheetФункцию нужно немного изменить.

Создать анимацию кадра последовательности

Здесь, чтобы представить класс инструментовMovieClip(Не обращайте слишком много внимания на имя класса >.

constructor MovieClip(
    { spritesheet, frames, position, keys,frameInterval} : 
    {
        spritesheet: egret.SpriteSheet;//精灵图
        frames: string[];//序列帧的图片的文件名序列
        position: number[];//设置动画位置
        frameInterval?: number;//相邻图片播放间隔,单位是帧,这会控制动画的播放速度
    }): MovieClip

Следующий код помещает анимацию золотой монеты на{x:100,y:100}положение, интервал воспроизведения соседних изображений составляет 3 кадра, а порядок воспроизведения изображений1.png~8.png.

const animation = new MovieClip({
    frameInterval: 3,
    frames: ['1', '2', '3', '4', '5', '6', '7', '8'],
    position: [100, 100],
    spritesheet: spritesheet
});
this.addChild(animation);//显示动画

Добавить реалистичный эффект падения в анимацию

Здесь представлен класс инструментов физических объектов.Body.

constructor Body({ x, y, vx, vy, gx, gy, host }: {
    x: number;//起始x
    y: number;//起始y
    vx: number;//起始x方向速度
    vy: number;//起始y方向速度
    gx: number;//x方向重力
    gy: number;//y方向重力
    host: egret.DisplayObject;//宿主显示对象
}): Body

Вот используемый код:

const x = 750 / 2;
const y = 750 / 2;
const vx = 10;
const vy = -10;
const animation = this.createCoinMovieClip(spritesheet);
const falling = new Body({
    x: x, y: y, vx: vx, vy: vy, gy: 1, host: animation
});

Создайте 3D-симуляцию разброса золотых монет

main.tsДобавьте функции для создания одной анимации:

createCoinMovieClip(spritesheet) {
    const animation = new MovieClip({
        frameInterval: 3,
        frames: ['1', '2', '3', '4', '5', '6', '7', '8'],
        loop: true,
        position: [100, 100],
        spritesheet: spritesheet
    });
    return animation;
}

Давайте создадим анимацию 100 золотых монет и установим случайную начальную позицию и скорость с гравитацией, установленной на 1. Вы можете настроить различные параметры в нем, чтобы получить желаемый эффект.

 let coinsFall = setInterval(() => {
    if (count < 100) {
        const x = 750 / 2 + Math.random() * 50 - 25;
        const y = 750 / 2 + Math.random() * 50 - 25;
        const vx = Math.random() * 20 - 10;
        const vy = -10 + Math.random() * 10 - 5;
        const animation = this.createCoinMovieClip(spritesheet);
        const falling = new Body({
            x: x, y: y, vx: vx, vy: vy, gy: 1, host: animation
        });
        this.addChild(animation);
        count++;
    } else {
        //结束
    }
}, 10)

полный код

Видно, что мы использовали менее 50 строк кода для достижения реального эффекта золотой монеты.

import Body from "./physics/Body";
import loadSpriteSheet from "./utils/loadSpriteSheet";
import MovieClip from "./movieclip/MovieClip";

class Main extends egret.DisplayObjectContainer {
    constructor() {
        super();
        this.once(egret.Event.ADDED_TO_STAGE, this.onAddToStage, this);
    }

    async onAddToStage() {
        const keys = ['assets/coin.json', 'assets/coin.png'];
        const spritesheet = await loadSpriteSheet(keys);
        let count = 0;
        let coinsFall = setInterval(() => {
            if (count < 100) {
                const x = 750 / 2 + Math.random() * 50 - 25;
                const y = 750 / 2 + Math.random() * 50 - 25;
                const vx = Math.random() * 20 - 10;
                const vy = -10 + Math.random() * 10 - 5;
                const animation = this.createCoinMovieClip(spritesheet);
                const falling = new Body({
                    x: x, y: y, vx: vx, vy: vy, gy: 1, host: animation
                });
                this.addChild(animation);
                count++;
            } else {
                //结束
            }
        }, 10)

    }

    createCoinMovieClip(spritesheet) {
        const animation = new MovieClip({
            frameInterval: 3,
            frames: ['1', '2', '3', '4', '5', '6', '7', '8'],
            loop: true,
            position: [100, 100],
            spritesheet: spritesheet
        });
        return animation;
    }
}

window['Main'] = Main;

egret.runEgret();