Updated soccer menu....moved soccer specific code to soccer.
This commit is contained in:
parent
18adccc77e
commit
7cfe2fe257
@ -1,4 +1,4 @@
|
|||||||
import {AbstractMesh, Observable, TransformNode, Vector3} from "@babylonjs/core";
|
import {AbstractMesh, Observable, TransformNode, Vector3, WebXRInputSource} from "@babylonjs/core";
|
||||||
|
|
||||||
export type ControllerEvent = {
|
export type ControllerEvent = {
|
||||||
type: ControllerEventType,
|
type: ControllerEventType,
|
||||||
@ -7,6 +7,7 @@ export type ControllerEvent = {
|
|||||||
endPosition?: Vector3,
|
endPosition?: Vector3,
|
||||||
duration?: number,
|
duration?: number,
|
||||||
gripId?: string;
|
gripId?: string;
|
||||||
|
controller?: WebXRInputSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ControllerEventType {
|
export enum ControllerEventType {
|
||||||
|
|||||||
@ -27,6 +27,7 @@ export class Left extends Base {
|
|||||||
});
|
});
|
||||||
this.initXButton(init.components['x-button']);
|
this.initXButton(init.components['x-button']);
|
||||||
this.initYButton(init.components['y-button']);
|
this.initYButton(init.components['y-button']);
|
||||||
|
this.initTrigger(init.components['xr-standard-trigger']);
|
||||||
init.components['xr-standard-thumbstick'].onButtonStateChangedObservable.add((value) => {
|
init.components['xr-standard-thumbstick'].onButtonStateChangedObservable.add((value) => {
|
||||||
if (value.pressed) {
|
if (value.pressed) {
|
||||||
log.trace('Left', 'thumbstick changed');
|
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) {
|
private initXButton(xbutton: WebXRControllerComponent) {
|
||||||
if (xbutton) {
|
if (xbutton) {
|
||||||
xbutton.onButtonStateChangedObservable.add((button) => {
|
xbutton.onButtonStateChangedObservable.add((button) => {
|
||||||
|
|||||||
@ -22,6 +22,7 @@ export class Right extends Base {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private startTime: number = null;
|
private startTime: number = null;
|
||||||
private endPosition: Vector3 = null;
|
private endPosition: Vector3 = null;
|
||||||
|
|
||||||
@ -46,32 +47,11 @@ export class Right extends Base {
|
|||||||
trigger
|
trigger
|
||||||
.onButtonStateChangedObservable
|
.onButtonStateChangedObservable
|
||||||
.add((button) => {
|
.add((button) => {
|
||||||
if (button.pressed) {
|
|
||||||
this.controllers.controllerObserver.notifyObservers({
|
this.controllers.controllerObserver.notifyObservers({
|
||||||
type: ControllerEventType.TRIGGER,
|
type: ControllerEventType.TRIGGER,
|
||||||
value: button.value
|
value: button.value,
|
||||||
|
controller: this.controller
|
||||||
});
|
});
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}, -1, false, this);
|
}, -1, false, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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 {Right} from "./right";
|
||||||
import {Left} from "./left";
|
import {Left} from "./left";
|
||||||
import {EditMenu} from "../menus/editMenu";
|
import {EditMenu} from "../menus/editMenu";
|
||||||
@ -124,45 +124,16 @@ export class Rigplatform {
|
|||||||
case ControllerEventType.MENU:
|
case ControllerEventType.MENU:
|
||||||
this.bMenu.toggle();
|
this.bMenu.toggle();
|
||||||
break;
|
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:
|
case ControllerEventType.MOTION:
|
||||||
this.logger.debug(JSON.stringify(event));
|
this.logger.debug(JSON.stringify(event));
|
||||||
this.buildKickLine(event.startPosition, event.endPosition);
|
|
||||||
break;
|
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() {
|
private initializeControllers() {
|
||||||
this.xr.input.onControllerAddedObservable.add((source) => {
|
this.xr.input.onControllerAddedObservable.add((source) => {
|
||||||
|
|||||||
@ -16,7 +16,7 @@ export class Ball {
|
|||||||
private readonly scene: Scene;
|
private readonly scene: Scene;
|
||||||
private transformNode: TransformNode;
|
private transformNode: TransformNode;
|
||||||
private mesh: AbstractMesh;
|
private mesh: AbstractMesh;
|
||||||
private position: Vector3 = new Vector3(0, .5, 0);
|
_position: Vector3 = new Vector3(0, .5, 0);
|
||||||
private parent: AbstractMesh;
|
private parent: AbstractMesh;
|
||||||
private controllers: Controllers;
|
private controllers: Controllers;
|
||||||
private physicsAggregate: PhysicsAggregate;
|
private physicsAggregate: PhysicsAggregate;
|
||||||
@ -39,6 +39,10 @@ export class Ball {
|
|||||||
this.physicsAggregate.body.applyImpulse(direction.scale(force), Vector3.Zero());
|
this.physicsAggregate.body.applyImpulse(direction.scale(force), Vector3.Zero());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get position(): Vector3 {
|
||||||
|
return this.physicsAggregate.transformNode.absolutePosition;
|
||||||
|
}
|
||||||
|
|
||||||
private buildBall() {
|
private buildBall() {
|
||||||
SceneLoader.ImportMesh(null, "/assets/models/", "ball.gltf", this.scene,
|
SceneLoader.ImportMesh(null, "/assets/models/", "ball.gltf", this.scene,
|
||||||
(meshes, particleSystems, skeletons, animationGroups) => {
|
(meshes, particleSystems, skeletons, animationGroups) => {
|
||||||
@ -47,7 +51,7 @@ export class Ball {
|
|||||||
this.parent = MeshBuilder.CreateSphere("ballParent", {diameter: .17}, this.scene);
|
this.parent = MeshBuilder.CreateSphere("ballParent", {diameter: .17}, this.scene);
|
||||||
|
|
||||||
this.parent.isVisible = false;
|
this.parent.isVisible = false;
|
||||||
this.parent.position = this.position;
|
this.parent.position = this._position;
|
||||||
|
|
||||||
this.scene.onBeforeRenderObservable.add(() => {
|
this.scene.onBeforeRenderObservable.add(() => {
|
||||||
if (!this.physicsAggregate &&
|
if (!this.physicsAggregate &&
|
||||||
|
|||||||
@ -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 {AbstractMenu} from "../menus/abstractMenu";
|
||||||
import {ControllerEventType, Controllers} from "../controllers/controllers";
|
import {ControllerEvent, ControllerEventType, Controllers} from "../controllers/controllers";
|
||||||
import {GUI3DManager, PlanePanel} from "@babylonjs/gui";
|
import {GUI3DManager, PlanePanel} from "@babylonjs/gui";
|
||||||
import log, {Logger} from "loglevel";
|
import log, {Logger} from "loglevel";
|
||||||
import {Field} from "./field";
|
import {Field} from "./field";
|
||||||
|
import {getFrontPosition} from "../util/functions/getFrontPosition";
|
||||||
|
|
||||||
enum SoccerMenuState {
|
enum SoccerMenuState {
|
||||||
PLAY,
|
PLAY,
|
||||||
@ -18,27 +19,112 @@ export class SoccerMenu extends AbstractMenu {
|
|||||||
private state: SoccerMenuState = SoccerMenuState.NONE;
|
private state: SoccerMenuState = SoccerMenuState.NONE;
|
||||||
private readonly field: Field;
|
private readonly field: Field;
|
||||||
private logger: Logger = log.getLogger('SoccerMenu')
|
private logger: Logger = log.getLogger('SoccerMenu')
|
||||||
|
private startTime: number;
|
||||||
|
private startPosition: Vector3;
|
||||||
|
|
||||||
constructor(scene: Scene, xr: WebXRDefaultExperience, controllers: Controllers) {
|
constructor(scene: Scene, xr: WebXRDefaultExperience, controllers: Controllers) {
|
||||||
super(scene, xr, controllers);
|
super(scene, xr, controllers);
|
||||||
this.field = new Field(this.scene);
|
this.field = new Field(this.scene);
|
||||||
this.manager = new GUI3DManager(this.scene);
|
this.manager = new GUI3DManager(this.scene);
|
||||||
|
|
||||||
this.controllers.controllerObserver.add((event) => {
|
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) {
|
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:
|
case ControllerEventType.MOTION:
|
||||||
this.field.ball.kick(event.startPosition.clone().subtract(event.endPosition).normalize(), event.duration / 100);
|
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;
|
break;
|
||||||
case ControllerEventType.GAZEPOINT:
|
case ControllerEventType.GAZEPOINT:
|
||||||
if (event.endPosition) {
|
if (event.endPosition) {
|
||||||
this.field.gazePoint = event.endPosition.clone();
|
this.field.gazePoint = event.endPosition.clone();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
private buildKickLine(direction: Vector3, force: number) {
|
||||||
this.buildMenu();
|
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) {
|
makeButton(name: string, id: string) {
|
||||||
@ -56,7 +142,9 @@ export class SoccerMenu extends AbstractMenu {
|
|||||||
panel.addControl(this.makeButton("Train", "Train"));
|
panel.addControl(this.makeButton("Train", "Train"));
|
||||||
panel.addControl(this.makeButton("Modify", "modify"));
|
panel.addControl(this.makeButton("Modify", "modify"));
|
||||||
this.manager.rootContainer.children[0].node.position.y = .2;
|
this.manager.rootContainer.children[0].node.position.y = .2;
|
||||||
|
this.manager.controlScaling = .2;
|
||||||
this.createHandle(this.manager.rootContainer.children[0].node);
|
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) {
|
private handleClick(_info, state) {
|
||||||
|
|||||||
@ -29,7 +29,6 @@ export class Team {
|
|||||||
this.playerFactory = new PlayerFactory(this.scene);
|
this.playerFactory = new PlayerFactory(this.scene);
|
||||||
this.playerFactory.onReadyObservable.add(() => {
|
this.playerFactory.onReadyObservable.add(() => {
|
||||||
this.buildTeam();
|
this.buildTeam();
|
||||||
this.players[5].runTo(new Vector2(3, -3 * this.goalSide));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user