I’ve been trying to wrap my head around using the h2d.Camera but I can’t quite get it just yet. Is there any basic example of using it so that my in-game elements are being followed while the HUD elements do not scroll with the background?
Actually once you’ve seen it it’s quite simple. You split the rendering for the scene that shows your game’s world and the scene that has the HUD/GUI. Like so:
// this method is from the hxd.App class, so override it in the class extending it
override function render(e:Engine) {
// all here are extending h2d.Scene (or h3d.Scene):
world.render(e); // your game's world, by default is the s2d scene and which has the camera
general_user_interface.render(e); // your HUD so to speak
}
Hope it works for you. Then you should be able to treat them separatedly.
import h3d.Engine;
import h2d.Scene;
class SomeApp extends hxd.App {
private var hud : h2d.Scene;
override function render(e:Engine) {
s2d.render(e);
hud.render(e);
}
override function update(dt:Float) {
moveCameraAround();
}
private function moveCameraAround() {
var c = s2d.camera;
if(hxd.Key.isPressed( hxd.Key.MOUSE_WHEEL_UP ))
c.scale(1.25, 1.25);
if(hxd.Key.isPressed( hxd.Key.MOUSE_WHEEL_DOWN ))
c.scale(0.8, 0.8);
var moveMapSpeed = 10;
if(hxd.Key.isDown( hxd.Key.RIGHT ))
c.x += moveMapSpeed / c.scaleX;
if(hxd.Key.isDown( hxd.Key.LEFT ))
c.x -= moveMapSpeed / c.scaleX;
if(hxd.Key.isDown( hxd.Key.DOWN ))
c.y += moveMapSpeed / c.scaleY;
if(hxd.Key.isDown( hxd.Key.UP ))
c.y -= moveMapSpeed / c.scaleY;
}
override function init() {
// world
var t = new h2d.Text( hxd.res.DefaultFont.get(), s2d );
t.setPosition( s2d.width/2, s2d.height/2 );
t.text = 'I´m fixed in the world';
// hud
this.hud = new MyHUD();
this.sevents.addScene( hud ); // otherwise the HUD cannot get evented by App.hxd, doesn't receive mouse interaction etc.
}
static function main() {
new SomeApp();
}
}
class MyHUD extends h2d.Scene {
public function new() {
super();
var ia = new h2d.Interactive( 200, 50, this );
ia.backgroundColor = 0xFFAAAAAA;
var t = new h2d.Text( hxd.res.DefaultFont.get(), ia );
t.text = "Button stays in HUD";
}
}
Oh, I was going to say that I was using the camera.follow
function to focus on the player entity and after I’ve overridden render
, it did work but some things like my ScaleMode goes funky and inconsistently behaving
late edit: actually when you use heaps buttons (h2d.Interactive
s) in your UI / HUD you would have to add another camera (just by new h2d.Camera();
) and configured like below:
// Second camera for sample controls
var uiCamera = new Camera();
// layerVisible allows to filter out layers that camera should not render.
uiCamera.layerVisible = (idx) -> idx == 2;
s2d.add(fui, 2);
// Add UI camera to scene. Note that order of cameras in array matters, as they are rendered in-order.
s2d.addCamera(uiCamera);
// Only one camera can handle user input events.
// When assigning newly-created camera as interactiveCamera - adding it to Scene can be omitted, as it will be added automatically.
s2d.interactiveCamera = uiCamera;
this is because only one camera can can response to click events.
and of course you use at least two layers like so:
final layer_world_stuff : Int = 0;
final layer_ui_or_hud : Int = 1; // must be higher value than in-world layer
see full code here! → https://github.com/HeapsIO/heaps/blob/98a780ecbcb23772267e3d23b735e7da08fbb57b/samples/Camera2D.hx#L69