package com.projectsacrifice.game; import java.util.Arrays; import java.util.Collections; import java.util.List; /** Immutable, Android-independent level data. */ public final class LevelDefinition { public enum HazardType { SPIKES, SAW, FREEZER, ELECTRIC, PIT, CRUSHER, FIRE, PROJECTILE, EXPLOSION } public enum SwitchType { PRESSURE, TOGGLE, TIMED } public enum PhysicalObjectType { BOX, ROCK, BALL, ICE_BLOCK, COUNTERWEIGHT } public static final class Box { public final float x; public final float y; public final float width; public final float height; public Box(float x, float y, float width, float height) { this.x = x; this.y = y; this.width = width; this.height = height; } public float right() { return x + width; } public float bottom() { return y + height; } } public static final class Platform { public final Box box; public final float travelX; public final float travelY; public final float periodSeconds; public final String controlId; public Platform(Box box) { this(box, 0f, 0f, 0f, null); } public Platform(Box box, float travelX, float travelY, float periodSeconds, String controlId) { this.box = box; this.travelX = travelX; this.travelY = travelY; this.periodSeconds = periodSeconds; this.controlId = controlId; } public boolean isMoving() { return travelX != 0f || travelY != 0f; } } public static final class Hazard { public final HazardType type; public final Box box; public final String relayId; public final float impulseX; public final float impulseY; public final float cycleSeconds; public final float activeSeconds; public final float speedX; public final float speedY; public final String visualStyle; public final String audioCue; public Hazard(HazardType type, Box box) { this(type, box, null, 0f, 0f); } public Hazard(HazardType type, Box box, String relayId, float impulseX, float impulseY) { this(type, box, relayId, impulseX, impulseY, 0f, 0f, 0f, 0f, null, null); } public Hazard(HazardType type, Box box, String relayId, float impulseX, float impulseY, float cycleSeconds, float activeSeconds, float speedX, float speedY, String visualStyle, String audioCue) { this.type = type; this.box = box; this.relayId = relayId; this.impulseX = impulseX; this.impulseY = impulseY; this.cycleSeconds = cycleSeconds; this.activeSeconds = activeSeconds; this.speedX = speedX; this.speedY = speedY; this.visualStyle = visualStyle; this.audioCue = audioCue; } } public static final class Switch { public final SwitchType type; public final Box box; public final String signalId; public final float durationSeconds; public final int requiredMass; public Switch(SwitchType type, Box box, String signalId, float durationSeconds, int requiredMass) { this.type = type; this.box = box; this.signalId = signalId; this.durationSeconds = durationSeconds; this.requiredMass = requiredMass; } } public static final class Door { public final Box box; public final List requiredSignals; public Door(Box box, String... requiredSignals) { this.box = box; this.requiredSignals = Collections.unmodifiableList(Arrays.asList(requiredSignals)); } } public static final class PhysicalObject { public final PhysicalObjectType type; public final Box box; public final int mass; public PhysicalObject(PhysicalObjectType type, Box box, int mass) { this.type = type; this.box = box; this.mass = mass; } } public final int number; public final int formatVersion; public final int physicsVersion; public final String levelId; public final String worldId; public final String title; public final String hint; public final String titleRu; public final String hintRu; public final float worldWidth; public final float worldHeight; public final float spawnX; public final float spawnY; public final Box goal; public final int targetDeaths; public final int targetSeconds; public final Box collectible; public final List objects; public final List platforms; public final List hazards; public final List switches; public final List doors; public LevelDefinition( int number, String title, String hint, float worldWidth, float spawnX, float spawnY, Box goal, int targetDeaths, int targetSeconds, List platforms, List hazards, List switches, List doors ) { this(1, 1, number, title, hint, title, hint, worldWidth, 1080f, spawnX, spawnY, goal, targetDeaths, targetSeconds, Collections.emptyList(), platforms, hazards, switches, doors); } public LevelDefinition( int formatVersion, int physicsVersion, int number, String title, String hint, String titleRu, String hintRu, float worldWidth, float worldHeight, float spawnX, float spawnY, Box goal, int targetDeaths, int targetSeconds, List platforms, List hazards, List switches, List doors ) { this(formatVersion, physicsVersion, number, title, hint, titleRu, hintRu, worldWidth, worldHeight, spawnX, spawnY, goal, targetDeaths, targetSeconds, Collections.emptyList(), platforms, hazards, switches, doors); } public LevelDefinition( int formatVersion, int physicsVersion, int number, String title, String hint, String titleRu, String hintRu, float worldWidth, float worldHeight, float spawnX, float spawnY, Box goal, int targetDeaths, int targetSeconds, List objects, List platforms, List hazards, List switches, List doors ) { this(formatVersion, physicsVersion, defaultLevelId(number), "legacy", number, title, hint, titleRu, hintRu, worldWidth, worldHeight, spawnX, spawnY, goal, targetDeaths, targetSeconds, null, objects, platforms, hazards, switches, doors); } public LevelDefinition( int formatVersion, int physicsVersion, String levelId, String worldId, int number, String title, String hint, String titleRu, String hintRu, float worldWidth, float worldHeight, float spawnX, float spawnY, Box goal, int targetDeaths, int targetSeconds, Box collectible, List objects, List platforms, List hazards, List switches, List doors ) { this.formatVersion = formatVersion; this.physicsVersion = physicsVersion; this.levelId = levelId; this.worldId = worldId; this.number = number; this.title = title; this.hint = hint; this.titleRu = titleRu; this.hintRu = hintRu; this.worldWidth = worldWidth; this.worldHeight = worldHeight; this.spawnX = spawnX; this.spawnY = spawnY; this.goal = goal; this.targetDeaths = targetDeaths; this.targetSeconds = targetSeconds; this.collectible = collectible; this.objects = Collections.unmodifiableList(objects); this.platforms = Collections.unmodifiableList(platforms); this.hazards = Collections.unmodifiableList(hazards); this.switches = Collections.unmodifiableList(switches); this.doors = Collections.unmodifiableList(doors); } public static String defaultLevelId(int number) { return "legacy.level-" + (number < 10 ? "0" : "") + number; } public boolean containsMechanic(HazardType type) { for (Hazard hazard : hazards) { if (hazard.type == type) return true; } return false; } public boolean containsMechanic(SwitchType type) { for (Switch item : switches) { if (item.type == type) return true; } return false; } public boolean hasMovingPlatform() { for (Platform platform : platforms) { if (platform.isMoving()) return true; } return false; } }