Skip to content

Commit

Permalink
Incorporate main menu #33. snippet #16XY6Z#5
Browse files Browse the repository at this point in the history
  • Loading branch information
jelster committed Mar 11, 2021
1 parent 7a16085 commit 9a3a018
Showing 1 changed file with 130 additions and 47 deletions.
177 changes: 130 additions & 47 deletions src/mainMenuScene.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,85 +3,168 @@ import { ArcRotateCamera } from "@babylonjs/core/Cameras/arcRotateCamera";
import { Color4 } from "@babylonjs/core/Maths/math";
import { StandardMaterial } from "@babylonjs/core/Materials/standardMaterial";
import { Texture } from "@babylonjs/core/Materials/Textures/texture"
import { Scene, Vector3, Sound, HemisphericLight } from "@babylonjs/core";
import { AdvancedDynamicTexture, Rectangle, Image, Button, StackPanel, Control, TextBlock } from "@babylonjs/gui";
import { Scene, Vector3, Scalar, Observable, Sound, HemisphericLight } from "@babylonjs/core";
import { AdvancedDynamicTexture, Rectangle, Image, Button, Control, TextBlock, Grid, TextWrapping } from "@babylonjs/gui";
import { StarfieldProceduralTexture } from "@babylonjs/procedural-textures/starfield/starfieldProceduralTexture";
import menuBackground from "../assets/menuBackground.png";
import titleMusic from "../assets/sounds/space-trucker-title-theme.m4a";
import selectionIcon from "../assets/ui-selection-icon.PNG";

class MainMenuScene {

get scene() {
return this._scene;
}
get selectedItemIndex() {
return this._selectedItemIndex || -1;
}
set selectedItemIndex(idx) {
const itemCount = this._menuGrid.rowCount;
const newIdx = Scalar.Repeat(idx, itemCount);
this._selectedItemIndex = newIdx;
this._selectedItemChanged.notifyObservers(newIdx);
}
constructor(engine) {
this._engine = engine;
let scene = this._scene = new Scene(engine);
// TODO: Use asset manager instead of directly instantiating
this._music = new Sound("titleMusic", titleMusic, scene, null, { autoplay: true, loop: true, volume: 0.4 });
scene.clearColor = new Color4(0, 0, 0, 1);

const camera = new ArcRotateCamera("menuCam", 0, 0, -30, Vector3.Zero(), scene, true);
this._setupBackgroundEnvironment();
const guiMenu = AdvancedDynamicTexture.CreateFullscreenUI("UI");
guiMenu.idealHeight = 720;
this._setupUi();
this._addMenuItems();
this._createSelectorIcon();
this._selectedItemChanged = new Observable();
this._selectedItemChanged.add((idx) => {

const menuGrid = this._menuGrid;
const selectedItem = menuGrid.getChildrenAt(idx, 1);
if (selectedItem[0].isEnabled !== true) {
this.selectedItemIndex = 1 + idx;
}
this._selectorIcon.isVisible = true;
menuGrid.removeControl(this._selectorIcon);
menuGrid.addControl(this._selectorIcon, idx);
});

scene.whenReadyAsync().then(() => this.selectedItemIndex = 0);
}

_setupBackgroundEnvironment() {
const light = new HemisphericLight("light", new Vector3(0, 0.5, 0), this._scene);
const starfieldPT = new StarfieldProceduralTexture("starfieldPT", 512, this._scene);
const starfieldMat = new StandardMaterial("starfield", this._scene);
const space = CylinderBuilder.CreateCylinder("space", { height: 100, diameterTop: 0, diameterBottom: 60 }, this._scene);
starfieldMat.diffuseTexture = starfieldPT;
starfieldMat.diffuseTexture.coordinatesMode = Texture.SKYBOX_MODE;
starfieldMat.backFaceCulling = false;
starfieldPT.beta = 0.1;
space.material = starfieldMat;
this._starfieldAnimationHandle = this._scene.registerBeforeRender(() => starfieldPT.time += this._scene.getEngine().getDeltaTime() / 1000);
}

_setupUi() {
const gui = AdvancedDynamicTexture.CreateFullscreenUI("UI");
gui.renderAtIdealSize = true;
this._guiMenu = gui;
const menuContainer = new Rectangle("menuContainer");
menuContainer.width = 0.8;
menuContainer.thickness = 0;
guiMenu.addControl(menuContainer);
menuContainer.thickness = 5;
menuContainer.cornerRadius = 13;

this._guiMenu.addControl(menuContainer);
this._menuContainer = menuContainer;

// TODO: find/make a better background image!
const menuBg = new Image("menuBg", menuBackground);
menuContainer.addControl(menuBg);

const menuPanel = new StackPanel("menuPanel");
// menuPanel.background = "rgba(150, 150, 150, 0.67)";
menuPanel.height = 0.9;
menuPanel.top = 0.05;
menuPanel.bottom = 0.05;
menuContainer.addControl(menuPanel);
const menuGrid = new Grid("menuGrid");
menuGrid.addColumnDefinition(0.33);
menuGrid.addColumnDefinition(0.33);
menuGrid.addColumnDefinition(0.33);
menuGrid.addRowDefinition(0.5);
menuGrid.addRowDefinition(0.5);
menuContainer.addControl(menuGrid);
this._menuGrid = menuGrid;

const titleText = new TextBlock("title", "Space-Truckers: The Video Game!");
const titleText = new TextBlock("title", "Space-Truckers");
titleText.resizeToFit = true;
titleText.fontSize = "56pt";
titleText.textWrapping = TextWrapping.WordWrap;
titleText.fontSize = "72pt";
titleText.color = "white";

titleText.width = 0.8;
titleText.width = 0.9;
titleText.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
titleText.paddingBottom = "28px";
menuPanel.addControl(titleText);
// buttonStyle.fontFamily = "Comic Sans Serif";


// TODO: extract this into a menu item factory method
const playButton = Button.CreateSimpleButton("btPlay", "Play");
playButton.fontSize = "36pt";
playButton.color = "white";
playButton.background = "red";
playButton.height = "80px";
playButton.width = "160px"
playButton.thickness = 4;
playButton.cornerRadius = 105;

playButton.verticalAlignment = Control.VERTICAL_ALIGNMENT_BOTTOM;
menuPanel.addControl(playButton);
titleText.paddingTop = titleText.paddingBottom = "18px";
titleText.shadowOffsetX = 3;
titleText.shadowOffsetY = 6;
titleText.shadowBlur = 2;
menuContainer.addControl(titleText);
}

_setupBackgroundEnvironment() {
const light = new HemisphericLight("light", new Vector3(0,0.5, 0), this._scene);
const starfieldPT = new StarfieldProceduralTexture("starfieldPT", 512, this._scene);
const starfieldMat = new StandardMaterial("starfield", this._scene);
const space = CylinderBuilder.CreateCylinder("space", { height: 100, diameterTop: 0, diameterBottom: 60 }, this._scene);
starfieldMat.diffuseTexture = starfieldPT;
starfieldMat.diffuseTexture.coordinatesMode = Texture.SKYBOX_MODE;
starfieldMat.backFaceCulling = false;
starfieldPT.beta = 0.1;
_addMenuItems() {

space.material = starfieldMat;
function createMenuItem(opts) {
const btn = Button.CreateSimpleButton(opts.name || "", opts.title);
btn.color = opts.color || "white";
btn.background = opts.background || "green";
btn.height = "80px";
btn.thickness = 4;
btn.cornerRadius = 80;
btn.shadowOffsetY = 12;
btn.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
btn.fontSize = "36pt";

this._starfieldAnimationHandle = this._scene.registerBeforeRender(() => starfieldPT.time += this._scene.getEngine().getDeltaTime() / 1000);
if (opts.onInvoked) {
btn.onPointerClickObservable.add((ed, es) => opts.onInvoked(ed, es));
}

return btn;
}

const pbOpts = {
name: "btPlay",
title: "Play",
background: "red",
color: "white",
onInvoked: () => console.log("Play button clicked")
};
const playButton = createMenuItem(pbOpts);
this._menuGrid.addControl(playButton, this._menuGrid.children.length, 1);

const ebOpts = {
name: "btExit",
title: "Exit",
background: "white",
color: "black",
onInvoked: () => console.log("Exit button clicked")
}
const exitButton = createMenuItem(ebOpts);
this._menuGrid.addControl(exitButton, this._menuGrid.children.length, 1);

}

_createSelectorIcon() {
const selectorIcon = new Image("selectorIcon", selectionIcon);
selectorIcon.width = "160px";
selectorIcon.height = "60px";
selectorIcon.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
selectorIcon.shadowOffsetX = 5;
selectorIcon.shadowOffsetY = 3;

selectorIcon.isVisible = false;
this._menuGrid.addControl(selectorIcon, 1, 0);
this._selectorIcon = selectorIcon;
this._selectorAnimationFrame = 0;
this._selectorIconHoverAnimation = this._scene.onBeforeRenderObservable.add(() => this._selectorIconAnimation());


}

_selectorIconAnimation() {
const animTimeSeconds = Math.PI * 2;
const dT = this._scene.getEngine().getDeltaTime() / 1000;
this._selectorAnimationFrame = Scalar.Repeat(this._selectorAnimationFrame + dT * 5, animTimeSeconds * 10);
this._selectorIcon.top = Math.sin(this._selectorAnimationFrame).toFixed(0) + "px";
}
}
export default MainMenuScene;

0 comments on commit 9a3a018

Please sign in to comment.