/** * Returns the bounding box for the output of the operation. The * implementation in this class computes the bounding box as the * intersection the bounding boxes of all the (renderable sources). * * @param paramBlock A <code>ParameterBlock</code> containing the * sources and parameters of the operation. * @return A <code>Rectangle2D</code> specifying the bounding box. */ public Rectangle2D getBounds2D(ParameterBlock paramBlock) { int numSources = paramBlock.getNumSources(); if (numSources == 0) { return null; } RenderableImage src = paramBlock.getRenderableSource(0); Rectangle2D.Float box1 = new Rectangle2D.Float(src.getMinX(), src.getMinY(), src.getWidth(), src.getHeight()); for (int i = 1; i < numSources; i++) { src = paramBlock.getRenderableSource(i); Rectangle2D.Float box2 = new Rectangle2D.Float(src.getMinX(), src.getMinY(), src.getWidth(), src.getHeight()); box1 = (Rectangle2D.Float)box1.createIntersection(box2); if(box1.isEmpty()) { break; } } return box1; }
@Override public void endBlock(Block b) { super.endBlock(b); float width = (float) (currBlockMaxX - currBlockMinX); float height = (float) (currBlockMaxY - currBlockMinY); boolean hasManyFontsizes = currBlockFontSizes.getMax() != currBlockFontSizes .getMin(); double medianFontsize = currBlockFontSizes.getPercentile(50); BBlock block = new BBlock() .setRegion( new Float((float) currBlockMinX, (float) currBlockMinY, width, height)).setId(currBlockId) .setText(pipeText(b)).setHasBold(currBlockHasBold) .setHasManyFontsizes(hasManyFontsizes) .setMedianFontsize(medianFontsize).setPageId(currPageId) .setLines(currLines); currLines = newArrayList();// reset currLineId = 0; doc.addBlock(block); ++currBlockId; }
/** * {@inheritDoc} */ @Override public void update(GameContainer container, int delta, List<Float> staticBounds, Map<AbstractMovingModel, Float> dynamicBounds) { AbstractMovingModel projectile = getModel(); if (projectile.isAlive()) { if (!isCollision(projectile.getX(), projectile.getY(), projectile.getHeight(), projectile.getWidth(), staticBounds, dynamicBounds)) { projectile.setX(projectile.getX() - (float) Math.cos(Math.toRadians(projectile .getRotation())) * (projectile.getVelocity() * delta)); projectile.setY(projectile.getY() - (float) Math.sin(Math.toRadians(projectile .getRotation())) * projectile.getVelocity() * delta); } } }
/** * Checks a way between two points against dynamic bounds * * @param dynamicBounds * A map of models and their collision bounds * @param point1X * x variable of first point * @param point1Y * y variable of first point * @param point2X * x variable of second point * @param point2Y * y variable of second point * @return true if path is blocked by a moving model. */ boolean isWayClear(Map<AbstractMovingModel, Float> dynamicBounds, float point1X, float point1Y, float point2X, float point2Y) { for (AbstractMovingModel otherModel : dynamicBounds.keySet()) { if (this.getModel() != otherModel && otherModel.isAlive() && !(otherModel instanceof HeroModel)) { Rectangle2D.Float bound = otherModel.getBounds(); if (CollisionHelper.recIntersectLine(bound, point1X, point1Y, point2X, point2Y)) { return false; } } } return true; }
/** * Method for checking if static collision with Rectangle2D object is about * to happen. * * @param staticBounds * list of rectangles representing static blocked object on the * map * @param bound1 * the Rectangle2D witch to check if colliding * @return true if collision, false otherwise */ boolean isStaticCollision(List<Rectangle2D.Float> staticBounds, Rectangle2D.Float bound1) { boolean staticCollision = false; // check static collisions for (Rectangle2D.Float bound2 : staticBounds) { if (bound1.intersects(bound2)) { staticCollision = true; if (model instanceof AbstractProjectileModel) { model.setAlive(false); } } } return staticCollision; }
/** * Method for rendering all model views in the room. * * @param container * The container holding this game. * @param g * The graphics context that can be used to render. However, * normal rendering routines can also be used. */ public void render(GameContainer container, Graphics g) { // render map map.render(0, 0); // tell enemy controllers to render all enemy views for (AbstractMovingModelController controller : movingModelControllers) { controller.render(container, g); } if (Constants.SHOW_BOUNDS) { g.setColor(Color.red); for (Rectangle2D.Float e : staticBounds) { g.drawRect((int) e.getX(), (int) e.getY(), (int) e.getWidth(), (int) e.getHeight()); } } }
@Override public void startBlock(Block b) { super.startBlock(b); // reinint currBlockMaxX = -1f; currBlockMinX = java.lang.Float.MAX_VALUE; currBlockMaxY = -1f; currBlockMinY = java.lang.Float.MAX_VALUE; currBlockHasBold = false; currBlockFontSizes = new DescriptiveStatistics(); }
@Override public void startLine(Line l) { super.startLine(l); Float region = new Float(); region.height = l.height(); region.width = l.width(); region.x = l.xpos(); region.y = l.ypos(); // Used for pdf table processing StringBuffer sb = new StringBuffer(); SpacingOutputTarget oh = new SpacingOutputTarget(sb, glyphCorrector); try { l.pipe(oh); } catch (IOException e) { e.printStackTrace(); } String lineText = sb.toString(); List<java.lang.Float> beginnings = oh.getBeginnings(); List<java.lang.Float> endings = oh.getEndings(); currLines.add(new BLine().setRegion(region).setPageId(currPageId) .setBlockId(currBlockId).setLineId(currLineId++) .setText(lineText).setBeginnings(beginnings) .setEndings(endings)); currBlockMaxX = Math.max(currBlockMaxX, l.endxpos()); currBlockMinX = Math.min(currBlockMinX, l.xpos()); currBlockMaxY = Math.max(currBlockMaxY, l.ypos()); currBlockMinY = Math.min(currBlockMinY, l.ypos() - l.height()); }
private boolean isSimilar(BBlock b1, BBlock b2) { // rough text lengh comparison String txt1 = b1.getText(), txt2 = b2.getText(); if (abs(txt1.length() - txt2.length()) > TEXT_LENGTH_THRESHOLD) { // System.out.println("TEXT_LENGTH_THRESHOLD"); return false; } // position comparison java.awt.geom.Rectangle2D.Float r1 = b1.getRegion(), r2 = b2 .getRegion(); double diff = abs(r1.getX() - r2.getX()) + // abs(r1.getY() - r2.getY()) + // abs(r1.getWidth() - r2.getWidth()) + // abs(r1.getHeight() - r2.getHeight()); if (diff > POSITION_THRESHOLD) { // System.out.println("POSITION_THRESHOLD"); return false; } // text comparison (Levenshtein) if (getLevenshteinDistance(txt1, txt2, EDIT_DISTANCE_THRESHOLD) == -1) { // System.out.println("EDIT_DISTANCE_THRESHOLD"); return false; } return true; }
@Override public void update(GameContainer container, int delta, List<Float> staticBounds, Map<AbstractMovingModel, Float> dynamicBounds) { AbstractMovingModel swing = getModel(); if (swing.isAlive()) { float oldX = swing.getX(); float oldY = swing.getY(); float newX = swing.getX() - (float) Math.cos(Math.toRadians(swing.getRotation())) * (swing.getVelocity() * delta); float newY = swing.getY() - (float) Math.sin(Math.toRadians(swing.getRotation())) * (swing.getVelocity() * delta); if ((float) Math.hypot((oldX - newX), (oldY - newY)) >= swing .getVelocity() * 5f / 4f) swing.setAlive(false); if (!isCollision(swing.getX(), swing.getY(), swing.getHeight(), swing.getWidth(), staticBounds, dynamicBounds)) { swing.setX(newX); swing.setY(newY); } } }
/** * Makes npc move along path if path exists. Sets npc rotation to next path * node. * * @param model * the model that moves * @param delta * time since last update * @param dynamicBounds * other moving models */ void moveAlongPath(AbstractMovingModel model, int delta, Map<AbstractMovingModel, Float> dynamicBounds) { if (myPath.getLength() >= currentStep) { float diffX = model.getX() - (myPath.getX(currentStep) * 32); float diffY = model.getY() - (myPath.getY(currentStep) * 32); double dir = Math.atan2(diffY, diffX); model.setRotation(Math.toDegrees(dir)); float speedY = (float) (model.getVelocity() * Math.sin(dir)); float speedX = (float) (model.getVelocity() * Math.cos(dir)); float tmpNewX = model.getX() - (delta * speedX); float tmpNewY = model.getY() - (delta * speedY); // if dynamic collision set path to null so a new random path will // be created if (isDynamicCollision(tmpNewX, tmpNewY, dynamicBounds)) { myPath = null; // Set the new positions } else { if (!isDynamicCollision(tmpNewX, model.getY(), dynamicBounds)) { model.setX(tmpNewX); } if (!isDynamicCollision(model.getX(), tmpNewY, dynamicBounds)) { model.setY(tmpNewY); } int currX = (int) (model.getX() + (model.getWidth() / 2)) / 32; int currY = (int) (model.getY() + (model.getHeight() / 2)) / 32; if (currX == myPath.getX(currentStep) && currY == myPath.getY(currentStep)) { currentStep++; } } } }
/** * Moves straight to the walking goal. If path blocked Boss will not be able * to get loose. * * @param model * @param delta * @param staticBounds * @param dynamicBounds */ private void moveToGoal(AbstractMovingModel model, int delta, List<Float> staticBounds, Map<AbstractMovingModel, Float> dynamicBounds) { float diffX = model.getX() - this.goalX; float diffY = model.getY() - this.goalY; double dir = Math.atan2(diffY, diffX); model.setRotation(Math.toDegrees(dir)); float speedY = (float) (model.getVelocity() * Math.sin(dir)); float speedX = (float) (model.getVelocity() * Math.cos(dir)); float tmpNewX = model.getX() - (delta * speedX); float tmpNewY = model.getY() - (delta * speedY); if (!isCollision(tmpNewX, model.getY(), model.getWidth(), model.getHeight(), staticBounds, dynamicBounds)) { model.setX(tmpNewX); } if (!isCollision(model.getX(), tmpNewY, model.getWidth(), model.getHeight(), staticBounds, dynamicBounds)) { model.setY(tmpNewY); } if (Math.abs(model.getX() - this.goalX) < 10 && Math.abs(model.getY() - this.goalY) < 10) { this.goalX = -1; this.goalY = -1; } }
/** * Creates a new AbstractMovingModelController. * * @param gameController * The game controller used in this game. */ RoomController(GameController gameController, RoomModel roomModel) { staticBounds = new ArrayList<Rectangle2D.Float>(); dynamicBounds = new HashMap<AbstractMovingModel, Rectangle2D.Float>(); movingModelControllers = new ArrayList<AbstractMovingModelController>(); this.gameController = gameController; this.roomModel = roomModel; this.setMap(roomModel.getLockedMapPath()); }
/** * Method for getting a map of all dynamic collision bounds. * * @return A map containing models and it's corresponding collision bounds. */ public Map<AbstractMovingModel, Rectangle2D.Float> getDynamicBounds() { // update bounds Iterator<AbstractMovingModel> it = dynamicBounds.keySet().iterator(); while (it.hasNext()) { AbstractMovingModel model = it.next(); if (model.isAlive()) { dynamicBounds.put(model, model.getBounds()); } else { it.remove(); } } return dynamicBounds; }
/** * Method for setting the map to be used in the room. * * @param mapPath * Path in filesystem to the tmx file representing a tiled map. */ public void setMap(String mapPath) { try { this.map = new TiledMap(mapPath); int layerCount = map.getLayerCount(); blockedLayerID = -1; for (int i = 0; i < layerCount; i++) { if (map.getLayerProperty(i, "blocked", "false").equals("true")) { blockedLayerID = i; } } staticBounds.clear(); // add static collision bounds for (int i = 0; i < map.getWidth(); i++) { for (int j = 0; j < map.getHeight(); j++) { int tileID = map.getTileId(i, j, blockedLayerID); String property = map.getTileProperty(tileID, "blocked", "false"); if (property.equals("true")) { staticBounds.add(new Rectangle2D.Float(i * 32, j * 32, 32, 32)); } } } } catch (SlickException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
/** * Update the game logic here. No rendering should take place in this method * though it won't do any harm. * * @param container * The container holing this game * @param delta * The amount of time that's passed since last update in * milliseconds * @param dynamicBounds * A map of dynamic collision bounds. * @param staticBounds * A list of static collision bounds. */ public void update(GameContainer container, int delta, List<Float> staticBounds, Map<AbstractMovingModel, Float> dynamicBounds) { getCurrentRoom().update(container, delta, staticBounds, dynamicBounds); RoomController currentRoom = getCurrentRoom(); if (allEnemiesDefeated() && !bossRoomUnlocked) { for (RoomController controller : rooms.values()) { RoomModel model = controller.getRoomModel(); if (model instanceof LobbyRoomModel) { controller.setMap("res/levels/lobby.tmx"); } } bossRoomUnlocked = true; currentRoom.unlockRoom(); SoundController.playGameMusic(GameMusic.BOSS_MUSIC); SoundController.playSound(SoundEffect.NARRATOR_BOSS); } else if (currentRoom.allDead() && !currentRoom.isUnlocked() && !bossRoomUnlocked) { currentRoom.unlockRoom(); SoundController.playSound(SoundEffect.NARRATOR_NEXT); } }
/** * {@inheritDoc} */ @Override public void update(GameContainer container, int delta, List<Float> staticBounds, Map<AbstractMovingModel, Float> dynamicBounds) { }
/** * Method for checking if dynamic collision with Rectangle2D object is about * to happen. * * @param dynamicBounds * map with moving models and their collision bounds * @param bound1 * the Rectangle2D witch to check if colliding * @return true if collision, false otherwise */ boolean isDynamicCollision( Map<AbstractMovingModel, Rectangle2D.Float> dynamicBounds, Rectangle2D.Float bound1) { boolean dynamicCollision = false; // check dynamic collisions for (AbstractMovingModel otherModel : dynamicBounds.keySet()) { Rectangle2D.Float bound2 = otherModel.getBounds(); if (bound1.intersects(bound2) && this.model != otherModel && otherModel.isAlive()) { dynamicCollision = true; if (model instanceof MeleeSwingModel && otherModel instanceof AbstractNpcModel) { getGameController().getHeroController().incHealth(); } if (model instanceof AbstractProjectileModel && otherModel instanceof AbstractProjectileModel) { dynamicCollision = false; } else if (model instanceof AbstractProjectileModel && otherModel instanceof AbstractCharacterModel) { AbstractProjectileModel projectile = (AbstractProjectileModel) model; int damage = projectile.getDamage(); otherModel.takeDamage(damage); if (otherModel.getHealth() <= 0) { otherModel.setAlive(false); if (otherModel instanceof BossModel) { SoundController.playSound(SoundEffect.BOSS_DEATH); getGameController().gameOver(true); } else { SoundController .playSound(SoundController.SoundEffect.ENEMY_DEATH); } } else { SoundController .playSound(SoundController.SoundEffect.ENEMY_HURT); } projectile.setAlive(false); } } } return dynamicCollision; }
/** * {@inheritDoc} */ @Override public void update(GameContainer container, int delta, List<Float> staticBounds, Map<AbstractMovingModel, Float> dynamicBounds) { if (hasFired) { createDonut(); hasFired = false; } AbstractMovingModel model = getModel(); AbstractMovingModel heroModel = getGameController().getHeroController() .getModel(); // Save old position float oldX = model.getX(); float oldY = model.getY(); // NPC current position int currX = (int) (oldX + (model.getWidth() / 2)); int currY = (int) (oldY + (model.getHeight() / 2)); float heroX = heroModel.getX() + heroModel.getWidth() / 2; float heroY = heroModel.getY() + heroModel.getHeight() / 2; // if hero is in sight. boolean heroTracking; heroTracking = CollisionHelper.isInSight(staticBounds, currX, currY, heroX, heroY); // If path is null or end of path reached if (this.goalX == -1 || this.goalY == -1) { // After a short pause make new path. if (pauseTimer()) { newRandomGoal(); } } else { // travel along path moveToGoal(model, delta, staticBounds, dynamicBounds); } // If hero is in sight set new direction and possibly attack if (heroTracking) { model.setRotation(Math.toDegrees(Math.atan2((currY - heroY), (currX - heroX)))); // If hero is in reach and no other npc is in the way attack! if (isWayClear(dynamicBounds, currX, currY, heroX, heroY)) { fireTimed(); } } // NPC new position float newX = model.getX(); float newY = model.getY(); // Set whether model is moving or not this.getModel().setMoving(!((oldX == newX) || (oldY == newY))); }
/** * {@inheritDoc} */ @Override public void update(GameContainer container, int delta, List<Float> staticBounds, Map<AbstractMovingModel, Float> dynamicBounds) { AbstractCharacterModel model = (AbstractCharacterModel) getModel(); if (!model.isAlive()) { getGameController().gameOver(false); return; } Input input = container.getInput(); // Handle changing of weapons changeWeapons(input, model); // Handle firing of weapon fireWeapon(input, model); // Make the model face the mouse cross-hair calculateFacing(input, model); // Calculate the new x and y Point nextPosition = calculateNextPosition(input, model, delta); // Check the new X against collision bounds. If no collision, allow // movement in X. if (!isCollision(nextPosition.getX(), model.getY(), model.getHeight(), model.getWidth(), staticBounds, dynamicBounds)) { model.setX(nextPosition.getX()); } // Check the new Y against collision bounds. If no collision, allow // movement in Y. if (!isCollision(model.getX(), nextPosition.getY(), model.getHeight(), model.getWidth(), staticBounds, dynamicBounds)) { model.setY(nextPosition.getY()); } // Handle checking for change of room. changeRoom(model); }
/** * {@inheritDoc} */ @Override public void update(GameContainer container, int delta, List<Float> staticBounds, Map<AbstractMovingModel, Float> dynamicBounds) { if (hasFired) { createBullet(); hasFired = false; } AbstractMovingModel model = getModel(); AbstractMovingModel heroModel = getGameController().getHeroController() .getModel(); // Save old position float oldX = model.getX(); float oldY = model.getY(); // NPC current position int currX = (int) (oldX + (model.getWidth() / 2)); int currY = (int) (oldY + (model.getHeight() / 2)); float heroX = heroModel.getX() + heroModel.getWidth() / 2; float heroY = heroModel.getY() + heroModel.getHeight() / 2; // if hero is in sight. boolean heroTracking; if (CollisionHelper.isInSight(staticBounds, currX, currY, heroX, heroY)) { heroTracking = true; // New path after hero pos calculateNewPath((int) heroX / 32, (int) heroY / 32); } else { heroTracking = false; } // If path is null or end of path reached if (!existsPath()) { // After a short pause make new path. if (pauseTimer()) { calculateRandomPath(); } } else { // travel along path moveAlongPath(model, delta, dynamicBounds); } // If hero is in sight set new direction and possibly attack if (heroTracking) { model.setRotation(Math.toDegrees(Math.atan2((currY - heroY), (currX - heroX)))); // If hero is in reach and no other npc is in the way attack! if (isWayClear(dynamicBounds, currX, currY, heroX, heroY)) { fireTimed(); } } // NPC new position float newX = this.getModel().getX(); float newY = this.getModel().getY(); // Set whether model is moving or not this.getModel().setMoving(!((oldX == newX) || (oldY == newY))); }
/** * {@inheritDoc} */ @Override public void update(GameContainer container, int delta, List<Float> staticBounds, Map<AbstractMovingModel, Float> dynamicBounds) { if (hasFired) { swingWeapon(); hasFired = false; } AbstractMovingModel model = getModel(); AbstractMovingModel heroModel = getGameController().getHeroController() .getModel(); // Save old position float oldX = model.getX(); float oldY = model.getY(); // NPC current position int currX = (int) (oldX + (model.getWidth() / 2)); int currY = (int) (oldY + (model.getHeight() / 2)); float heroX = heroModel.getX() + heroModel.getWidth() / 2; float heroY = heroModel.getY() + heroModel.getHeight() / 2; // if hero is in sight. boolean heroTracking; if (CollisionHelper.isInSight(staticBounds, currX, currY, heroX, heroY)) { heroTracking = true; // New path after hero pos calculateNewPath((int) heroX / 32, (int) heroY / 32); } else { heroTracking = false; } // If path is null or end of path reached if (!existsPath()) { // After a short pause make new path. if (pauseTimer()) { calculateRandomPath(); } } else { // travel along path moveAlongPath(model, delta, dynamicBounds); } // If hero is in sight set new direction and possibly attack if (heroTracking) { model.setRotation(Math.toDegrees(Math.atan2((currY - heroY), (currX - heroX)))); // If hero is in reach and no other npc is in the way attack! if (Math.hypot(currX - heroX, currY - heroY) < 100 && isWayClear(dynamicBounds, currX, currY, heroX, heroY)) { fireTimed(); } } // NPC new position float newX = this.getModel().getX(); float newY = this.getModel().getY(); // Set whether model is moving or not this.getModel().setMoving(!((oldX == newX) || (oldY == newY))); }
/** * Method for checking if collision with width and height is about to happen * in position (x,y). * * @param x * the x coordinate * @param y * the y coordinate * @param width * The width of area to check * @param height * The height of area to check * @param staticBounds * list of rectangles representing static blocked object on the * map * @param dynamicBounds * map with moving models and their collision bounds * @return true if collision, false otherwise */ boolean isCollision(float x, float y, float width, float height, List<Rectangle2D.Float> staticBounds, Map<AbstractMovingModel, Rectangle2D.Float> dynamicBounds) { Rectangle2D.Float bound1 = new Rectangle2D.Float(x, y, width, height); return isCollision(staticBounds, dynamicBounds, bound1); }
/** * Method for checking if collision with Rectangle2D object is about to * happen. * * @param staticBounds * list of rectangles representing static blocked object on the * map * @param dynamicBounds * map with moving models and their collision bounds * @param bound1 * the Rectangle2D witch to check if colliding * @return true if collision, false otherwise */ boolean isCollision(List<Rectangle2D.Float> staticBounds, Map<AbstractMovingModel, Rectangle2D.Float> dynamicBounds, Rectangle2D.Float bound1) { // check static collisions boolean staticCollision = isStaticCollision(staticBounds, bound1); // check dynamic collisions boolean dynamicCollision = isDynamicCollision(dynamicBounds, bound1); return staticCollision || dynamicCollision; }
/** * Method for checking if dynamic collision with model is about to happen. * * @param x * the x coordinate * @param y * the y coordinate * @param dynamicBounds * map with moving models and their collision bounds * @return true if collision, false otherwise */ boolean isDynamicCollision(float x, float y, Map<AbstractMovingModel, Rectangle2D.Float> dynamicBounds) { Rectangle2D.Float bound1 = new Rectangle2D.Float(x, y, model.getWidth(), model.getHeight()); return isDynamicCollision(dynamicBounds, bound1); }
/** * Method for updating the logic of all the models * * @param container * The container holding this game. * @param delta * The amount of time that's passed since last update in * milliseconds * @param dynamicBounds * the dynamic bounds of moving objects * @param staticBounds * the static bounds of current map */ public abstract void update(GameContainer container, int delta, List<Float> staticBounds, Map<AbstractMovingModel, Float> dynamicBounds);
/** * Method for getting the static collision bounds of the room. * * @return A list of static collision bounds. */ public List<Rectangle2D.Float> getStaticBounds() { return staticBounds; }