private void fire(Person person, Room room) { AbstractWeapon gun = person.getWeapon(); person.setShotCooldown(System.currentTimeMillis() + gun.getShotTimeout()); gun.setTotalClip(gun.getTotalClip() - 1); gun.setCurrentClip(gun.getCurrentClip() - 1); Integer id = gameContext.getProjectilesIds().getAndIncrement(); Projectile[] projectilesBatch = new Projectile[gun.getBulletsPerShot()]; for (int i = 0; i < projectilesBatch.length; i++) { Projectile projectile = getCompatibleProjectile(person); projectile.setId(i); projectilesBatch[i] = projectile; float angle = projectile.getAngle(); if (angle == 90) { projectile.setxEnd((int) person.getX()); int gunLimit = (int) (projectile.getRadius() + person.getY()); projectile.setyEnd(gunLimit > room.getMap().getY() ? room.getMap().getY() : gunLimit); } else if (angle == 180) { projectile.setyEnd((int) person.getY()); int gunLimit = (int) person.getX() - (int) projectile.getRadius(); projectile.setyEnd(gunLimit > 0 ? gunLimit : 0); } else if (angle == 270) { projectile.setxEnd((int) person.getX()); int gunLimit = (int) person.getY() - (int) projectile.getRadius(); projectile.setyEnd(gunLimit > 0 ? gunLimit : 0); } else if (angle == 0) { projectile.setyEnd((int) person.getY()); int gunLimit = (int) person.getX() + (int) projectile.getRadius(); projectile.setyEnd(gunLimit > room.getMap().getX() ? room.getMap().getX() : gunLimit); } else { double y = projectile.getRadius() * Math.sin(angle * Math.PI / 180); double x = projectile.getRadius() * Math.cos(angle * Math.PI / 180); projectile.setxEnd((int) x + (int) person.getX()); projectile.setyEnd((int) y + (int) person.getY()); } if (projectile.isInstant()) { calculateInstantImpacts(person, projectile, room); } } room.getProjectiles().put(id, projectilesBatch); }
private synchronized void calculateInstantImpacts( Person shooter, Projectile projectile, Room room) { double xStart = projectile.getxStart(); double yStart = projectile.getyStart(); Person closestPerson = null; Point closestPoint = null; for (AbstractZone zone : room.getMap().getZones()) { if (zone.isShootable()) { continue; } Bounds zoneBounds = GeometryService.getRectangle(zone); Point[] zoneIntersection = LineService.lineBoundsIntersections( new Line( new Point(shooter.getX(), shooter.getY()), new Point(projectile.getxEnd(), projectile.getyEnd())), zoneBounds); Point closest = isMoreClose( (int) projectile.getxStart(), (int) projectile.getyStart(), new Point(projectile.getxEnd(), projectile.getyEnd()), zoneIntersection); if (closest != null) { closestPoint = closest; projectile.setxEnd((int) closest.getX()); projectile.setyEnd((int) closest.getY()); } } for (Person person : room.getPersons().values()) { Point linePointB = new Point((double) projectile.getxEnd(), (double) projectile.getyEnd()); Point[] intersectionPoints = LineService.lineIntersectCircle( new Line(new Point(xStart, yStart), linePointB), new Circle(person.getX(), person.getY(), PersonWebSocketEndpoint.PERSON_RADIUS)); if (shooter == person) { projectile.setxStart((int) intersectionPoints[0].getX()); projectile.setyStart((int) intersectionPoints[0].getY()); continue; } if (intersectionPoints != null && intersectionPoints.length > 0) { Point closest = isMoreClose( (int) shooter.getX(), (int) shooter.getY(), closestPoint, intersectionPoints); if (closest != null) { if (projectile.isPiercing()) { onDamage(shooter, projectile.getDamage(), person, room); } else { closestPoint = closest; closestPerson = person; } } } } if (closestPerson != null) { onDamage(shooter, projectile.getDamage(), closestPerson, room); } if (closestPoint != null) { projectile.setxEnd((int) closestPoint.getX()); projectile.setyEnd((int) closestPoint.getY()); } }