利用pixi.js制作簡單的跑酷小游戲
前言
此項目使用pixi.js和vue實現(xiàn),部分素材來自愛給網(wǎng),本項目僅作用于 pixi.js 學習用途,侵權(quán)立刪。
項目地址
demo地址

初始化項目
使用vite初始化項目
pnpm create vite my-vue-app
安裝pixi.js和pixi-tweener
pixi-tweener一個做過度動畫的開源庫
pnpm i pixi.js pixi-tweener
主要邏輯
useParkour
此函數(shù)用于創(chuàng)建pixi app,將場景,障礙物,人物添加到app中
- containerRef canvas的容器
- gameStart 開始游戲
- start 開始狀態(tài)
- score 分數(shù)
- hp 血量
export function useParkour() {
const containerRef = ref();
const app = new Application({
width: BODY_HEIGHT,
height: BODY_WIDTH,
backgroundColor: 0xffffff,
});
const start = ref(false);
Tweener.init(app.ticker);
const container = new Container();
app.stage.addChild(container);
const player = new Player();
const { scene, runScene, stopScene } = useScene();
const { trap, runHurdle, score, hp } = useHurdle();
container.addChild(player);
container.addChild(scene);
container.addChild(trap);
container.sortChildren();
runScene();
function gameStart() {
start.value = true;
player.play();
const timer = setTimeout(() => {
runHurdle(player);
clearTimeout(timer);
}, 1000);
}
watch(hp, (value) => {
if (value === 0) {
player.stop();
stopScene();
start.value = false;
}
});
onMounted(() => {
if (containerRef.value) containerRef.value.appendChild(app.view);
});
return { containerRef, app, score, hp, gameStart, start };
}useScene
此函數(shù)用于創(chuàng)建天空、地面場景
加載天空、地面紋理,創(chuàng)建平鋪精靈(TilingSprite),這個TilingSprite類比較方便做場景的移動
創(chuàng)建ticker遞減精靈的x坐標實現(xiàn)場景移動
export function useScene() {
const loader = new Loader();
const scene = new Container();
scene.height = 130;
scene.zIndex = 1;
const ticker = new Ticker();
loader
.add("footer", FooterImg)
.add("sky", SkyImg)
.load(() => {
const footer = new TilingSprite(
loader.resources.footer.texture as Texture,
BODY_HEIGHT,
130
);
footer.y = BODY_WIDTH - 130;
footer.zIndex = 2;
const sky = new TilingSprite(
loader.resources.sky.texture as Texture,
BODY_HEIGHT,
BODY_WIDTH - 80
);
sky.tileScale.y = 0.6;
sky.zIndex = 1;
sky.y = -30;
scene.addChild(footer);
scene.addChild(sky);
scene.sortChildren();
const sceneTicker = () => {
footer.tilePosition.x -= 3;
sky.tilePosition.x -= 3;
};
ticker.add(sceneTicker);
});
function runScene() {
ticker.start();
}
function stopScene() {
ticker.stop();
}
return { scene, runScene, stopScene };
}useHurdle
此函數(shù)用于創(chuàng)建障礙物
和創(chuàng)建場景其實差不多,只是障礙物是普通的精靈類(Sprite),創(chuàng)建ticker移動其x
在移動時做和人物的碰撞檢測,如果碰撞則減少生命值,如果沒有則增加分數(shù)
export function useHurdle() {
const loader = new Loader();
const trap = new Container();
const ticker = new Ticker();
const textures: Texture[] = [];
let player: Sprite | null = null;
const hp = ref(100);
const score = ref(0);
let timer: NodeJS.Timer;
trap.zIndex = 3;
loader.add("trap", TrapImg).load((_, resources) => {
TrapTexturePosition.forEach((position) => {
const t = new Texture(
resources.trap.texture as any,
new Rectangle(...position)
);
textures.push(t);
});
});
loader.load(() => {
timer = setInterval(() => {
const index = Math.floor(Math.random() * 2) + 1;
const item = new Sprite(textures[index]);
item.width = 80;
item.height = 40;
item.x = BODY_HEIGHT;
item.y = BODY_WIDTH - 120;
trap.addChild(item);
let scoreFlag = true;
let hpFlag = true;
let isHit = false;
function itemTicker() {
item.x -= 8;
if (player && !isHit) {
isHit = hitTestRectangle(player, item);
if (hpFlag && isHit) {
hp.value -= 10;
hpFlag = false;
if (hp.value === 0) stopGame();
} else if (scoreFlag && item.x < player.x) {
score.value++;
scoreFlag = false;
}
}
if (item.x < -item.width) {
ticker.remove(itemTicker);
trap.removeChild(item);
}
}
ticker.add(itemTicker);
}, 2000);
});
function runHurdle(target: Sprite) {
player = target;
ticker.start();
}
function stopGame() {
timer && clearInterval(timer);
ticker.stop();
}
return { trap, runHurdle, score, hp };
}Player
玩家類:實現(xiàn)跑動、上跳、滑鏟、入場的效果
通過變換Sprite的texture實現(xiàn)跑動效果,監(jiān)聽鍵盤事件,上鍵時減y,下鍵時更換滑鏟紋理
export class Player extends Sprite {
defaultY = BODY_WIDTH - 160;
textures: Texture[] = [];
status: "run" | "jump" | "slide" = "run";
ticker = new Ticker();
constructor() {
super();
this.width = 80;
this.height = 80;
this.x = -120;
this.y = this.defaultY;
this.zIndex = 10;
this.loader();
this.watchEvent();
}
private loader() {
const loader = new Loader();
loader.add("player", PlayerImg).load((_, resources) => {
PlayerTexturePosition.forEach((position, i) => {
const texture = new Texture(
resources.player.texture as any,
new Rectangle(...position)
);
this.textures.push(texture);
});
});
}
private watchEvent() {
document.addEventListener("keydown", this.keydown);
document.addEventListener("keyup", this.keyup);
}
private clearEvent() {
document.removeEventListener("keyup", this.keydown);
document.removeEventListener("keydown", this.keyup);
}
private keydown = (e: any) => {
if (e.code === "ArrowUp") {
this.status = "jump";
if (this.y === this.defaultY) {
Tweener.add(
{ target: this, duration: 0.3, ease: Easing.easeInOutQuint },
{ y: this.y - 120 }
);
}
} else if (e.code === "ArrowDown") {
this.status = "slide";
this.texture = this.textures[10];
}
};
private keyup = () => {
this.status = "run";
};
stop() {
this.ticker.stop();
this.clearEvent();
}
play() {
this.ticker.autoStart = true;
const runTicker = () => {
this.down();
this.entrance();
if (this.status === "run") this.run();
else if (this.status === "jump") this.jump();
};
this.ticker.add(runTicker);
}
// 跑
run() {
this.texture = this.textures[Math.floor(Date.now() / 100) % 8];
}
jump() {
this.texture = this.textures[(Math.floor(Date.now() / 100) % 5) + 11];
}
// 下落
down() {
if (this.y < this.defaultY) {
this.status = "jump";
this.y += 5;
} else {
if (this.status === "jump") {
this.status = "run";
}
}
}
// 入場
entrance() {
if (this.x < 120) this.x += 5;
}
}到此這篇關(guān)于利用pixi.js制作簡單的跑酷小游戲的文章就介紹到這了,更多相關(guān)pixi.js跑酷游戲內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
js數(shù)組方法reduce經(jīng)典用法代碼分享
本文給大家整理了很多關(guān)于js數(shù)組方法reduce的經(jīng)典代碼片段,能夠讓大家更好的理解reduce的實例用法,一起學習下吧。2018-01-01
JavaScript使用DeviceOne開發(fā)實戰(zhàn)(四)仿優(yōu)酷視頻應用
這篇文章主要介紹了JavaScript使用DeviceOne開發(fā)實戰(zhàn)(四)仿優(yōu)酷視頻應用的相關(guān)資料,需要的朋友可以參考下2015-12-12
JavaScript 監(jiān)聽組合按鍵思路及代碼實現(xiàn)
這篇文章主要介紹了JavaScript 監(jiān)聽組合按鍵思路及代碼實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-07-07
基于JavaScript實現(xiàn)文本一鍵復制和長按復制功能
本文主要內(nèi)容分三部分,第一部分是需求分析,第二部分是實現(xiàn)步驟,第三部分是問題詳解,如果您只需要解決問題,請閱讀第一、二部分即可,如果您有更多時間,進一步學習問題相關(guān)知識點,請閱讀至第三部分2023-10-10

