diff --git a/data/ui/touch/energy.png b/data/ui/touch/energy.png new file mode 100644 index 00000000..635d6d17 Binary files /dev/null and b/data/ui/touch/energy.png differ diff --git a/data/ui/touch/up-arrow.png b/data/ui/touch/up-arrow.png new file mode 100644 index 00000000..dce2ae35 Binary files /dev/null and b/data/ui/touch/up-arrow.png differ diff --git a/src/CameraController.hx b/src/CameraController.hx index badb11f5..ecf8e07c 100644 --- a/src/CameraController.hx +++ b/src/CameraController.hx @@ -106,7 +106,7 @@ class CameraController extends Object { #end } - public function orbit(mouseX:Float, mouseY:Float) { + public function orbit(mouseX:Float, mouseY:Float, isTouch:Bool = false) { var scaleFactor = 1.0; #if js scaleFactor = 1 / js.Browser.window.devicePixelRatio; @@ -118,7 +118,8 @@ class CameraController extends Object { deltaposY = 0; } - var factor = Util.lerp(1 / 2500, 1 / 100, Settings.controlsSettings.cameraSensitivity); + var factor = isTouch ? Util.lerp(1 / 1500, 1 / 50, + Settings.controlsSettings.cameraSensitivity) : Util.lerp(1 / 2500, 1 / 100, Settings.controlsSettings.cameraSensitivity); CameraPitch += deltaposY * factor; CameraYaw += deltaposX * factor; diff --git a/src/Marble.hx b/src/Marble.hx index c2fd1010..c7bfacef 100644 --- a/src/Marble.hx +++ b/src/Marble.hx @@ -1344,10 +1344,10 @@ class Marble extends GameObject { if (Key.isDown(Settings.controlsSettings.right)) { move.d.y -= 1; } - if (Key.isDown(Settings.controlsSettings.jump)) { + if (Key.isDown(Settings.controlsSettings.jump) || MarbleGame.instance.touchInput.jumpButton.pressed) { move.jump = true; } - if (Key.isDown(Settings.controlsSettings.powerup)) { + if (Key.isDown(Settings.controlsSettings.powerup) || MarbleGame.instance.touchInput.powerupButton.pressed) { move.powerup = true; } } diff --git a/src/MarbleGame.hx b/src/MarbleGame.hx index 58ddba49..cf6b500c 100644 --- a/src/MarbleGame.hx +++ b/src/MarbleGame.hx @@ -144,8 +144,9 @@ class MarbleGame { handlePauseGame(); #end #if js - if (paused) + if (paused) { paused = false; + } handlePauseGame(); #end } diff --git a/src/MarbleWorld.hx b/src/MarbleWorld.hx index 177da58e..129a4cf8 100644 --- a/src/MarbleWorld.hx +++ b/src/MarbleWorld.hx @@ -1037,12 +1037,14 @@ class MarbleWorld extends Scheduler { return false; this.marble.heldPowerup = powerUp; this.playGui.setPowerupImage(powerUp.identifier); + MarbleGame.instance.touchInput.powerupButton.setEnabled(true); return true; } public function deselectPowerUp() { this.marble.heldPowerup = null; this.playGui.setPowerupImage(""); + MarbleGame.instance.touchInput.powerupButton.setEnabled(false); } /** Get the current interpolated orientation quaternion. */ diff --git a/src/Settings.hx b/src/Settings.hx index bd4cc9c8..396ae897 100644 --- a/src/Settings.hx +++ b/src/Settings.hx @@ -217,8 +217,8 @@ class Settings { Settings.optionsSettings.screenHeight = cast wnd.height / zoomRatio; #end #if js - Settings.optionsSettings.screenWidth = cast js.Browser.window.screen.width * js.Browser.window.devicePixelRatio; // 1024; // cast(js.Browser.window.innerWidth / js.Browser.window.innerHeight) * 768; // cast js.Browser.window.innerWidth * js.Browser.window.devicePixelRatio * 0.5; - Settings.optionsSettings.screenHeight = cast js.Browser.window.screen.height * js.Browser.window.devicePixelRatio; // 768; // cast js.Browser.window.innerHeight * js.Browser.window.devicePixelRatio * 0.5; + Settings.optionsSettings.screenWidth = cast js.Browser.window.screen.width; // 1024; // cast(js.Browser.window.innerWidth / js.Browser.window.innerHeight) * 768; // cast js.Browser.window.innerWidth * js.Browser.window.devicePixelRatio * 0.5; + Settings.optionsSettings.screenHeight = cast js.Browser.window.screen.height; // 768; // cast js.Browser.window.innerHeight * js.Browser.window.devicePixelRatio * 0.5; var canvasElement = js.Browser.document.getElementById("webgl"); canvasElement.style.width = "100%"; diff --git a/src/gui/GuiGraphics.hx b/src/gui/GuiGraphics.hx new file mode 100644 index 00000000..2d5fb1a4 --- /dev/null +++ b/src/gui/GuiGraphics.hx @@ -0,0 +1,51 @@ +package gui; + +import h2d.Graphics; +import gui.GuiControl.MouseState; +import h2d.Scene; +import h2d.Tile; +import h2d.Bitmap; +import src.MarbleGame; + +@:publicFields +class GuiGraphics extends GuiControl { + var graphics:Graphics; + + public var pressedAction:GuiControl->Void = null; + + public function new(graphics:Graphics) { + super(); + this.graphics = graphics; + } + + public override function render(scene2d:Scene) { + var renderRect = this.getRenderRectangle(); + graphics.setPosition(Math.floor(renderRect.position.x), Math.floor(renderRect.position.y)); + // bmp.scaleX = renderRect.extent.x / bmp.tile.width; + // bmp.scaleY = renderRect.extent.y / bmp.tile.height; + if (scene2d.contains(graphics)) { + scene2d.removeChild(graphics); // Refresh "layer" + } + scene2d.addChild(graphics); + super.render(scene2d); + } + + public override function dispose() { + super.dispose(); + this.graphics.remove(); + } + + public override function onMouseRelease(mouseState:MouseState) { + super.onMouseRelease(mouseState); + if (this.pressedAction != null) { + this.pressedAction(this); + } + } + + public override function onRemove() { + super.onRemove(); + if (MarbleGame.canvas.scene2d.contains(graphics)) { + MarbleGame.canvas.scene2d.removeChild(graphics); // Refresh "layer" + } + } +} diff --git a/src/gui/PlayGui.hx b/src/gui/PlayGui.hx index 21f2b7a2..5ae447a9 100644 --- a/src/gui/PlayGui.hx +++ b/src/gui/PlayGui.hx @@ -130,6 +130,8 @@ class PlayGui { initPowerupBox(); initTexts(); + MarbleGame.instance.touchInput.showControls(this.playGuiCtrl); + playGuiCtrl.render(scene2d); resizeEv = () -> { diff --git a/src/touch/CameraInput.hx b/src/touch/CameraInput.hx index f056b304..f6df4062 100644 --- a/src/touch/CameraInput.hx +++ b/src/touch/CameraInput.hx @@ -20,20 +20,25 @@ class CameraInput { doing = true; } } - } else { + } + if (doing) { // Get our identifier for (touch in touchState.changedTouches) { - if (touch.identifier == this.identifier && touch.state == Release) { - doing = false; - return; // lol - } - if (touch.identifier == this.identifier && touch.state == Move) { - MarbleGame.instance.world.marble.camera.orbit(touch.deltaPosition.x, touch.deltaPosition.y); - return; + if (touch.identifier == this.identifier) { + switch (touch.state) { + case Release: + doing = false; + return; + + case Move: + MarbleGame.instance.world.marble.camera.orbit(touch.deltaPosition.x, touch.deltaPosition.y); + return; + + case _: + return; + } } } - // Could not find - doing = false; } } } diff --git a/src/touch/JumpButton.hx b/src/touch/JumpButton.hx new file mode 100644 index 00000000..5586fba7 --- /dev/null +++ b/src/touch/JumpButton.hx @@ -0,0 +1,13 @@ +package touch; + +import touch.TouchInput.Touch; +import h3d.Vector; +import hxd.Window; +import src.ResourceLoader; +import src.Settings; + +class JumpButton extends TouchButton { + public function new() { + super(ResourceLoader.getImage("data/ui/touch/up-arrow.png").resource, new Vector(440, 320), 60); + } +} diff --git a/src/touch/PowerupButton.hx b/src/touch/PowerupButton.hx new file mode 100644 index 00000000..4ec6c08b --- /dev/null +++ b/src/touch/PowerupButton.hx @@ -0,0 +1,14 @@ +package touch; + +import touch.TouchInput.Touch; +import h3d.Vector; +import hxd.Window; +import src.ResourceLoader; +import src.Settings; + +class PowerupButton extends TouchButton { + public function new() { + super(ResourceLoader.getImage("data/ui/touch/energy.png").resource, new Vector(440, 180), 60); + this.setEnabled(false); + } +} diff --git a/src/touch/TouchButton.hx b/src/touch/TouchButton.hx new file mode 100644 index 00000000..db078bb7 --- /dev/null +++ b/src/touch/TouchButton.hx @@ -0,0 +1,113 @@ +package touch; + +import src.Settings; +import gui.GuiControl; +import gui.GuiGraphics; +import touch.TouchInput.Touch; +import touch.TouchInput.TouchEventState; +import h3d.Vector; +import hxd.res.Image; +import src.MarbleGame; + +class TouchButton { + public var img:Image; + + public var guiElement:GuiGraphics; + + public var position:Vector; + + public var radius:Float; + + var doing = false; + + var added = false; + + public var pressed = false; + + public var enabled = true; + + var identifier:Int = -1; + + var collider:h2d.Interactive; + + public function new(img:Image, position:Vector, radius:Float) { + var imgTile = img.toTile(); + + var iconScale = 1.5; + + var g = new h2d.Graphics(); + g.beginFill(0xffffff); + g.drawCircle(0, 0, radius); + g.beginTileFill(-(imgTile.width * iconScale * radius / imgTile.width) / 2, -(imgTile.height * iconScale * radius / imgTile.width) / 2, + iconScale * radius / imgTile.width, iconScale * radius / imgTile.height, imgTile); + g.drawRect(-(imgTile.width * iconScale * radius / imgTile.width) / 2, -(imgTile.height * iconScale * radius / imgTile.width / 2), + (imgTile.width * iconScale * radius / imgTile.width), (imgTile.height * iconScale * radius / imgTile.width)); + g.endFill(); + // g.setPosition(position.x, position.y); + this.guiElement = new GuiGraphics(g); + this.guiElement.position = position; + this.guiElement.extent = new Vector(2 * radius, 2 * radius); + this.guiElement.horizSizing = Left; + this.guiElement.vertSizing = Top; + this.radius = radius; + + this.collider = new h2d.Interactive(2 * radius, 2 * radius, this.guiElement.graphics, new h2d.col.Circle(0, 0, radius)); + this.collider.onPush = (e) -> { + onClick(); + if (this.enabled) { + g.alpha = 0.9; + } else { + g.alpha = 0.5; + } + } + this.collider.onRelease = (e) -> { + onRelease(); + + if (this.enabled) { + g.alpha = 0.4; + } else { + g.alpha = 0.2; + } + } + + if (this.enabled) { + g.alpha = 0.4; + } else { + g.alpha = 0.2; + } + } + + public function add(parentGui:GuiControl) { + parentGui.addChild(this.guiElement); + added = true; + } + + public function remove(parentGui:GuiControl) { + parentGui.removeChild(this.guiElement); + added = false; + } + + public function setEnabled(enabled:Bool) { + this.enabled = enabled; + if (this.enabled) { + this.guiElement.graphics.alpha = 0.4; + } else { + this.guiElement.graphics.alpha = 0.2; + } + if (this.pressed) { + if (this.enabled) { + this.guiElement.graphics.alpha = 0.9; + } else { + this.guiElement.graphics.alpha = 0.5; + } + } + } + + public dynamic function onClick() { + pressed = true; + } + + public dynamic function onRelease() { + pressed = false; + } +} diff --git a/src/touch/TouchInput.hx b/src/touch/TouchInput.hx index 6bbdeb5a..59b535bb 100644 --- a/src/touch/TouchInput.hx +++ b/src/touch/TouchInput.hx @@ -1,7 +1,9 @@ package touch; +import gui.GuiControl; import src.MarbleWorld; import h3d.Vector; +import src.Settings; enum TouchState { Pressed; @@ -32,14 +34,22 @@ class TouchEventState { } class TouchInput { - public var cameraInput:CameraInput; + var cameraInput:CameraInput; + + public var jumpButton:JumpButton; + + public var powerupButton:PowerupButton; public var currentTouchState:TouchEventState; public var previousTouchState:TouchEventState; + var touches:Map = []; + public function new() { this.cameraInput = new CameraInput(); + this.jumpButton = new JumpButton(); + this.powerupButton = new PowerupButton(); this.currentTouchState = new TouchEventState(); this.previousTouchState = new TouchEventState(); } @@ -47,28 +57,33 @@ class TouchInput { // Registers the callbacks to the native stuff public function registerTouchInput() { #if js - var pointercontainer = js.Browser.document.querySelector("#pointercontainer"); + var pointercontainer = js.Browser.document.querySelector("#webgl"); pointercontainer.addEventListener('touchstart', (e:js.html.TouchEvent) -> { for (touch in e.changedTouches) { var t = new Touch(Pressed, new Vector(touch.clientX, touch.clientY), new Vector(0, 0), touch.identifier); currentTouchState.changedTouches.push(t); + touches.set(touch.identifier, t); + // trace("Touch Start"); } }); pointercontainer.addEventListener('touchmove', (e:js.html.TouchEvent) -> { for (touch in e.changedTouches) { - var prevt = previousTouchState.changedTouches.filter(x -> x.identifier == touch.identifier); + var prevt = touches.get(touch.identifier); // previousTouchState.changedTouches.filter(x -> x.identifier == touch.identifier); var prevDelta = new Vector(0, 0); - if (prevt.length != 0) { - prevDelta = new Vector(touch.clientX, touch.clientY).sub(prevt[0].position); + if (prevt != null) { + prevDelta = new Vector(touch.clientX, touch.clientY).sub(prevt.position); } var t = new Touch(Move, new Vector(touch.clientX, touch.clientY), prevDelta, touch.identifier); currentTouchState.changedTouches.push(t); + // trace("Touch Move"); } }); pointercontainer.addEventListener('touchend', (e:js.html.TouchEvent) -> { for (touch in e.changedTouches) { var t = new Touch(Release, new Vector(touch.clientX, touch.clientY), new Vector(0, 0), touch.identifier); currentTouchState.changedTouches.push(t); + touches.remove(touch.identifier); + // trace("Touch End"); } }); #end @@ -79,4 +94,14 @@ class TouchInput { previousTouchState = currentTouchState; currentTouchState = new TouchEventState(); } + + public function showControls(parentGui:GuiControl) { + jumpButton.add(parentGui); + powerupButton.add(parentGui); + } + + public function hideControls(parentGui:GuiControl) { + jumpButton.remove(parentGui); + powerupButton.remove(parentGui); + } }