我們將會用50行不到的程式碼來實現一個3D模擬撒金幣動效。你只需要一點Egret基礎就能夠快速上手,如果你不瞭解Egret,這裡有一篇3分鐘建立hello world來帶你快速入門。
實現效果
原始碼和線上demo
- 完整的工程請見:github.com/wildfirecod…
- 線上訪問地址:wildfirecode.com/fallingCoin…
資源準備
圖片序列幀在工程的design/coin
下。我們需要用TextureMerge
工具來建立一個精靈圖
(SpriteSheet)。具體方式檢視 這裡 。最後將精靈圖匯入assets/
資料夾,檔名為coin.json
和coin.png
。
注意:序列幀圖片的檔名為1.png~8.png
。
載入資源
我們通過精靈圖的方式載入這8張序列幀圖片。這裡有一個工具函式:
const loadSpriteSheet: (keys: string[]) => Promise<egret.SpriteSheet>
複製程式碼
我們將精靈圖的keys傳入就可以獲取到一個egret.SpriteSheet
型別的物件,使用程式碼:
const keys = ['assets/coin.json', 'assets/coin.png'];
const spritesheet = await loadSpriteSheet(keys);
複製程式碼
注意:如果你想用TexturePacker來建立精靈圖也是可以的,只是loadSpriteSheet
函式需要有少許的變動。
建立序列幀圖片動畫
這裡要引入一個工具類MovieClip
(不要太在意類的命名 >.<)。看下API:
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();
複製程式碼