Skip to content

Instantly share code, notes, and snippets.

@popzatem
Last active March 30, 2022 10:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save popzatem/a450c948754bd4b00942c428afbe2523 to your computer and use it in GitHub Desktop.
Save popzatem/a450c948754bd4b00942c428afbe2523 to your computer and use it in GitHub Desktop.
Slot-PixiJS

1.เริ่มวางโครง HTML กันก่อนเลย

<!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);

ก็จะได้หน้าตาประมาณนี้ alt_text

ต่อไปเรามาทำการสร้าง 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;

alt_text

ว้าวววได้ 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;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment