瀏覽代碼

Add h2d Camera (#459)

Pavel Alexandrov 6 年之前
父節點
當前提交
cc837fec09
共有 2 個文件被更改,包括 174 次插入0 次删除
  1. 121 0
      h2d/Camera.hx
  2. 53 0
      samples/Camera2D.hx

+ 121 - 0
h2d/Camera.hx

@@ -0,0 +1,121 @@
+package h2d;
+
+class Camera extends h2d.Object {
+
+	/** X position of the camera anchor point. **/
+	public var viewX(get, set) : Float;
+	/** Y position of the camera anchor point. **/
+	public var viewY(get, set) : Float;
+
+	/** Current camera width. Cannot be set directly, please use `horizontalRatio`. **/
+	public var width(default, null) : Int;
+	/** Current camera height. Cannot be set directly, please use `verticalRatio`. **/
+	public var height(default, null) : Int;
+	/** Percent value of horizontal camera size relative to s2d size. (default : 1) **/
+	public var horizontalRatio(default, set) : Float;
+	/** Percent value of vertical camera size relative to s2d size. (default : 1) **/
+	public var verticalRatio(default, set) : Float;
+	/** Horizontal anchor position inside ratio boundaries used for anchoring and resize compensation. ( default : 0.5 ) **/
+	public var anchorX(default, set) : Float;
+	/** Vertical anchor position inside ratio boundaries used for anchoring and resize compensation. ( default : 0.5 ) **/
+	public var anchorY(default, set) : Float;
+
+	var ratioChanged : Bool;
+	var sceneWidth : Int;
+	var sceneHeight : Int;
+	var anchorWidth : Float;
+	var anchorHeight : Float;
+	var scene : Scene;
+
+	public function new( ?parent : h2d.Object, horizontalRatio : Float = 1, verticalRatio : Float = 1, anchorX : Float = 0.5, anchorY : Float = 0.5 ) {
+		super(parent);
+		this.horizontalRatio = horizontalRatio;
+		this.verticalRatio = verticalRatio;
+		this.anchorX = anchorX;
+		this.anchorY = anchorY;
+		this.width = 0; this.height = 0;
+		this.anchorWidth = 0; this.anchorHeight = 0;
+		this.sceneWidth = 0; this.sceneHeight = 0;
+		ratioChanged = true;
+		if ( parent != null ) {
+			initScene();
+		}
+	}
+
+	inline function get_viewX() { return -this.x + anchorWidth; }
+	inline function get_viewY() { return -this.y + anchorHeight; }
+
+	inline function set_viewX( v : Float ) {
+		this.x = -v - anchorWidth;
+		return -v;
+	}
+	inline function set_viewY( v : Float ) {
+		this.y = -v - anchorHeight;
+		return -v;
+	}
+
+	inline function set_horizontalRatio( v ) {
+		ratioChanged = true;
+		return horizontalRatio = hxd.Math.clamp(v, 0, 1);
+	}
+	
+	inline function set_verticalRatio( v ) {
+		ratioChanged = true;
+		return verticalRatio = hxd.Math.clamp(v, 0, 1);
+	}
+
+	inline function set_anchorX( v ) {
+		anchorX = hxd.Math.clamp(v, 0, 1);
+		anchorWidth = sceneWidth * anchorX;
+		return anchorX;
+	}
+
+	inline function set_anchorY( v ) {
+		anchorY = hxd.Math.clamp(v, 0, 1);
+		anchorHeight = sceneHeight * anchorY;
+		return anchorY;
+	}
+
+	override private function onAdd()
+	{
+		initScene();
+		super.onAdd();
+	}
+
+	override private function onRemove()
+	{
+		this.scene = null;
+		super.onRemove();
+	}
+
+	override private function sync( ctx : RenderContext )
+	{
+		if ( scene != null && (ratioChanged || scene.width != sceneWidth || scene.height != sceneHeight) ) {
+			var oldX = -this.x + anchorWidth;
+			var oldY = -this.y + anchorHeight;
+			this.sceneWidth = scene.width;
+			this.sceneHeight = scene.height;
+			this.width = Math.round(scene.width * horizontalRatio);
+			this.height = Math.round(scene.height * verticalRatio);
+			this.anchorWidth = width * anchorX;
+			this.anchorHeight = height * anchorY;
+			this.x = oldX - anchorWidth;
+			this.y = oldY - anchorHeight;
+			this.ratioChanged = false;
+		}
+		super.sync(ctx);
+	}
+
+	inline function initScene() {
+		this.scene = parent.getScene();
+		if ( scene != parent ) throw "Camera can be added only to Scene or MultiCamera!";
+		if ( sceneWidth == 0 )
+		{
+			sceneWidth = scene.width;
+			sceneHeight = scene.height;
+			anchorWidth = sceneWidth * anchorX;
+			anchorHeight = sceneHeight * anchorY;
+		}
+	}
+
+}

+ 53 - 0
samples/Camera2D.hx

@@ -0,0 +1,53 @@
+import h2d.Object;
+import h2d.Camera;
+import hxd.Timer;
+import h3d.mat.Texture;
+import h2d.Tile;
+
+class Camera2D extends SampleApp {
+
+	var followObject : h2d.Graphics;
+	var camera : Camera;
+
+	override private function init()
+	{
+		super.init();
+
+		// Initialize camera.
+		camera = new Camera(s2d);
+
+		// Backdrop to show the camera frame.
+		new h2d.Bitmap(h2d.Tile.fromColor(0xffffff, s2d.width, s2d.height, 0.2), camera);
+
+		// Interactive inside camera
+		var inter = new h2d.Interactive(100, 40, camera);
+		inter.backgroundColor = 0xff0000ff;
+		inter.x = s2d.width * .5 - 50;
+		inter.y = s2d.height * .5 - 20;
+		var interText = new h2d.Text(getFont(), inter);
+		interText.textAlign = Center;
+		interText.maxWidth = 100;
+		interText.text = "In-camera Interactive";
+
+		var camX = camera.x;
+		var camY = camera.y;
+		addText("Camera");
+		addSlider("Anchor X", function() { return camera.anchorX; }, function(v) { camera.anchorX = v; }, 0, 1);
+		addSlider("Anchor Y", function() { return camera.anchorY; }, function(v) { camera.anchorY = v; }, 0, 1);
+		addSlider("View X", function() { return camera.viewX; }, function(v) { camera.viewX = v; camX = camera.x; }, -s2d.width, s2d.width);
+		addSlider("View Y", function() { return camera.viewY; }, function(v) { camera.viewY = v; camY = camera.y; }, -s2d.height, s2d.height);
+		addSlider("X", function() { return camera.x; }, function(v) { camera.x = v; camX = v; }, -s2d.width, s2d.width);
+		addSlider("Y", function() { return camera.y; }, function(v) { camera.y = v; camY = v; }, -s2d.height, s2d.height);
+		// addSlider("Rotation", function() { return hxd.Math.radToDeg(camera.rotation); }, function(v) { camera.rotation = hxd.Math.degToRad(v); }, 0, 360);
+		addSlider("Scale X", function() { return camera.scaleX; }, function(v) { camera.scaleX = v; }, 0, 5);
+		addSlider("Scale Y", function() { return camera.scaleY; }, function(v) { camera.scaleY = v; }, 0, 5);
+
+	}
+
+	static function main() {
+		hxd.Res.initEmbed();
+		new Camera2D();
+	}
+
+
+}