468 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
		
		
			
		
	
	
			468 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
|  | package kha; | ||
|  | 
 | ||
|  | import kha.System.SystemOptions; | ||
|  | import kha.input.Keyboard; | ||
|  | import kha.input.KeyCode; | ||
|  | import kha.input.Mouse; | ||
|  | import kha.java.Graphics; | ||
|  | import kha.System; | ||
|  | import kha.Window; | ||
|  | import java.javax.swing.JFrame; | ||
|  | import java.lang.Class; | ||
|  | import java.lang.System in Sys; | ||
|  | import java.lang.Object; | ||
|  | import java.lang.Throwable; | ||
|  | import java.NativeArray; | ||
|  | 
 | ||
|  | @:access(kha.System) | ||
|  | class JWindow extends JFrame implements java.awt.event.KeyListener implements java.awt.event.MouseListener implements java.awt.event.MouseMotionListener | ||
|  | 		implements java.awt.event.MouseWheelListener { | ||
|  | 	public var instance: JWindow; | ||
|  | 
 | ||
|  | 	var WIDTH: Int; | ||
|  | 	var HEIGHT: Int; | ||
|  | 	var syncrate = 60; | ||
|  | 	var canvas: java.awt.Canvas; | ||
|  | 	var vsynced = false; | ||
|  | 	var reset = false; | ||
|  | 	var framebuffer: kha.Framebuffer; | ||
|  | 	var painter: kha.java.Painter; | ||
|  | 
 | ||
|  | 	public static var mouseX: Int; | ||
|  | 	public static var mouseY: Int; | ||
|  | 
 | ||
|  | 	public function new() { | ||
|  | 		super(); | ||
|  | 		instance = this; | ||
|  | 		painter = new kha.java.Painter(); | ||
|  | 		framebuffer = new kha.Framebuffer(0, null, painter, null); | ||
|  | 		var g1 = new kha.graphics2.Graphics1(framebuffer); | ||
|  | 		framebuffer.init(g1, painter, null); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public function start(): Void { | ||
|  | 		createGame(); | ||
|  | 		setupWindow(); | ||
|  | 		createVSyncedDoubleBuffer(); | ||
|  | 		mainLoop(); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	function setupWindow(): Void { | ||
|  | 		setIgnoreRepaint(true); | ||
|  | 		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); | ||
|  | 		canvas = new java.awt.Canvas(); | ||
|  | 		canvas.setIgnoreRepaint(true); | ||
|  | 		canvas.setSize(WIDTH, HEIGHT); | ||
|  | 		canvas.setFocusable(false); | ||
|  | 		add(canvas); | ||
|  | 		setResizable(false); | ||
|  | 		pack(); | ||
|  | 		var screen: java.awt.Dimension = java.awt.Toolkit.getDefaultToolkit().getScreenSize(); | ||
|  | 		var x = Std.int((screen.width - WIDTH) / 2); | ||
|  | 		var y = Std.int((screen.height - HEIGHT) / 2); | ||
|  | 		setLocation(x, y); | ||
|  | 		setTitle("Game"); | ||
|  | 		setVisible(true); | ||
|  | 		addKeyListener(this); | ||
|  | 		canvas.addMouseListener(this); | ||
|  | 		canvas.addMouseMotionListener(this); | ||
|  | 		canvas.addMouseWheelListener(this); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	function createVSyncedDoubleBuffer(): Void { | ||
|  | 		vsynced = true; | ||
|  | 		canvas.createBufferStrategy(2); | ||
|  | 		var bufferStrategy: java.awt.image.BufferStrategy = canvas.getBufferStrategy(); | ||
|  | 		if (bufferStrategy != null) { | ||
|  | 			var caps: java.awt.BufferCapabilities = bufferStrategy.getCapabilities(); | ||
|  | 			try { | ||
|  | 				// Class<?> | ||
|  | 				var ebcClass = Class.forName("sun.java2d.pipe.hw.ExtendedBufferCapabilities"); | ||
|  | 				var vstClass = Class.forName("sun.java2d.pipe.hw.ExtendedBufferCapabilities$VSyncType"); | ||
|  | 				// java.lang.reflect.Constructor<?> | ||
|  | 				// new Class[] { java.awt.BufferCapabilities.class, vstClass } | ||
|  | 				untyped var _class = untyped __java__("java.awt.BufferCapabilities.class"); | ||
|  | 				var classes: NativeArray<Class<Dynamic>> = NativeArray.make(_class, vstClass); | ||
|  | 				var ebcConstructor = ebcClass.getConstructor(classes[0]); | ||
|  | 				var vSyncType: Object = vstClass.getField("VSYNC_ON").get(null); | ||
|  | 				// (java.awt.BufferCapabilities) | ||
|  | 				// new Object[] | ||
|  | 				var objs: NativeArray<Object> = NativeArray.make(cast(caps, Object), vSyncType); | ||
|  | 				var newCaps: java.awt.BufferCapabilities = ebcConstructor.newInstance(objs); | ||
|  | 				canvas.createBufferStrategy(2, newCaps); | ||
|  | 				// setCanChangeRefreshRate(false); | ||
|  | 				// setRefreshRate(60); | ||
|  | 			} | ||
|  | 			catch (t:Throwable) { | ||
|  | 				vsynced = false; | ||
|  | 				t.printStackTrace(); | ||
|  | 				canvas.createBufferStrategy(2); | ||
|  | 			} | ||
|  | 		} | ||
|  | 		if (vsynced) | ||
|  | 			checkVSync(); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	function checkVSync(): Void { | ||
|  | 		var starttime = Sys.nanoTime(); | ||
|  | 		for (i in 0...3) { | ||
|  | 			canvas.getBufferStrategy().show(); | ||
|  | 			java.awt.Toolkit.getDefaultToolkit().sync(); | ||
|  | 		} | ||
|  | 		var endtime = Sys.nanoTime(); | ||
|  | 		if (endtime - starttime > 1000 * 1000 * 1000 / 60) { | ||
|  | 			vsynced = true; | ||
|  | 			Sys.out.println("VSync enabled."); | ||
|  | 		} | ||
|  | 		else | ||
|  | 			Sys.out.println("VSync not enabled, sorry."); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	function mainLoop(): Void { | ||
|  | 		var lasttime = Sys.nanoTime(); | ||
|  | 		while (true) { | ||
|  | 			if (vsynced) | ||
|  | 				update(); | ||
|  | 			else { | ||
|  | 				var time = Sys.nanoTime(); | ||
|  | 				while (time >= lasttime + 1000 * 1000 * 1000 / syncrate) { | ||
|  | 					lasttime += 1000 * 1000 * 1000 / syncrate; | ||
|  | 					update(); | ||
|  | 				} | ||
|  | 			} | ||
|  | 			render(); | ||
|  | 			if (reset) | ||
|  | 				resetGame(); | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	function createGame(): Void { | ||
|  | 		WIDTH = System.windowWidth(); | ||
|  | 		HEIGHT = System.windowHeight(); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	function resetGame(): Void { | ||
|  | 		reset = false; | ||
|  | 		createGame(); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	@:overload | ||
|  | 	function update(): Void { | ||
|  | 		Scheduler.executeFrame(); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	function render(): Void { | ||
|  | 		var bf: java.awt.image.BufferStrategy = canvas.getBufferStrategy(); | ||
|  | 		var g: java.awt.Graphics2D = null; | ||
|  | 		try { | ||
|  | 			g = cast bf.getDrawGraphics(); | ||
|  | 			painter.graphics = g; | ||
|  | 			painter.setRenderHint(); | ||
|  | 			System.render([framebuffer]); | ||
|  | 		} | ||
|  | 		catch (e:Any) { | ||
|  | 			trace(e); | ||
|  | 		} | ||
|  | 		g.dispose(); | ||
|  | 		bf.show(); | ||
|  | 		java.awt.Toolkit.getDefaultToolkit().sync(); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	@Override | ||
|  | 	public function keyPressed(e: java.awt.event.KeyEvent): Void { | ||
|  | 		// var keyCode: Int = e.getKeyCode(); | ||
|  | 		// switch (keyCode) { | ||
|  | 		// case java.awt.event.KeyEvent.VK_RIGHT: | ||
|  | 		// 	pressKey(keyCode, KeyCode.RIGHT); | ||
|  | 		// case java.awt.event.KeyEvent.VK_LEFT: | ||
|  | 		// 	pressKey(keyCode, KeyCode.LEFT); | ||
|  | 		// case java.awt.event.KeyEvent.VK_UP: | ||
|  | 		// 	pressKey(keyCode, KeyCode.UP); | ||
|  | 		// case java.awt.event.KeyEvent.VK_DOWN: | ||
|  | 		// 	pressKey(keyCode, KeyCode.DOWN); | ||
|  | 		// case java.awt.event.KeyEvent.VK_SPACE: | ||
|  | 		// 	pressKey(keyCode, KeyCode.BUTTON_1); | ||
|  | 		// case java.awt.event.KeyEvent.VK_CONTROL: | ||
|  | 		// 	pressKey(keyCode, KeyCode.BUTTON_2); | ||
|  | 		// case java.awt.event.KeyEvent.VK_ENTER: | ||
|  | 		// 	//pressKey(keyCode, Key.ENTER); | ||
|  | 		// case java.awt.event.KeyEvent.VK_BACK_SPACE: | ||
|  | 		// 	//pressKey(keyCode, Key.BACKSPACE); | ||
|  | 		// default: | ||
|  | 		// } | ||
|  | 	} | ||
|  | 
 | ||
|  | 	@Override | ||
|  | 	public function keyReleased(e: java.awt.event.KeyEvent): Void { | ||
|  | 		// var keyCode: Int = e.getKeyCode(); | ||
|  | 		// switch (keyCode) { | ||
|  | 		// case java.awt.event.KeyEvent.VK_RIGHT: | ||
|  | 		// 	releaseKey(keyCode, KeyCode.RIGHT); | ||
|  | 		// case java.awt.event.KeyEvent.VK_LEFT: | ||
|  | 		// 	releaseKey(keyCode, KeyCode.LEFT); | ||
|  | 		// case java.awt.event.KeyEvent.VK_UP: | ||
|  | 		// 	releaseKey(keyCode, KeyCode.UP); | ||
|  | 		// case java.awt.event.KeyEvent.VK_DOWN: | ||
|  | 		// 	releaseKey(keyCode, KeyCode.DOWN); | ||
|  | 		// case java.awt.event.KeyEvent.VK_SPACE: | ||
|  | 		// 	releaseKey(keyCode, KeyCode.BUTTON_1); | ||
|  | 		// case java.awt.event.KeyEvent.VK_CONTROL: | ||
|  | 		// 	releaseKey(keyCode, KeyCode.BUTTON_2); | ||
|  | 		// case java.awt.event.KeyEvent.VK_ENTER: | ||
|  | 		// 	//releaseKey(keyCode, Key.ENTER); | ||
|  | 		// case java.awt.event.KeyEvent.VK_BACK_SPACE: | ||
|  | 		// 	//releaseKey(keyCode, Key.BACKSPACE); | ||
|  | 		// default: | ||
|  | 		// } | ||
|  | 	} | ||
|  | 
 | ||
|  | 	@Override | ||
|  | 	public function keyTyped(e: java.awt.event.KeyEvent): Void { | ||
|  | 		// game.charKey(e.getKeyChar()); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public function getSyncrate(): Int { | ||
|  | 		return syncrate; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	@Override | ||
|  | 	public function mouseClicked(arg0: java.awt.event.MouseEvent): Void {} | ||
|  | 
 | ||
|  | 	@Override | ||
|  | 	public function mouseEntered(arg0: java.awt.event.MouseEvent): Void {} | ||
|  | 
 | ||
|  | 	@Override | ||
|  | 	public function mouseExited(arg0: java.awt.event.MouseEvent): Void {} | ||
|  | 
 | ||
|  | 	@Override | ||
|  | 	public function mousePressed(arg0: java.awt.event.MouseEvent): Void { | ||
|  | 		mouseX = arg0.getX(); | ||
|  | 		mouseY = arg0.getY(); | ||
|  | 
 | ||
|  | 		// if (javax.swing.SwingUtilities.isLeftMouseButton(arg0)) | ||
|  | 		// 	game.mouseDown(arg0.getX(), arg0.getY()); | ||
|  | 		// else if (javax.swing.SwingUtilities.isRightMouseButton(arg0)) | ||
|  | 		// 	game.rightMouseDown(arg0.getX(), arg0.getY()); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	@Override | ||
|  | 	public function mouseReleased(arg0: java.awt.event.MouseEvent): Void { | ||
|  | 		mouseX = arg0.getX(); | ||
|  | 		mouseY = arg0.getY(); | ||
|  | 
 | ||
|  | 		// if (javax.swing.SwingUtilities.isLeftMouseButton(arg0)) | ||
|  | 		// 	game.mouseUp(arg0.getX(), arg0.getY()); | ||
|  | 		// else if (javax.swing.SwingUtilities.isRightMouseButton(arg0)) | ||
|  | 		// 	game.rightMouseUp(arg0.getX(), arg0.getY()); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	@Override | ||
|  | 	public function mouseDragged(arg0: java.awt.event.MouseEvent): Void { | ||
|  | 		mouseX = arg0.getX(); | ||
|  | 		mouseY = arg0.getY(); | ||
|  | 		// game.mouseMove(arg0.getPoint().x, arg0.getPoint().y); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	@Override | ||
|  | 	public function mouseMoved(arg0: java.awt.event.MouseEvent): Void { | ||
|  | 		mouseX = arg0.getX(); | ||
|  | 		mouseY = arg0.getY(); | ||
|  | 		// if (game != null) game.mouseMove(arg0.getPoint().x, arg0.getPoint().y); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	@Override | ||
|  | 	public function mouseWheelMoved(arg0: java.awt.event.MouseWheelEvent): Void { | ||
|  | 		mouseX = arg0.getX(); | ||
|  | 		mouseY = arg0.getY(); | ||
|  | 
 | ||
|  | 		// game.mouseWheel(-arg0.getWheelRotation()); //invert | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | @:allow(kha.SystemImpl.JWindow) | ||
|  | class SystemImpl { | ||
|  | 	public static var graphics(default, null): Graphics; | ||
|  | 	static var keyboard: Keyboard; | ||
|  | 	static var mouse: Mouse; | ||
|  | 	static var keyreleased: Array<Bool>; | ||
|  | 
 | ||
|  | 	public static function init(options: SystemOptions, callback: Window->Void) { | ||
|  | 		init2(); | ||
|  | 		Scheduler.init(); | ||
|  | 		if (options.width != -1) | ||
|  | 			myPixelWidth = options.width; | ||
|  | 		if (options.height != -1) | ||
|  | 			myPixelHeight = options.height; | ||
|  | 
 | ||
|  | 		var window = new Window(options.width, options.height); | ||
|  | 		Scheduler.start(); | ||
|  | 		callback(window); | ||
|  | 		var jWindow = new JWindow(); | ||
|  | 		jWindow.start(); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public static function initEx(title: String, options: Array<WindowOptions>, windowCallback: Int->Void, callback: Window->Void) { | ||
|  | 		init({title: title, width: options[0].width, height: options[0].height}, callback); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	static var startTime: Float; | ||
|  | 
 | ||
|  | 	public static function init2(): Void { | ||
|  | 		graphics = new Graphics(); | ||
|  | 		startTime = getTimestamp(); | ||
|  | 		mouse = new Mouse(); | ||
|  | 		keyboard = new Keyboard(); | ||
|  | 		keyreleased = [for (i in 0...256) true]; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public static function getKeyboard(num: Int): Keyboard { | ||
|  | 		if (num == 0) | ||
|  | 			return keyboard; | ||
|  | 		else | ||
|  | 			return null; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public static function getMouse(num: Int): Mouse { | ||
|  | 		if (num == 0) | ||
|  | 			return mouse; | ||
|  | 		else | ||
|  | 			return null; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	function pressKey(keyCode: Int, button: KeyCode): Void { | ||
|  | 		if (keyreleased[keyCode]) { // avoid auto-repeat | ||
|  | 			keyreleased[keyCode] = false; | ||
|  | 			keyboard.sendDownEvent(button); | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	function releaseKey(keyCode: Int, button: KeyCode): Void { | ||
|  | 		keyreleased[keyCode] = true; | ||
|  | 		keyboard.sendUpEvent(button); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public static function getFrequency(): Int { | ||
|  | 		return 1000; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public static function getTimestamp(): Float { | ||
|  | 		return cast java.lang.System.currentTimeMillis(); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public static function getTime(): Float { | ||
|  | 		return (getTimestamp() - startTime) / getFrequency(); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public static function getScreenRotation(): ScreenRotation { | ||
|  | 		return ScreenRotation.RotationNone; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public static function getVsync(): Bool { | ||
|  | 		return true; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public static function getRefreshRate(): Int { | ||
|  | 		return 60; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public static function getSystemId(): String { | ||
|  | 		return "java"; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public static function vibrate(ms: Int): Void {} | ||
|  | 
 | ||
|  | 	public static function getLanguage(): String { | ||
|  | 		final lang = java.util.Locale.getDefault().getLanguage(); | ||
|  | 		return lang.substr(0, 2).toLowerCase(); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	static var myPixelWidth = 640; | ||
|  | 	static var myPixelHeight = 480; | ||
|  | 
 | ||
|  | 	public static function windowWidth(id: Int): Int { | ||
|  | 		return myPixelWidth; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public static function windowHeight(id: Int): Int { | ||
|  | 		return myPixelHeight; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public static function screenDpi(): Int { | ||
|  | 		return 96; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public static function changeResolution(width: Int, height: Int): Void {} | ||
|  | 
 | ||
|  | 	public static function requestShutdown(): Bool { | ||
|  | 		return false; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public static function canSwitchFullscreen(): Bool { | ||
|  | 		return false; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public static function isFullscreen(): Bool { | ||
|  | 		return false; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public static function requestFullscreen(): Void {} | ||
|  | 
 | ||
|  | 	public static function exitFullscreen(): Void {} | ||
|  | 
 | ||
|  | 	public static function notifyOfFullscreenChange(func: Void->Void, error: Void->Void): Void {} | ||
|  | 
 | ||
|  | 	public static function removeFromFullscreenChange(func: Void->Void, error: Void->Void): Void {} | ||
|  | 
 | ||
|  | 	public function lockMouse(): Void {} | ||
|  | 
 | ||
|  | 	public function unlockMouse(): Void {} | ||
|  | 
 | ||
|  | 	public function canLockMouse(): Bool { | ||
|  | 		return false; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public function isMouseLocked(): Bool { | ||
|  | 		return false; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public function notifyOfMouseLockChange(func: Void->Void, error: Void->Void): Void {} | ||
|  | 
 | ||
|  | 	public function removeFromMouseLockChange(func: Void->Void, error: Void->Void): Void {} | ||
|  | 
 | ||
|  | 	public static function setKeepScreenOn(on: Bool): Void {} | ||
|  | 
 | ||
|  | 	public static function loadUrl(url: String): Void {} | ||
|  | 
 | ||
|  | 	public static function safeZone(): Float { | ||
|  | 		return 1.0; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public static function waitingForLogin(): Bool { | ||
|  | 		return false; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public static function disallowUserChange(): Void {} | ||
|  | 
 | ||
|  | 	public static function allowUserChange(): Void {} | ||
|  | 
 | ||
|  | 	public static function login(): Void {} | ||
|  | 
 | ||
|  | 	public static function automaticSafeZone(): Bool { | ||
|  | 		return true; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public static function setSafeZone(value: Float): Void {} | ||
|  | 
 | ||
|  | 	public static function unlockAchievement(id: Int): Void {} | ||
|  | 
 | ||
|  | 	public static function getGamepadId(index: Int): String { | ||
|  | 		return "unkown"; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public static function getGamepadVendor(index: Int): String { | ||
|  | 		return "unknown"; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public static function setGamepadRumble(index: Int, leftAmount: Float, rightAmount: Float) {} | ||
|  | } |