diff --git a/src/main/java/labs/introtoprogramming/lab5/Main.java b/src/main/java/labs/introtoprogramming/lab5/Main.java index e0c95fb..1616f55 100644 --- a/src/main/java/labs/introtoprogramming/lab5/Main.java +++ b/src/main/java/labs/introtoprogramming/lab5/Main.java @@ -1,11 +1,39 @@ package labs.introtoprogramming.lab5; -import labs.introtoprogramming.lab5.exception.NotImplementedException; +import labs.introtoprogramming.lab5.controllers.KeyAndMouseMovementController; +import labs.introtoprogramming.lab5.geometry.Vector3; +import labs.introtoprogramming.lab5.graphics.BufferedImageRaster; +import labs.introtoprogramming.lab5.graphics.Raster; +import labs.introtoprogramming.lab5.gui.SceneRendererWindow; +import labs.introtoprogramming.lab5.scene.Scene; +import labs.introtoprogramming.lab5.scene.Camera; +import labs.introtoprogramming.lab5.scene.Transform; +import labs.introtoprogramming.lab5.scenes.DemoScene; public class Main { + private static final String APP_TILE = "ray tracing demo"; + private static final int SCREEN_WIDTH = 640; + private static final int SCREEN_HEIGHT = 640; + public static void main(String[] args) { - throw new NotImplementedException(); + new Main().run(); } + private void run() { + Scene demoScene = new DemoScene(); + Camera camera = createCamera(); + demoScene.addSceneObjects(camera); + demoScene.addController(new KeyAndMouseMovementController(camera)); + + SceneRendererWindow window = new SceneRendererWindow(demoScene); + window.setTitle(APP_TILE); + window.setDisplayFPS(true); + window.show(); + } + + private Camera createCamera() { + Raster raster = new BufferedImageRaster(SCREEN_WIDTH, SCREEN_HEIGHT); + return new Camera(raster, new Transform(Vector3.ZERO)); + } } diff --git a/src/main/java/labs/introtoprogramming/lab5/controllers/Controller.java b/src/main/java/labs/introtoprogramming/lab5/controllers/Controller.java new file mode 100644 index 0000000..72a8e46 --- /dev/null +++ b/src/main/java/labs/introtoprogramming/lab5/controllers/Controller.java @@ -0,0 +1,9 @@ +package labs.introtoprogramming.lab5.controllers; + +import labs.introtoprogramming.lab5.gui.Input; + +public abstract class Controller { + + public abstract void update(int delta, Input input); + +} diff --git a/src/main/java/labs/introtoprogramming/lab5/controllers/KeyAndMouseMovementController.java b/src/main/java/labs/introtoprogramming/lab5/controllers/KeyAndMouseMovementController.java new file mode 100644 index 0000000..4818230 --- /dev/null +++ b/src/main/java/labs/introtoprogramming/lab5/controllers/KeyAndMouseMovementController.java @@ -0,0 +1,28 @@ +package labs.introtoprogramming.lab5.controllers; + +import labs.introtoprogramming.lab5.gui.Input; +import labs.introtoprogramming.lab5.scene.SceneObject; + +public class KeyAndMouseMovementController extends Controller { + + private static double DEFAULT_MOVEMENT_SPEED = 0.0015; + private static double DEFAULT_MOUSE_SENSITIVITY = 0.006; + private double movementSpeed = DEFAULT_MOVEMENT_SPEED; + private double mouseSensitivity = DEFAULT_MOUSE_SENSITIVITY; + + private SceneObject controllableObject; + + public KeyAndMouseMovementController(SceneObject controllableObject) { + this.controllableObject = controllableObject; + } + + @Override + public void update(int delta, Input input) { + controllableObject.getTransform().setPosition(controllableObject.getTransform().position().add( + input.movementVector().multiply(movementSpeed * delta) + )); + controllableObject.getTransform().setRotation(controllableObject.getTransform().rotation().add( + input.mouseMovement().multiply(mouseSensitivity * delta) + )); + } +} diff --git a/src/main/java/labs/introtoprogramming/lab5/graphics/BufferedImageRaster.java b/src/main/java/labs/introtoprogramming/lab5/graphics/BufferedImageRaster.java index 874b74e..b7eaecf 100644 --- a/src/main/java/labs/introtoprogramming/lab5/graphics/BufferedImageRaster.java +++ b/src/main/java/labs/introtoprogramming/lab5/graphics/BufferedImageRaster.java @@ -3,6 +3,7 @@ import java.awt.Color; import java.awt.GraphicsEnvironment; import java.awt.Image; +import java.awt.Transparency; import java.awt.image.BufferedImage; public class BufferedImageRaster implements Raster { @@ -14,9 +15,9 @@ public BufferedImageRaster(int width, int height) { if (!GraphicsEnvironment.isHeadless()) { image = GraphicsEnvironment.getLocalGraphicsEnvironment() .getDefaultScreenDevice() - .getDefaultConfiguration().createCompatibleImage(width, height); + .getDefaultConfiguration().createCompatibleImage(width, height, Transparency.BITMASK); } else { - image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); } } diff --git a/src/main/java/labs/introtoprogramming/lab5/gui/Input.java b/src/main/java/labs/introtoprogramming/lab5/gui/Input.java new file mode 100644 index 0000000..2f131a7 --- /dev/null +++ b/src/main/java/labs/introtoprogramming/lab5/gui/Input.java @@ -0,0 +1,59 @@ +package labs.introtoprogramming.lab5.gui; + +import labs.introtoprogramming.lab5.geometry.Vector3; + +public class Input { + + private boolean forwardKeyDown = false; + private boolean backwardKeyDown = false; + private boolean leftKeyDown = false; + private boolean rightKeyDown = false; + private boolean upKeyDown = false; + private boolean downKeyDown = false; + + private double mouseDeltaX = 0; + private double mouseDeltaY = 0; + + public Vector3 movementVector() { + return new Vector3((leftKeyDown ? -1 : 0) + (rightKeyDown ? 1 : 0), + (upKeyDown ? 1 : 0) + (downKeyDown ? -1 : 0), + (forwardKeyDown ? -1 : 0) + (backwardKeyDown ? 1 : 0)); + } + + public Vector3 mouseMovement() { + //noinspection SuspiciousNameCombination + return new Vector3(mouseDeltaY, mouseDeltaX, 0); + } + + public void setMouseDeltaX(double mouseDeltaX) { + this.mouseDeltaX = mouseDeltaX; + } + + public void setMouseDeltaY(double mouseDeltaY) { + this.mouseDeltaY = mouseDeltaY; + } + + public void setForwardKeyDown(boolean forwardKeyDown) { + this.forwardKeyDown = forwardKeyDown; + } + + public void setBackwardKeyDown(boolean backwardKeyDown) { + this.backwardKeyDown = backwardKeyDown; + } + + public void setLeftKeyDown(boolean leftKeyDown) { + this.leftKeyDown = leftKeyDown; + } + + public void setRightKeyDown(boolean rightKeyDown) { + this.rightKeyDown = rightKeyDown; + } + + public void setUpKeyDown(boolean upKeyDown) { + this.upKeyDown = upKeyDown; + } + + public void setDownKeyDown(boolean downKeyDown) { + this.downKeyDown = downKeyDown; + } +} diff --git a/src/main/java/labs/introtoprogramming/lab5/gui/InputKeyListener.java b/src/main/java/labs/introtoprogramming/lab5/gui/InputKeyListener.java new file mode 100644 index 0000000..4e37221 --- /dev/null +++ b/src/main/java/labs/introtoprogramming/lab5/gui/InputKeyListener.java @@ -0,0 +1,49 @@ +package labs.introtoprogramming.lab5.gui; + +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; + +class InputKeyListener implements KeyListener { + + private Input input; + + InputKeyListener(Input input) { + this.input = input; + } + + @Override + public void keyTyped(KeyEvent e) { + // ignore + } + + @Override + public void keyPressed(KeyEvent e) { + keyCodeUpdate(e.getKeyCode(), true); + } + + @Override + public void keyReleased(KeyEvent e) { + keyCodeUpdate(e.getKeyCode(), false); + } + + private void keyCodeUpdate(int keyCode, boolean isDown) { + if (keyCode == KeyEvent.VK_W || keyCode == KeyEvent.VK_UP) { + input.setForwardKeyDown(isDown); + } + if (keyCode == KeyEvent.VK_S || keyCode == KeyEvent.VK_DOWN) { + input.setBackwardKeyDown(isDown); + } + if (keyCode == KeyEvent.VK_A || keyCode == KeyEvent.VK_LEFT) { + input.setLeftKeyDown(isDown); + } + if (keyCode == KeyEvent.VK_D || keyCode == KeyEvent.VK_RIGHT) { + input.setRightKeyDown(isDown); + } + if (keyCode == KeyEvent.VK_Q) { + input.setUpKeyDown(isDown); + } + if (keyCode == KeyEvent.VK_Z) { + input.setDownKeyDown(isDown); + } + } +} diff --git a/src/main/java/labs/introtoprogramming/lab5/gui/MouseController.java b/src/main/java/labs/introtoprogramming/lab5/gui/MouseController.java new file mode 100644 index 0000000..5909296 --- /dev/null +++ b/src/main/java/labs/introtoprogramming/lab5/gui/MouseController.java @@ -0,0 +1,57 @@ +package labs.introtoprogramming.lab5.gui; + +import java.awt.AWTException; +import java.awt.Cursor; +import java.awt.MouseInfo; +import java.awt.Point; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.image.BufferedImage; +import javax.swing.JFrame; + +class MouseController { + + private static final String BLANK_CURSOR_NAME = "blank cursor"; + + private Input input; + private JFrame frame; + + private Robot robot; + private Point prevLocation; + + MouseController(Input input, JFrame frame) { + this.input = input; + this.frame = frame; + try { + this.robot = new Robot(); + } catch(AWTException e) { + throw new AssertionError(e); + } + } + + void hideCursor() { + BufferedImage cursorImg = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB); + Cursor blankCursor = Toolkit.getDefaultToolkit().createCustomCursor( + cursorImg, new Point(0, 0), BLANK_CURSOR_NAME); + frame.setCursor(blankCursor); + } + + void update() { + if (!frame.isFocused()) { + return; + } + + int centerX = frame.getX() + frame.getWidth() / 2; + int centerY = frame.getY() + frame.getHeight() / 2; + Point mouseLocation = MouseInfo.getPointerInfo().getLocation(); + + if (prevLocation != null) { + input.setMouseDeltaX(mouseLocation.getX() - centerX); + input.setMouseDeltaY(mouseLocation.getY() - centerY); + } + + prevLocation = mouseLocation; + robot.mouseMove(centerX, centerY); + } + +} diff --git a/src/main/java/labs/introtoprogramming/lab5/gui/SceneRendererWindow.java b/src/main/java/labs/introtoprogramming/lab5/gui/SceneRendererWindow.java new file mode 100644 index 0000000..8388086 --- /dev/null +++ b/src/main/java/labs/introtoprogramming/lab5/gui/SceneRendererWindow.java @@ -0,0 +1,68 @@ +package labs.introtoprogramming.lab5.gui; + +import java.util.Timer; +import java.util.TimerTask; +import labs.introtoprogramming.lab5.exception.NoCameraException; +import labs.introtoprogramming.lab5.scene.BasicRaytracingRender; +import labs.introtoprogramming.lab5.scene.Scene; +import labs.introtoprogramming.lab5.scene.SceneRender; + +public class SceneRendererWindow extends Window { + + private static final String UPDATE_LOOP_TIMER_NAME = "UpdateLoop"; + private static final int UPDATE_LOOP_DELAY = 100; // ms + private static final int TARGET_FPS = 60; + private static final int UPDATE_RATE = 1000/TARGET_FPS; + + private SceneRender render; + private Scene scene; + private MouseController mouseController; + private Input input; + + public SceneRendererWindow(Scene scene) { + this(new BasicRaytracingRender(scene), scene); + } + + public SceneRendererWindow(SceneRender render, Scene scene) { + this.render = render; + this.scene = scene; + input = new Input(); + scene.getCamera().ifPresent(camera -> setRaster(camera.raster())); + mouseController = new MouseController(input, frame); + } + + public void show() { + super.show(); + startUpdateLoop(); + setupKeyboardListener(); + mouseController.hideCursor(); + } + + private void setupKeyboardListener() { + frame.addKeyListener(new InputKeyListener(input)); + } + + private void startUpdateLoop() { + new Timer(UPDATE_LOOP_TIMER_NAME, true).scheduleAtFixedRate(new TimerTask() { + long previousTime = System.currentTimeMillis(); + + @Override + public void run() { + long currentTime = System.currentTimeMillis(); + updateIteration((int) (currentTime - previousTime)); + previousTime = currentTime; + } + }, UPDATE_LOOP_DELAY, UPDATE_RATE); + } + + private void updateIteration(int delta) { + this.mouseController.update(); + scene.update(delta, input); + render.render(scene); + this.update(); + } + + private void setScene(Scene scene) { + this.scene = scene; + } +} diff --git a/src/main/java/labs/introtoprogramming/lab5/gui/Window.java b/src/main/java/labs/introtoprogramming/lab5/gui/Window.java index 2759e57..25a6cc4 100644 --- a/src/main/java/labs/introtoprogramming/lab5/gui/Window.java +++ b/src/main/java/labs/introtoprogramming/lab5/gui/Window.java @@ -8,7 +8,7 @@ public class Window { private static final int FPS_UPDATE_RATE = 100; - private JFrame frame; + protected JFrame frame; private RasterRendererComponent renderer; private Toolkit toolkit; private String title; @@ -74,6 +74,7 @@ public void setTitle(String text) { } public void setRaster(Raster raster) { + setDimensions(raster.getWidth(), raster.getHeight()); this.renderer.setRaster(raster); } diff --git a/src/main/java/labs/introtoprogramming/lab5/scene/BasicRaytracingRender.java b/src/main/java/labs/introtoprogramming/lab5/scene/BasicRaytracingRender.java index 9ae2c15..339bece 100644 --- a/src/main/java/labs/introtoprogramming/lab5/scene/BasicRaytracingRender.java +++ b/src/main/java/labs/introtoprogramming/lab5/scene/BasicRaytracingRender.java @@ -10,6 +10,14 @@ public class BasicRaytracingRender implements SceneRender { private Raster raster; + public BasicRaytracingRender(Scene scene) { + this(scene.getCamera().orElseThrow(NoCameraException::new)); + } + + public BasicRaytracingRender(Camera camera) { + this(camera.raster()); + } + public BasicRaytracingRender(Raster raster) { this.raster = raster; } diff --git a/src/main/java/labs/introtoprogramming/lab5/scene/BasicScene.java b/src/main/java/labs/introtoprogramming/lab5/scene/BasicScene.java index ab695bc..8554b07 100644 --- a/src/main/java/labs/introtoprogramming/lab5/scene/BasicScene.java +++ b/src/main/java/labs/introtoprogramming/lab5/scene/BasicScene.java @@ -1,12 +1,16 @@ package labs.introtoprogramming.lab5.scene; import java.awt.Color; +import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; +import labs.introtoprogramming.lab5.controllers.Controller; +import labs.introtoprogramming.lab5.gui.Input; -public class BasicScene implements Scene { +public class BasicScene extends Scene { private List entities; + private List controllers = new ArrayList<>(); private Color background; public BasicScene(List entities, Color background) { @@ -18,6 +22,15 @@ public BasicScene(List entities) { this(entities, new Color(0, 0, 0)); } + public BasicScene() { + this(new ArrayList<>()); + } + + @Override + public void update(int delta, Input input) { + controllers.forEach(controller -> controller.update(delta, input)); + } + @Override public List getSceneObjects() { return entities; @@ -31,6 +44,11 @@ public List getLights() { .collect(Collectors.toList()); } + @Override + public List getControllers() { + return controllers; + } + @Override public Optional getCamera() { return entities.stream() @@ -43,4 +61,14 @@ public Optional getCamera() { public Color getBackgroundColor() { return background; } + + @Override + public void addSceneObject(SceneObject obj) { + entities.add(obj); + } + + @Override + public void addController(Controller controller) { + this.controllers.add(controller); + } } diff --git a/src/main/java/labs/introtoprogramming/lab5/scene/Camera.java b/src/main/java/labs/introtoprogramming/lab5/scene/Camera.java index 80ac2ba..2571c2e 100644 --- a/src/main/java/labs/introtoprogramming/lab5/scene/Camera.java +++ b/src/main/java/labs/introtoprogramming/lab5/scene/Camera.java @@ -57,4 +57,8 @@ public void lookAt(Vector3 from, Vector3 to) { Vector3 up = forward.crossProduct(right); transform.setMatrix(right, up, forward, from); } + + public Raster raster() { + return raster; + } } diff --git a/src/main/java/labs/introtoprogramming/lab5/scene/Scene.java b/src/main/java/labs/introtoprogramming/lab5/scene/Scene.java index dad60a4..dfc6ea2 100644 --- a/src/main/java/labs/introtoprogramming/lab5/scene/Scene.java +++ b/src/main/java/labs/introtoprogramming/lab5/scene/Scene.java @@ -1,17 +1,31 @@ package labs.introtoprogramming.lab5.scene; import java.awt.Color; +import java.util.Arrays; import java.util.List; import java.util.Optional; +import labs.introtoprogramming.lab5.controllers.Controller; +import labs.introtoprogramming.lab5.gui.Input; -public interface Scene { +public abstract class Scene { - List getSceneObjects(); + public abstract void update(int delta, Input input); - List getLights(); + public abstract List getSceneObjects(); - Optional getCamera(); + public abstract List getLights(); - Color getBackgroundColor(); + public abstract List getControllers(); + public abstract Optional getCamera(); + + abstract Color getBackgroundColor(); + + public abstract void addSceneObject(SceneObject obj); + + public void addSceneObjects(SceneObject... obj) { + Arrays.stream(obj).forEach(this::addSceneObject); + } + + public abstract void addController(Controller controller); } diff --git a/src/main/java/labs/introtoprogramming/lab5/scenes/DemoScene.java b/src/main/java/labs/introtoprogramming/lab5/scenes/DemoScene.java new file mode 100644 index 0000000..6b65c44 --- /dev/null +++ b/src/main/java/labs/introtoprogramming/lab5/scenes/DemoScene.java @@ -0,0 +1,18 @@ +package labs.introtoprogramming.lab5.scenes; + +import labs.introtoprogramming.lab5.geometry.Vector3; +import labs.introtoprogramming.lab5.object.Box; +import labs.introtoprogramming.lab5.object.Sphere; +import labs.introtoprogramming.lab5.scene.BasicScene; +import labs.introtoprogramming.lab5.scene.Transform; + +public class DemoScene extends BasicScene { + + public DemoScene() { + addSceneObjects( + new Sphere(new Transform(Vector3.FORWARD.multiply(-3)), 1), + new Box(new Transform(Vector3.FORWARD.multiply(-10)), 1), + new Box(new Transform(Vector3.RIGHT.multiply(5)), 1) + ); + } +} diff --git a/src/test/java/com/labs/introtoprogramming/lab5/MainTests.java b/src/test/java/com/labs/introtoprogramming/lab5/MainTests.java deleted file mode 100644 index 9e76a9e..0000000 --- a/src/test/java/com/labs/introtoprogramming/lab5/MainTests.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.labs.introtoprogramming.lab5; - -public class MainTests { -} diff --git a/src/test/java/labs/introtoprogramming/lab5/controllers/KeyAndMouseControllerTests.java b/src/test/java/labs/introtoprogramming/lab5/controllers/KeyAndMouseControllerTests.java new file mode 100644 index 0000000..9a5b4e8 --- /dev/null +++ b/src/test/java/labs/introtoprogramming/lab5/controllers/KeyAndMouseControllerTests.java @@ -0,0 +1,29 @@ +package labs.introtoprogramming.lab5.controllers; + +import static junit.framework.TestCase.assertTrue; + +import labs.introtoprogramming.lab5.geometry.Vector3; +import labs.introtoprogramming.lab5.graphics.BufferedImageRaster; +import labs.introtoprogramming.lab5.graphics.Raster; +import labs.introtoprogramming.lab5.gui.Input; +import labs.introtoprogramming.lab5.scene.Camera; +import labs.introtoprogramming.lab5.scene.SceneObject; +import labs.introtoprogramming.lab5.scene.Transform; +import org.junit.Test; + +public class KeyAndMouseControllerTests { + + @Test + public void testUpdate() { + Raster raster = new BufferedImageRaster(100, 100); + SceneObject camera = new Camera(raster, new Transform(Vector3.ZERO)); + KeyAndMouseMovementController controller = new KeyAndMouseMovementController(camera); + Input input = new Input(); + input.setForwardKeyDown(true); + input.setRightKeyDown(true); + controller.update(10, input); + assertTrue(camera.getTransform().position().x > 0); + assertTrue(camera.getTransform().position().z < 0); + } + +} diff --git a/src/test/java/labs/introtoprogramming/lab5/gui/InputTests.java b/src/test/java/labs/introtoprogramming/lab5/gui/InputTests.java new file mode 100644 index 0000000..e104931 --- /dev/null +++ b/src/test/java/labs/introtoprogramming/lab5/gui/InputTests.java @@ -0,0 +1,60 @@ +package labs.introtoprogramming.lab5.gui; + +import static org.junit.Assert.assertEquals; + +import java.awt.event.KeyEvent; +import labs.introtoprogramming.lab5.geometry.Vector3; +import org.junit.Test; + +public class InputTests { + + @Test + public void testKeyForward() { + Input input = new Input(); + input.setForwardKeyDown(true); + assertEquals(new Vector3(0, 0, -1), input.movementVector()); + } + + @Test + public void testKeyBackward() { + Input input = new Input(); + input.setBackwardKeyDown(true); + assertEquals(new Vector3(0, 0, 1), input.movementVector()); + } + + @Test + public void testKeyLeft() { + Input input = new Input(); + input.setLeftKeyDown(true); + assertEquals(new Vector3(-1, 0, 0), input.movementVector()); + } + + @Test + public void testKeyRight() { + Input input = new Input(); + input.setRightKeyDown(true); + assertEquals(new Vector3(1, 0, 0), input.movementVector()); + } + + @Test + public void testKeyUp() { + Input input = new Input(); + input.setUpKeyDown(true); + assertEquals(new Vector3(0, 1, 0), input.movementVector()); + } + + @Test + public void testKeyDown() { + Input input = new Input(); + input.setDownKeyDown(true); + assertEquals(new Vector3(0, -1, 0), input.movementVector()); + } + + @Test + public void testMouseDelta() { + Input input = new Input(); + input.setMouseDeltaX(2); + input.setMouseDeltaY(3); + assertEquals(new Vector3(3, 2, 0), input.mouseMovement()); + } +} diff --git a/src/test/java/labs/introtoprogramming/lab5/scene/CameraTests.java b/src/test/java/labs/introtoprogramming/lab5/scene/CameraTests.java index d9793a8..884470b 100644 --- a/src/test/java/labs/introtoprogramming/lab5/scene/CameraTests.java +++ b/src/test/java/labs/introtoprogramming/lab5/scene/CameraTests.java @@ -17,6 +17,7 @@ public void testInstantiation() { assertEquals(cam.size(), 1, DELTA); assertEquals(cam.fieldOfView(), 2 * Math.atan(1), DELTA); assertEquals(cam.aspectRatio(), 600.0 / 400.0, DELTA); + assertEquals(DUMMY_RASTER, cam.raster()); } @Test diff --git a/src/test/java/labs/introtoprogramming/lab5/scene/SceneTests.java b/src/test/java/labs/introtoprogramming/lab5/scene/SceneTests.java new file mode 100644 index 0000000..fefda33 --- /dev/null +++ b/src/test/java/labs/introtoprogramming/lab5/scene/SceneTests.java @@ -0,0 +1,35 @@ +package labs.introtoprogramming.lab5.scene; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import labs.introtoprogramming.lab5.controllers.Controller; +import labs.introtoprogramming.lab5.geometry.Vector3; +import labs.introtoprogramming.lab5.gui.Input; +import labs.introtoprogramming.lab5.object.Box; +import org.junit.Test; + +public class SceneTests { + + @Test + public void testSceneUpdateUpdatesControllers() { + Scene scene = new BasicScene(); + MockSceneController controller = new MockSceneController(); + scene.addSceneObjects(new Box(new Transform(Vector3.ZERO), 1)); + scene.addController(controller); + scene.update(10, new Input()); + assertTrue(controller.updated); + assertEquals(10, controller.updatedWithDelta); + } + + private class MockSceneController extends Controller { + boolean updated = false; + int updatedWithDelta = 0; + + @Override + public void update(int delta, Input input) { + this.updated = true; + this.updatedWithDelta = delta; + } + } +} diff --git a/src/test/java/labs/introtoprogramming/lab5/scenes/DemoSceneTests.java b/src/test/java/labs/introtoprogramming/lab5/scenes/DemoSceneTests.java new file mode 100644 index 0000000..baed622 --- /dev/null +++ b/src/test/java/labs/introtoprogramming/lab5/scenes/DemoSceneTests.java @@ -0,0 +1,14 @@ +package labs.introtoprogramming.lab5.scenes; + +import static junit.framework.TestCase.assertTrue; + +import org.junit.Test; + +public class DemoSceneTests { + + @Test + public void testInstantiation() { + DemoScene scene = new DemoScene(); + assertTrue(scene.getSceneObjects().size() > 0); + } +} diff --git a/troubleshooting.md b/troubleshooting.md new file mode 100644 index 0000000..f82f1f4 --- /dev/null +++ b/troubleshooting.md @@ -0,0 +1,4 @@ +# Camera movements are limited +If camera rotations are limited, then most probably `Robot` fails to center the cursor. +That's because `moveMouse` does not work on Wayland. The only solution is to switch to +Xorg. \ No newline at end of file