From 7ef8c0c71840fc9afe593afb01c395fa942414df Mon Sep 17 00:00:00 2001 From: George FunBook Date: Tue, 29 Aug 2023 13:26:22 -0500 Subject: [PATCH 01/10] modernize demo with new camera features --- Features/FlxCamera/assets/Border.png | Bin 7619 -> 559 bytes Features/FlxCamera/source/HUD.hx | 75 ----- Features/FlxCamera/source/Main.hx | 3 + Features/FlxCamera/source/Orb.hx | 36 --- Features/FlxCamera/source/PlayState.hx | 301 ++++++------------ .../FlxCamera/source/props/BorderSprite.hx | 18 ++ Features/FlxCamera/source/props/Orb.hx | 77 +++++ Features/FlxCamera/source/props/OtherOrb.hx | 39 +++ Features/FlxCamera/source/props/PlayerOrb.hx | 54 ++++ .../FlxCamera/source/ui/DeadzoneOverlay.hx | 81 +++++ Features/FlxCamera/source/ui/HUD.hx | 97 ++++++ 11 files changed, 464 insertions(+), 317 deletions(-) delete mode 100644 Features/FlxCamera/source/HUD.hx delete mode 100644 Features/FlxCamera/source/Orb.hx create mode 100644 Features/FlxCamera/source/props/BorderSprite.hx create mode 100644 Features/FlxCamera/source/props/Orb.hx create mode 100644 Features/FlxCamera/source/props/OtherOrb.hx create mode 100644 Features/FlxCamera/source/props/PlayerOrb.hx create mode 100644 Features/FlxCamera/source/ui/DeadzoneOverlay.hx create mode 100644 Features/FlxCamera/source/ui/HUD.hx diff --git a/Features/FlxCamera/assets/Border.png b/Features/FlxCamera/assets/Border.png index f8ca1125c64be55c9e93c5d27352915dd18f64b5..1ff3f834537063b932952e962f2ca49b99cf5ac1 100644 GIT binary patch literal 559 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nC-#^NA%Cx&(BWL^Tw6@P~ZJvJqga5v`UDNkeJS@@KS9<%)w=yxQ z966OmdS(oRrPldBVCj#_0v~NTg9*TUn_h+Dp5s&O)1e(>5>5v zNI-wm-hFbb^se0hvD9hiS@-_Zyuat{TW5(b6ihpv;HL2%steeZauXQi4$=o9uZN70U)A^(6 z71xxrYL2IUSZNu^FdgVmyugoTJEUN0|TItY-UJAiF1B#Zfaf$kjuc} zT$GwvlA5AWo>`Ki;O^-gkfN8$4pgV^>EaktaqG?9-C3c55^fj&w|I1QIJTN>j3I+UcZCmR<%cYl$= z^KJS(Aloi{_;qjY&mUhd=H$iRnR|Ej_4MrLpVowFp9V=DnDu)@je+|5xHC6jp3IrE z$7%B>)YgtIogYm4{Q)O^3Z`>ectU;nhvFQ0y{{QY4aSXv?BFbhc8 z1yu$nAmuQF0c>32Y&DQ*!`H2Qx7%B@x9|VE{rG;C1Fe>fK+y;PH|*WM|CXi2pU36v z7(gyNAoXkZ4|8RR5woC1Few0K7+N?RK$L(Qs`;am3=D~*fiM~fknA>^5=K+PXi9+B zKBL)TG&_uDhtcc+Y&ebv!e}6j_8mq$Pz}IrFxrb84TRD01YjB%4TRA^80{mC_K`;W zNThcU;&1PqFRJ_6pzrW^>m@fu%w8$nv@cW^(T&>ifx(7Ne6H*9%bq1{Ygxqgl*F4( zxGZ2(>N>pV(U(g$YqKu%>@5CO5c|6NYiwOb9sg)C3~G*y)cv%da+?lu2<+mGMunIGJo zd-vy~Yi|YrgOoieiI|p}mZlf;zigX+z1{8bb>}u$+n=@h@%`;a#)8*>i;L5K|Is;p zG3M8^XEg;sjaP%_;|^$UvaB$*7S})b=FPdZz4q<;^JS~c-`F$s^W8u5?CZZZVbPoa zo}9k#A2U#KLvUK;w8;M-pUc?XoV{1Reunt>_j1+ckAxpAK5V{u=FI2&?`#B5>&
)WO1bV}HCl_UXIu{qX*G=YO4?_Y~w 0); } - + hud = new HUD(); add(hud); - + // Camera Overlay - deadzoneOverlay = new FlxSprite(-10000, -10000); - deadzoneOverlay.makeGraphic(FlxG.width, FlxG.height, FlxColor.TRANSPARENT, true); - deadzoneOverlay.antialiasing = true; - - overlayCamera = new FlxCamera(0, 0, 640, 720); - overlayCamera.bgColor = FlxColor.TRANSPARENT; - overlayCamera.follow(deadzoneOverlay); - FlxG.cameras.add(overlayCamera); + deadzoneOverlay = new DeadzoneOverlay(); add(deadzoneOverlay); - - FlxG.camera.setScrollBoundsRect(LEVEL_MIN_X, LEVEL_MIN_Y, LEVEL_MAX_X + Math.abs(LEVEL_MIN_X), LEVEL_MAX_Y + Math.abs(LEVEL_MIN_Y), true); - FlxG.camera.follow(orb, LOCKON, 1); - drawDeadzone(); // now that deadzone is present - - hudCam = new FlxCamera(440, 0, hud.width, hud.height); - hudCam.zoom = 1; // For 1/2 zoom out. - hudCam.follow(hud.background, FlxCameraFollowStyle.NO_DEAD_ZONE); - hudCam.alpha = .5; - FlxG.cameras.add(hudCam); + + FlxG.camera.pixelPerfectRender = false; + FlxG.camera.setScrollBounds(levelMinX, levelMaxX, levelMinY, levelMaxY); + FlxG.worldBounds.set(levelMinX, levelMinY, levelWidth, levelHeight); + FlxG.camera.follow(player, followStyles[0], 1); + deadzoneOverlay.redraw(FlxG.camera); // now that deadzone is present } - - function drawDeadzone() + + override public function update(elapsed:Float):Void { - deadzoneOverlay.fill(FlxColor.TRANSPARENT); - var dz:FlxRect = FlxG.camera.deadzone; - if (dz == null) - return; - - var lineLength:Int = 20; - var lineStyle:LineStyle = {color: FlxColor.WHITE, thickness: 3}; - - // adjust points slightly so lines will be visible when at screen edges - dz.x += lineStyle.thickness / 2; - dz.width -= lineStyle.thickness; - dz.y += lineStyle.thickness / 2; - dz.height -= lineStyle.thickness; - - // Left Up Corner - deadzoneOverlay.drawLine(dz.left, dz.top, dz.left + lineLength, dz.top, lineStyle); - deadzoneOverlay.drawLine(dz.left, dz.top, dz.left, dz.top + lineLength, lineStyle); - // Right Up Corner - deadzoneOverlay.drawLine(dz.right, dz.top, dz.right - lineLength, dz.top, lineStyle); - deadzoneOverlay.drawLine(dz.right, dz.top, dz.right, dz.top + lineLength, lineStyle); - // Bottom Left Corner - deadzoneOverlay.drawLine(dz.left, dz.bottom, dz.left + lineLength, dz.bottom, lineStyle); - deadzoneOverlay.drawLine(dz.left, dz.bottom, dz.left, dz.bottom - lineLength, lineStyle); - // Bottom Right Corner - deadzoneOverlay.drawLine(dz.right, dz.bottom, dz.right - lineLength, dz.bottom, lineStyle); - deadzoneOverlay.drawLine(dz.right, dz.bottom, dz.right, dz.bottom - lineLength, lineStyle); + super.update(elapsed); + + final justPressed = FlxG.keys.justPressed; + + if (justPressed.Y) setStyle(1); + if (justPressed.H) setStyle(-1); + + if (justPressed.U) setLerp(.1); + if (justPressed.J) setLerp(-.1); + + if (justPressed.I) setLead(.5); + if (justPressed.K) setLead(-.5); + + if (justPressed.O) setZoom(.1); + if (justPressed.L) setZoom(-.1); + + if (justPressed.M) FlxG.camera.shake(); } - - public function setZoom(zoom:Float) + + public function setZoom(delta:Float) { - FlxG.camera.zoom = FlxMath.bound(zoom, 0.5, 4); + final newZoom = FlxG.camera.zoom + delta; + FlxG.camera.zoom = FlxMath.bound(Math.round(newZoom * 10) / 10, 0.5, 4); hud.updateZoom(FlxG.camera.zoom); } - - function createFloorTiles() - { - var floorImg = Assets.getBitmapData("assets/FloorTexture.png"); - var imgWidth = floorImg.width; - var imgHeight = floorImg.height; - var i = LEVEL_MIN_X; - var j = LEVEL_MIN_Y; - - while (i <= LEVEL_MAX_X) - { - while (j <= LEVEL_MAX_Y) - { - add(new FlxSprite(i, j, floorImg)); - j += imgHeight; - } - i += imgWidth; - j = LEVEL_MIN_Y; - } - } - - override public function update(elapsed:Float):Void - { - super.update(elapsed); - - var speed = 20; - if (FlxG.keys.anyPressed([A, LEFT])) - orb.body.applyImpulse(new Vec2(-speed, 0)); - if (FlxG.keys.anyPressed([S, DOWN])) - orb.body.applyImpulse(new Vec2(0, speed)); - if (FlxG.keys.anyPressed([D, RIGHT])) - orb.body.applyImpulse(new Vec2(speed, 0)); - if (FlxG.keys.anyPressed([W, UP])) - orb.body.applyImpulse(new Vec2(0, -speed)); - - if (FlxG.keys.justPressed.Y) - setStyle(1); - if (FlxG.keys.justPressed.H) - setStyle(-1); - - if (FlxG.keys.justPressed.U) - setLerp(.1); - if (FlxG.keys.justPressed.J) - setLerp(-.1); - - if (FlxG.keys.justPressed.I) - setLead(.5); - if (FlxG.keys.justPressed.K) - setLead(-.5); - - if (FlxG.keys.justPressed.O) - setZoom(FlxG.camera.zoom + .1); - if (FlxG.keys.justPressed.L) - setZoom(FlxG.camera.zoom - .1); - - if (FlxG.keys.justPressed.M) - FlxG.camera.shake(); - } - - function setLead(lead:Float) + + function setLead(delta:Float) { var cam = FlxG.camera; - cam.followLead.x += lead; - cam.followLead.y += lead; - + cam.followLead.x += delta; + cam.followLead.y += delta; + if (cam.followLead.x < 0) { cam.followLead.x = 0; cam.followLead.y = 0; } - + hud.updateCamLead(cam.followLead.x); } - - function setLerp(lerp:Float) + + function setLerp(delta:Float) { var cam = FlxG.camera; - cam.followLerp += lerp; + cam.followLerp += delta; cam.followLerp = Math.round(10 * cam.followLerp) / 10; // adding or subtracting .1 causes roundoff errors hud.updateCamLerp(cam.followLerp); } - - function setStyle(i:Int) + + function setStyle(delta:Int) { - var newCamStyleIndex:Int = Type.enumIndex(FlxG.camera.style) + i; - newCamStyleIndex < 0 ? newCamStyleIndex += 6 : newCamStyleIndex %= 6; - - var newCamStyle = Type.createEnumIndex(FlxCameraFollowStyle, newCamStyleIndex); - FlxG.camera.follow(orb, newCamStyle, FlxG.camera.followLerp); - drawDeadzone(); - - hud.updateStyle(Std.string(FlxG.camera.style)); - - if (FlxG.camera.style == SCREEN_BY_SCREEN) - { - setZoom(1); - } + final nextStyleIndex = (followStyles.indexOf(FlxG.camera.style) + delta) % followStyles.length; + FlxG.camera.follow(player, followStyles[nextStyleIndex], FlxG.camera.followLerp); + + deadzoneOverlay.redraw(FlxG.camera); + + hud.updateStyle(FlxG.camera.style); } } diff --git a/Features/FlxCamera/source/props/BorderSprite.hx b/Features/FlxCamera/source/props/BorderSprite.hx new file mode 100644 index 000000000..37b8489b3 --- /dev/null +++ b/Features/FlxCamera/source/props/BorderSprite.hx @@ -0,0 +1,18 @@ +package props; + +import flixel.math.FlxRect; +import flixel.addons.display.FlxSliceSprite; + +@:forward +abstract BorderSprite(FlxSliceSprite) from FlxSliceSprite to FlxSliceSprite +{ + inline public function new (x = 0.0, y = 0.0, width:Float, height:Float) + { + this = new FlxSliceSprite("assets/Border.png", new FlxRect(15, 15, 20, 20), width, height); + this.x = x; + this.y = y; + #if debug + this.ignoreDrawDebug = true; + #end + } +} \ No newline at end of file diff --git a/Features/FlxCamera/source/props/Orb.hx b/Features/FlxCamera/source/props/Orb.hx new file mode 100644 index 000000000..3f501c844 --- /dev/null +++ b/Features/FlxCamera/source/props/Orb.hx @@ -0,0 +1,77 @@ +package props; + +import flixel.FlxG; +import flixel.FlxSprite; +import flixel.addons.nape.FlxNapeSprite; +import flixel.util.FlxDestroyUtil; + +/** + * @author TiagoLr ( ~~~ProG4mr~~~ ) + */ +class Orb extends FlxNapeSprite +{ + var shadow:FlxSprite; + + public function new(x = 0.0, y = 0.0, radius:Int, ?graphic, ?shadowGraphic) + { + super(x, y, null, false); + createCircularBody(radius); + body.allowRotation = false; + pixelPerfectPosition = false; + pixelPerfectRender = false; + + // create a shadow that follows the sprite around + shadow = new FlxSprite(x, y, shadowGraphic); + shadow.blend = MULTIPLY; + shadow.pixelPerfectPosition = false; + shadow.pixelPerfectRender = false; + #if debug + shadow.ignoreDrawDebug = true; + #end + + // call loadGraphic after the body is created so it adjusts the hitbox + if (graphic != null) + loadGraphic(graphic); + } + + override function loadGraphic(graphic, animated = false, frameWidth = 0, frameHeight = 0, unique = false, ?key:String) + { + super.loadGraphic(graphic, animated, frameWidth, frameHeight, unique, key); + + // adjust flixel hitbox to match the radius for tighter camera following + if (body != null && body.shapes != null) + { + width = body.bounds.width; + height = body.bounds.height; + centerOffsets(false); + origin.set(width / 2, height / 2); + + // same offset for shadowP + shadow.offset.copyFrom(offset); + } + + return this; + } + + override public function update(elapsed:Float):Void + { + super.update(elapsed); + + shadow.update(elapsed); + shadow.x = x; + shadow.y = y; + } + + override function draw() + { + // draw shadow first, so it's underneath + shadow.draw(); + super.draw(); + } + + override function destroy() + { + super.destroy(); + shadow = FlxDestroyUtil.destroy(shadow); + } +} diff --git a/Features/FlxCamera/source/props/OtherOrb.hx b/Features/FlxCamera/source/props/OtherOrb.hx new file mode 100644 index 000000000..22459afa3 --- /dev/null +++ b/Features/FlxCamera/source/props/OtherOrb.hx @@ -0,0 +1,39 @@ +package props; + +import flixel.FlxG; +import flixel.FlxSprite; +// import flixel.math.FlxMath; +import flixel.util.FlxDestroyUtil; +// import nape.geom.Vec2; + +class OtherOrb extends Orb +{ + public function new(x = 0.0, y = 0.0, colorIndex:Int) + { + super(x, y, 50, null, "assets/OtherOrbShadow.png"); + + loadGraphic("assets/OtherOrb.png", true, 140, 140); + animation.frameIndex = colorIndex; + setBodyMaterial(1, 0.0, 0.0, 0.5); + } + + /** + * Randomizes the position of this orb within the given bounds + */ + public function randomizePosition(minX = 0, maxX = 0, minY = 0, maxY = 0) + { + x = body.position.x = FlxG.random.int(minX, maxX - Math.ceil(width)); + y = body.position.y = FlxG.random.int(minY, maxY - Math.ceil(height)); + return this; + } + + /** + * Randomizes the velocity of this orb with the given absolute speed range and a random angle + */ + public function randomizeVelocity(min = 100, max = 200) + { + body.velocity.setxy(FlxG.random.float(min, max), 0); + body.velocity.angle = FlxG.random.float(0, 2 * Math.PI); + return this; + } +} \ No newline at end of file diff --git a/Features/FlxCamera/source/props/PlayerOrb.hx b/Features/FlxCamera/source/props/PlayerOrb.hx new file mode 100644 index 000000000..c594f4875 --- /dev/null +++ b/Features/FlxCamera/source/props/PlayerOrb.hx @@ -0,0 +1,54 @@ +package props; + +import flixel.FlxG; +import nape.geom.Vec2; + +/** + * User controlled orb + */ +class PlayerOrb extends Orb +{ + /** + * The impulse applied each frame when pressing the corresponding key + */ + static inline var IMPULSE = 20; + + /** + * Used Internally to avoid creating new instances each frame + */ + static final impulseHelper = new Vec2(); + + public function new(x = 0.0, y = 0.0) + { + super(x, y, 18, "assets/Orb.png", "assets/OrbShadow.png"); + // small amount of drag + setDrag(0.98); + } + + override function update(elapsed:Float) + { + super.update(elapsed); + + // apply impusles to the body based on key presses + + if (FlxG.keys.anyPressed([A, LEFT])) + applyImpulseXY(-IMPULSE, 0); + + if (FlxG.keys.anyPressed([S, DOWN])) + applyImpulseXY(0, IMPULSE); + + if (FlxG.keys.anyPressed([D, RIGHT])) + applyImpulseXY(IMPULSE, 0); + + if (FlxG.keys.anyPressed([W, UP])) + applyImpulseXY(0, -IMPULSE); + } + + /** + * Helper to apply impulse via x and y floats to avoid creating new Vec2 instances each frame + */ + inline function applyImpulseXY(x:Float, y:Float) + { + body.applyImpulse(impulseHelper.setxy(x, y)); + } +} \ No newline at end of file diff --git a/Features/FlxCamera/source/ui/DeadzoneOverlay.hx b/Features/FlxCamera/source/ui/DeadzoneOverlay.hx new file mode 100644 index 000000000..909738dd9 --- /dev/null +++ b/Features/FlxCamera/source/ui/DeadzoneOverlay.hx @@ -0,0 +1,81 @@ +package ui; + +import flixel.FlxCamera; +import flixel.FlxG; +import flixel.FlxSprite; +import flixel.math.FlxRect; +import flixel.util.FlxColor; + +using flixel.util.FlxSpriteUtil; + +/** + * Sprite used to draw a representation of the current follow styles. + * For most styles, it draws the deadzone. + */ +class DeadzoneOverlay extends FlxSprite +{ + public function new () + { + super(); + + scrollFactor.set(0, 0);// move with the camera + + #if debug + ignoreDrawDebug = true; + #end + } + + public function redraw(targetCamera:FlxCamera) + { + if (targetCamera.style == SCREEN_BY_SCREEN) + { + // just hide it, otherwise we'd need to redraw it with zoom changes + visible = false; + return; + } + visible = true; + + final lineLength = 12; + final padding = 2; + final thickness = 3 + padding; + final halfThickness = thickness / 2; + final lineStyle:LineStyle = {color: FlxColor.WHITE, thickness: thickness - padding}; + + if (targetCamera.style == NO_DEAD_ZONE) + { + // No deadzone, draw a simple crosshair in the center of the camera's view + final reticalSize = 20; + // pad the graphic a little, for thick lines + makeGraphic(reticalSize + thickness, reticalSize + thickness, FlxColor.TRANSPARENT, true); + x = (camera.width - frameWidth) / 2; + y = (camera.height - frameHeight) / 2; + + final centerX = frameWidth / 2; + final centerY = frameHeight / 2; + final reticalHalfSize = reticalSize / 2; + this.drawLine(centerX, centerY - reticalHalfSize, centerX, centerY + reticalHalfSize, lineStyle); + this.drawLine(centerX - reticalHalfSize, centerY, centerX + reticalHalfSize, centerY, lineStyle); + return; + } + + // draw the deadzone's corners + final dz:FlxRect = targetCamera.deadzone; + x = dz.x - halfThickness; + y = dz.y - halfThickness; + // pad the graphic a little, for thick lines + makeGraphic(Std.int(dz.width + thickness), Std.int(dz.height + thickness), FlxColor.TRANSPARENT, true); + + // Top-Left + this.drawLine(dz.left - x, dz.top - y, dz.left - x + lineLength, dz.top - y, lineStyle); + this.drawLine(dz.left - x, dz.top - y, dz.left - x, dz.top + lineLength - y, lineStyle); + // Top-Right + this.drawLine(dz.right - x, dz.top - y, dz.right - x - lineLength, dz.top - y, lineStyle); + this.drawLine(dz.right - x, dz.top - y, dz.right - x, dz.top + lineLength - y, lineStyle); + // Bottom-Left + this.drawLine(dz.left - x, dz.bottom - y, dz.left - x + lineLength, dz.bottom - y, lineStyle); + this.drawLine(dz.left - x, dz.bottom - y, dz.left - x, dz.bottom - lineLength - y, lineStyle); + // Bottom-Right + this.drawLine(dz.right - x, dz.bottom - y, dz.right - x - lineLength, dz.bottom - y, lineStyle); + this.drawLine(dz.right - x, dz.bottom - y, dz.right - x, dz.bottom - lineLength - y, lineStyle); + } +} \ No newline at end of file diff --git a/Features/FlxCamera/source/ui/HUD.hx b/Features/FlxCamera/source/ui/HUD.hx new file mode 100644 index 000000000..66c545269 --- /dev/null +++ b/Features/FlxCamera/source/ui/HUD.hx @@ -0,0 +1,97 @@ +package ui; + +import flixel.FlxCamera; +import flixel.FlxG; +import flixel.FlxSprite; +import flixel.group.FlxGroup; +import flixel.text.FlxText; + +inline var WIDTH = 200; +inline var HEIGHT = 180; + +/** + * @author TiagoLr ( ~~~ProG4mr~~~ ) + */ +class HUD extends FlxGroup +{ + var txtStyle:Text; + var txtLerp:Text; + var txtLead:Text; + var txtZoom:Text; + + public function new() + { + super(); + + var left = 6; + var startY = 10; + + add(new Text(left, startY, "[W,A,S,D] or arrows to control the orb.")); + + add(new Text(left, startY + 20, "[H] to change follow style.")); + add(txtStyle = new GreenText(left, startY + 33, "LOCKON")); + + add(new Text(left, startY + 55, "[U] or [J] to change lerp.")); + add(txtLerp = new GreenText(left, startY + 68, "Camera lerp: 1")); + + add(new Text(left, startY + 95, "[I] or [K] to change lead.")); + add(txtLead = new GreenText(left, startY + 108, "Camera lead: 0")); + + add(new Text(left, startY + 135, "[O] or [L] to change zoom.")); + add(txtZoom = new GreenText(left, startY + 148, "Camera zoom: 1")); + + // create new camera in the top-right corner that only draws this + camera = new FlxCamera(440, 0, WIDTH, HEIGHT, 1.0); + camera.alpha = .5; + camera.bgColor = 0x80000000; + FlxG.cameras.add(camera, false); + } + + public function updateStyle(style:FlxCameraFollowStyle) + { + txtStyle.text = Std.string(style); + } + + public function updateCamLerp(lerp:Float) + { + txtLerp.text = "Camera lerp: " + lerp; + } + + public function updateCamLead(lead:Float) + { + txtLead.text = "Camera lead: " + lead; + } + + public function updateZoom(zoom:Float) + { + txtZoom.text = "Camera Zoom: " + Math.floor(zoom * 10) / 10; + } +} + +/** + * A simplified, specialized FlxText instance, mainly used to omit the fieldWidth arg + */ +@:forward +abstract Text(FlxText) from FlxText to FlxText +{ + inline public function new (x = 0.0, y = 0.0, fieldWidth = WIDTH, ?text:String, size = 8) + { + this = new FlxText(x, y, fieldWidth, text, size); + #if debug + this.ignoreDrawDebug = true; + #end + } +} + +/** + * An even more specialized version of Text used to highlight the changing camera values + */ +@:forward +abstract GreenText(Text) from Text to Text +{ + inline public function new (x = 0.0, y = 0.0, fieldWidth = WIDTH, ?text:String) + { + this = new Text(x, y, WIDTH, text); + this.setFormat(null, 11, 0x55FF55); + } +} From 64cca0164945b18b031e07f796e44c1e87c15755 Mon Sep 17 00:00:00 2001 From: George FunBook Date: Tue, 29 Aug 2023 14:33:22 -0500 Subject: [PATCH 02/10] add mobile and gamepad controls --- Features/FlxCamera/source/PlayState.hx | 5 +- Features/FlxCamera/source/input/Controls.hx | 113 +++++++++++++++++++ Features/FlxCamera/source/props/PlayerOrb.hx | 13 ++- 3 files changed, 126 insertions(+), 5 deletions(-) create mode 100644 Features/FlxCamera/source/input/Controls.hx diff --git a/Features/FlxCamera/source/PlayState.hx b/Features/FlxCamera/source/PlayState.hx index c61c820bf..ba299283b 100644 --- a/Features/FlxCamera/source/PlayState.hx +++ b/Features/FlxCamera/source/PlayState.hx @@ -65,7 +65,10 @@ class PlayState extends FlxState // Player orb player = new PlayerOrb(levelMinX + levelWidth / 2, levelMinY + levelHeight / 2); add(player); - + // if the player is using a virtual pad, add it to the state + if (player.controls.virtualPad != null) + add(player.controls.virtualPad); + // Other orbs for (i in 0...5) { diff --git a/Features/FlxCamera/source/input/Controls.hx b/Features/FlxCamera/source/input/Controls.hx new file mode 100644 index 000000000..94c760109 --- /dev/null +++ b/Features/FlxCamera/source/input/Controls.hx @@ -0,0 +1,113 @@ +package input; + +import flixel.FlxG; +import flixel.input.gamepad.FlxGamepadInputID; +import flixel.input.keyboard.FlxKey; +import flixel.ui.FlxVirtualPad; + +class Controls +{ + /** + * Maps input types to their corresponding keyboard button + */ + static public var keyMap:Map> = + [ + Input.LEFT => [FlxKey.A, FlxKey.LEFT], + Input.DOWN => [FlxKey.S, FlxKey.DOWN], + Input.RIGHT => [FlxKey.D, FlxKey.RIGHT], + Input.UP => [FlxKey.W, FlxKey.UP] + ]; + + #if FLX_GAMEPAD + /** + * Maps input types to their corresponding gamepad dpad button + */ + static public var buttonMap:Map = + [ + Input.LEFT => { dpad:DPAD_LEFT , analog:LEFT_STICK_DIGITAL_LEFT }, + Input.DOWN => { dpad:DPAD_DOWN , analog:LEFT_STICK_DIGITAL_DOWN }, + Input.RIGHT => { dpad:DPAD_RIGHT, analog:LEFT_STICK_DIGITAL_RIGHT }, + Input.UP => { dpad:DPAD_UP , analog:LEFT_STICK_DIGITAL_UP } + ]; + #end + + /** + * Reference to the gamepad controlling this orb + */ + public var virtualPad:VirtualPad = null; + + public function new() + { + // create a virtual pad to play on mobile devices + final useVirtualPad = #if html5 FlxG.html5.onMobile #elseif mobile true #else false #end; + if (useVirtualPad) + virtualPad = new VirtualPad(); + } + + /** + * Helper to detect keyboard or virtual pad presses + */ + inline public function inputPressed(input:Input) + { + return keyPressed(input) || virtualPadPressed(input) || gamePadPressed(input); + } + + /** + * Helper to detect keyboard presses + */ + inline function keyPressed(input:Input) + { + return FlxG.keys.anyPressed(keyMap[input]); + } + + /** + * Helper to detect virtual pad presses + */ + inline function virtualPadPressed(input:Input) + { + return virtualPad != null && virtualPad.pressed(input); + } + + /** + * Helper to detect gamepad presses + */ + inline function gamePadPressed(input:Input) + { + #if FLX_GAMEPAD + final buttons = buttonMap[input]; + return FlxG.gamepads.anyPressed(buttons.dpad) || FlxG.gamepads.anyPressed(buttons.analog); + #else + return false; + #end + } +} + +/** + * Simplified virtual pad that takes an Input and returns whether the corresponding button is pressed + */ +abstract VirtualPad(FlxVirtualPad) from FlxVirtualPad to FlxVirtualPad +{ + inline public function new() + { + this = new FlxVirtualPad(FULL, NONE); + } + + public function pressed(input:Input) + { + return switch(input) + { + case Input.LEFT : this.buttonLeft.pressed; + case Input.RIGHT: this.buttonRight.pressed; + case Input.UP : this.buttonUp.pressed; + case Input.DOWN : this.buttonDown.pressed; + } + } +} + +enum Input +{ + LEFT; + RIGHT; + UP; + DOWN; +} \ No newline at end of file diff --git a/Features/FlxCamera/source/props/PlayerOrb.hx b/Features/FlxCamera/source/props/PlayerOrb.hx index c594f4875..ac34f987c 100644 --- a/Features/FlxCamera/source/props/PlayerOrb.hx +++ b/Features/FlxCamera/source/props/PlayerOrb.hx @@ -1,6 +1,7 @@ package props; import flixel.FlxG; +import input.Controls; import nape.geom.Vec2; /** @@ -18,11 +19,15 @@ class PlayerOrb extends Orb */ static final impulseHelper = new Vec2(); + public var controls:Controls; + public function new(x = 0.0, y = 0.0) { super(x, y, 18, "assets/Orb.png", "assets/OrbShadow.png"); // small amount of drag setDrag(0.98); + + controls = new Controls(); } override function update(elapsed:Float) @@ -31,16 +36,16 @@ class PlayerOrb extends Orb // apply impusles to the body based on key presses - if (FlxG.keys.anyPressed([A, LEFT])) + if (controls.inputPressed(LEFT)) applyImpulseXY(-IMPULSE, 0); - if (FlxG.keys.anyPressed([S, DOWN])) + if (controls.inputPressed(DOWN)) applyImpulseXY(0, IMPULSE); - if (FlxG.keys.anyPressed([D, RIGHT])) + if (controls.inputPressed(RIGHT)) applyImpulseXY(IMPULSE, 0); - if (FlxG.keys.anyPressed([W, UP])) + if (controls.inputPressed(UP)) applyImpulseXY(0, -IMPULSE); } From 2e1b6bc531e00d1c2d51cd62bdf5e70859465ea6 Mon Sep 17 00:00:00 2001 From: George FunBook Date: Tue, 29 Aug 2023 14:42:30 -0500 Subject: [PATCH 03/10] rename controls class --- .../input/{Controls.hx => PlayerControls.hx} | 18 ++++++++++++++---- Features/FlxCamera/source/props/PlayerOrb.hx | 4 ++-- 2 files changed, 16 insertions(+), 6 deletions(-) rename Features/FlxCamera/source/input/{Controls.hx => PlayerControls.hx} (88%) diff --git a/Features/FlxCamera/source/input/Controls.hx b/Features/FlxCamera/source/input/PlayerControls.hx similarity index 88% rename from Features/FlxCamera/source/input/Controls.hx rename to Features/FlxCamera/source/input/PlayerControls.hx index 94c760109..beb0696f8 100644 --- a/Features/FlxCamera/source/input/Controls.hx +++ b/Features/FlxCamera/source/input/PlayerControls.hx @@ -5,17 +5,17 @@ import flixel.input.gamepad.FlxGamepadInputID; import flixel.input.keyboard.FlxKey; import flixel.ui.FlxVirtualPad; -class Controls +class PlayerControls { /** * Maps input types to their corresponding keyboard button */ static public var keyMap:Map> = [ - Input.LEFT => [FlxKey.A, FlxKey.LEFT], - Input.DOWN => [FlxKey.S, FlxKey.DOWN], + Input.LEFT => [FlxKey.A, FlxKey.LEFT ], + Input.DOWN => [FlxKey.S, FlxKey.DOWN ], Input.RIGHT => [FlxKey.D, FlxKey.RIGHT], - Input.UP => [FlxKey.W, FlxKey.UP] + Input.UP => [FlxKey.W, FlxKey.UP ] ]; #if FLX_GAMEPAD @@ -44,6 +44,15 @@ class Controls virtualPad = new VirtualPad(); } + public function isGamepadConnected() + { + #if FLX_GAMEPAD + return FlxG.gamepads.numActiveGamepads > 0; + #else + return false; + #end + } + /** * Helper to detect keyboard or virtual pad presses */ @@ -100,6 +109,7 @@ abstract VirtualPad(FlxVirtualPad) from FlxVirtualPad to FlxVirtualPad case Input.RIGHT: this.buttonRight.pressed; case Input.UP : this.buttonUp.pressed; case Input.DOWN : this.buttonDown.pressed; + default: false; } } } diff --git a/Features/FlxCamera/source/props/PlayerOrb.hx b/Features/FlxCamera/source/props/PlayerOrb.hx index ac34f987c..bf4d07bd5 100644 --- a/Features/FlxCamera/source/props/PlayerOrb.hx +++ b/Features/FlxCamera/source/props/PlayerOrb.hx @@ -19,7 +19,7 @@ class PlayerOrb extends Orb */ static final impulseHelper = new Vec2(); - public var controls:Controls; + public var controls:PlayerControls; public function new(x = 0.0, y = 0.0) { @@ -27,7 +27,7 @@ class PlayerOrb extends Orb // small amount of drag setDrag(0.98); - controls = new Controls(); + controls = new PlayerControls(); } override function update(elapsed:Float) From 5f558c33432722701ecf4110ed429f18a2f3627b Mon Sep 17 00:00:00 2001 From: George FunBook Date: Tue, 29 Aug 2023 14:42:49 -0500 Subject: [PATCH 04/10] add [Y] to HUD --- Features/FlxCamera/source/ui/HUD.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Features/FlxCamera/source/ui/HUD.hx b/Features/FlxCamera/source/ui/HUD.hx index 66c545269..14cf845cb 100644 --- a/Features/FlxCamera/source/ui/HUD.hx +++ b/Features/FlxCamera/source/ui/HUD.hx @@ -28,7 +28,7 @@ class HUD extends FlxGroup add(new Text(left, startY, "[W,A,S,D] or arrows to control the orb.")); - add(new Text(left, startY + 20, "[H] to change follow style.")); + add(new Text(left, startY + 20, "[H] or [Y] to change follow style.")); add(txtStyle = new GreenText(left, startY + 33, "LOCKON")); add(new Text(left, startY + 55, "[U] or [J] to change lerp.")); From 2475190b00498b8618aa4fdd1e73ad05eb4a3fc0 Mon Sep 17 00:00:00 2001 From: George FunBook Date: Tue, 29 Aug 2023 14:47:26 -0500 Subject: [PATCH 05/10] whoopsies --- Features/FlxCamera/source/props/PlayerOrb.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Features/FlxCamera/source/props/PlayerOrb.hx b/Features/FlxCamera/source/props/PlayerOrb.hx index bf4d07bd5..a2ae435a9 100644 --- a/Features/FlxCamera/source/props/PlayerOrb.hx +++ b/Features/FlxCamera/source/props/PlayerOrb.hx @@ -1,7 +1,7 @@ package props; import flixel.FlxG; -import input.Controls; +import input.PlayerControls; import nape.geom.Vec2; /** From 36b660b4761ab649417273e6a474e2c4c107f313 Mon Sep 17 00:00:00 2001 From: George FunBook Date: Tue, 29 Aug 2023 14:58:27 -0500 Subject: [PATCH 06/10] fix flash CI --- Features/FlxCamera/source/ui/HUD.hx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Features/FlxCamera/source/ui/HUD.hx b/Features/FlxCamera/source/ui/HUD.hx index 14cf845cb..6e9862c39 100644 --- a/Features/FlxCamera/source/ui/HUD.hx +++ b/Features/FlxCamera/source/ui/HUD.hx @@ -74,9 +74,9 @@ class HUD extends FlxGroup @:forward abstract Text(FlxText) from FlxText to FlxText { - inline public function new (x = 0.0, y = 0.0, fieldWidth = WIDTH, ?text:String, size = 8) + inline public function new (x = 0.0, y = 0.0, ?text:String, size = 8) { - this = new FlxText(x, y, fieldWidth, text, size); + this = new FlxText(x, y, WIDTH, text, size); #if debug this.ignoreDrawDebug = true; #end @@ -89,9 +89,9 @@ abstract Text(FlxText) from FlxText to FlxText @:forward abstract GreenText(Text) from Text to Text { - inline public function new (x = 0.0, y = 0.0, fieldWidth = WIDTH, ?text:String) + inline public function new (x = 0.0, y = 0.0, ?text:String) { - this = new Text(x, y, WIDTH, text); + this = new Text(x, y, text); this.setFormat(null, 11, 0x55FF55); } } From 3e24a351adfd4cd409f08e7b84a06096843a287f Mon Sep 17 00:00:00 2001 From: George FunBook Date: Tue, 29 Aug 2023 14:59:25 -0500 Subject: [PATCH 07/10] more flash CI fixes --- Features/FlxCamera/source/PlayState.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Features/FlxCamera/source/PlayState.hx b/Features/FlxCamera/source/PlayState.hx index ba299283b..650d74b19 100644 --- a/Features/FlxCamera/source/PlayState.hx +++ b/Features/FlxCamera/source/PlayState.hx @@ -57,7 +57,7 @@ class PlayState extends FlxState // create nape wall colliders final border = 10; - FlxNapeSpace.createWalls(levelMinX + border, levelMinY + border, levelMaxX - border, levelMaxY - border, new Material(1.0, 0.0, 0.0, 1)); + FlxNapeSpace.createWalls(levelMinX + border, levelMinY + border, levelMaxX - border, levelMaxY - border, border, new Material(1.0, 0.0, 0.0, 1)); // Walls border sprite add(new BorderSprite(levelMinX, levelMinY, levelWidth, levelHeight)); From 8d41d9072580025a4bb84cdad7cfed7fe0cc243a Mon Sep 17 00:00:00 2001 From: George FunBook Date: Tue, 29 Aug 2023 15:10:40 -0500 Subject: [PATCH 08/10] revert border to normal FlxSprite for mac perf --- Features/FlxCamera/assets/Border.png | Bin 559 -> 7619 bytes Features/FlxCamera/source/PlayState.hx | 6 ++++-- .../FlxCamera/source/props/BorderSprite.hx | 18 ------------------ 3 files changed, 4 insertions(+), 20 deletions(-) delete mode 100644 Features/FlxCamera/source/props/BorderSprite.hx diff --git a/Features/FlxCamera/assets/Border.png b/Features/FlxCamera/assets/Border.png index 1ff3f834537063b932952e962f2ca49b99cf5ac1..f8ca1125c64be55c9e93c5d27352915dd18f64b5 100644 GIT binary patch literal 7619 zcmeAS@N?(olHy`uVBq!ia0y~yUFdgVmyugoTJEUN0|TItY-UJAiF1B#Zfaf$kjuc} zT$GwvlA5AWo>`Ki;O^-gkfN8$4pgV^>EaktaqG?9-C3c55^fj&w|I1QIJTN>j3I+UcZCmR<%cYl$= z^KJS(Aloi{_;qjY&mUhd=H$iRnR|Ej_4MrLpVowFp9V=DnDu)@je+|5xHC6jp3IrE z$7%B>)YgtIogYm4{Q)O^3Z`>ectU;nhvFQ0y{{QY4aSXv?BFbhc8 z1yu$nAmuQF0c>32Y&DQ*!`H2Qx7%B@x9|VE{rG;C1Fe>fK+y;PH|*WM|CXi2pU36v z7(gyNAoXkZ4|8RR5woC1Few0K7+N?RK$L(Qs`;am3=D~*fiM~fknA>^5=K+PXi9+B zKBL)TG&_uDhtcc+Y&ebv!e}6j_8mq$Pz}IrFxrb84TRD01YjB%4TRA^80{mC_K`;W zNThcU;&1PqFRJ_6pzrW^>m@fu%w8$nv@cW^(T&>ifx(7Ne6H*9%bq1{Ygxqgl*F4( zxGZ2(>N>pV(U(g$YqKu%>@5CO5c|6NYiwOb9sg)C3~G*y)cv%da+?lu2<+mGMunIGJo zd-vy~Yi|YrgOoieiI|p}mZlf;zigX+z1{8bb>}u$+n=@h@%`;a#)8*>i;L5K|Is;p zG3M8^XEg;sjaP%_;|^$UvaB$*7S})b=FPdZz4q<;^JS~c-`F$s^W8u5?CZZZVbPoa zo}9k#A2U#KLvUK;w8;M-pUc?XoV{1Reunt>_j1+ckAxpAK5V{u=FI2&?`#B5>&
)WO1bV}HCl_UXIu{qX*G=YO4?_Y~ww6@P~ZJvJqga5v`UDNkeJS@@KS9<%)w=yxQ z966OmdS(oRrPldBVCj#_0v~NTg9*TUn_h+Dp5s&O)1e(>5>5v zNI-wm-hFbb^se0hvD9hiS@-_Zyuat{TW5(b6ihpv;HL2%steeZauXQi4$=o9uZN70U)A^(6 z71xxrYL2IUSZNu^ Date: Wed, 30 Aug 2023 13:27:11 -0500 Subject: [PATCH 09/10] add back BorderSlice and fix perf on windows --- Features/FlxCamera/assets/BorderSlice.png | Bin 0 -> 559 bytes Features/FlxCamera/source/PlayState.hx | 6 ++--- .../FlxCamera/source/props/BorderSlice.hx | 24 ++++++++++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 Features/FlxCamera/assets/BorderSlice.png create mode 100644 Features/FlxCamera/source/props/BorderSlice.hx diff --git a/Features/FlxCamera/assets/BorderSlice.png b/Features/FlxCamera/assets/BorderSlice.png new file mode 100644 index 0000000000000000000000000000000000000000..1ff3f834537063b932952e962f2ca49b99cf5ac1 GIT binary patch literal 559 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nC-#^NA%Cx&(BWL^Tw6@P~ZJvJqga5v`UDNkeJS@@KS9<%)w=yxQ z966OmdS(oRrPldBVCj#_0v~NTg9*TUn_h+Dp5s&O)1e(>5>5v zNI-wm-hFbb^se0hvD9hiS@-_Zyuat{TW5(b6ihpv;HL2%steeZauXQi4$=o9uZN70U)A^(6 z71xxrYL2IUSZNu^ Date: Thu, 31 Aug 2023 10:44:44 -0500 Subject: [PATCH 10/10] more slice optimizations --- Features/FlxCamera/source/props/BorderSlice.hx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Features/FlxCamera/source/props/BorderSlice.hx b/Features/FlxCamera/source/props/BorderSlice.hx index 6c1045066..5c59e4503 100644 --- a/Features/FlxCamera/source/props/BorderSlice.hx +++ b/Features/FlxCamera/source/props/BorderSlice.hx @@ -8,10 +8,11 @@ abstract BorderSlice(FlxSliceSprite) from FlxSliceSprite to FlxSliceSprite { inline public function new (x = 0.0, y = 0.0, width:Float, height:Float) { - this = new FlxSliceSprite("assets/Border.png", new FlxRect(15, 15, 20, 20), width, height); + this = new FlxSliceSprite("assets/BorderSlice.png", new FlxRect(15, 15, 20, 20), width, height); this.x = x; this.y = y; // reduce vertice counts by stretching rather than tiling + this.fillCenter = false; this.stretchBottom = true; this.stretchTop = true; this.stretchLeft = true;