@Test public void testIncorrectKey() { key = new Key(); EngineEntity entity = createModelEntityWithKeyboardInteraction(5, true, false, false); KeyPressedComponent keyPressedComponent = gameLoop.createComponent(KeyPressedComponent.class); RuntimeKey runtimeKeyEvent = new RuntimeKey(); runtimeKeyEvent.setKeycode(5); keyPressedComponent.getKeyEvents().add(runtimeKeyEvent); entity.add(keyPressedComponent); gameLoop.update(1); gameLoop.update(0); // One more cycle so the effect system can actually // execute the effects assertTrue("Effect wasn't executed", executed == 0); assertNull( "Entity shouldn't have a Keyboard Interaction component, since all Keyboard Interactions should be finished", entity.getComponent(KeyPressedComponent.class)); }
@Override public void execute(Entity target, SetCamera effect) { // Get camera EngineEntity cameraEntity = gameView.getLayer(Layer.CAMERA); IntMap<Entity> entitiesWithCameras = gameLoop.getEntitiesFor(Family.getFamilyFor(CamerasComponent.class)); EngineEntity sceneEntity; if (entitiesWithCameras == null || entitiesWithCameras.size == 0 || (sceneEntity = (EngineEntity) entitiesWithCameras.values().next()) == null) { Gdx.app.log(LOG_TAG, "There are no cameras available. Effect will be skipped."); return; } if (!sceneEntity.hasComponent(CamerasComponent.class)) { Gdx.app.log(LOG_TAG, "No cameras in scene. Effect will be skipped."); return; } Camera camera = sceneEntity.getComponent(CamerasComponent.class).getCamera(effect.getCameraId()); if (camera == null) { Gdx.app.log( LOG_TAG, "No camera with id " + effect.getCameraId() + " is av Effect will be skipped."); return; } // Get old values. Used for additional tweaking if the effect is // animated. float oldOriginX = cameraEntity.getGroup().getOriginX(); float oldOriginY = cameraEntity.getGroup().getOriginY(); float oldX = cameraEntity.getGroup().getX(); float oldY = cameraEntity.getGroup().getY(); float oldScaleX = cameraEntity.getGroup().getScaleX(); float oldScaleY = cameraEntity.getGroup().getScaleY(); float oldRotation = cameraEntity.getGroup().getRotation(); // /////////////////////////// // Calculate new values // /////////////////////////// Float viewportWidth = (float) (Integer) variablesManager.getValue(VarsContext.RESERVED_VIEWPORT_WIDTH_VAR); Float viewportHeight = (float) (Integer) variablesManager.getValue(VarsContext.RESERVED_VIEWPORT_HEIGHT_VAR); // Camera width and height float w = camera.getWidth(); float h = camera.getHeight(); // Rotation float newRotation = camera.getRotation(); // X and Y /* * After the matrix transformation is applied, we want that M * (x y 1) * = (0 0 1) The goal is to get the left-bottom vertex of the camera * aligned with the left-bottom vertex of the screen. */ float x = camera.getX(); float y = camera.getY(); // Calculate the origin. /* * Must be the center of the camera in scene coordinates. There is no * need to adjust it as the origin translation is the first step in * Group.computeTransform() */ float newOriginX = x + w / 2.0F; float newOriginY = y + h / 2.0F; // Calculate scale. /* * If the camera's width is smaller than the viewport, zoom-in will be * performed. Otherwise zoom out will apply. */ float newScaleX = viewportWidth / w; float newScaleY = viewportHeight / h; /* * Calculate the x and y coordinates for the camera entity as to get * screen's bottom-left corner aligned with camera's bottom left corner. * It's a bit tricky since Group.computeTransform() translates to the * origin, then scales and "undoes" the origin translation, but since * the matrix is at that point scaled, not all the origin is removed. * * Calculus is described in class javadoc */ float newX = -x * newScaleX - newOriginX * (1 - newScaleX); float newY = -y * newScaleY - newOriginY * (1 - newScaleY); // Check there's actually a transformation to apply: float t = 0.1F; if (MathUtils.isEqual(oldX, newX, t) && MathUtils.isEqual(oldY, newY, t) && MathUtils.isEqual(oldOriginX, newOriginX, t) && MathUtils.isEqual(oldOriginY, newOriginY, t) && MathUtils.isEqual(oldScaleX, newScaleX, t) && MathUtils.isEqual(oldScaleY, newScaleY, t) && MathUtils.isEqual(oldRotation, newRotation, t)) { Gdx.app.debug(LOG_TAG, "There's no transformation to apply. Effect skipped."); return; } // Set new origin cameraEntity.getGroup().setOrigin(newOriginX, newOriginY); // Instantaneous effect: just apply transformation if (effect.getAnimationTime() == 0F) { // Translate cameraEntity.getGroup().setX(newX); cameraEntity.getGroup().setY(newY); // Scale cameraEntity.getGroup().setScaleX(newScaleX); cameraEntity.getGroup().setScaleY(newScaleY); // Rotate cameraEntity.getGroup().setRotation(newRotation); } else { // Animated effect /* * New origin has been set but values are not actually transformed * until tweens start to run a loop later. This causes an * unintentional translational effect all of a sudden. To correct * that, x and y has to be adjusted so the entity does not actually * move */ float cos = MathUtils.cosDeg(oldRotation); float sin = MathUtils.sinDeg(oldRotation); float adjX = oldScaleX * cos * (newOriginX - oldOriginX) + oldScaleY * sin * (oldOriginY - newOriginY) + oldOriginX - newOriginX; float adjY = oldScaleX * sin * (newOriginX - oldOriginX) + oldScaleY * cos * (newOriginY - oldOriginY) + oldOriginY - newOriginY; cameraEntity.getGroup().setX(oldX + adjX); cameraEntity.getGroup().setY(oldY + adjY); // Animated effect: create and add tweens TweensComponent tweensComponent = gameLoop.addAndGetComponent(cameraEntity, TweensComponent.class); RotateTween rotateTween = new RotateTween(); rotateTween.setRotation(camera.getRotation()); rotateTween.setDuration(effect.getAnimationTime()); rotateTween.setRelative(false); ScaleTween scaleTween = new ScaleTween(); scaleTween.setScaleX(newScaleX); scaleTween.setScaleY(newScaleY); scaleTween.setDuration(effect.getAnimationTime()); MoveTween moveTween = new MoveTween(); moveTween.setX(newX); moveTween.setY(newY); moveTween.setDuration(effect.getAnimationTime()); tweensComponent.addTween(moveTween); tweensComponent.addTween(scaleTween); tweensComponent.addTween(rotateTween); } }