Updated soccer menu....moved soccer specific code to soccer.

This commit is contained in:
Michael Mainguy 2023-09-19 15:25:02 -05:00
parent 18adccc77e
commit 7cfe2fe257
7 changed files with 136 additions and 77 deletions

View File

@ -1,4 +1,4 @@
import {AbstractMesh, Observable, TransformNode, Vector3} from "@babylonjs/core";
import {AbstractMesh, Observable, TransformNode, Vector3, WebXRInputSource} from "@babylonjs/core";
export type ControllerEvent = {
type: ControllerEventType,
@ -7,6 +7,7 @@ export type ControllerEvent = {
endPosition?: Vector3,
duration?: number,
gripId?: string;
controller?: WebXRInputSource;
}
export enum ControllerEventType {

View File

@ -27,6 +27,7 @@ export class Left extends Base {
});
this.initXButton(init.components['x-button']);
this.initYButton(init.components['y-button']);
this.initTrigger(init.components['xr-standard-trigger']);
init.components['xr-standard-thumbstick'].onButtonStateChangedObservable.add((value) => {
if (value.pressed) {
log.trace('Left', 'thumbstick changed');
@ -40,6 +41,21 @@ export class Left extends Base {
});
}
private initTrigger(trigger: WebXRControllerComponent) {
if (trigger) {
trigger
.onButtonStateChangedObservable
.add((button) => {
this.controllers.controllerObserver.notifyObservers({
type: ControllerEventType.TRIGGER,
value: button.value,
controller: this.controller
});
}, -1, false, this);
}
}
private initXButton(xbutton: WebXRControllerComponent) {
if (xbutton) {
xbutton.onButtonStateChangedObservable.add((button) => {

View File

@ -22,6 +22,7 @@ export class Right extends Base {
});
}
}
private startTime: number = null;
private endPosition: Vector3 = null;
@ -46,32 +47,11 @@ export class Right extends Base {
trigger
.onButtonStateChangedObservable
.add((button) => {
if (button.pressed) {
this.controllers.controllerObserver.notifyObservers({
type: ControllerEventType.TRIGGER,
value: button.value
});
if (!this.startTime) {
this.startTime = new Date().getTime();
this.startPosition = this.controller.pointer.absolutePosition.clone();
}
} else {
this.endPosition = this.controller.pointer.absolutePosition.clone();
if (this.startTime && this.startPosition) {
const duration = new Date().getTime() - this.startTime;
this.controllers.controllerObserver.notifyObservers({
type: ControllerEventType.MOTION,
startPosition: this.startPosition,
endPosition: this.endPosition,
duration: duration
});
this.startTime = null;
this.startPosition = null;
}
}
this.controllers.controllerObserver.notifyObservers({
type: ControllerEventType.TRIGGER,
value: button.value,
controller: this.controller
});
}, -1, false, this);
}
}

View File

@ -1,4 +1,4 @@
import {Angle, Color3, Mesh, MeshBuilder, Quaternion, Scene, Vector3, WebXRDefaultExperience} from "@babylonjs/core";
import {Angle, Mesh, Quaternion, Scene, Vector3, WebXRDefaultExperience} from "@babylonjs/core";
import {Right} from "./right";
import {Left} from "./left";
import {EditMenu} from "../menus/editMenu";
@ -124,45 +124,16 @@ export class Rigplatform {
case ControllerEventType.MENU:
this.bMenu.toggle();
break;
case ControllerEventType.TRIGGER:
const worldRay = this.scene.activeCamera.getForwardRay();
worldRay.origin = this.scene.activeCamera.globalPosition;
const pickInfo = this.scene.pickWithRay(worldRay, null);
if (pickInfo?.hit) {
const circle = MeshBuilder.CreateSphere("circle", {diameter: .02}, this.scene);
circle.position = pickInfo.pickedPoint;
setTimeout(() => {
circle.dispose();
}, 500);
if (pickInfo?.pickedMesh?.name == 'Football Ball.001') {
this.controllers.controllerObserver.notifyObservers({
type: ControllerEventType.GAZEPOINT,
endPosition: pickInfo.pickedPoint,
startPosition: this.xr.baseExperience.camera.globalPosition
})
}
}
break;
case ControllerEventType.MOTION:
this.logger.debug(JSON.stringify(event));
this.buildKickLine(event.startPosition, event.endPosition);
break;
}
});
}
}
private buildKickLine(start: Vector3, end: Vector3) {
if (end.y < start.y) {
const line = MeshBuilder.CreateLines("kickLine", {points: [start, end]}, this.scene);
line.color = new Color3(1, 0, 0);
line.isPickable = false;
setTimeout(() => {
line.dispose();
}, 2000);
}
}
private initializeControllers() {
this.xr.input.onControllerAddedObservable.add((source) => {

View File

@ -16,7 +16,7 @@ export class Ball {
private readonly scene: Scene;
private transformNode: TransformNode;
private mesh: AbstractMesh;
private position: Vector3 = new Vector3(0, .5, 0);
_position: Vector3 = new Vector3(0, .5, 0);
private parent: AbstractMesh;
private controllers: Controllers;
private physicsAggregate: PhysicsAggregate;
@ -39,6 +39,10 @@ export class Ball {
this.physicsAggregate.body.applyImpulse(direction.scale(force), Vector3.Zero());
}
public get position(): Vector3 {
return this.physicsAggregate.transformNode.absolutePosition;
}
private buildBall() {
SceneLoader.ImportMesh(null, "/assets/models/", "ball.gltf", this.scene,
(meshes, particleSystems, skeletons, animationGroups) => {
@ -47,7 +51,7 @@ export class Ball {
this.parent = MeshBuilder.CreateSphere("ballParent", {diameter: .17}, this.scene);
this.parent.isVisible = false;
this.parent.position = this.position;
this.parent.position = this._position;
this.scene.onBeforeRenderObservable.add(() => {
if (!this.physicsAggregate &&

View File

@ -1,9 +1,10 @@
import {Scene, WebXRDefaultExperience} from "@babylonjs/core";
import {Color3, MeshBuilder, Quaternion, Scene, Vector3, WebXRDefaultExperience} from "@babylonjs/core";
import {AbstractMenu} from "../menus/abstractMenu";
import {ControllerEventType, Controllers} from "../controllers/controllers";
import {ControllerEvent, ControllerEventType, Controllers} from "../controllers/controllers";
import {GUI3DManager, PlanePanel} from "@babylonjs/gui";
import log, {Logger} from "loglevel";
import {Field} from "./field";
import {getFrontPosition} from "../util/functions/getFrontPosition";
enum SoccerMenuState {
PLAY,
@ -18,29 +19,114 @@ export class SoccerMenu extends AbstractMenu {
private state: SoccerMenuState = SoccerMenuState.NONE;
private readonly field: Field;
private logger: Logger = log.getLogger('SoccerMenu')
private startTime: number;
private startPosition: Vector3;
constructor(scene: Scene, xr: WebXRDefaultExperience, controllers: Controllers) {
super(scene, xr, controllers);
this.field = new Field(this.scene);
this.manager = new GUI3DManager(this.scene);
this.controllers.controllerObserver.add((event) => {
switch (event.type) {
case ControllerEventType.MOTION:
this.field.ball.kick(event.startPosition.clone().subtract(event.endPosition).normalize(), event.duration / 100);
break;
case ControllerEventType.GAZEPOINT:
if (event.endPosition) {
this.field.gazePoint = event.endPosition.clone();
}
break;
}
});
this.controllers.controllerObserver.add(this.controllerEventHandler, -1, false, this);
this.buildMenu();
}
private controllerEventHandler(event: ControllerEvent) {
switch (this.state) {
case SoccerMenuState.PLAY:
this.playControllerEventHandler(event);
break;
case SoccerMenuState.PLAN:
break;
case SoccerMenuState.TRAIN:
break;
case SoccerMenuState.NONE:
break
}
}
private playControllerEventHandler(event: ControllerEvent) {
switch (event.type) {
case ControllerEventType.TRIGGER:
if (event.value > .8) {
if (!this.startTime) {
this.startTime = new Date().getTime();
this.startPosition = event.controller.pointer.position.clone();
}
} else {
if (this.startTime) {
const endPosition = event.controller.pointer.position.clone();
if (this.startTime && this.startPosition) {
const duration = new Date().getTime() - this.startTime;
this.controllers.controllerObserver.notifyObservers({
type: ControllerEventType.MOTION,
startPosition: this.startPosition,
endPosition: endPosition,
duration: duration
});
this.startTime = null;
this.startPosition = null;
}
}
}
const worldRay = this.scene.activeCamera.getForwardRay();
worldRay.origin = this.scene.activeCamera.globalPosition;
const pickInfo = this.scene.pickWithRay(worldRay, null);
if (pickInfo?.hit) {
const circle = MeshBuilder.CreateSphere("circle", {diameter: .04}, this.scene);
circle.position = pickInfo.pickedPoint;
setTimeout(() => {
circle.dispose();
}, 1500);
if (pickInfo?.pickedMesh?.name == 'Football Ball.001') {
this.controllers.controllerObserver.notifyObservers({
type: ControllerEventType.GAZEPOINT,
endPosition: pickInfo.pickedPoint,
startPosition: this.xr.baseExperience.camera.globalPosition
})
}
}
const mesh = this.scene.getPointerOverMesh();
if (mesh) {
const meta = mesh?.parent?.parent?.parent
if (meta) {
console.log(meta.id);
}
}
break;
case ControllerEventType.MOTION:
const start = event.startPosition.clone();
const direction = start.subtract(event.endPosition);
const force = direction.length() * 10;
const dir = direction.normalize();
const e = this.xr.baseExperience.camera.absoluteRotation.toEulerAngles();
direction.applyRotationQuaternionInPlace(Quaternion.FromEulerAngles(0, e.y, 0));
this.buildKickLine(dir, force);
this.field.ball.kick(dir, force);
break;
case ControllerEventType.GAZEPOINT:
if (event.endPosition) {
this.field.gazePoint = event.endPosition.clone();
}
break;
}
}
private buildKickLine(direction: Vector3, force: number) {
const start = this.field.ball.position.clone();
const line = MeshBuilder.CreateLines("kickLine", {points: [start, start.add(direction.scale(force))]}, this.scene);
line.color = new Color3(1, 1, .5);
line.isPickable = false;
setTimeout(() => {
line.dispose();
}, 2000);
}
makeButton(name: string, id: string) {
const button = super.makeButton(name, id);
button.onPointerClickObservable.add(this.handleClick, -1, false, this);
@ -56,7 +142,9 @@ export class SoccerMenu extends AbstractMenu {
panel.addControl(this.makeButton("Train", "Train"));
panel.addControl(this.makeButton("Modify", "modify"));
this.manager.rootContainer.children[0].node.position.y = .2;
this.manager.controlScaling = .2;
this.createHandle(this.manager.rootContainer.children[0].node);
this.handle.mesh.position = getFrontPosition(3, this.scene).add(new Vector3(0, .5, 0));
}
private handleClick(_info, state) {

View File

@ -29,7 +29,6 @@ export class Team {
this.playerFactory = new PlayerFactory(this.scene);
this.playerFactory.onReadyObservable.add(() => {
this.buildTeam();
this.players[5].runTo(new Vector2(3, -3 * this.goalSide));
});
}