<!DOCTYPE html>
<html lang="th">
<head>
<title>Slot-PixiJS</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/4.7.1/pixi.min.js"></script>
</head>
<body>
</body>
</html>
เสร็จแล้วเราเริ่มเขียน css ให้ต่อกันเลย
html,
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
background-image: url("https://i.imgur.com/vxkXEu8.jpg");
background-color: #cccccc;
background-size: cover;
}
canvas {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border: 2px #D82257 solid;
border-radius: 1rem;
}
h1 {
text-transform: uppercase;
font-size: 22px;
color: #D82257;
position: absolute;
top: 50%;
width: 100%;
text-align: center;
margin-top: -240px;
}
ต่อไปเริ่มเขียน javascript โดยเริ่มต้นจากเรียกใช้ PixiJS
const app = new PIXI.Application(640, 360, {
transparent: true,
autoResize: true,
antialias: true,
resolution: 1,
});
document.body.appendChild(app.view);
ต่อไปเรามาทำการสร้าง class สำหรับใช้ config ตัวเกมส์กัน
class Game {
constructor(balance, stake, win) {
this.balance = 500; //จำนวนเงินขณะเริ่มเกมส์
this.stake = 1; //จำนวนเงินเดิมพัน
// คำสั่งเพิ่มเงินเดิมพัน
this.addStake = function () {
if (playerResources.stake >= 1 && playerResources.stake <= 2) {
playerResources.stake ++;
}
};
// คำสั่งลดเงินเดิมพัน
this.minusStake = function minusStake() {
if (playerResources.stake > 1) {
playerResources.stake --;
}
};
// คำสั่งลดจำนวนเงินเมื่อมีการ กด spin
this.reduceBalance = function (){
this.balance = this.balance - this.stake;
}
}
}
พอทำการสร้าง class config แล้วเรามาเริ่มทำ ui สำหรับเกมส์เราดีกว่า
// สร้าง container UI สำหรับ footer
const UIfooterContainer = new PIXI.Container();
// สร้าง UI Box สำหรับเป็นพื้นหลัง จำนวนเงินเดิมพัน
let graphicsTwo = new PIXI.Graphics();
graphicsTwo.lineStyle(2, 0xFF00FF, 1);
graphicsTwo.beginFill(0xFF00BB, 0.25);
graphicsTwo.drawRoundedRect(255, 296, 120, 35, 15);
graphicsTwo.endFill();
// สร้าง style สำหรับใช้ใน text ต่างๆ
const style = new PIXI.TextStyle({
fontFamily: 'Arial',
fontSize: 24,
fontStyle: 'italic',
fontWeight: 'bold',
fill: ['#ffffff', '#00ff99'],
stroke: '#4a1850',
strokeThickness: 5,
dropShadow: true,
dropShadowColor: '#000000',
dropShadowBlur: 4,
dropShadowAngle: Math.PI / 6,
dropShadowDistance: 6,
wordWrap: true,
wordWrapWidth: 300
});
//text จำนวนเงินเดิมพัน
let stackText = new PIXI.Text(`${playerResources.stake}`, style);
stackText.x = (app.screen.width / 2 - 10);
stackText.y = 295;
// เพิ่ม text เข้าไปใน UIfooterContainer
UIfooterContainer.addChild(stackText);
app.stage.addChild(UIfooterContainer);
//สร้าง container สำหรับปุ่มต่างๆ
const buttonsHolder = new PIXI.Container();
buttonsHolder.x = 0;
buttonsHolder.y = 0;
//สร้าง Background สำหรับพื่นหลังของ footer
const background = new PIXI.Graphics();
background.beginFill(0, 1);
background.drawRect(0, 240 + margin, app.screen.width, margin);
// function สำหรับใช้ปุ่มต่างๆ
const makeImageButton = (image, audioMP3, audioOGG, x, y, scale) => {
const button = PIXI.Sprite.fromImage(image);
button.interactive = true;
button.buttonMode = true;
buttonsHolder.addChild(button);
button.x = x;
button.y = y;
button.scale.set(scale);
return button;
};
//ปุ่มสำหรับลดเงินเดิมพัน
const leftArrow = makeImageButton(
'https://i.imgur.com/vMlheaP.png',
'https://www.dropbox.com/s/1qj55ghc8bzv8h4/multimedia_button_click_006.mp3?dl=1',
'https://www.dropbox.com/s/tyxkypl5qfv3rqh/multimedia_button_click_006.ogg?dl=1',
220,
296,
0.05
);
//ปุ่มสำหรับเพิ่มเงินเดิมพัน
const rightArrow = makeImageButton(
'https://i.imgur.com/jwJZBa4.png',
'https://www.dropbox.com/s/1qj55ghc8bzv8h4/multimedia_button_click_006.mp3?dl=1',
'https://www.dropbox.com/s/tyxkypl5qfv3rqh/multimedia_button_click_006.ogg?dl=1',
380,
296,
0.05
);
//ปุ่มสำหรับกดแล้ว sprin
const buttonActive = makeImageButton(
'https://i.imgur.com/r0oI14y.png',
'.https://www.dropbox.com/s/19ko1ucgfq5hfue/zapsplat_foley_money_pouch_fabric_coins_down_on_surface_006_15052.mp3?dl=1',
'.https://www.dropbox.com/s/10w3je29js16ryu/zapsplat_foley_money_pouch_fabric_coins_down_on_surface_006_15052.ogg?dl=1',
450,
235,
0.2
);
UIfooterContainer.addChild(
background,
graphicsTwo,
buttonsHolder,
buttonActive,
stackText,
);
UIfooterContainer.x = 0;
UIfooterContainer.y = 20;
ว้าวววได้ UI กันแล้วแต่เรายังไม่สามารถกดหรือทำ action ยังไม่ได้งั้นมาสร้างเงื่อนไขต่างๆกันเลย
//กำหนด action ปุ๋มขวา
rightArrow.addListener("pointerdown", () => {
playerResources.addStake();
// อัพเดทค่าเดิมพัน screen
stackText.text = playerResources.stake;
});
//กำหนด action ปุ๋มซ้าย
leftArrow.addListener("pointerdown", () => {
playerResources.minusStake();
// อัพเดทค่าเดิมพัน screen
stackText.text = playerResources.stake;
});
แต่เราลองประกอบดูโค๊ดเต็มกันเลย
const app = new PIXI.Application(640, 360, {
transparent: true,
autoResize: true,
antialias: true,
resolution: 1,
});
document.body.appendChild(app.view);
class Game {
constructor(balance, stake, win) {
this.balance = 500;
this.stake = 1;
this.win = 0;
this.playing = false;
this.addStake = function () {
if (playerResources.stake >= 1 && playerResources.stake <= 9) {
playerResources.stake++;
}
};
this.minusStake = function minusStake() {
if (playerResources.stake > 1) {
playerResources.stake--;
}
};
this.reduceBalance = function () {
this.balance = this.balance - this.stake;
}
}
}
let playerResources = new Game();
const REEL_WIDTH = 90;
const SYMBOL_SIZE = 80;
let reels = [];
let anotherSlot = [];
let slotTextures = [];
let anotherSlotTextures = [];
let reelContainer;
let reel;
const margin = 50;
function onAssetsLoaded() {
let u1 = PIXI.Texture.fromImage("https://i.imgur.com/hpjuqb1.png");
let u2 = PIXI.Texture.fromImage("https://i.imgur.com/S2GtCJP.png");
let u3 = PIXI.Texture.fromImage("https://i.imgur.com/YYoVVYv.png");
let u4 = PIXI.Texture.fromImage("https://i.imgur.com/9za3Pl0.png");
//Create different slot symbols.
slotTextures = [
u1,
u2,
u3,
u4
];
// สร้าง container UI สำหรับ footer
const UIfooterContainer = new PIXI.Container();
// สร้าง UI Box สำหรับเป็นพื้นหลัง จำนวนเงินเดิมพัน
let graphicsTwo = new PIXI.Graphics();
graphicsTwo.lineStyle(2, 0xFF00FF, 1);
graphicsTwo.beginFill(0xFF00BB, 0.25);
graphicsTwo.drawRoundedRect(255, 296, 120, 35, 15);
graphicsTwo.endFill();
// สร้าง style สำหรับใช้ใน text ต่างๆ
const style = new PIXI.TextStyle({
fontFamily: 'Arial',
fontSize: 24,
fontStyle: 'italic',
fontWeight: 'bold',
fill: ['#ffffff', '#00ff99'],
stroke: '#4a1850',
strokeThickness: 5,
dropShadow: true,
dropShadowColor: '#000000',
dropShadowBlur: 4,
dropShadowAngle: Math.PI / 6,
dropShadowDistance: 6,
wordWrap: true,
wordWrapWidth: 300
});
//text จำนวนเงินเดิมพัน
let stackText = new PIXI.Text(`${playerResources.stake}`, style);
stackText.x = (app.screen.width / 2 - 10);
stackText.y = 295;
// เพิ่ม text เข้าไปใน UIfooterContainer
UIfooterContainer.addChild(stackText);
//สร้าง container สำหรับปุ่มต่างๆ
const buttonsHolder = new PIXI.Container();
buttonsHolder.x = 0;
buttonsHolder.y = 0;
//สร้าง Background สำหรับพื่นหลังของ footer
const background = new PIXI.Graphics();
background.beginFill(0, 1);
background.drawRect(0, 240 + margin, app.screen.width, margin);
// function สำหรับใช้ปุ่มต่างๆ
const makeImageButton = (image, audioMP3, audioOGG, x, y, scale) => {
const button = PIXI.Sprite.fromImage(image);
button.interactive = true;
button.buttonMode = true;
buttonsHolder.addChild(button);
button.x = x;
button.y = y;
button.scale.set(scale);
return button;
};
//ปุ่มสำหรับลดเงินเดิมพัน
const leftArrow = makeImageButton(
'https://i.imgur.com/vMlheaP.png',
'https://www.dropbox.com/s/1qj55ghc8bzv8h4/multimedia_button_click_006.mp3?dl=1',
'https://www.dropbox.com/s/tyxkypl5qfv3rqh/multimedia_button_click_006.ogg?dl=1',
220,
296,
0.05
);
//ปุ่มสำหรับเพิ่มเงินเดิมพัน
const rightArrow = makeImageButton(
'https://i.imgur.com/jwJZBa4.png',
'https://www.dropbox.com/s/1qj55ghc8bzv8h4/multimedia_button_click_006.mp3?dl=1',
'https://www.dropbox.com/s/tyxkypl5qfv3rqh/multimedia_button_click_006.ogg?dl=1',
380,
296,
0.05
);
//ปุ่มสำหรับกดแล้ว sprin
const buttonActive = makeImageButton(
'https://i.imgur.com/r0oI14y.png',
'.https://www.dropbox.com/s/19ko1ucgfq5hfue/zapsplat_foley_money_pouch_fabric_coins_down_on_surface_006_15052.mp3?dl=1',
'.https://www.dropbox.com/s/10w3je29js16ryu/zapsplat_foley_money_pouch_fabric_coins_down_on_surface_006_15052.ogg?dl=1',
450,
235,
0.2
);
//กำหนด action ปุ๋มขวา
rightArrow.addListener("pointerdown", () => {
playerResources.addStake();
// อัพเดทค่าเดิมพัน screen
stackText.text = playerResources.stake;
});
//กำหนด action ปุ๋มซ้าย
leftArrow.addListener("pointerdown", () => {
playerResources.minusStake();
// อัพเดทค่าเดิมพัน screen
stackText.text = playerResources.stake;
});
buttonActive.addListener('pointerdown', () => {
startPlay();
playerResources.reduceBalance();
balanceText.text = playerResources.balance;
console.log(`button clicked`);
});
reelContainer = new PIXI.Container();
for (let i = 0; i < 6; i++) {
const rc = new PIXI.Container();
rc.x = i * REEL_WIDTH;
reelContainer.addChild(rc);
reel = {
container: rc,
symbols: [],
position: 0,
previousPosition: 0,
blur: new PIXI.filters.BlurFilter()
};
reel.blur.blurX = 0;
reel.blur.blurY = 0;
rc.filters = [reel.blur];
for (let j = 0; j < 4; j++) {
const symbol = new PIXI.Sprite(slotTextures[Math.floor(Math.random() * slotTextures.length)]);
symbol.y = j * SYMBOL_SIZE;
symbol.scale.x = symbol.scale.y = Math.min(SYMBOL_SIZE / symbol.width, SYMBOL_SIZE / symbol.height);
symbol.x = Math.round((SYMBOL_SIZE - symbol.width) / 9);
reel.symbols.push(symbol);
rc.addChild(symbol);
}
reels.push(reel);
}
app.stage.addChild(reelContainer);
reelContainer.y = margin * 1.5;
reelContainer.x = 50;
app.stage.addChild(UIfooterContainer);
UIfooterContainer.addChild(
background,
graphicsTwo,
buttonsHolder,
buttonActive,
stackText,
);
UIfooterContainer.x = 0;
UIfooterContainer.y = 20;
const top = new PIXI.Graphics();
top.beginFill(0xFF00BB, 0.25);
top.drawRect(0, 0, app.screen.width, margin);
let balanceText = new PIXI.Text(`${playerResources.balance}`, style);
balanceText.x = 535;
balanceText.y = 7;
top.addChild(balanceText);
app.stage.addChild(top);
let running = false;
function startPlay() {
if (running) return;
running = true;
for (let i = 0; i < reels.length; i++) {
const r = reels[i];
const extra = Math.floor(Math.random() * 3);
tweenTo(r, "position", r.position + 10 + i * 5 + extra, 2500 + i * 600 + extra * 600, backout(0.6), null, i == reels.length - 1 ? reelsComplete : null);
}
}
function reelsComplete() {
running = false;
}
app.ticker.add(delta => {
for (const r of reels) {
r.blur.blurY = (r.position - r.previousPosition) * 8;
r.previousPosition = r.position;
for (let j = 0; j < r.symbols.length; j++) {
const s = r.symbols[j];
const prevy = s.y;
s.y = (r.position + j) % r.symbols.length * SYMBOL_SIZE - SYMBOL_SIZE;
if (s.y < 0 && prevy > SYMBOL_SIZE) {
s.texture = slotTextures[Math.floor(Math.random() * slotTextures.length)];
s.scale.x = s.scale.y = Math.min(SYMBOL_SIZE / s.texture.width, SYMBOL_SIZE / s.texture.height);
s.x = Math.round((SYMBOL_SIZE - s.width) / 2);
}
}
}
});
}
PIXI.loader
.add("u1", "https://i.imgur.com/hpjuqb1.png")
.add("u2", "https://i.imgur.com/S2GtCJP.png")
.add("u3", "https://i.imgur.com/YYoVVYv.png")
.add("u4", "https://i.imgur.com/9za3Pl0.png")
.load(onAssetsLoaded);
const tweening = [];
function tweenTo(object, property, target, time, easing, onchange, oncomplete) {
const tween = {
object,
property,
propertyBeginValue: object[property],
target,
easing,
time,
change: onchange,
complete: oncomplete,
start: Date.now()
};
tweening.push(tween);
return tween;
}
app.ticker.add(delta => {
const now = Date.now();
const remove = [];
for (var i = 0; i < tweening.length; i++) {
const t = tweening[i];
const phase = Math.min(1, (now - t.start) / t.time);
t.object[t.property] = lerp(t.propertyBeginValue, t.target, t.easing(phase));
if (t.change) t.change(t);
if (phase == 1) {
t.object[t.property] = t.target;
if (t.complete)
t.complete(t);
remove.push(t);
}
}
for (var i = 0; i < remove.length; i++) {
tweening.splice(tweening.indexOf(remove[i]), 1);
}
});
function lerp(a1, a2, t) {
return a1 * (1 - t) + a2 * t;
}
backout = amount => t => --t * t * ((amount + 1) * t + amount) + 1;