113 lines
6.1 KiB
Plaintext
113 lines
6.1 KiB
Plaintext
(function updateKeyControl [:FlxCamera camera :Float elapsed :Float speed :Void->Bool leftKey :Void->Bool rightKey :Void->Bool upKey :Void->Bool downKey]
|
|
(let [scrollAmount (* speed elapsed)
|
|
&mut :FlxVector movement (new FlxPoint)]
|
|
(when (leftKey) (-= movement.x 1))
|
|
(when (rightKey) (+= movement.x 1))
|
|
(when (upKey) (-= movement.y 1))
|
|
(when (downKey) (+= movement.y 1))
|
|
(when (< 0 movement.length)
|
|
(set movement (movement.normalize)))
|
|
(movement.scale scrollAmount)
|
|
(+= camera.scroll.x movement.x)
|
|
(+= camera.scroll.y movement.y)))
|
|
|
|
(var :Map<FlxCamera,FlxCamera> borderCameras (new Map))
|
|
|
|
// Add a border sprite on top of this camera's viewport, scaling the border to frame the viewport,
|
|
// and downsizing and shifting the viewport to fit within the border's opaque frame
|
|
(function addBorder [:FlxCamera camera :FlxSprite border]
|
|
(let [borderCamera
|
|
(new FlxCamera (Std.int camera.x) (Std.int camera.y) camera.width camera.height)
|
|
:BitmapData borderPixels
|
|
(border.updateFramePixels)
|
|
isTransparent
|
|
->c (= c FlxColor.TRANSPARENT)
|
|
borderHorizontal
|
|
(borderPixels.getVector (new Rectangle 0 (iHalf border.height) border.width 1))
|
|
borderVertical
|
|
(borderPixels.getVector (new Rectangle (iHalf border.width) 0 1 border.height))
|
|
borderSizeLeft
|
|
(borderHorizontal.findIndex isTransparent)
|
|
borderSizeTop
|
|
(borderVertical.findIndex isTransparent)
|
|
borderSizeRight
|
|
(.findIndex (borderHorizontal.reverse) isTransparent)
|
|
borderSizeBottom
|
|
(.findIndex (borderVertical.reverse) isTransparent)]
|
|
(set border.x 0) // It will be 0,0 relative to its own camera
|
|
(set border.y 0)
|
|
(border.setGraphicSize camera.width camera.height)
|
|
(border.updateHitbox)
|
|
(FlxG.cameras.add borderCamera false)
|
|
(dictSet borderCameras camera borderCamera)
|
|
(set border.cameras [borderCamera])
|
|
(set borderCamera.bgColor FlxColor.TRANSPARENT)
|
|
(FlxG.state.add border)
|
|
(let [dx (* border.scale.x borderSizeLeft)
|
|
dy (* border.scale.y borderSizeTop)]
|
|
(+= camera.x dx)
|
|
(+= camera.y dy)
|
|
(-= camera.width dx (* border.scale.x borderSizeRight))
|
|
(-= camera.height dy (* border.scale.y borderSizeBottom)))))
|
|
|
|
// GOTCHA: if you change FlxG.camera to a moving camera, you MUST provide a default camera for FlxG.mouse.getScreenPosition()
|
|
(function updateMouseBorderControl [:FlxCamera camera :Float elapsed :Float speed :Float heightFraction :FlxCamera screenCamera]
|
|
(let [viewport (ifLet [bc (dictGet borderCameras camera)] bc camera)
|
|
left viewport.x
|
|
top viewport.y
|
|
right (+ viewport.x viewport.width)
|
|
bottom (+ viewport.y viewport.height)
|
|
// Use the same margin size for x and y, and calculate it based on height
|
|
// (in a landscape view, this just makes more sense to me)
|
|
margin (* viewport.height heightFraction)
|
|
mPos (FlxG.mouse.getScreenPosition screenCamera)]
|
|
(updateKeyControl camera elapsed speed
|
|
// when the camera takes the whole screen, count the letterbox zones as margin
|
|
->(if (= left 0)
|
|
(<= mPos.x (+ left margin))
|
|
(<= left mPos.x (+ left margin)))
|
|
->(if (= right FlxG.width)
|
|
(<= (- right margin) mPos.x)
|
|
(<= (- right margin) mPos.x right))
|
|
->(if (= top 0)
|
|
(<= mPos.y (+ top margin))
|
|
(<= top mPos.y (+ top margin)))
|
|
->(if (= bottom FlxG.height)
|
|
(<= (- bottom margin) mPos.y)
|
|
(<= (- bottom margin) mPos.y bottom)))))
|
|
|
|
// GOTCHA: if you change FlxG.camera to a moving camera, you MUST provide a default camera for FlxG.mouse.getScreenPosition()
|
|
(function updateScrollWheelZoom [:FlxCamera camera :Float elapsed :Float speed &opt :FlxCamera screenCamera]
|
|
(case FlxG.mouse.wheel
|
|
(0 null)
|
|
(v
|
|
(let [deltaZoom (* camera.zoom v elapsed speed)
|
|
scrollPosition (camera.scroll.copyTo)
|
|
mouseWorldPosition (FlxG.mouse.getWorldPosition camera)]
|
|
(+= camera.zoom deltaZoom)
|
|
(let [newMouseWorldPosition (FlxG.mouse.getWorldPosition camera)
|
|
deltaMousePosition (newMouseWorldPosition.subtractPoint mouseWorldPosition)]
|
|
(camera.scroll.subtractPoint deltaMousePosition))
|
|
// Undo any zooming out that expands the viewport past its bounds
|
|
(when (> 0 deltaZoom)
|
|
(unless (.equals (camera.getViewRect) (.intersection (getScrollBounds camera) (camera.getViewRect)))
|
|
(-= camera.zoom deltaZoom)
|
|
(set camera.scroll scrollPosition)))))
|
|
(otherwise null)))
|
|
|
|
(function getScrollBounds [:FlxCamera camera]
|
|
(.fromTwoPoints (new FlxRect) (new FlxPoint camera.minScrollX camera.minScrollY) (new FlxPoint camera.maxScrollX camera.maxScrollY)))
|
|
|
|
// GOTCHA: if you change FlxG.camera to a moving camera, you MUST provide a default camera for FlxG.mouse.getScreenPosition()
|
|
(function calculateScrollBounds <>[:FlxSprite T] [:FlxCamera camera :FlxTypedGroup<T> group &opt :FlxCamera screenCamera :Float margin]
|
|
(let [r (GroupTools.calculateScreenBounds group screenCamera margin)]
|
|
(camera.setScrollBoundsRect r.x r.y r.width r.height)))
|
|
|
|
// GOTCHA: if you change FlxG.camera to a moving camera, you MUST provide a default camera for FlxG.mouse.getScreenPosition()
|
|
(function extendScrollBounds [:FlxCamera camera :FlxSprite sprite &opt :FlxCamera screenCamera :Float margin]
|
|
// if the given object is out of bounds, extend the bounds
|
|
(let [r (sprite.getScreenBounds camera)]
|
|
(setMin camera.minScrollX (- r.left margin))
|
|
(setMin camera.minScrollY (- r.top margin))
|
|
(setMax camera.maxScrollX (+ r.right margin))
|
|
(setMax camera.maxScrollY (+ r.bottom margin)))) |