QuintusHegie

Members
  • Content Count

    49
  • Joined

  • Last visited

  • Days Won

    1

QuintusHegie last won the day on August 12

QuintusHegie had the most liked content!

About QuintusHegie

  • Rank
    Advanced Member

Contact Methods

  • Website URL
    https://quintushegie.com

Profile Information

  • Location
    The Netherlands
  • Interests
    BabylonJS, Model Trains

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. QuintusHegie

    Friendly competition - Retro Remake Challenge!

    Well, although I didn't arrive at a finished level, the retro competition still helped me make lots of progress and add new features to my work-in-progress game. You can play the uncompleted model train retro level (created for this challenge) here: https://quintushegie.com/gardentrains/#retrotrains2 This level (and all others) will become more exciting as my programming progress continues. Yesterday for example I added the shadows and improved lighting, which look nice. So my benefit of the challenge was that it helped me get excited about trying out new things and getting things to work. Not so much that I was able to complete a whole new mini retro game... but that wasn't my goal anyways. πŸ™‚
  2. QuintusHegie

    Screen fade/motion blur effect

    Received the book BabylonJs Essentials yesterday. Although some parts I already knew because I'm developing in BabylonJs already, no problem. There were still parts that I didn't know or didn't come about yet... so still useful. Plus the paperback book looks nice on my night cabinet. It's real 3D you know, real paper texture πŸ™‚
  3. QuintusHegie

    Quick poll

    I use https://preview.babylonjs.com/babylon.js but I'm still developing so production and testing is the same for me. πŸ™‚ When I would decide to make a copy of the test of my game for real production/go live, then I'll probably stick to the most recent version at that time (so the code doesn't break on later updates).
  4. QuintusHegie

    Pointerup observable bug ?

    FYI Playground http://www.babylonjs-playground.com/#7RH606 from https://doc.babylonjs.com/how_to/gui probably has same error. When you click the button it doesn't count (call the onPointerClickObservable).
  5. QuintusHegie

    Friendly competition - Retro Remake Challenge!

    Busy during weekdays, but still making some progress though. Thanks for the hosting offer. Could use some math help more needed though. πŸ™‚ To fix an annoying bug with the rail track layout, I'm trying to continue a Curve with a Path segment that needs to be connected *in reverse* and in 180 degrees rotation on the tangent line of the end point of the Path to connect to (e.g. "backward" instead of "forward"). Continuing tracks in forward direction with Path segments that start at Zero() no problemo, but the reverse math... aargh! How to compose the translation matrix to use on the Path segment points to prepare it for the Curve.continue? See picture in X0Z plane: Path3D A starts in Z+ ends in X+ direction Path3D B starts in ZX+ ends in Z+ direction Curve that continues A with B no problemo; finishes in X+ direction. Curve that adds B reversed as incoming to A at end point = what translation to do on B points before continuing it on A? I already translated all points of B so that the blue dot become origin. But then a rotation translation is needed on the points in order to properly align axis on reversed tangent of A's blue endpoint direction. Q
  6. QuintusHegie

    Slime Quest (mmo demo)

    Great start! Keep up the good work! When you change the collision of the slimey from box to circle, it'll probably navigate better around the wall corners. At least that is my experience with similar 2D maps where a player navigates through a maze.
  7. QuintusHegie

    Friendly competition - Retro Remake Challenge!

    Still happily working on the western train town level I showed you earlier in this post: Created some new 3D models (large steam locomotive, western wagons, lumber & oil structures, goods, some scenery) Added support for bullets and arrows (sheriff/cowboy and indians carry weapons) and weapon aiming Applied the random tiled shader to the ground texture (see other post) Been playing with inputs for the FollowCamera (see other post), but have to learn TypeScript etc. first before I can proceed and commit Lots and lots of refactoring (for the good, luckily) - most stuff is configurable via a settings file now Some railroad track computations are still a mess though... if I don't get that fixed then the level won't be playable/winnable for users. πŸ˜• Q
  8. QuintusHegie

    Search engine usage

    I use Google Custom Search https://cse.google.com/cse/ on my site (free, with ads, data shared with Google of course). There's also Bing Custom Search, which looks free up to 1000 queries per month and shows love to Microsoft. And then there's a Search box on babylonjs.com as well, for which you can find the code on github I presume. πŸ™‚
  9. Ok. Thanks for the kickstarter guide. This will take me some time for me to learn and get started with, but seems doable. Q
  10. I'll bet you'll start to love this camera when you play my game when the new camera controls are ready πŸ˜‰ Anyway, ok, something like this? FollowCameraKeyboardMoveInput: I wrote an untested example code for the Keyboard Input: /** * Keyboard input to control the 'radius' (up/down), 'rotationOffset' (left/right) and 'heightOffset' parameters of FollowCamera. * @see http://www.html5gamedevs.com/topic/40164-missing-camerainputmanager-support-for-followcamera-camerainputs/ */ var FollowCameraKeyboardMoveInput = function () { /** * Defines the camera the input is attached to. */ this.camera = null; /** * Gets or Set the list of keyboard keys used to control the forward move of the camera. */ this.keysUp = [38]; // Arrow Up key /** * Gets or Set the list of keyboard keys used to control the backward move of the camera. */ this.keysDown = [40]; // Arrow Down key /** * Gets or Set the list of keyboard keys used to control the left strafe move of the camera. */ this.keysLeft = [37]; // Arrow Left key /** * Gets or Set the list of keyboard keys used to control the right strafe move of the camera. */ this.keysRight = [39]; // Arrow Right key this._keys = []; this._shiftKey = false; // TODO let developer choose whether to use shiftKey, ctrlKey, altKey or metaKey this._onCanvasBlurObserver = null; this._onKeyboardObserver = null; this._engine = null; this._scene = null; }; /** * Attach the input controls to a specific dom element to get the input from. * @param element Defines the element the controls should be listened from * @param noPreventDefault Defines whether event caught by the controls should call preventdefault() (https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault) */ FollowCameraKeyboardMoveInput.prototype.attachControl = function(element, noPreventDefault) { if (this._onCanvasBlurObserver) return; this._scene = this.camera.getScene(); this._engine = this._scene.getEngine(); this._onCanvasBlurObserver = this._engine.onCanvasBlurObservable.add(() => { this._keys = []; this._shiftKey = false; }); this._onKeyboardObserver = this._scene.onKeyboardObservable.add(info => { let evt = info.event; // Store the shift key state this._shiftKey = (evt.shiftKey != false); if (info.type === KeyboardEventTypes.KEYDOWN) { // A key is pressed if (this.keysUp.indexOf(evt.keyCode) !== -1 || this.keysDown.indexOf(evt.keyCode) !== -1 || this.keysLeft.indexOf(evt.keyCode) !== -1 || this.keysRight.indexOf(evt.keyCode) !== -1) { var i = this._keys.indexOf(evt.keyCode); // Add the key to the list of pressed keys if (i === -1) this._keys.push(evt.keyCode); if (!noPreventDefault) evt.preventDefault(); } } else { // A key is no longer pressed if (this.keysUp.indexOf(evt.keyCode) !== -1 || this.keysDown.indexOf(evt.keyCode) !== -1 || this.keysLeft.indexOf(evt.keyCode) !== -1 || this.keysRight.indexOf(evt.keyCode) !== -1) { var i = this._keys.indexOf(evt.keyCode); // Remove the key to the list of pressed keys if (i >= 0) this._keys.splice(i, 1); if (!noPreventDefault) evt.preventDefault(); } } }); }; /** * Detach the current controls from the specified dom element. * @param element Defines the element to stop listening the inputs from */ FollowCameraKeyboardMoveInput.prototype.detachControl = function(element) { if (this._scene) { if (this._onKeyboardObserver) this._scene.onKeyboardObservable.remove(this._onKeyboardObserver); if (this._onCanvasBlurObserver) this._engine.onCanvasBlurObservable.remove(this._onCanvasBlurObserver); this._onKeyboardObserver = null; this._onCanvasBlurObserver = null; } this._keys = []; this._shiftKey = false; }; /** * Update the current camera state depending on the inputs that have been used this frame. * This is a dynamically created lambda to avoid the performance penalty of looping for inputs in the render loop. */ FollowCameraKeyboardMoveInput.prototype.checkInputs = function() { if (this._onKeyboardObserver) { // Keyboard for (var i = 0; i < this._keys.length; i++) { var keyCode = this._keys[i]; var speed = this.camera._computeLocalCameraSpeed(); if (this.keysLeft.indexOf(keyCode) !== -1) { // Left = rotate clockwise around target this.camera.rotationOffset = (this.camera.rotationOffset + -speed) % 360; } else if (this.keysUp.indexOf(keyCode) !== -1) { // Up = move closer to target (or with shift pressed: heighten altitude) if (this._shiftKey) this.camera.heightOffset += speed; else this.camera.radius += -speed; } else if (this.keysRight.indexOf(keyCode) !== -1) { // Right = rotate counter-clockwise around target this.camera.rotationOffset = (this.camera.rotationOffset + speed) % 360; } else if (this.keysDown.indexOf(keyCode) !== -1) { // Down = move further away from target (or with shift pressed: lower altitude) if (this._shiftKey) this.camera.heightOffset += -speed; else this.camera.radius += speed; } /* // TODO take this into account or not? if (this.camera.getScene().useRightHandedSystem) this.camera._localDirection.z *= -1; */ /* // TODO replace with updating the camera position and rotation... this.camera.getViewMatrix().invertToRef(this.camera._cameraTransformMatrix); Vector3.TransformNormalToRef(this.camera._localDirection, this.camera._cameraTransformMatrix, this.camera._transformedDirection); this.camera.cameraDirection.addInPlace(this.camera._transformedDirection); */ } } } /** * Gets the class name of the current intput. * @returns the class name */ FollowCameraKeyboardMoveInput.prototype.getClassName = function() { return "FollowCameraKeyboardMoveInput"; }; /** @hidden */ FollowCameraKeyboardMoveInput.prototype._onLostFocus = function (e) { this._keys = []; this._shiftKey = false; }; /** * Get the friendly name associated with the input class. * @returns the input friendly name */ FollowCameraKeyboardMoveInput.prototype.getSimpleName = function() { return "keyboard"; }; FollowCameraInputsManager: And the untested inputs manager to associate with it: /** * Default Inputs manager for the FollowCamera. * It groups all the default supported inputs for ease of use. * @version 1 Mouse only * @see http://www.html5gamedevs.com/topic/40164-missing-camerainputmanager-support-for-followcamera-camerainputs/ */ var FollowCameraInputsManager = function(camera) { BABYLON.CameraInputsManager.call(this, camera); }; FollowCameraInputsManager.prototype = Object.create(BABYLON.CameraInputsManager.prototype); FollowCameraInputsManager.prototype.constructor = FollowCameraInputsManager; /** * Add keyboard input support to the input manager. * @returns the current input manager */ FollowCameraInputsManager.prototype.addKeyboard = function() { this.add(new FollowCameraKeyboardMoveInput()); return this; }; /** * Add mouse input support to the input manager. * @returns the current input manager */ FollowCameraInputsManager.prototype.addMouse = function(touchEnabled = true) { //this.add(new FollowCameraMouseMoveInput(touchEnabled)); return this; } /** * Add orientation input support to the input manager. * @returns the current input manager */ FollowCameraInputsManager.prototype.addDeviceOrientation = function() { //this.add(new FollowCameraDeviceOrientationInput()); return this; } /** * Add touch input support to the input manager. * @returns the current input manager */ FollowCameraInputsManager.prototype.addTouch = function() { //this.add(new FollowCameraTouchInput()); return this; } /** * Add virtual joystick input support to the input manager. * @returns the current input manager */ FollowCameraInputsManager.prototype.addVirtualJoystick = function() { //this.add(new FollowCameraVirtualJoystickInput()); return this; } FollowCamera And then also some minor changes to the existing FollowCamera are needed to add support in the first place of this camera for working with an input manager... do I need to spell this syntax out? πŸ™‚ Bonus: FollowCameraMouseMoveInput Untested code for click+dragging and mouse wheel. Simply uncomment in above input manager to add support. /** * Mouse input to control the 'radius' (wheel), 'rotationOffset' (left/right drag) and 'heightOffset' (up/down drag) parameters of FollowCamera. * @see http://www.html5gamedevs.com/topic/40164-missing-camerainputmanager-support-for-followcamera-camerainputs/ */ var FollowCameraMouseMoveInput = function (touchEnabled = true) { /** * Defines the camera the input is attached to. */ this.camera = null; /** * Defines the buttons associated with the input to handle camera move. */ this.buttons = [0, 1, 2]; /** * Defines the pointer angular sensibility along the X and Y axis or how fast is the camera rotating. */ this.angularSensibility = 2000.0; /** * Gets or Set the mouse wheel precision or how fast is the camera zooming. */ this.wheelPrecision = 3.0; /** * wheelDeltaPercentage will be used instead of wheelPrecision if different from 0. * It defines the percentage of current camera.radius to use as delta when wheel is used. */ this.wheelDeltaPercentage = 0; /** * Define if touch is enabled in the mouse input */ this.touchEnabled = touchEnabled; this._pointerInput = null; this._onMouseMove = null; this._observer = null; this.previousPosition = null; }; /** * Attach the input controls to a specific dom element to get the input from. * @param element Defines the element the controls should be listened from * @param noPreventDefault Defines whether event caught by the controls should call preventdefault() (https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault) */ FollowCameraMouseMoveInput.prototype.attachControl = function (element, noPreventDefault) { var engine = this.camera.getEngine(); if (!this._pointerInput) { this._pointerInput = (p, s) => { var evt = p.event; if (engine.isInVRExclusivePointerMode) return; if (!this.touchEnabled && evt.pointerType === "touch") return; // FIXME update this condition for wheel if (p.type !== PointerEventTypes.POINTERMOVE && this.buttons.indexOf(evt.button) === -1) return; let srcElement = (evt.srcElement || evt.target); if (p.type === PointerEventTypes.POINTERDOWN && srcElement) { try { srcElement.setPointerCapture(evt.pointerId); } catch (e) { //Nothing to do with the error. Execution will continue. } this.previousPosition = { x: evt.clientX, y: evt.clientY }; if (!noPreventDefault) { evt.preventDefault(); element.focus(); } } else if (p.type === PointerEventTypes.POINTERUP && srcElement) { try { srcElement.releasePointerCapture(evt.pointerId); } catch (e) { //Nothing to do with the error. } this.previousPosition = null; if (!noPreventDefault) evt.preventDefault(); } else if (p.type === PointerEventTypes.POINTERMOVE) { if (!this.previousPosition || engine.isPointerLock) return; var offsetX = evt.clientX - this.previousPosition.x; if (this.camera.getScene().useRightHandedSystem) offsetX *= -1; if (this.camera.parent && this.camera.parent._getWorldMatrixDeterminant() < 0) offsetX *= -1; this.camera.rotationOffset += offsetX / this.angularSensibility; var offsetY = evt.clientY - this.previousPosition.y; this.camera.heightOffset += offsetY / this.angularSensibility; this.previousPosition = { x: evt.clientX, y: evt.clientY }; if (!noPreventDefault) evt.preventDefault(); } else if (p.type === PointerEventTypes.POINTERWHEEL) { var delta = 0; if (evt.wheelDelta) { if (this.wheelDeltaPercentage) { var wheelDelta = (evt.wheelDelta * 0.01 * this.wheelDeltaPercentage) * this.camera.radius; if (evt.wheelDelta > 0) { delta = wheelDelta / (1.0 + this.wheelDeltaPercentage); } else { delta = wheelDelta * (1.0 + this.wheelDeltaPercentage); } } else { delta = evt.wheelDelta / (this.wheelPrecision * 40); } } else if (evt.detail) { delta = -evt.detail / this.wheelPrecision; } if (delta) this.camera.radius += delta; if (evt.preventDefault) { if (!noPreventDefault) evt.preventDefault(); } } }; } if (!this._onMouseMove) { this._onMouseMove = evt => { if (!engine.isPointerLock) return; if (engine.isInVRExclusivePointerMode) return; var offsetX = evt.movementX || evt.mozMovementX || evt.webkitMovementX || evt.msMovementX || 0; if (this.camera.getScene().useRightHandedSystem) offsetX *= -1; if (this.camera.parent && this.camera.parent._getWorldMatrixDeterminant() < 0) offsetX *= -1; this.camera.rotationOffset += offsetX / this.angularSensibility; var offsetY = evt.movementY || evt.mozMovementY || evt.webkitMovementY || evt.msMovementY || 0; this.camera.heightOffset += offsetY / this.angularSensibility; this.previousPosition = null; if (!noPreventDefault) evt.preventDefault(); }; } this._observer = this.camera.getScene().onPointerObservable.add(this._pointerInput, PointerEventTypes.POINTERDOWN | PointerEventTypes.POINTERUP | PointerEventTypes.POINTERMOVE | PointerEventTypes.POINTERWHEEL); element.addEventListener("mousemove", this._onMouseMove, false); } /** * Detach the current controls from the specified dom element. * @param element Defines the element to stop listening the inputs from */ FollowCameraMouseMoveInput.prototype.detachControl = function (element) { if (this._observer && element) { this.camera.getScene().onPointerObservable.remove(this._observer); if (this._onMouseMove) element.removeEventListener("mousemove", this._onMouseMove); this._observer = null; this._onMouseMove = null; this.previousPosition = null; } } /** * Gets the class name of the current intput. * @returns the class name */ FollowCameraMouseMoveInput.prototype.getClassName = function () { return "FollowCameraMouseMoveInput"; } /** * Get the friendly name associated with the input class. * @returns the input friendly name */ FollowCameraMouseMoveInput.prototype.getSimpleName = function () { return "mouse"; } Q
  11. QuintusHegie

    Camera mode like freelancer game

    The camera is apparently not following your space ship but the other way around. Have you looked into the mesh.lookAt() and scene.pickMesh() functions? You can look up the code behind it on GitHub. Instead of instantly looking your mesh (camera) at the target (pickedMesh.position), the transition is smoothed to a max delta angle per frame. If there's no mesh (e.g. enemy ship) under your cursor, no problemo. You can still transform the pointed pixel back to a Ray cast from the camera by transforming 2D point using Camera view matrix to world 3D. This is basic 3D math and BabylonJS provides some default functions to transform positions and rotations to different spaces (CAMERA, LOCAL, WORLD). So the computation is translating the 2D cross hair position in camera space to 3D cross hair world space position. Your space ship is like the FollowCamera logic of inertia. It's following a point in front of the real camera used. You can see that clearly when turning and stopping turning: the ship smoothly transitions back to the center bottom of the screen. Finally the guns on your spaceship are then pointed to the 3D point that the screen cursor is pointing at. If there's a mesh under the cursor, that gives you the distance. If not, then you can default to a certain distance in Z-axis (e.g. near infinity). You can use mesh.lookAt() to target the guns to the 3D cross hair location. Again you can use interpolation (smoothing) to give the guns some time to aim at the new direction. Hope these tips help. If you solved it I would glad to hear about the solution. πŸ™‚ I'm looking for a similar aiming for my BabylonJS Model Train Simulator game, but then the Spaceship/guns is replaced with a Locomotive/crane. The above steps describe how I would start tackling this click-and-aim challenge. Q Added: Check out this post from @renjianfeng : for inspiration and help:
  12. Once the CameraInputsManager is there on the FollowCamera, this is my idea for the controls: What to control with input device camera.radius = desired distance to followed target camera.rotationOffset = desired rotation offset from axis of followed target (xz-plane / y-axis) in degrees camera.heightOffset = desired height offset from axis of followed target (xz-plane / y-axis) The FollowCamera's Up always remains Up with the world (avoids roller coaster looping sickness πŸ˜‰ ). It's a Camera that moves through the world but tries to follow a target. A camera that fully aligns with the orientation vector of the followed object (e.g. a Plane viewed from it's tail) is a different type of camera. How to control that The controls should intuitively probably be such that they are relative to the view from the camera on the target. The sensitivity and/or deadzone of the controls should be configurable and perhaps also some option to invert axis for heightOffset. Here's my idea so far: Keyboard up (-) / down (+) to control radius left (?) / right (?) to control rotationOffset SHIFT + [up (+) / down (-)] to control heightOffset Mouse wheel forward (-) / wheel backward (+) scroll to control radius drag left (?) / right (?) to control rotationOffset drag up (?) / down (?) to control heightOffset Touch same as mouse but wheel is changed to 2 finger zoom in (2 fingers drag away from center to opposite side) / zoom out (2 fingers drag to center from opposite sides) Gamepad right stick Y up (-) / down (+) to control radius right stick X to control rotationOffset left stick Y to control heightOffset VirtualJoystick same as gamepad DeviceOrientation lean forward (-) / backward (+) to control radius rotate left/right around Up-axis to control rotationOffset Pointer no clue; perhaps point to a world location and then the new desired radius and rotationOffset is computed measured from current location locked target and pointed location, given the same desired heightOffset from the locked target's zx-plane? That's about what I figured thus far would fit in the experience of the game I'm making. Your comments are welcome so I can make the controls more generic and in conformance with the other already existing input controls. Q
  13. Sure, if a Pull Request is the way to go to add code looks fine to me. Need some help though, because this will be my first Pull Request ever. Q
  14. Hi guys and gals, I was reading the docs on Customizing Camera Inputs https://doc.babylonjs.com/how_to/customizing_camera_inputs and I want to customize the camera input for the FollowCamera. But it has no camera.inputs set at the moment when I look at the definition: https://github.com/BabylonJS/Babylon.js/blob/master/src/Cameras/babylon.followCamera.ts While for example the FreeCamera has: https://github.com/BabylonJS/Babylon.js/blob/master/src/Cameras/babylon.freeCamera.ts#L164 My question is: Can you set the camera.inputs to a new CameraInputsManager instance? Perhaps a DummyCameraInputsManager that's just an empty shell, doesn't need to do anything with input for now... just being there. So then I can add my own inputs to this camera using: camera.inputs.add(new MyFancyNewFollowCameraKeyboardInput()); I can then write camera input controllers (in JavaScript) that would adjust the FollowCamera's radius, rotationOffset and heightOffset. If you like my camera input controllers for the FollowCamera I can share the code, so they might even become default. πŸ™‚ Some background info: I use a FollowCamera in my BabylonJS Model Train Simulator game. It follows the train quite nicely, even in curves. πŸ™‚ But when the train gets longer, I want the user to be able to adjust the radius to get the train in view again (zoom in/out). Also when the player operates the train at a station, I want the user to be able to adjust the rotationOffset to get a clear view on loading/unloading the train at that station. So it's kinda like an ArcRotate input but slightly different. Let me know how I can help achieve this or if there's a similar solution that achieves more or less the same. Thanks, Quintus
  15. QuintusHegie

    Screen fade/motion blur effect

    I can understand the confusion between default settings (when creating StandardRenderingPipeline) and default settings (when not doing anything with StandardRenderingPipeline)πŸ™‚ I'm trying to recreate the default anti-alias settings of https://playground.babylonjs.com (and any other effects) when I apply a newly instanced and further unconfigured StandardRenderingPipeline to a camera. Apparantly tby the change in visually rendered image the settings for FxaaPostProcess in babylon.standardRenderingPipeline.ts line 545 (when enabling fxaa) differ from the above standard playground (and thus standard scene), which doesn't have an unconfigured StandardRenderingPipeline explicitely set in code. So I want to stack specific effects on the current effects already present in any camera pipeline, instead of having all effects removed and rebuilding from scratch (because in the latter case I need to know about what current feature was already on and with what setting, instead of focusing on the specific added effect). Q