app.ts

作者: skoll | 来源:发表于2021-02-07 20:20 被阅读0次

import "@babylonjs/core/Debug/debugLayer";
import "@babylonjs/inspector";
import "@babylonjs/loaders/glTF";
import { Engine, Scene, Vector3, Mesh, Color3, Color4, ShadowGenerator, GlowLayer, PointLight, FreeCamera, CubeTexture, Sound, PostProcess, Effect, SceneLoader, Matrix, MeshBuilder, Quaternion, AssetsManager } from "@babylonjs/core";
import { AdvancedDynamicTexture, StackPanel, Button, TextBlock, Rectangle, Control, Image } from "@babylonjs/gui";
import {En1} from './environment/en1'

// 游戏状态枚举
enum State{Start=0,Game=1,Lose=2,Cutscene=3}

class App {
private _scene:Scene;
private _canvas:HTMLCanvasElement;
private _engine:Engine;

private _state:number=0;

private _transition:boolean=false

constructor() {
    
    this._canvas=this._createCanvas()
    this._engine = new Engine(this._canvas, true);
    this._scene = new Scene(this._engine);
    
    window.addEventListener("keydown", (ev) => {
        // Shift+Ctrl+Alt+I
        if (ev.shiftKey && ev.ctrlKey && ev.altKey && ev.keyCode === 73) {
            if (this._scene.debugLayer.isVisible()) {
                this._scene.debugLayer.hide();
            } else {
                this._scene.debugLayer.show();
            }
        }
    });

    this._main()
}
private _createCanvas():HTMLCanvasElement{
    document.documentElement.style['overflow']='hidden'
    document.documentElement.style.overflow='hidden'
    document.documentElement.style.width='100%'
    document.documentElement.style.height='100%'
    document.documentElement.style.margin='0'
    document.documentElement.style.padding='0'
    document.body.style.overflow='hidden'
    document.body.style.width='100%'
    document.body.style.height='100%'
    document.body.style.margin='0'
    document.body.style.padding='0'

    this._canvas=document.createElement('canvas')
    this._canvas.style.width="100%"
    this._canvas.style.height="100%"
    this._canvas.id="gameCanvas"
    document.body.appendChild(this._canvas)
    return this._canvas
}

private async _main():Promise<void>{
    await this._gotoStart()

    this._engine.runRenderLoop(()=>{
        switch(this._state){
            case State.Start:
                this._scene.render()
            case State.Cutscene:
                this._scene.render()
                case State.Game:
                    //if 240seconds/ 4mins have have passed, go to the lose state
                    // if (this._ui.time >= 240 && !this._player.win) {
                    //     this._goToLose();
                    //     this._ui.stopTimer();
                    // }
                    // if (this._ui.quit) {
                    //     this._goToStart();
                    //     this._ui.quit = false;
                    // }
                    this._scene.render();
                    break;
                case State.Lose:
                    this._scene.render();
                    break;
                default: break;

        }
    })
}

private async _gotoStart(){
    // 登陆界面
    this._scene.detachControl();
    let scene = new Scene(this._engine);

    scene.clearColor = new Color4(0, 0, 0, 1);
    let camera = new FreeCamera("camera1", new Vector3(0, 0, 0), scene);
    camera.setTarget(Vector3.Zero()); 

    const start=new Sound('startSong','./source/sounds/copycat(revised).mp3',scene,function(){},{
        volume:0.25,
        loop:true,
        autoplay:true
    })
    const sfx=new Sound('select','./source/sounds/vgmenuselect.wav',scene,function(){})

    // GUI

    const guiMenu = AdvancedDynamicTexture.CreateFullscreenUI("UI");
    guiMenu.idealHeight = 720;

    // backgroundImage 
    const imageRect=new Rectangle('titleContainer')
    imageRect.width=0.8
    imageRect.thickness=0
    guiMenu.addControl(imageRect)

    const startbg=new Image('startbg','../source/sprites/start.jpeg')
    imageRect.addControl(startbg)

    const title = new TextBlock("title", "SUMMER'S FESTIVAL");
    title.resizeToFit = true;
    title.fontFamily = "Ceviche One";
    title.fontSize = "64px";
    title.color = "white";
    title.resizeToFit = true;
    title.top = "14px";
    title.width = 0.8;
    title.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
    imageRect.addControl(title);

    const startBtn = Button.CreateSimpleButton("start", "PLAY");
    startBtn.fontFamily = "Viga";
    startBtn.width = 0.2
    startBtn.height = "40px";
    startBtn.color = "white";
    startBtn.top = "-14px";
    startBtn.thickness = 0;
    startBtn.verticalAlignment = Control.VERTICAL_ALIGNMENT_BOTTOM;
    imageRect.addControl(startBtn);


    Effect.RegisterShader("fade",
        "precision highp float;" +
        "varying vec2 vUV;" +
        "uniform sampler2D textureSampler; " +
        "uniform float fadeLevel; " +
        "void main(void){" +
        "vec4 baseColor = texture2D(textureSampler, vUV) * fadeLevel;" +
        "baseColor.a = 1.0;" +
        "gl_FragColor = baseColor;" +
        "}");

    let fadeLevel = 1.0;
    this._transition = false;
    scene.registerBeforeRender(() => {
        if (this._transition) {
            fadeLevel -= .05;
            if(fadeLevel <= 0){
                this._gotoCutScene();
                this._transition = false;
            }
        }
    })

    startBtn.onPointerClickObservable.add(()=>{
        const postProcess = new PostProcess("Fade", "fade", ["fadeLevel"], null, 1.0, camera);
        postProcess.onApply=(effect)=>{
            effect.setFloat("fadeLevel", fadeLevel);
        }
        this._transition=true

        sfx.play()
        scene.detachControl()
    })

    await scene.whenReadyAsync()
    this._engine.hideLoadingUI()
    this._scene.dispose()
    // 这里一开始错了
    this._scene=scene
    this._state=State.Start
}

private async _gotoCutScene(){
    // 主要是展示过场动画
    // this._engine.displayLoadingUI();
    this._scene.detachControl();

    let cutScene = new Scene(this._engine);

    let camera = new FreeCamera("camera1", new Vector3(0, 0, 0), cutScene);
    camera.setTarget(Vector3.Zero());
    cutScene.clearColor = new Color4(0, 0, 0, 1);
    
    const cutSceneUI = AdvancedDynamicTexture.CreateFullscreenUI("cutscene");
    let transition = 0;
    let canplay = false;
    let finished_anim = false;
    let anims_loaded = 0;
    let animTimer:any;
    let anim2Timer:any;
    let anim = 1;

    const beginning_anim=new Image('sparkLife','../source/sprites/beginning_anim.png')
    beginning_anim.stretch = Image.STRETCH_UNIFORM;
    beginning_anim.cellId = 0;
    beginning_anim.cellHeight = 480;
    beginning_anim.cellWidth = 480;
    beginning_anim.sourceWidth = 480;
    beginning_anim.sourceHeight = 480;
    cutSceneUI.addControl(beginning_anim);
    beginning_anim.onImageLoadedObservable.add(() => {
        anims_loaded++;
        console.log(anims_loaded)
    })

    const working_anim = new Image("sparkLife", "../source/sprites/working_anim.png");
    working_anim.stretch = Image.STRETCH_UNIFORM;
    working_anim.cellId = 0;
    working_anim.cellHeight = 480;
    working_anim.cellWidth = 480;
    working_anim.sourceWidth = 480;
    working_anim.sourceHeight = 480;
    working_anim.isVisible = false;
    cutSceneUI.addControl(working_anim);
    working_anim.onImageLoadedObservable.add(() => {
        anims_loaded++;
    })
    const dropoff_anim = new Image("sparkLife", "../source/sprites/dropoff_anim.png");
    dropoff_anim.stretch = Image.STRETCH_UNIFORM;
    dropoff_anim.cellId = 0;
    dropoff_anim.cellHeight = 480;
    dropoff_anim.cellWidth = 480;
    dropoff_anim.sourceWidth = 480;
    dropoff_anim.sourceHeight = 480;
    dropoff_anim.isVisible = false;
    cutSceneUI.addControl(dropoff_anim);
    dropoff_anim.onImageLoadedObservable.add(() => {
        anims_loaded++;
    })
    const leaving_anim = new Image("sparkLife", "../source/sprites/leaving_anim.png");
    leaving_anim.stretch = Image.STRETCH_UNIFORM;
    leaving_anim.cellId = 0;
    leaving_anim.cellHeight = 480;
    leaving_anim.cellWidth = 480;
    leaving_anim.sourceWidth = 480;
    leaving_anim.sourceHeight = 480;
    leaving_anim.isVisible = false;
    cutSceneUI.addControl(leaving_anim);
    leaving_anim.onImageLoadedObservable.add(() => {
        anims_loaded++;
    })
    const watermelon_anim = new Image("sparkLife", "../source/sprites/watermelon_anim.png");
    watermelon_anim.stretch = Image.STRETCH_UNIFORM;
    watermelon_anim.cellId = 0;
    watermelon_anim.cellHeight = 480;
    watermelon_anim.cellWidth = 480;
    watermelon_anim.sourceWidth = 480;
    watermelon_anim.sourceHeight = 480;
    watermelon_anim.isVisible = false;
    cutSceneUI.addControl(watermelon_anim);
    watermelon_anim.onImageLoadedObservable.add(() => {
        anims_loaded++;
    })
    const reading_anim = new Image("sparkLife", "../source/sprites/reading_anim.png");
    reading_anim.stretch = Image.STRETCH_UNIFORM;
    reading_anim.cellId = 0;
    reading_anim.cellHeight = 480;
    reading_anim.cellWidth = 480;
    reading_anim.sourceWidth = 480;
    reading_anim.sourceHeight = 480;
    reading_anim.isVisible = false;
    cutSceneUI.addControl(reading_anim);
    reading_anim.onImageLoadedObservable.add(() => {
        anims_loaded++;
    })

    //Dialogue animations
    const dialogueBg = new Image("sparkLife", "../source/sprites/bg_anim_text_dialogue.png");
    dialogueBg.stretch = Image.STRETCH_UNIFORM;
    dialogueBg.cellId = 0;
    dialogueBg.cellHeight = 480;
    dialogueBg.cellWidth = 480;
    dialogueBg.sourceWidth = 480;
    dialogueBg.sourceHeight = 480;
    dialogueBg.horizontalAlignment = 0;
    dialogueBg.verticalAlignment = 0;
    dialogueBg.isVisible = false;
    cutSceneUI.addControl(dialogueBg);
    dialogueBg.onImageLoadedObservable.add(() => {
        anims_loaded++;
    })

    const dialogue = new Image("sparkLife", "../source/sprites/text_dialogue.png");
    dialogue.stretch = Image.STRETCH_UNIFORM;
    dialogue.cellId = 0;
    dialogue.cellHeight = 480;
    dialogue.cellWidth = 480;
    dialogue.sourceWidth = 480;
    dialogue.sourceHeight = 480;
    dialogue.horizontalAlignment = 0;
    dialogue.verticalAlignment = 0;
    dialogue.isVisible = false;
    cutSceneUI.addControl(dialogue);
    dialogue.onImageLoadedObservable.add(() => {
        anims_loaded++;
    })

    // 加载了全部的过场动画
    let dialogueTimer = setInterval(() => {
        if(finished_anim && dialogueBg.cellId < 3){
            dialogueBg.cellId++;
        } else {
            dialogueBg.cellId = 0;
        }
    }, 250);
    // 对话的标志位


    const skipBtn = Button.CreateSimpleButton("skip", "SKIP");
    skipBtn.fontFamily = "Viga";
    skipBtn.width = "45px";
    skipBtn.left = "-14px";
    skipBtn.height = "40px";
    skipBtn.color = "white";
    skipBtn.top = "14px";
    skipBtn.thickness = 0;
    skipBtn.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
    skipBtn.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_RIGHT;
    cutSceneUI.addControl(skipBtn);

    skipBtn.onPointerDownObservable.add(()=> {
        cutScene.detachControl();
        clearInterval(animTimer);
        clearInterval(anim2Timer);
        clearInterval(dialogueTimer);
        this._engine.displayLoadingUI();
        canplay = true;
    });

    // 跳过剧情动画的操作

    const next = Button.CreateImageOnlyButton("next", "../source/sprites/arrowBtn.png");
    next.rotation = Math.PI / 2;
    next.thickness = 0;
    next.verticalAlignment = Control.VERTICAL_ALIGNMENT_BOTTOM;
    next.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_RIGHT;
    next.width = "64px";
    next.height = "64px";
    next.top = "-3%";
    next.left = "-12%";
    next.isVisible = false;
    cutSceneUI.addControl(next);

    next.onPointerUpObservable.add(() => {
        if (transition == 8) { 
            cutScene.detachControl();
            this._engine.displayLoadingUI(); 
            transition = 0;
            canplay = true;
        } else if(transition < 8){
            transition++;
            dialogue.cellId++;
        }
    })
    // 下一步操作
    
    // 自动处理动画的逻辑
    cutScene.onBeforeRenderObservable.add(()=>{
        if(anims_loaded==8){
            this._engine.hideLoadingUI()
            anims_loaded=0;

            animTimer=setInterval(()=>{
                switch(anim) {
                    case 1:
                        if(beginning_anim.cellId == 9){ //each animation could have a different number of frames
                            anim++;
                            beginning_anim.isVisible = false; // current animation hidden
                            working_anim.isVisible = true; // show the next animation
                        } else {
                            beginning_anim.cellId++;
                        }
                        break;
                    case 2:
                        if(working_anim.cellId == 11){
                            anim++;
                            working_anim.isVisible = false;
                            dropoff_anim.isVisible = true;
                        } else {
                            working_anim.cellId++;
                        }
                        break;
                    case 3:
                        if(dropoff_anim.cellId == 11){
                            anim++;
                            dropoff_anim.isVisible = false;
                            leaving_anim.isVisible = true;
                        } else {
                            dropoff_anim.cellId++;
                        }
                        break;
                    case 4:
                        if(leaving_anim.cellId == 9){
                            anim++;
                            leaving_anim.isVisible = false;
                            watermelon_anim.isVisible = true;
                        } else {
                            leaving_anim.cellId++;
                        }
                        break;
                    default:
                        break;
                }   
            },250)

            anim2Timer=setInterval(()=>{
                switch(anim) {
                    case 5:
                        if(watermelon_anim.cellId == 8){
                            anim++;
                            watermelon_anim.isVisible = false;
                            reading_anim.isVisible = true;
                        } else {
                            watermelon_anim.cellId++;
                        }
                        break;
                    case 6:
                        if(reading_anim.cellId == 11){
                            reading_anim.isVisible = false;
                            finished_anim = true;
                            dialogueBg.isVisible = true;
                            dialogue.isVisible = true;
                            next.isVisible = true;
                        } else {
                            reading_anim.cellId++;
                        }
                        break;
                }
            },750)


        }

        if(finishedLoading&&canplay){
            canplay=true
            this._goToGame()
        }
    })



    // 最后的处理
    await cutScene.whenReadyAsync();
    this._scene.dispose();
    this._state = State.Cutscene;
    this._scene = cutScene;

    var finishedLoading=false
    await this._setUpGame().then((res)=>{
        finishedLoading=true
    })
}

private async _goToLose():Promise<void>{
    this._engine.displayLoadingUI();
    //--SCENE SETUP--
    this._scene.detachControl();
    let scene = new Scene(this._engine);
    scene.clearColor = new Color4(0, 0, 0, 1);
    let camera = new FreeCamera("camera1", new Vector3(0, 0, 0), scene);
    camera.setTarget(Vector3.Zero());
    //--GUI--
    const guiMenu = AdvancedDynamicTexture.CreateFullscreenUI("UI");
    const mainBtn = Button.CreateSimpleButton("mainmenu", "MAIN MENU");
    mainBtn.width = 0.2;
    mainBtn.height = "40px";
    mainBtn.color = "white";
    guiMenu.addControl(mainBtn);
    mainBtn.onPointerUpObservable.add(() => {
        this._gotoStart();
    });
    //--SCENE FINISHED LOADING--
    await scene.whenReadyAsync();
    this._engine.hideLoadingUI(); 
    this._scene.dispose();
    this._scene = scene;
    this._state = State.Lose;
}
private async _goToGame():Promise<void>{
    
}

private async _setUpGame(){
    let scene=new Scene(this._engine)
    const environment = new En1(scene);
    // this._environment = environment; //class variable for App
    await environment.load();
}

}
new App();

相关文章

网友评论

      本文标题:app.ts

      本文链接:https://www.haomeiwen.com/subject/joqtxltx.html