├── settings.gradle ├── html ├── webapp │ ├── soundmanager2-setup.js │ ├── WEB-INF │ │ └── web.xml │ ├── refresh.png │ ├── styles.css │ ├── index.html │ └── soundmanager2-jsmin.js ├── src │ └── io │ │ └── piotrjastrzebski │ │ └── dungen │ │ ├── GdxDefinition.gwt.xml │ │ ├── GdxDefinitionSuperdev.gwt.xml │ │ └── client │ │ └── HtmlLauncher.java └── build.gradle ├── core ├── assets │ ├── ss-v1.png │ ├── ss-v2.png │ └── badlogic.jpg ├── build.gradle └── src │ ├── Dungen.gwt.xml │ └── io │ └── piotrjastrzebski │ └── dungen │ ├── gui │ ├── Saver.java │ ├── Restarter.java │ ├── HelpGUI.java │ ├── DrawSettingsGUI.java │ └── GenSettingsGUI.java │ ├── PlatformBridge.java │ ├── DungenGame.java │ ├── Grid.java │ ├── RoomNode.java │ ├── RoomEdge.java │ ├── Utils.java │ ├── DrawSettings.java │ ├── Room.java │ ├── RoomGraph.java │ ├── HallwayPath.java │ ├── GenSettings.java │ ├── BaseScreen.java │ ├── DungenScreen.java │ └── DungeonGenerator.java ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── CONTRIBUTORS ├── AUTHORS ├── README.md ├── .gitignore ├── desktop ├── build.gradle └── src │ └── io │ └── piotrjastrzebski │ └── dungen │ └── desktop │ └── DesktopLauncher.java ├── gradlew.bat ├── gradlew └── LICENSE /settings.gradle: -------------------------------------------------------------------------------- 1 | include 'desktop', 'html', 'core' -------------------------------------------------------------------------------- /html/webapp/soundmanager2-setup.js: -------------------------------------------------------------------------------- 1 | window.SM2_DEFER = true; -------------------------------------------------------------------------------- /html/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /core/assets/ss-v1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotr-j/dungen/HEAD/core/assets/ss-v1.png -------------------------------------------------------------------------------- /core/assets/ss-v2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotr-j/dungen/HEAD/core/assets/ss-v2.png -------------------------------------------------------------------------------- /core/assets/badlogic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotr-j/dungen/HEAD/core/assets/badlogic.jpg -------------------------------------------------------------------------------- /html/webapp/refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotr-j/dungen/HEAD/html/webapp/refresh.png -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.daemon=true 2 | org.gradle.jvmargs=-Xms128m -Xmx512m 3 | org.gradle.configureondemand=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotr-j/dungen/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | # This is the official list of people who can contribute 2 | # (and who have contributed) code to the Dungen project 3 | # repository. 4 | # The AUTHORS file lists the copyright holders; this file 5 | # lists people. 6 | # 7 | Piotr Jastrzębski 8 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the official list of the AUTHORS of Dungen 2 | # for copyright purposes. 3 | # This file is distinct from the CONTRIBUTORS files. 4 | # See the latter for an explanation. 5 | 6 | # Names should be added to this file as 7 | # Name or Organization 8 | # The email address is not required for organizations. 9 | 10 | Piotr Jastrzębski 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dungeon generator 2 | 3 | ## Features 4 | - A lot of settings. 5 | - Toggles for visualization 6 | - Json export 7 | 8 | ## Inspiration 9 | 10 | [this reddit post](https://www.reddit.com/r/gamedev/comments/1dlwc4/procedural_dungeon_generation_algorithm_explained/) and [that blog post](https://github.com/adonaac/blog/issues/7) 11 | 12 | ##[Web version](https://piotr-j.github.io/dungen/dungen/) 13 | 14 | ![screenshot](core/assets/ss-v2.png) 15 | 16 | ## TODO: 17 | - ??? 18 | 19 | ## Build with: 20 | - [libgdx](https://github.com/libgdx/libgdx) 21 | - [VisUI](https://github.com/kotcrab/VisEditor/wiki/VisUI) 22 | 23 | ## License 24 | Dungen is licensed under the [Apache 2 License](http://www.apache.org/licenses/LICENSE-2.0.html), meaning you 25 | can use it free of charge, without strings attached in commercial and non-commercial projects. 26 | -------------------------------------------------------------------------------- /core/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | apply plugin: "java" 19 | 20 | sourceCompatibility = 1.7 21 | [compileJava, compileTestJava]*.options*.encoding = 'UTF-8' 22 | 23 | sourceSets.main.java.srcDirs = ["src/"] 24 | 25 | 26 | eclipse.project { 27 | name = appName + "-core" 28 | } 29 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2015 See AUTHORS file. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # 17 | 18 | #Sat Sep 21 13:08:26 CEST 2013 19 | distributionBase=GRADLE_USER_HOME 20 | distributionPath=wrapper/dists 21 | zipStoreBase=GRADLE_USER_HOME 22 | zipStorePath=wrapper/dists 23 | distributionUrl=http\://services.gradle.org/distributions/gradle-2.4-all.zip 24 | -------------------------------------------------------------------------------- /core/src/Dungen.gwt.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Java 2 | 3 | *.class 4 | *.war 5 | *.ear 6 | hs_err_pid* 7 | 8 | ## GWT 9 | war/ 10 | html/war/gwt_bree/ 11 | html/gwt-unitCache/ 12 | .apt_generated/ 13 | html/war/WEB-INF/deploy/ 14 | html/war/WEB-INF/classes/ 15 | .gwt/ 16 | gwt-unitCache/ 17 | www-test/ 18 | .gwt-tmp/ 19 | 20 | ## Android Studio and Intellij and Android in general 21 | android/libs/armeabi/ 22 | android/libs/armeabi-v7a/ 23 | android/libs/x86/ 24 | android/gen/ 25 | .idea/ 26 | *.ipr 27 | *.iws 28 | *.iml 29 | out/ 30 | com_crashlytics_export_strings.xml 31 | 32 | ## Eclipse 33 | .classpath 34 | .project 35 | .metadata 36 | **/bin/ 37 | tmp/ 38 | *.tmp 39 | *.bak 40 | *.swp 41 | *~.nib 42 | local.properties 43 | .settings/ 44 | .loadpath 45 | .externalToolBuilders/ 46 | *.launch 47 | 48 | ## NetBeans 49 | **/nbproject/private/ 50 | build/ 51 | nbbuild/ 52 | dist/ 53 | nbdist/ 54 | nbactions.xml 55 | nb-configuration.xml 56 | 57 | ## Gradle 58 | 59 | .gradle 60 | gradle-app.setting 61 | 62 | ## OS Specific 63 | .DS_Store 64 | .log 65 | -------------------------------------------------------------------------------- /core/src/io/piotrjastrzebski/dungen/gui/Saver.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2015 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | ******************************************************************************/ 17 | 18 | package io.piotrjastrzebski.dungen.gui; 19 | 20 | 21 | /** 22 | * Created by PiotrJ on 10/09/15. 23 | */ 24 | public interface Saver { 25 | void save (String name); 26 | } 27 | -------------------------------------------------------------------------------- /core/src/io/piotrjastrzebski/dungen/PlatformBridge.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2015 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | ******************************************************************************/ 17 | 18 | package io.piotrjastrzebski.dungen; 19 | 20 | /** 21 | * Created by PiotrJ on 28/07/15. 22 | */ 23 | public interface PlatformBridge { 24 | float getPixelScaleFactor (); 25 | void save (String name, String data); 26 | } 27 | -------------------------------------------------------------------------------- /core/src/io/piotrjastrzebski/dungen/gui/Restarter.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2015 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | ******************************************************************************/ 17 | 18 | package io.piotrjastrzebski.dungen.gui; 19 | 20 | import io.piotrjastrzebski.dungen.DrawSettings; 21 | import io.piotrjastrzebski.dungen.GenSettings; 22 | 23 | /** 24 | * Created by PiotrJ on 10/09/15. 25 | */ 26 | public interface Restarter { 27 | public void restart (GenSettings settings); 28 | public void update (DrawSettings settings); 29 | } 30 | -------------------------------------------------------------------------------- /html/webapp/styles.css: -------------------------------------------------------------------------------- 1 | canvas { 2 | cursor: default; 3 | outline: none; 4 | } 5 | 6 | body { 7 | background-color: #222222; 8 | } 9 | 10 | .superdev { 11 | color: rgb(37, 37, 37); 12 | text-shadow: 0px 1px 1px rgba(250, 250, 250, 0.1); 13 | font-size: 50pt; 14 | display: block; 15 | position: relative; 16 | text-decoration: none; 17 | background-color: rgb(83, 87, 93); 18 | box-shadow: 0px 3px 0px 0px rgb(34, 34, 34), 19 | 0px 7px 10px 0px rgb(17, 17, 17), 20 | inset 0px 1px 1px 0px rgba(250, 250, 250, .2), 21 | inset 0px -12px 35px 0px rgba(0, 0, 0, .5); 22 | width: 70px; 23 | height: 70px; 24 | border: 0; 25 | border-radius: 35px; 26 | text-align: center; 27 | line-height: 68px; 28 | } 29 | 30 | .superdev:active { 31 | box-shadow: 0px 0px 0px 0px rgb(34, 34, 34), 32 | 0px 3px 7px 0px rgb(17, 17, 17), 33 | inset 0px 1px 1px 0px rgba(250, 250, 250, .2), 34 | inset 0px -10px 35px 5px rgba(0, 0, 0, .5); 35 | background-color: rgb(83, 87, 93); 36 | top: 3px; 37 | color: #fff; 38 | text-shadow: 0px 0px 3px rgb(250, 250, 250); 39 | } 40 | 41 | .superdev:hover { 42 | background-color: rgb(100, 100, 100); 43 | } 44 | -------------------------------------------------------------------------------- /html/src/io/piotrjastrzebski/dungen/GdxDefinition.gwt.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /html/src/io/piotrjastrzebski/dungen/GdxDefinitionSuperdev.gwt.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /desktop/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "java" 2 | 3 | sourceCompatibility = 1.7 4 | sourceSets.main.java.srcDirs = ["src/"] 5 | 6 | project.ext.mainClassName = "io.piotrjastrzebski.dungen.desktop.DesktopLauncher" 7 | project.ext.assetsDir = new File("../core/assets"); 8 | 9 | task run(dependsOn: classes, type: JavaExec) { 10 | main = project.mainClassName 11 | classpath = sourceSets.main.runtimeClasspath 12 | standardInput = System.in 13 | workingDir = project.assetsDir 14 | ignoreExitValue = true 15 | } 16 | 17 | task dist(type: Jar) { 18 | from files(sourceSets.main.output.classesDir) 19 | from files(sourceSets.main.output.resourcesDir) 20 | from { configurations.compile.collect { zipTree(it) } } 21 | from files(project.assetsDir); 22 | 23 | manifest { 24 | attributes 'Main-Class': project.mainClassName 25 | } 26 | } 27 | 28 | dist.dependsOn classes 29 | 30 | eclipse { 31 | project { 32 | name = appName + "-desktop" 33 | linkedResource name: 'assets', type: '2', location: 'PARENT-1-PROJECT_LOC/core/assets' 34 | } 35 | } 36 | 37 | task afterEclipseImport(description: "Post processing after project generation", group: "IDE") { 38 | doLast { 39 | def classpath = new XmlParser().parse(file(".classpath")) 40 | new Node(classpath, "classpathentry", [kind: 'src', path: 'assets']); 41 | def writer = new FileWriter(file(".classpath")) 42 | def printer = new XmlNodePrinter(new PrintWriter(writer)) 43 | printer.setPreserveWhitespace(true) 44 | printer.print(classpath) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /html/webapp/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Dungen - simple dungeon generator 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 |
View the Project on GitHub piotr-j/dungen
15 | 16 | 17 | 34 | 38 | 44 | 45 | -------------------------------------------------------------------------------- /core/src/io/piotrjastrzebski/dungen/DungenGame.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2015 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | ******************************************************************************/ 17 | 18 | package io.piotrjastrzebski.dungen; 19 | 20 | import com.badlogic.gdx.Game; 21 | import com.kotcrab.vis.ui.VisUI; 22 | 23 | public class DungenGame extends Game { 24 | // 'target' resolution 25 | public final static int WIDTH = 1280; 26 | public final static int HEIGHT = 720; 27 | public final static float SCALE = 32f; 28 | public final static float INV_SCALE = 1.f / SCALE; 29 | public final static float VP_WIDTH = WIDTH * INV_SCALE; 30 | public final static float VP_HEIGHT = HEIGHT * INV_SCALE; 31 | 32 | protected PlatformBridge bridge; 33 | public DungenGame (PlatformBridge bridge) { 34 | this.bridge = bridge; 35 | } 36 | 37 | @Override public void create () { 38 | if (bridge.getPixelScaleFactor() > 1.5f) { 39 | VisUI.load(VisUI.SkinScale.X2); 40 | } else { 41 | VisUI.load(VisUI.SkinScale.X1); 42 | } 43 | setScreen(new DungenScreen(this)); 44 | } 45 | 46 | @Override public void dispose () { 47 | super.dispose(); 48 | VisUI.dispose(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /desktop/src/io/piotrjastrzebski/dungen/desktop/DesktopLauncher.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2015 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | ******************************************************************************/ 17 | 18 | package io.piotrjastrzebski.dungen.desktop; 19 | 20 | import com.badlogic.gdx.backends.lwjgl.LwjglApplication; 21 | import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration; 22 | import io.piotrjastrzebski.dungen.DungenGame; 23 | import io.piotrjastrzebski.dungen.PlatformBridge; 24 | import org.lwjgl.opengl.Display; 25 | 26 | public class DesktopLauncher { 27 | public static void main (String[] arg) { 28 | LwjglApplicationConfiguration config = new LwjglApplicationConfiguration(); 29 | config.width = DungenGame.WIDTH; 30 | config.height = DungenGame.HEIGHT; 31 | config.useHDPI = true; 32 | config.samples = 4; 33 | new LwjglApplication(new DungenGame(new DesktopBridge()), config); 34 | } 35 | 36 | public static class DesktopBridge implements PlatformBridge { 37 | @Override public float getPixelScaleFactor () { 38 | return Display.getPixelScaleFactor(); 39 | } 40 | 41 | @Override public void save (String name, String data) { 42 | 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /html/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "java" 2 | apply plugin: "jetty" 3 | 4 | gwt { 5 | gwtVersion = '2.6.0' // Should match the gwt version used for building the gwt backend 6 | maxHeapSize = "1G" // Default 256m is not enough for gwt compiler. GWT is HUNGRY 7 | minHeapSize = "1G" 8 | 9 | src = files(file("src/")) // Needs to be in front of "modules" below. 10 | modules 'io.piotrjastrzebski.dungen.GdxDefinition' 11 | devModules 'io.piotrjastrzebski.dungen.GdxDefinitionSuperdev' 12 | project.webAppDirName = 'webapp' 13 | 14 | compiler { 15 | strict = true; 16 | enableClosureCompiler = true; 17 | disableCastChecking = true; 18 | } 19 | } 20 | 21 | task draftRun(type: JettyRunWar) { 22 | dependsOn draftWar 23 | dependsOn.remove('war') 24 | webApp = draftWar.archivePath 25 | daemon = true 26 | } 27 | 28 | task superDev(type: de.richsource.gradle.plugins.gwt.GwtSuperDev) { 29 | dependsOn draftRun 30 | doFirst { 31 | gwt.modules = gwt.devModules 32 | } 33 | } 34 | 35 | task dist(dependsOn: [clean, compileGwt]) { 36 | doLast { 37 | file("build/dist").mkdirs() 38 | copy { 39 | from "build/gwt/out" 40 | into "build/dist" 41 | } 42 | copy { 43 | from "webapp" 44 | into "build/dist" 45 | } 46 | copy { 47 | from "war" 48 | into "build/dist" 49 | } 50 | } 51 | } 52 | 53 | draftWar { 54 | from "war" 55 | } 56 | 57 | task addSource << { 58 | sourceSets.main.compileClasspath += files(project(':core').sourceSets.main.allJava.srcDirs) 59 | } 60 | 61 | tasks.compileGwt.dependsOn(addSource) 62 | tasks.draftCompileGwt.dependsOn(addSource) 63 | 64 | sourceCompatibility = 1.7 65 | sourceSets.main.java.srcDirs = ["src/"] 66 | 67 | 68 | eclipse.project { 69 | name = appName + "-html" 70 | } 71 | -------------------------------------------------------------------------------- /core/src/io/piotrjastrzebski/dungen/Grid.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2015 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | ******************************************************************************/ 17 | 18 | package io.piotrjastrzebski.dungen; 19 | 20 | import com.badlogic.gdx.graphics.Color; 21 | import com.badlogic.gdx.graphics.glutils.ShapeRenderer; 22 | 23 | /** 24 | * Created by PiotrJ on 04/09/15. 25 | */ 26 | public class Grid { 27 | float size; 28 | float w, h; 29 | Color color = new Color(0.25f, 0.25f, 0.25f, 1f); 30 | 31 | public void render (ShapeRenderer renderer) { 32 | renderer.setColor(color); 33 | int hSegments = (int)(w / size); 34 | for (int i = 0; i < hSegments / 2; i++) { 35 | float x = i * size; 36 | renderer.line(x, -h / 2, x, h / 2); 37 | renderer.line(-x, -h / 2, -x, h / 2); 38 | } 39 | int vSegments = (int)(h / size); 40 | for (int i = 0; i < vSegments / 2; i++) { 41 | float y = i * size; 42 | renderer.line(-w / 2, y, w / 2, y); 43 | renderer.line(-w / 2, -y, w / 2, -y); 44 | } 45 | } 46 | 47 | public Grid setSize (float size) { 48 | this.size = size; 49 | return this; 50 | } 51 | 52 | public Grid setColor (float r, float g, float b, float a) { 53 | this.color.set(r, g, b, a); 54 | return this; 55 | } 56 | 57 | public void resize (int width, int height) { 58 | w = width; 59 | h = height; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /core/src/io/piotrjastrzebski/dungen/gui/HelpGUI.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2015 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | ******************************************************************************/ 17 | 18 | package io.piotrjastrzebski.dungen.gui; 19 | 20 | import com.badlogic.gdx.Gdx; 21 | import com.badlogic.gdx.scenes.scene2d.InputEvent; 22 | import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; 23 | import com.kotcrab.vis.ui.widget.*; 24 | 25 | public class HelpGUI extends VisDialog { 26 | 27 | public HelpGUI () { 28 | super("HALP!"); 29 | addCloseButton(); 30 | closeOnEscape(); 31 | setModal(true); 32 | VisTable c = new VisTable(true); 33 | c.add(new VisLabel("Welcome to Dungen!")).row(); 34 | VisLabel link = new VisLabel("View this project on github!"); 35 | link.setColor(0.2f, 0.4f, 1, 1); 36 | link.addListener(new ClickListener(){ 37 | @Override public void clicked (InputEvent event, float x, float y) { 38 | Gdx.net.openURI("https://github.com/piotr-j/dungen"); 39 | } 40 | }); 41 | c.add(link).row(); 42 | c.add(new VisLabel("Setting panels are movable")).row(); 43 | c.add().row(); 44 | c.add(new VisLabel("WSAD/arrows to pan view")).row(); 45 | c.add(new VisLabel("Left click and drag to pan view")).row(); 46 | c.add(new VisLabel("Q/E to zoom in/out")).row(); 47 | c.add(new VisLabel("Scroll to zoom in/out")).row(); 48 | c.add(new VisLabel("Space to restart")).row(); 49 | c.add(new VisLabel("ESC to dismiss this dialog")).row(); 50 | add(c); 51 | pack(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /core/src/io/piotrjastrzebski/dungen/RoomNode.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2015 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | ******************************************************************************/ 17 | 18 | package io.piotrjastrzebski.dungen; 19 | 20 | import com.badlogic.gdx.utils.Array; 21 | 22 | /** 23 | * Created by PiotrJ on 03/09/15. 24 | */ 25 | public class RoomNode { 26 | public Room room; 27 | public Array edges = new Array<>(); 28 | 29 | public void add (Room add) { 30 | RoomEdge edge = new RoomEdge(); 31 | edge.roomA = room; 32 | edge.roomB = add; 33 | edges.add(edge); 34 | } 35 | 36 | public void add (RoomEdge add) { 37 | RoomEdge edge = new RoomEdge(); 38 | if (add.roomA == room) { 39 | edge.roomA = add.roomA; 40 | edge.roomB = add.roomB; 41 | } else { 42 | edge.roomA = add.roomB; 43 | edge.roomB = add.roomA; 44 | } 45 | edges.add(edge); 46 | } 47 | 48 | @Override public boolean equals (Object o) { 49 | if (this == o) 50 | return true; 51 | if (o == null || getClass() != o.getClass()) 52 | return false; 53 | 54 | RoomNode roomNode = (RoomNode)o; 55 | 56 | if (room != null ? !room.equals(roomNode.room) : roomNode.room != null) 57 | return false; 58 | return !(edges != null ? !edges.equals(roomNode.edges) : roomNode.edges != null); 59 | 60 | } 61 | 62 | @Override public int hashCode () { 63 | int result = room != null ? room.hashCode() : 0; 64 | result = 31 * result + (edges != null ? edges.hashCode() : 0); 65 | return result; 66 | } 67 | 68 | @Override public String toString () { 69 | return "RoomNode{" + 70 | "room=" + room + 71 | '}'; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /core/src/io/piotrjastrzebski/dungen/RoomEdge.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2015 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | ******************************************************************************/ 17 | 18 | package io.piotrjastrzebski.dungen; 19 | 20 | import com.badlogic.gdx.math.Vector2; 21 | 22 | /** 23 | * Created by PiotrJ on 03/09/15. 24 | */ 25 | public class RoomEdge { 26 | private static Vector2 tmp = new Vector2(); 27 | public Room roomA; 28 | public Room roomB; 29 | public float len; 30 | public boolean mst; 31 | public boolean recon; 32 | 33 | public void set (Room roomA, Room roomB) { 34 | this.roomA = roomA; 35 | this.roomB = roomB; 36 | len = tmp.set(roomA.cx(), roomA.cy()).sub(roomB.cx(), roomB.cy()).len(); 37 | } 38 | 39 | public float ax () { 40 | return roomA.cx(); 41 | } 42 | 43 | public float ay () { 44 | return roomA.cy(); 45 | } 46 | 47 | public float by () { 48 | return roomB.cy(); 49 | } 50 | 51 | public float bx () { 52 | return roomB.cx(); 53 | } 54 | 55 | @Override public boolean equals (Object o) { 56 | if (this == o) 57 | return true; 58 | if (o == null || getClass() != o.getClass()) 59 | return false; 60 | 61 | RoomEdge edge = (RoomEdge)o; 62 | if (edge.roomA == roomA && edge.roomB == roomB) 63 | return true; 64 | if (edge.roomA == roomB && edge.roomB == roomA) 65 | return true; 66 | return false; 67 | } 68 | 69 | @Override public int hashCode () { 70 | int result = roomA != null ? roomA.hashCode() : 0; 71 | result = 31 * result + (roomB != null ? roomB.hashCode() : 0); 72 | result = 31 * result + (len != +0.0f ? Float.floatToIntBits(len) : 0); 73 | return result; 74 | } 75 | 76 | @Override public String toString () { 77 | return "RoomEdge{" + 78 | "roomA=" + roomA + 79 | ", roomB=" + roomB + 80 | ", mst=" + mst + 81 | '}'; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /core/src/io/piotrjastrzebski/dungen/Utils.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2015 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | ******************************************************************************/ 17 | 18 | package io.piotrjastrzebski.dungen; 19 | 20 | import com.badlogic.gdx.math.MathUtils; 21 | import com.badlogic.gdx.math.Vector2; 22 | import com.badlogic.gdx.utils.TimeUtils; 23 | 24 | import java.util.Random; 25 | 26 | /** 27 | * Created by PiotrJ on 04/09/15. 28 | */ 29 | public class Utils { 30 | 31 | public static Vector2 pointInCircle (float radius, Vector2 out) { 32 | return pointInEllipse(radius * 2, radius * 2, out); 33 | } 34 | 35 | public static Vector2 pointInEllipse (float width, float height, Vector2 out) { 36 | float t = (float)(MathUtils.random() * Math.PI * 2); 37 | float u = MathUtils.random() + MathUtils.random(); 38 | float r = (u > 1) ? (2 - u) : u; 39 | out.set(width * r * MathUtils.cos(t) / 2, height * r * MathUtils.sin(t) / 2); 40 | return out; 41 | } 42 | 43 | public static Vector2 roundedPointInEllipse (float width, float height, float size, Vector2 out) { 44 | Utils.pointInEllipse(width, height, out); 45 | out.x = roundToSize(out.x, size); 46 | out.y = roundToSize(out.y, size); 47 | return out; 48 | } 49 | 50 | public static float roundToSize (float value, float size) { 51 | return ((Math.round(value / size)) * size); 52 | } 53 | 54 | public static Vector2 roundToSize (Vector2 value, float size) { 55 | value.x = roundToSize(value.x, size); 56 | value.y = roundToSize(value.y, size); 57 | return value; 58 | } 59 | 60 | private static Random rng = new Random(TimeUtils.millis()); 61 | 62 | public static float rngFloat () { 63 | return (float)(rng.nextGaussian()); 64 | } 65 | 66 | public static float rngFloat (float mean) { 67 | return mean + rngFloat(); 68 | } 69 | public static float rngFloat (float mean, float scale) { 70 | return mean + rngFloat() * scale; 71 | } 72 | 73 | public static float roundedRngFloat (float mean, float scale, float size) { 74 | return Utils.roundToSize(Utils.rngFloat(mean, scale), size); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /core/src/io/piotrjastrzebski/dungen/DrawSettings.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2015 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | ******************************************************************************/ 17 | 18 | package io.piotrjastrzebski.dungen; 19 | 20 | /** 21 | * Created by PiotrJ on 04/09/15. 22 | */ 23 | public class DrawSettings { 24 | public boolean drawMinSpanTree; 25 | public boolean drawHallWayPaths; 26 | public boolean drawHallWays; 27 | public boolean drawBodies; 28 | public boolean drawUnused; 29 | public boolean drawMain; 30 | public boolean drawExtra; 31 | public boolean drawEdges; 32 | public boolean drawSpawnArea; 33 | 34 | public DrawSettings () { 35 | 36 | } 37 | 38 | public void copy (DrawSettings o) { 39 | this.drawMinSpanTree = o.drawMinSpanTree; 40 | this.drawHallWayPaths = o.drawHallWayPaths; 41 | this.drawHallWays = o.drawHallWays; 42 | this.drawBodies = o.drawBodies; 43 | this.drawUnused = o.drawUnused; 44 | this.drawMain = o.drawMain; 45 | this.drawExtra = o.drawExtra; 46 | this.drawEdges = o.drawEdges; 47 | this.drawSpawnArea = o.drawSpawnArea; 48 | } 49 | 50 | public DrawSettings setDrawMinSpanTree (boolean drawMinSpanTree) { 51 | this.drawMinSpanTree = drawMinSpanTree; 52 | return this; 53 | } 54 | 55 | public DrawSettings setDrawHallWayPaths (boolean drawHallWayPaths) { 56 | this.drawHallWayPaths = drawHallWayPaths; 57 | return this; 58 | } 59 | 60 | public DrawSettings setDrawHallWays (boolean drawHallWays) { 61 | this.drawHallWays = drawHallWays; 62 | return this; 63 | } 64 | 65 | public DrawSettings setDrawBodies (boolean drawBodies) { 66 | this.drawBodies = drawBodies; 67 | return this; 68 | } 69 | 70 | public DrawSettings setDrawUnused (boolean drawUnused) { 71 | this.drawUnused = drawUnused; 72 | return this; 73 | } 74 | 75 | public DrawSettings setDrawMain (boolean drawMain) { 76 | this.drawMain = drawMain; 77 | return this; 78 | } 79 | 80 | public DrawSettings setDrawExtra (boolean drawExtra) { 81 | this.drawExtra = drawExtra; 82 | return this; 83 | } 84 | 85 | public DrawSettings setDrawEdges (boolean drawEdges) { 86 | this.drawEdges = drawEdges; 87 | return this; 88 | } 89 | 90 | public DrawSettings setDrawSpawnArea (boolean drawSpawnArea) { 91 | this.drawSpawnArea = drawSpawnArea; 92 | return this; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /html/src/io/piotrjastrzebski/dungen/client/HtmlLauncher.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2015 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | ******************************************************************************/ 17 | 18 | package io.piotrjastrzebski.dungen.client; 19 | 20 | import com.badlogic.gdx.ApplicationListener; 21 | import com.badlogic.gdx.Gdx; 22 | import com.badlogic.gdx.backends.gwt.GwtApplication; 23 | import com.badlogic.gdx.backends.gwt.GwtApplicationConfiguration; 24 | import com.badlogic.gdx.utils.Base64Coder; 25 | import com.google.gwt.core.client.GWT; 26 | import com.google.gwt.dom.client.AnchorElement; 27 | import com.google.gwt.dom.client.Document; 28 | import com.google.gwt.dom.client.NativeEvent; 29 | import com.google.gwt.user.client.Window; 30 | import io.piotrjastrzebski.dungen.BaseScreen; 31 | import io.piotrjastrzebski.dungen.DungenGame; 32 | import io.piotrjastrzebski.dungen.PlatformBridge; 33 | 34 | public class HtmlLauncher extends GwtApplication { 35 | 36 | @Override public GwtApplicationConfiguration getConfig () { 37 | GwtApplicationConfiguration config = new GwtApplicationConfiguration(DungenGame.WIDTH, 38 | DungenGame.HEIGHT); 39 | config.antialiasing = true; 40 | return config; 41 | } 42 | 43 | @Override public ApplicationListener getApplicationListener () { 44 | return new DungenGame(new HtmlBridge()); 45 | } 46 | 47 | public static class HtmlBridge implements PlatformBridge { 48 | @Override public float getPixelScaleFactor () { 49 | return 1; 50 | } 51 | 52 | @Override public void save (String name, String data) { 53 | String toSave = "data:application/octet-stream;charset=utf-8;base64,"; 54 | toSave += Base64Coder.encodeString(data); 55 | toSave+="\n"; 56 | dl(name, toSave); 57 | } 58 | 59 | private static native void dl(String filename, String uri) 60 | /*-{ 61 | var link = document.createElement('a'); 62 | if (typeof link.download === 'string') { 63 | link.href = uri; 64 | link.download = filename; 65 | 66 | //Firefox requires the link to be in the body 67 | document.body.appendChild(link); 68 | 69 | //simulate click 70 | link.click(); 71 | 72 | //remove the link when done 73 | document.body.removeChild(link); 74 | } else { 75 | window.open(uri); 76 | } 77 | }-*/; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /core/src/io/piotrjastrzebski/dungen/Room.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2015 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | ******************************************************************************/ 17 | 18 | package io.piotrjastrzebski.dungen; 19 | 20 | import com.badlogic.gdx.graphics.glutils.ShapeRenderer; 21 | import com.badlogic.gdx.math.Rectangle; 22 | import com.badlogic.gdx.math.Vector2; 23 | import com.badlogic.gdx.physics.box2d.Body; 24 | 25 | /** 26 | * Created by PiotrJ on 03/09/15. 27 | */ 28 | public class Room { 29 | public int id; 30 | public Rectangle bounds = new Rectangle(); 31 | public Body body; 32 | public float gridSize; 33 | public boolean isMain; 34 | public boolean isHallway; 35 | public boolean isExtra; 36 | 37 | public Room (int id, float gridSize) { 38 | this.id = id; 39 | this.gridSize = gridSize; 40 | } 41 | 42 | public boolean isUnused() { 43 | return !isMain && !isHallway && !isExtra; 44 | } 45 | 46 | public void update () { 47 | if (body == null) 48 | return; 49 | Vector2 pos = body.getPosition(); 50 | bounds.setPosition(Utils.roundToSize(pos.x - bounds.width / 2, gridSize), 51 | Utils.roundToSize(pos.y - bounds.height / 2, gridSize)); 52 | } 53 | 54 | public boolean isSleeping () { 55 | if (body == null) 56 | return false; 57 | return !body.isAwake(); 58 | } 59 | 60 | public void draw (ShapeRenderer renderer) { 61 | float s = gridSize * 0.16f; 62 | renderer.rect(bounds.x + s, bounds.y + s, bounds.width - 2 * s, bounds.height - 2 * s); 63 | } 64 | 65 | public void set (float x, float y, float w, float h) { 66 | if (w < 0) 67 | w = -w; 68 | if (h < 0) 69 | h = -h; 70 | bounds.set(x, y, w, h); 71 | } 72 | 73 | public float cx () { 74 | return bounds.x + bounds.width / 2; 75 | } 76 | 77 | public float cy () { 78 | return bounds.y + bounds.height / 2; 79 | } 80 | 81 | @Override public String toString () { 82 | return "Room{" + 83 | "id=" + id + 84 | '}'; 85 | } 86 | 87 | @Override public boolean equals (Object o) { 88 | if (this == o) 89 | return true; 90 | if (o == null || getClass() != o.getClass()) 91 | return false; 92 | 93 | Room room = (Room)o; 94 | 95 | if (id != room.id) 96 | return false; 97 | if (Float.compare(room.gridSize, gridSize) != 0) 98 | return false; 99 | if (isMain != room.isMain) 100 | return false; 101 | if (bounds != null ? !bounds.equals(room.bounds) : room.bounds != null) 102 | return false; 103 | return !(body != null ? !body.equals(room.body) : room.body != null); 104 | 105 | } 106 | 107 | @Override public int hashCode () { 108 | int result = id; 109 | result = 31 * result + (bounds != null ? bounds.hashCode() : 0); 110 | result = 31 * result + (body != null ? body.hashCode() : 0); 111 | result = 31 * result + (gridSize != +0.0f ? Float.floatToIntBits(gridSize) : 0); 112 | result = 31 * result + (isMain ? 1 : 0); 113 | return result; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /core/src/io/piotrjastrzebski/dungen/RoomGraph.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2015 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | ******************************************************************************/ 17 | 18 | package io.piotrjastrzebski.dungen; 19 | 20 | import com.badlogic.gdx.graphics.Color; 21 | import com.badlogic.gdx.graphics.glutils.ShapeRenderer; 22 | import com.badlogic.gdx.utils.Array; 23 | import com.badlogic.gdx.utils.ObjectMap; 24 | 25 | /** 26 | * Created by PiotrJ on 03/09/15. 27 | */ 28 | public class RoomGraph { 29 | Array edges = new Array<>(); 30 | ObjectMap roomToNode = new ObjectMap<>(); 31 | Array nodes = new Array<>(); 32 | 33 | public RoomGraph () { 34 | } 35 | 36 | public void add (RoomEdge edge) { 37 | add(edge.roomA, edge.roomB); 38 | } 39 | 40 | public void add (Room roomA, Room roomB) { 41 | RoomEdge edge = new RoomEdge(); 42 | edge.set(roomA, roomB); 43 | if (!edges.contains(edge, false)) { 44 | edges.add(edge); 45 | } 46 | addNode(roomA, roomB); 47 | addNode(roomB, roomA); 48 | } 49 | 50 | private void addNode (Room roomA, Room roomB) { 51 | RoomNode nodeA = roomToNode.get(roomA); 52 | if (nodeA == null) { 53 | nodeA = new RoomNode(); 54 | nodeA.room = roomA; 55 | roomToNode.put(roomA, nodeA); 56 | nodes.add(nodeA); 57 | } 58 | nodeA.add(roomB); 59 | } 60 | 61 | public void render (ShapeRenderer renderer, boolean drawEdges, boolean mst, float grid) { 62 | if (edges.size == 0) 63 | return; 64 | if (drawEdges) { 65 | for (RoomEdge e : edges) { 66 | renderer.setColor(0, 1, 0, 0.5f); 67 | renderer.rectLine(e.ax(), e.ay(), e.bx(), e.by(), grid * 0.2f); 68 | } 69 | } 70 | if (mst) { 71 | for (RoomEdge e : edges) { 72 | if (e.recon) { 73 | renderer.setColor(Color.ORANGE); 74 | renderer.rectLine(e.ax(), e.ay(), e.bx(), e.by(), grid * 0.4f); 75 | } else if (e.mst) { 76 | renderer.setColor(Color.LIME); 77 | renderer.rectLine(e.ax(), e.ay(), e.bx(), e.by(), grid * 0.4f); 78 | } 79 | } 80 | } 81 | } 82 | 83 | public void clear () { 84 | edges.clear(); 85 | roomToNode.clear(); 86 | nodes.clear(); 87 | } 88 | 89 | public Array getEdges () { 90 | return edges; 91 | } 92 | 93 | Array open = new Array<>(); 94 | Array closed = new Array<>(); 95 | 96 | public boolean isConnected (RoomEdge edge) { 97 | if (edges.size == 0) 98 | return false; 99 | // find if there is an existing path between edge.roomA and edge.roomB 100 | Room start = edge.roomA; 101 | Room target = edge.roomB; 102 | RoomNode sNode = roomToNode.get(start); 103 | // start not yet in graph 104 | if (sNode == null) 105 | return false; 106 | 107 | closed.clear(); 108 | open.clear(); 109 | open.add(sNode); 110 | while (open.size > 0) { 111 | RoomNode first = open.get(0); 112 | closed.add(first); 113 | open.removeIndex(0); 114 | for (RoomEdge e : first.edges) { 115 | RoomNode node = roomToNode.get(e.roomB); 116 | if (node.room == target) { 117 | return true; 118 | } 119 | if (!closed.contains(node, true)) { 120 | open.add(node); 121 | } 122 | } 123 | } 124 | return false; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /core/src/io/piotrjastrzebski/dungen/HallwayPath.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2015 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | ******************************************************************************/ 17 | 18 | package io.piotrjastrzebski.dungen; 19 | 20 | import com.badlogic.gdx.graphics.Color; 21 | import com.badlogic.gdx.graphics.glutils.ShapeRenderer; 22 | import com.badlogic.gdx.math.*; 23 | import com.badlogic.gdx.utils.Array; 24 | 25 | /** 26 | * Created by PiotrJ on 03/09/15. 27 | */ 28 | public class HallwayPath { 29 | private static int ID = 0; 30 | public int id; 31 | public Vector2 start = new Vector2(); 32 | public Vector2 bend = new Vector2(); 33 | public Vector2 end = new Vector2(); 34 | public Rectangle hallA = new Rectangle(); 35 | public Rectangle hallB = new Rectangle(); 36 | public boolean hasBend; 37 | public boolean recon; 38 | public int width = 1; 39 | public Room roomA; 40 | public Room roomB; 41 | public Array overlap = new Array<>(); 42 | private float gridSize; 43 | 44 | public HallwayPath (float gridSize, int width) { 45 | this.gridSize = gridSize; 46 | this.width = width; 47 | this.id = ID++; 48 | } 49 | 50 | Vector2 tmp = new Vector2(); 51 | public void draw (ShapeRenderer renderer) { 52 | if (recon) { 53 | renderer.setColor(Color.ORANGE); 54 | } else { 55 | renderer.setColor(Color.LIME); 56 | } 57 | if (hasBend) { 58 | renderer.rectLine(start.x, start.y, bend.x, bend.y, gridSize * 0.33f); 59 | renderer.rectLine(bend.x, bend.y, end.x, end.y, gridSize * 0.33f); 60 | } else { 61 | renderer.rectLine(start.x, start.y, end.x, end.y, gridSize * 0.33f); 62 | } 63 | } 64 | 65 | private Rectangle setPathRect(Vector2 start, Vector2 end, Rectangle rect) { 66 | tmp.set(end).sub(start); 67 | float grid = gridSize * width; 68 | float sx = start.x > end.x? end.x:start.x; 69 | float sy = start.y > end.y? end.y:start.y; 70 | float width = grid - gridSize / 2; 71 | float height = grid - gridSize / 2; 72 | if (MathUtils.isZero(tmp.x)) { 73 | // horizontal path 74 | sx = sx - grid / 2 + gridSize / 4; 75 | sy = sy - grid / 2 + gridSize / 4; 76 | height = Math.abs(end.y - start.y) + grid - gridSize / 2; 77 | rect.set(sx, sy, width, height); 78 | } else { 79 | // vertical path 80 | sx = sx - grid / 2 + gridSize / 4; 81 | sy = sy - grid / 2 + gridSize / 4; 82 | width = Math.abs(end.x - start.x) + grid - gridSize / 2; 83 | rect.set(sx, sy, width, height); 84 | } 85 | return rect; 86 | } 87 | 88 | public void set (float sx, float sy, float ex, float ey) { 89 | start.set(sx, sy); 90 | end.set(ex, ey); 91 | hasBend = false; 92 | setPathRect(start, end, hallA); 93 | } 94 | 95 | public void set (float sx, float sy, float bx, float by, float ex, float ey) { 96 | start.set(sx, sy); 97 | bend.set(bx, by); 98 | end.set(ex, ey); 99 | hasBend = true; 100 | setPathRect(start, bend, hallA); 101 | setPathRect(bend, end, hallB); 102 | } 103 | 104 | public boolean intersects (Room room) { 105 | Rectangle b = room.bounds; 106 | if (hasBend) { 107 | return b.overlaps(hallA) || b.overlaps(hallB); 108 | } else { 109 | return b.overlaps(hallA); 110 | } 111 | } 112 | 113 | @Override public String toString () { 114 | return "Hallway{" + 115 | "id=" + id + 116 | '}'; 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /core/src/io/piotrjastrzebski/dungen/GenSettings.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2015 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | ******************************************************************************/ 17 | 18 | package io.piotrjastrzebski.dungen; 19 | 20 | /** 21 | * Created by PiotrJ on 04/09/15. 22 | */ 23 | public class GenSettings { 24 | private float gridSize; 25 | private float spawnWidth, spawnHeight; 26 | private float roomWidth, roomHeight; 27 | private float mainRoomScale; 28 | private float reconnectChance; 29 | private int hallwaysWidth; 30 | private int count; 31 | private int b2bIters; 32 | 33 | public GenSettings () { 34 | } 35 | 36 | public int getHallwaysWidth () { 37 | return hallwaysWidth; 38 | } 39 | 40 | public GenSettings setHallwaysWidth (int hallwaysWidth) { 41 | this.hallwaysWidth = hallwaysWidth; 42 | return this; 43 | } 44 | 45 | public float getGridSize () { 46 | return gridSize; 47 | } 48 | 49 | public GenSettings setGridSize (float gridSize) { 50 | this.gridSize = gridSize; 51 | return this; 52 | } 53 | 54 | public float getSpawnWidth () { 55 | return spawnWidth * gridSize; 56 | } 57 | 58 | public float getRawSpawnWidth () { 59 | return spawnWidth; 60 | } 61 | 62 | public GenSettings setSpawnWidth (float ellipseWidth) { 63 | this.spawnWidth = ellipseWidth; 64 | return this; 65 | } 66 | 67 | public float getSpawnHeight () { 68 | return spawnHeight * gridSize; 69 | } 70 | 71 | 72 | public float getRawSpawnHeight () { 73 | return spawnHeight; 74 | } 75 | 76 | public GenSettings setSpawnHeight (float ellipseHeight) { 77 | this.spawnHeight = ellipseHeight; 78 | return this; 79 | } 80 | 81 | public float getRoomWidth () { 82 | return roomWidth * gridSize; 83 | } 84 | public float getRawRoomWidth () { 85 | return roomWidth; 86 | } 87 | 88 | public GenSettings setRoomWidth (float roomWidth) { 89 | this.roomWidth = roomWidth; 90 | return this; 91 | } 92 | 93 | public float getRoomHeight () { 94 | return roomHeight * gridSize; 95 | } 96 | public float getRawRoomHeight () { 97 | return roomHeight; 98 | } 99 | 100 | public GenSettings setRoomHeight (float roomHeight) { 101 | this.roomHeight = roomHeight; 102 | return this; 103 | } 104 | 105 | public float getMainRoomScale () { 106 | return mainRoomScale; 107 | } 108 | 109 | public GenSettings setMainRoomScale (float mainRoomScale) { 110 | this.mainRoomScale = mainRoomScale; 111 | return this; 112 | } 113 | 114 | public float getReconnectChance () { 115 | return reconnectChance; 116 | } 117 | 118 | public GenSettings setReconnectChance (float reconnectChance) { 119 | this.reconnectChance = reconnectChance; 120 | return this; 121 | } 122 | 123 | public GenSettings setCount (int count) { 124 | this.count = count; 125 | return this; 126 | } 127 | 128 | public int getCount () { 129 | return count; 130 | } 131 | 132 | public GenSettings setB2bIters (int b2bIters) { 133 | this.b2bIters = b2bIters; 134 | return this; 135 | } 136 | 137 | public int getB2bIters () { 138 | return b2bIters; 139 | } 140 | 141 | public void copy (GenSettings s) { 142 | this.gridSize = s.gridSize; 143 | this.spawnWidth = s.spawnWidth; 144 | this.spawnHeight = s.spawnHeight; 145 | this.roomWidth = s.roomWidth; 146 | this.roomHeight = s.roomHeight; 147 | this.mainRoomScale = s.mainRoomScale; 148 | this.reconnectChance = s.reconnectChance; 149 | this.hallwaysWidth = s.hallwaysWidth; 150 | this.count = s.count; 151 | this.b2bIters = s.b2bIters; 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /core/src/io/piotrjastrzebski/dungen/BaseScreen.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2015 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | ******************************************************************************/ 17 | 18 | package io.piotrjastrzebski.dungen; 19 | 20 | import com.badlogic.gdx.*; 21 | import com.badlogic.gdx.graphics.GL20; 22 | import com.badlogic.gdx.graphics.OrthographicCamera; 23 | import com.badlogic.gdx.graphics.g2d.SpriteBatch; 24 | import com.badlogic.gdx.graphics.glutils.ShapeRenderer; 25 | import com.badlogic.gdx.scenes.scene2d.Stage; 26 | import com.badlogic.gdx.scenes.scene2d.ui.Table; 27 | import com.badlogic.gdx.utils.viewport.ExtendViewport; 28 | import com.badlogic.gdx.utils.viewport.ScreenViewport; 29 | 30 | /** 31 | * Created by EvilEntity on 07/06/2015. 32 | */ 33 | public abstract class BaseScreen implements Screen, InputProcessor { 34 | private final static String TAG = "BaseScreen"; 35 | 36 | protected OrthographicCamera gameCamera; 37 | protected OrthographicCamera guiCamera; 38 | protected ExtendViewport gameViewport; 39 | protected ScreenViewport guiViewport; 40 | 41 | protected SpriteBatch batch; 42 | protected ShapeRenderer renderer; 43 | 44 | protected Stage stage; 45 | protected Table root; 46 | 47 | protected final InputMultiplexer multiplexer; 48 | 49 | boolean debugStage; 50 | 51 | public BaseScreen () { 52 | gameCamera = new OrthographicCamera(); 53 | gameViewport = new ExtendViewport(DungenGame.VP_WIDTH, DungenGame.VP_HEIGHT, gameCamera); 54 | guiCamera = new OrthographicCamera(); 55 | guiViewport = new ScreenViewport(guiCamera); 56 | 57 | batch = new SpriteBatch(); 58 | renderer = new ShapeRenderer(); 59 | 60 | stage = new Stage(guiViewport, batch); 61 | stage.setDebugAll(debugStage); 62 | root = new Table(); 63 | root.setFillParent(true); 64 | stage.addActor(root); 65 | Gdx.input.setInputProcessor(multiplexer = new InputMultiplexer(stage, this)); 66 | 67 | Gdx.app.log(TAG, "F1 - toggle stage debug"); 68 | } 69 | 70 | @Override public void show () { 71 | 72 | } 73 | 74 | @Override public void render (float delta) { 75 | Gdx.gl.glClearColor(0, 0, 0, 1); 76 | Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); 77 | } 78 | 79 | @Override public void resize (int width, int height) { 80 | gameViewport.update(width, height, false); 81 | guiViewport.update(width, height, true); 82 | } 83 | 84 | @Override public void pause () { 85 | 86 | } 87 | 88 | @Override public void resume () { 89 | 90 | } 91 | 92 | @Override public void hide () { 93 | dispose(); 94 | } 95 | 96 | @Override public void dispose () { 97 | batch.dispose(); 98 | renderer.dispose(); 99 | stage.dispose(); 100 | } 101 | 102 | @Override public boolean keyDown (int keycode) { 103 | if (keycode == Input.Keys.F1) { 104 | debugStage = !debugStage; 105 | stage.setDebugAll(debugStage); 106 | Gdx.app.log(TAG, "F1 - Stage debug is " + (debugStage ? "enabled" : "disabled")); 107 | } 108 | return false; 109 | } 110 | 111 | @Override public boolean keyUp (int keycode) { 112 | return false; 113 | } 114 | 115 | @Override public boolean keyTyped (char character) { 116 | return false; 117 | } 118 | 119 | @Override public boolean touchDown (int screenX, int screenY, int pointer, int button) { 120 | return false; 121 | } 122 | 123 | @Override public boolean touchUp (int screenX, int screenY, int pointer, int button) { 124 | return false; 125 | } 126 | 127 | @Override public boolean touchDragged (int screenX, int screenY, int pointer) { 128 | return false; 129 | } 130 | 131 | @Override public boolean mouseMoved (int screenX, int screenY) { 132 | return false; 133 | } 134 | 135 | @Override public boolean scrolled (int amount) { 136 | return false; 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /core/src/io/piotrjastrzebski/dungen/gui/DrawSettingsGUI.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2015 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | ******************************************************************************/ 17 | 18 | package io.piotrjastrzebski.dungen.gui; 19 | 20 | import com.badlogic.gdx.scenes.scene2d.Actor; 21 | import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener; 22 | import com.kotcrab.vis.ui.VisUI; 23 | import com.kotcrab.vis.ui.widget.*; 24 | import io.piotrjastrzebski.dungen.DrawSettings; 25 | 26 | public class DrawSettingsGUI extends VisWindow { 27 | DrawSettings settings; 28 | Restarter restarter; 29 | 30 | VisCheckBox drawMinSpanTree; 31 | VisCheckBox drawHallWayPaths; 32 | VisCheckBox drawHallWays; 33 | VisCheckBox drawBodies; 34 | VisCheckBox drawUnused; 35 | VisCheckBox drawMain; 36 | VisCheckBox drawExtra; 37 | VisCheckBox drawEdges; 38 | VisCheckBox drawSpawnArea; 39 | 40 | public DrawSettingsGUI (Restarter restarter) { 41 | super("Display settings"); 42 | this.restarter = restarter; 43 | VisUI.getSkin().getFont("default-font").getData().markupEnabled = true; 44 | settings = new DrawSettings(); 45 | VisTable c = new VisTable(true); 46 | c.add(new VisLabel("Hover for tooltips")).row(); 47 | 48 | drawBodies = toggle(c, "Bodies", "Draw box2d bodies used for separation", settings.drawBodies, new Toggle() { 49 | @Override public void toggle (boolean value) { 50 | settings.drawBodies = value; 51 | } 52 | }); 53 | c.row(); 54 | drawUnused = toggle(c, "[#9c9c9c]Unused[]", "Draw rooms that are [#9c9c9c]unused[]", settings.drawUnused, new Toggle() { 55 | @Override public void toggle (boolean value) { 56 | settings.drawUnused = value; 57 | } 58 | }); 59 | drawExtra = toggle(c, "[#cccccc]Extra[]", "Draw [#cccccc]extra[] rooms, added to form paths", settings.drawExtra, new Toggle() { 60 | @Override public void toggle (boolean value) { 61 | settings.drawExtra = value; 62 | } 63 | }); 64 | c.row(); 65 | drawHallWays = toggle(c, "[#3366ff]Hallways[]", "Draw rooms that are part of [#3366ff]hallways[]", settings.drawHallWays, new Toggle() { 66 | @Override public void toggle (boolean value) { 67 | settings.drawHallWays = value; 68 | } 69 | }); 70 | drawMain = toggle(c, "[#ff3319]Main[]", "Draw [#ff3319]main[] rooms", settings.drawMain, new Toggle() { 71 | @Override public void toggle (boolean value) { 72 | settings.drawMain = value; 73 | } 74 | }); 75 | c.row(); 76 | String ptt = "Draw hallway paths connecting main rooms\n" + 77 | "[#32cd32]from min span tree[]\n" + 78 | "[ORANGE]reconnected[]"; 79 | drawHallWayPaths = toggle(c, "Hallway Paths", ptt, settings.drawHallWayPaths, new Toggle() { 80 | @Override public void toggle (boolean value) { 81 | settings.drawHallWayPaths = value; 82 | } 83 | }); 84 | drawSpawnArea = toggle(c, "Spawn Area", "Draw initial spawn area of rooms", settings.drawSpawnArea, new Toggle() { 85 | @Override public void toggle (boolean value) { 86 | settings.drawSpawnArea = value; 87 | } 88 | }); 89 | c.row(); 90 | String msttt = "Draw minimum spanning tree for main rooms\n" + 91 | "[#32cd32]min span tree[]\n" + 92 | "[ORANGE]reconnected[]"; 93 | drawMinSpanTree = toggle(c, "Min Span Tree", msttt, settings.drawMinSpanTree, new Toggle() { 94 | @Override public void toggle (boolean value) { 95 | settings.drawMinSpanTree = value; 96 | } 97 | }); 98 | drawEdges = toggle(c, "Triangulation", "Draw triangulation for main rooms", settings.drawEdges, new Toggle() { 99 | @Override public void toggle (boolean value) { 100 | settings.drawEdges = value; 101 | } 102 | }); 103 | 104 | add(c); 105 | pack(); 106 | } 107 | 108 | private VisCheckBox toggle (VisTable c, String text, String tt, boolean def, final Toggle toggle) { 109 | final VisCheckBox cb = new VisCheckBox(text, def); 110 | new Tooltip(cb, tt); 111 | cb.addListener(new ChangeListener() { 112 | @Override public void changed (ChangeEvent event, Actor actor) { 113 | toggle.toggle(cb.isChecked()); 114 | restarter.update(settings); 115 | } 116 | }); 117 | c.add(cb).left(); 118 | return cb; 119 | } 120 | 121 | private abstract class Toggle { 122 | public abstract void toggle(boolean checked); 123 | } 124 | 125 | public void setDefaults(DrawSettings settings) { 126 | this.settings.copy(settings); 127 | drawBodies.setChecked(settings.drawBodies); 128 | drawUnused.setChecked(settings.drawUnused); 129 | drawExtra.setChecked(settings.drawExtra); 130 | drawHallWays.setChecked(settings.drawHallWays); 131 | drawHallWayPaths.setChecked(settings.drawHallWayPaths); 132 | drawMain.setChecked(settings.drawMain); 133 | drawEdges.setChecked(settings.drawEdges); 134 | drawMinSpanTree.setChecked(settings.drawMinSpanTree); 135 | drawSpawnArea.setChecked(settings.drawSpawnArea); 136 | pack(); 137 | } 138 | 139 | public DrawSettings getSettings () { 140 | return settings; 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /core/src/io/piotrjastrzebski/dungen/gui/GenSettingsGUI.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2015 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | ******************************************************************************/ 17 | 18 | package io.piotrjastrzebski.dungen.gui; 19 | 20 | import com.badlogic.gdx.Gdx; 21 | import com.badlogic.gdx.scenes.scene2d.Actor; 22 | import com.badlogic.gdx.scenes.scene2d.InputEvent; 23 | import com.badlogic.gdx.scenes.scene2d.ui.Table; 24 | import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener; 25 | import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; 26 | import com.badlogic.gdx.utils.Align; 27 | import com.badlogic.gdx.utils.Base64Coder; 28 | import com.badlogic.gdx.utils.StringBuilder; 29 | import com.kotcrab.vis.ui.VisUI; 30 | import com.kotcrab.vis.ui.widget.*; 31 | import io.piotrjastrzebski.dungen.DungenScreen; 32 | import io.piotrjastrzebski.dungen.GenSettings; 33 | 34 | public class GenSettingsGUI extends VisWindow { 35 | GenSettings settings; 36 | VisSlider grid; 37 | VisSlider count; 38 | VisSlider sWidth; 39 | VisSlider sHeight; 40 | VisSlider rWidth; 41 | VisSlider rHeight; 42 | VisSlider mainScale; 43 | VisSlider reconChance; 44 | VisSlider hallWidth; 45 | VisSlider b2dIters; 46 | 47 | public GenSettingsGUI (final Restarter restarter, final Saver saver) { 48 | super("Generator settings"); 49 | settings = new GenSettings(); 50 | VisTable c = new VisTable(true); 51 | 52 | VisTextButton restart = new VisTextButton("Restart"); 53 | restart.addListener(new ClickListener() { 54 | @Override public void clicked (InputEvent event, float x, float y) { 55 | restarter.restart(settings); 56 | } 57 | }); 58 | VisTextButton export = new VisTextButton("Export"); 59 | export.addListener(new ClickListener() { 60 | @Override public void clicked (InputEvent event, float x, float y) { 61 | // TODO add a dialog to pick a name? 62 | saver.save("dungen"); 63 | } 64 | }); 65 | VisTable top = new VisTable(true); 66 | top.add(restart); 67 | top.add(export).expandX(); 68 | top.add(new VisLabel("Hover for tooltips")); 69 | c.add(top).expandX().fillX().colspan(3); 70 | c.row(); 71 | 72 | grid = slider(c, "Grid Size", "Size of the grid in units\n1u=32px at 720p", 0.1f, 1.f, 0.05f, new SliderAction() { 73 | @Override public void setValue (float value) { 74 | settings.setGridSize(value); 75 | } 76 | }); 77 | c.row(); 78 | count = slider(c, "Room Count", "Number of rooms to be spawned", 50f, 1000f, 10f, new SliderAction() { 79 | @Override public void setValue (float value) { 80 | settings.setCount((int)value); 81 | } 82 | }); 83 | c.row(); 84 | sWidth = slider(c, "Spawn Width", "Width of the ellipse the rooms will be spawned in\nin grid units", 5f, 100f, 5f, new SliderAction() { 85 | @Override public void setValue (float value) { 86 | settings.setSpawnWidth(value); 87 | } 88 | }); 89 | c.row(); 90 | sHeight = slider(c, "Spawn Height", "Height of the ellipse the rooms will be spawned in\nin grid units", 5f, 100f, 5f, new SliderAction() { 91 | @Override public void setValue (float value) { 92 | settings.setSpawnHeight(value); 93 | } 94 | }); 95 | c.row(); 96 | rWidth = slider(c, "Room Width", "Mean room width in grid units", 1f, 10f, 1f, new SliderAction() { 97 | @Override public void setValue (float value) { 98 | settings.setRoomWidth(value); 99 | } 100 | }); 101 | c.row(); 102 | rHeight = slider(c, "Room Height", "Mean room height in grid units", 1f, 10f, 1f, new SliderAction() { 103 | @Override public void setValue (float value) { 104 | settings.setRoomHeight(value); 105 | } 106 | }); 107 | c.row(); 108 | mainScale = slider(c, "Main Scale", "Percent of the mean size for a room to be marked as main", 0.5f, 2.f, 0.05f, new SliderAction() { 109 | @Override public void setValue (float value) { 110 | settings.setMainRoomScale(value); 111 | } 112 | }); 113 | c.row(); 114 | reconChance = slider(c, "Reconnect %", "Chance to reconnect the path after\nminimum spanning tree is created", 115 | 0.0f, 1.f, 0.05f, new SliderAction() { 116 | @Override public void setValue (float value) { 117 | settings.setReconnectChance(value); 118 | } 119 | }); 120 | add(c); 121 | c.row(); 122 | hallWidth = slider(c, "Hallway Width", "Width of hallways in grid units", 123 | 1, 10, 1, new SliderAction() { 124 | @Override public void setValue (float value) { 125 | settings.setHallwaysWidth((int)value); 126 | } 127 | }); 128 | add(c); 129 | c.row(); 130 | b2dIters = slider(c, "B2D Iterations", "Iterations per frame for settling bodies, more -> faster settling", 131 | 5, 1000, 5, new SliderAction() { 132 | @Override public void setValue (float value) { 133 | settings.setB2bIters((int)value); 134 | } 135 | }); 136 | add(c); 137 | pack(); 138 | } 139 | 140 | private abstract class SliderAction { 141 | public abstract void setValue (float value); 142 | } 143 | 144 | private VisSlider slider(Table container, String text, String tooltip, float min, float max, float step, final SliderAction action) { 145 | VisLabel label = new VisLabel(text); 146 | final VisSlider slider = new VisSlider(min, max, step, false); 147 | container.add(label).left(); 148 | new Tooltip(label, tooltip); 149 | float scale = VisUI.getSizes().scaleFactor; 150 | container.add(slider).prefWidth(120 * scale); 151 | final VisLabel val = new VisLabel("000.00"); 152 | slider.addListener(new ChangeListener() { 153 | @Override public void changed (ChangeEvent event, Actor actor) { 154 | val.setText(toStr(slider.getValue())); 155 | action.setValue(slider.getValue()); 156 | } 157 | }); 158 | val.setAlignment(Align.right); 159 | container.add(val).right().width(45 * scale); 160 | return slider; 161 | } 162 | 163 | /* 164 | Simple String.format() replacements as it doesnt work on GWT 165 | */ 166 | StringBuilder sb = new StringBuilder(); 167 | private String toStr(float value) { 168 | sb.setLength(0); 169 | sb.append(value); 170 | int dot = sb.indexOf("."); 171 | if (dot > 0 && sb.length() > dot + 3) { 172 | sb.setLength(dot + 3); 173 | } 174 | return sb.toString(); 175 | } 176 | 177 | public void setDefaults(GenSettings settings) { 178 | this.settings.copy(settings); 179 | grid.setValue(settings.getGridSize()); 180 | count.setValue(settings.getCount()); 181 | sWidth.setValue(settings.getRawSpawnWidth()); 182 | sHeight.setValue(settings.getRawSpawnHeight()); 183 | rWidth.setValue(settings.getRawRoomWidth()); 184 | rHeight.setValue(settings.getRawRoomHeight()); 185 | mainScale.setValue(settings.getMainRoomScale()); 186 | reconChance.setValue(settings.getReconnectChance()); 187 | hallWidth.setValue(settings.getHallwaysWidth()); 188 | b2dIters.setValue(settings.getB2bIters()); 189 | pack(); 190 | } 191 | 192 | public GenSettings getSettings () { 193 | return settings; 194 | } 195 | 196 | } 197 | -------------------------------------------------------------------------------- /core/src/io/piotrjastrzebski/dungen/DungenScreen.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2015 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | ******************************************************************************/ 17 | 18 | package io.piotrjastrzebski.dungen; 19 | 20 | import com.badlogic.gdx.Gdx; 21 | import com.badlogic.gdx.Input; 22 | import com.badlogic.gdx.Preferences; 23 | import com.badlogic.gdx.graphics.glutils.ShapeRenderer; 24 | import com.badlogic.gdx.input.GestureDetector; 25 | import com.badlogic.gdx.math.MathUtils; 26 | import com.badlogic.gdx.math.Vector2; 27 | import com.badlogic.gdx.scenes.scene2d.InputEvent; 28 | import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; 29 | import com.badlogic.gdx.utils.JsonWriter; 30 | import com.kotcrab.vis.ui.widget.VisTable; 31 | import com.kotcrab.vis.ui.widget.VisTextButton; 32 | import io.piotrjastrzebski.dungen.gui.*; 33 | 34 | /** 35 | * Created by PiotrJ on 02/09/15. 36 | */ 37 | public class DungenScreen extends BaseScreen implements Restarter, Saver, GestureDetector.GestureListener { 38 | DungeonGenerator generator; 39 | Grid grid; 40 | GenSettingsGUI genGui; 41 | GenSettings genSettings; 42 | DrawSettingsGUI drawGui; 43 | DrawSettings drawSettings; 44 | DungenGame game; 45 | 46 | HelpGUI helpGUI; 47 | 48 | public DungenScreen (DungenGame game) { 49 | super(); 50 | this.game = game; 51 | 52 | genSettings = new GenSettings() 53 | .setGridSize(.25f) 54 | .setCount(150) 55 | .setSpawnWidth(20).setSpawnHeight(10) 56 | .setRoomWidth(4).setRoomHeight(4) 57 | .setMainRoomScale(1.15f) 58 | .setReconnectChance(.2f) 59 | .setHallwaysWidth(2) 60 | .setB2bIters(100); 61 | 62 | drawSettings = new DrawSettings() 63 | .setDrawExtra(true) 64 | .setDrawMain(true) 65 | .setDrawHallWays(true) 66 | .setDrawUnused(true); 67 | 68 | generator = new DungeonGenerator(); 69 | generator.init(genSettings); 70 | 71 | grid = new Grid(); 72 | grid.setSize(genSettings.getGridSize()); 73 | 74 | genGui = new GenSettingsGUI(this, this); 75 | genGui.setDefaults(genSettings); 76 | stage.addActor(genGui); 77 | genGui.setPosition(10, 10); 78 | 79 | drawGui = new DrawSettingsGUI(this); 80 | drawGui.setDefaults(drawSettings); 81 | stage.addActor(drawGui); 82 | drawGui.setPosition(10, stage.getHeight() - drawGui.getHeight() - 10); 83 | 84 | multiplexer.addProcessor(this); 85 | multiplexer.addProcessor(new GestureDetector(this)); 86 | 87 | helpGUI = new HelpGUI(); 88 | VisTable helpCont = new VisTable(); 89 | helpCont.setFillParent(true); 90 | VisTextButton showHelp = new VisTextButton("Help!"); 91 | showHelp.addListener(new ClickListener() { 92 | @Override public void clicked (InputEvent event, float x, float y) { 93 | helpGUI.show(stage); 94 | } 95 | }); 96 | helpCont.add(showHelp).right().top().expand().pad(10); 97 | stage.addActor(helpCont); 98 | 99 | Preferences dungen = Gdx.app.getPreferences("Dungen"); 100 | if (!dungen.getBoolean("help-shown", false)) { 101 | helpGUI.show(stage); 102 | dungen.putBoolean("help-shown", true); 103 | dungen.flush(); 104 | } 105 | } 106 | 107 | @Override public void save (String name) { 108 | // TODO settings for type and pretty print 109 | String json = generator.toJson(JsonWriter.OutputType.javascript, true); 110 | if (!name.endsWith(".json")) 111 | name += ".json"; 112 | game.bridge.save(name, json); 113 | } 114 | 115 | private int moveVert; 116 | private int moveHor; 117 | private int zoom; 118 | @Override public void render (float delta) { 119 | super.render(delta); 120 | generator.update(delta); 121 | if (zoom > 0) { 122 | gameCamera.zoom = MathUtils.clamp(gameCamera.zoom + gameCamera.zoom * 0.05f, 0.01f, 10); 123 | } else if (zoom < 0) { 124 | gameCamera.zoom = MathUtils.clamp(gameCamera.zoom - gameCamera.zoom * 0.05f, 0.01f, 10); 125 | 126 | } 127 | if (moveVert > 0) { 128 | gameCamera.position.y += 10 * delta; 129 | } else if (moveVert < 0) { 130 | gameCamera.position.y -= 10 * delta; 131 | } 132 | if (moveHor > 0) { 133 | gameCamera.position.x += 10 * delta; 134 | } else if (moveHor < 0) { 135 | gameCamera.position.x -= 10 * delta; 136 | } 137 | gameCamera.update(); 138 | 139 | renderer.setProjectionMatrix(gameCamera.combined); 140 | renderer.begin(ShapeRenderer.ShapeType.Line); 141 | grid.render(renderer); 142 | renderer.end(); 143 | 144 | renderer.begin(ShapeRenderer.ShapeType.Filled); 145 | generator.render(renderer, gameCamera); 146 | renderer.end(); 147 | 148 | stage.act(delta); 149 | stage.draw(); 150 | } 151 | 152 | @Override public void resize (int width, int height) { 153 | super.resize(width, height); 154 | grid.resize(width, height); 155 | } 156 | 157 | @Override public boolean keyDown (int keycode) { 158 | switch (keycode) { 159 | case Input.Keys.SPACE: 160 | restart(genGui.getSettings()); 161 | break; 162 | case Input.Keys.C: 163 | resetCamera(); 164 | break; 165 | case Input.Keys.Q: 166 | zoom++; 167 | break; 168 | case Input.Keys.E: 169 | zoom--; 170 | break; 171 | case Input.Keys.UP: 172 | case Input.Keys.W: 173 | moveVert++; 174 | break; 175 | case Input.Keys.DOWN: 176 | case Input.Keys.S: 177 | moveVert--; 178 | break; 179 | case Input.Keys.LEFT: 180 | case Input.Keys.A: 181 | moveHor--; 182 | break; 183 | case Input.Keys.RIGHT: 184 | case Input.Keys.D: 185 | moveHor++; 186 | break; 187 | } 188 | return super.keyDown(keycode); 189 | } 190 | 191 | 192 | @Override public boolean keyUp (int keycode) { 193 | switch (keycode) { 194 | case Input.Keys.Q: 195 | zoom--; 196 | break; 197 | case Input.Keys.E: 198 | zoom++; 199 | break; 200 | case Input.Keys.UP: 201 | case Input.Keys.W: 202 | moveVert--; 203 | break; 204 | case Input.Keys.DOWN: 205 | case Input.Keys.S: 206 | moveVert++; 207 | break; 208 | case Input.Keys.LEFT: 209 | case Input.Keys.A: 210 | moveHor++; 211 | break; 212 | case Input.Keys.RIGHT: 213 | case Input.Keys.D: 214 | moveHor--; 215 | break; 216 | } 217 | return super.keyDown(keycode); 218 | } 219 | 220 | private void resetCamera () { 221 | gameCamera.position.setZero(); 222 | gameCamera.zoom = 1; 223 | gameCamera.update(); 224 | } 225 | 226 | @Override public boolean scrolled (int amount) { 227 | gameCamera.zoom = MathUtils.clamp(gameCamera.zoom + gameCamera.zoom * amount * 0.05f, 0.01f, 10); 228 | gameCamera.update(); 229 | return super.scrolled(amount); 230 | } 231 | 232 | @Override public void dispose () { 233 | super.dispose(); 234 | generator.dispose(); 235 | } 236 | 237 | @Override public void restart (GenSettings settings) { 238 | this.genSettings.copy(settings); 239 | generator.init(settings); 240 | grid.setSize(settings.getGridSize()); 241 | } 242 | 243 | @Override public void update (DrawSettings settings) { 244 | generator.setDrawSettings(settings); 245 | } 246 | 247 | @Override public boolean pan (float x, float y, float deltaX, float deltaY) { 248 | // this feels wrong... 249 | float ppw = gameViewport.getWorldWidth() / gameViewport.getScreenWidth(); 250 | float pph = gameViewport.getWorldHeight() / gameViewport.getScreenHeight(); 251 | gameCamera.position.add(-deltaX * ppw * gameCamera.zoom, deltaY * pph * gameCamera.zoom, 0); 252 | gameCamera.update(); 253 | return false; 254 | } 255 | 256 | @Override public boolean panStop (float x, float y, int pointer, int button) { 257 | return false; 258 | } 259 | 260 | @Override public boolean zoom (float initialDistance, float distance) { 261 | // TODO touch screen zoom 262 | return false; 263 | } 264 | 265 | @Override public boolean touchDown (float x, float y, int pointer, int button) { 266 | return false; 267 | } 268 | 269 | @Override public boolean tap (float x, float y, int count, int button) { 270 | return false; 271 | } 272 | 273 | @Override public boolean longPress (float x, float y) { 274 | return false; 275 | } 276 | 277 | @Override public boolean fling (float velocityX, float velocityY, int button) { 278 | return false; 279 | } 280 | 281 | @Override public boolean pinch (Vector2 initialPointer1, Vector2 initialPointer2, Vector2 pointer1, Vector2 pointer2) { 282 | return false; 283 | } 284 | } 285 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS -------------------------------------------------------------------------------- /core/src/io/piotrjastrzebski/dungen/DungeonGenerator.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2015 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | ******************************************************************************/ 17 | 18 | package io.piotrjastrzebski.dungen; 19 | 20 | import com.badlogic.gdx.Gdx; 21 | import com.badlogic.gdx.graphics.Color; 22 | import com.badlogic.gdx.graphics.GL20; 23 | import com.badlogic.gdx.graphics.OrthographicCamera; 24 | import com.badlogic.gdx.graphics.glutils.ShapeRenderer; 25 | import com.badlogic.gdx.math.DelaunayTriangulator; 26 | import com.badlogic.gdx.math.MathUtils; 27 | import com.badlogic.gdx.math.Rectangle; 28 | import com.badlogic.gdx.math.Vector2; 29 | import com.badlogic.gdx.physics.box2d.*; 30 | import com.badlogic.gdx.utils.Array; 31 | import com.badlogic.gdx.utils.Json; 32 | import com.badlogic.gdx.utils.JsonWriter; 33 | import com.badlogic.gdx.utils.ShortArray; 34 | 35 | import java.io.StringWriter; 36 | import java.util.Comparator; 37 | 38 | /** 39 | * Created by PiotrJ on 02/09/15. 40 | */ 41 | public class DungeonGenerator { 42 | private int roomID; 43 | Array rooms = new Array<>(); 44 | 45 | World b2d; 46 | Box2DDebugRenderer b2dd; 47 | Vector2 tmp = new Vector2(); 48 | GenSettings settings; 49 | DrawSettings drawSettings; 50 | Rectangle map = new Rectangle(); 51 | 52 | public DungeonGenerator () { 53 | super(); 54 | b2d = new World(new Vector2(), true); 55 | b2dd = new Box2DDebugRenderer(); 56 | settings = new GenSettings(); 57 | drawSettings = new DrawSettings(); 58 | } 59 | 60 | public void init (GenSettings settings) { 61 | this.settings.copy(settings); 62 | 63 | graph.clear(); 64 | mainRooms.clear(); 65 | if (rooms.size > 0) { 66 | for (Room room : rooms) { 67 | if (room.body != null) 68 | b2d.destroyBody(room.body); 69 | } 70 | } 71 | rooms.clear(); 72 | paths.clear(); 73 | 74 | float gridSize = settings.getGridSize(); 75 | float roomWidth = settings.getRoomWidth(); 76 | float roomHeight = settings.getRoomHeight(); 77 | float spawnWidth = settings.getSpawnWidth(); 78 | float spawnHeight = settings.getSpawnHeight(); 79 | for (int i = 0; i < settings.getCount(); i++) { 80 | Room room = new Room(roomID++, gridSize); 81 | float w = Utils.roundedRngFloat(roomWidth, gridSize, gridSize); 82 | float h = Utils.roundedRngFloat(roomHeight, gridSize, gridSize); 83 | if (w < gridSize || h < gridSize) { 84 | continue; 85 | } 86 | Utils.roundedPointInEllipse(spawnWidth, spawnHeight, gridSize, tmp); 87 | room.set(tmp.x, tmp.y, w, h); 88 | createBody(room); 89 | rooms.add(room); 90 | } 91 | } 92 | 93 | public void setDrawSettings (DrawSettings drawSettings) { 94 | this.drawSettings.copy(drawSettings); 95 | } 96 | 97 | private void createBody (Room room) { 98 | Rectangle b = room.bounds; 99 | if (b.width < 0.1f || b.height < 0.1f) { 100 | return; 101 | } 102 | BodyDef bodyDef = new BodyDef(); 103 | bodyDef.fixedRotation = true; 104 | bodyDef.type = BodyDef.BodyType.DynamicBody; 105 | bodyDef.position.set(b.x, b.y); 106 | Body body = b2d.createBody(bodyDef); 107 | 108 | PolygonShape shape = new PolygonShape(); 109 | shape.setAsBox(b.width / 2, b.height / 2); 110 | 111 | FixtureDef fd = new FixtureDef(); 112 | fd.restitution = 0; 113 | fd.friction = 0.5f; 114 | fd.density = 1; 115 | fd.shape = shape; 116 | 117 | body.createFixture(fd); 118 | 119 | shape.dispose(); 120 | 121 | room.body = body; 122 | } 123 | 124 | boolean settled; 125 | public void update (float delta) { 126 | // no need to run this if we have rooms 127 | if (mainRooms.size > 0) return; 128 | settled = true; 129 | for (int i = 0; i < settings.getB2bIters(); i++) { 130 | b2d.step(0.16f, 6, 4); 131 | for (Room room : rooms) { 132 | if (!room.isSleeping()) { 133 | settled = false; 134 | break; 135 | } 136 | } 137 | if (settled) 138 | break; 139 | } 140 | for (Room room : rooms) { 141 | room.update(); 142 | } 143 | } 144 | 145 | public void render (ShapeRenderer renderer, OrthographicCamera camera) { 146 | if (drawSettings.drawBodies) { 147 | b2dd.render(b2d, camera.combined); 148 | } 149 | 150 | if (mainRooms.size == 0) { 151 | renderer.setColor(0.4f, 0.2f, 0.1f, 1); 152 | for (Room room : rooms) { 153 | room.draw(renderer); 154 | } 155 | } 156 | 157 | float size = settings.getGridSize(); 158 | if (drawSettings.drawUnused) { 159 | renderer.setColor(0.3f, 0.3f, 0.3f, 1); 160 | for (Room room : rooms) { 161 | if (room.isUnused()) { 162 | room.draw(renderer); 163 | } 164 | } 165 | } 166 | 167 | if (drawSettings.drawExtra) { 168 | renderer.setColor(0.8f, 0.8f, 0.8f, 1); 169 | for (Room room : rooms) { 170 | if (room.isExtra) { 171 | room.draw(renderer); 172 | } 173 | } 174 | } 175 | if (drawSettings.drawHallWays) { 176 | renderer.setColor(0.2f, 0.4f, 1, 1); 177 | for (Room room : rooms) { 178 | if (room.isHallway) { 179 | room.draw(renderer); 180 | } 181 | } 182 | } 183 | if (drawSettings.drawMain) { 184 | for (Room room : rooms) { 185 | if (room.isMain) { 186 | renderer.setColor(1, 0.2f, 0.1f, 1); 187 | room.draw(renderer); 188 | } 189 | } 190 | } 191 | if (settled && mainRooms.size == 0) { 192 | float mw = settings.getRoomWidth() * settings.getMainRoomScale(); 193 | float mh = settings.getRoomHeight() * settings.getMainRoomScale(); 194 | for (Room room : rooms) { 195 | map.merge(room.bounds); 196 | if (room.bounds.width >= mw && room.bounds.height >= mh) { 197 | room.isMain = true; 198 | mainRooms.add(room); 199 | } 200 | } 201 | // extend map bounds by 1 tile in all directions 202 | map.x -= size; 203 | map.y -= size; 204 | map.width += size * 2; 205 | map.height += size * 2; 206 | // sort so main rooms are drawn lsat 207 | rooms.sort(new Comparator() { 208 | @Override public int compare (Room o1, Room o2) { 209 | int main = Boolean.compare(o1.isMain, o2.isMain); 210 | if (main != 0) { 211 | return main; 212 | } 213 | return Boolean.compare(o1.isHallway, o2.isHallway); 214 | } 215 | }); 216 | triangulate(); 217 | } 218 | graph.render(renderer, drawSettings.drawEdges, drawSettings.drawMinSpanTree, size); 219 | if (drawSettings.drawHallWayPaths) { 220 | renderer.setColor(Color.YELLOW); 221 | for (HallwayPath path : paths) { 222 | path.draw(renderer); 223 | } 224 | } 225 | if (drawSettings.drawSpawnArea) { 226 | Gdx.gl.glEnable(GL20.GL_BLEND); 227 | renderer.setColor(1, 1, 1, 0.5f); 228 | renderer.ellipse( 229 | -settings.getSpawnWidth()/2, -settings.getSpawnHeight()/2, 230 | settings.getSpawnWidth(), settings.getSpawnHeight()); 231 | } 232 | } 233 | 234 | Array mainRooms = new Array<>(); 235 | RoomGraph graph = new RoomGraph(); 236 | 237 | private void triangulate () { 238 | DelaunayTriangulator triangulator = new DelaunayTriangulator(); 239 | 240 | float[] points = new float[mainRooms.size * 2]; 241 | for (int i = 0; i < points.length; i += 2) { 242 | Room room = mainRooms.get(i / 2); 243 | points[i] = room.cx(); 244 | points[i + 1] = room.cy(); 245 | } 246 | 247 | ShortArray indicies = triangulator.computeTriangles(points, 0, points.length, false); 248 | 249 | graph.clear(); 250 | 251 | for (int i = 0; i < indicies.size; i += 3) { 252 | int p1 = indicies.get(i) * 2; 253 | int p2 = indicies.get(i + 1) * 2; 254 | int p3 = indicies.get(i + 2) * 2; 255 | // this is pretty dumb... 256 | Room roomA = getRoom(points[p1], points[p1 + 1]); 257 | Room roomB = getRoom(points[p2], points[p2 + 1]); 258 | Room roomC = getRoom(points[p3], points[p3 + 1]); 259 | graph.add(roomA, roomB); 260 | graph.add(roomA, roomC); 261 | graph.add(roomB, roomC); 262 | } 263 | 264 | createMST(); 265 | } 266 | 267 | private void createMST () { 268 | /* 269 | kruskal's algorithm, we dont need anything fancy 270 | */ 271 | Array edges = graph.getEdges(); 272 | edges.sort(new Comparator() { 273 | @Override public int compare (RoomEdge o1, RoomEdge o2) { 274 | return Float.compare(o1.len, o2.len); 275 | } 276 | }); 277 | RoomGraph mstGraph = new RoomGraph(); 278 | for (RoomEdge edge : edges) { 279 | if (!mstGraph.isConnected(edge)) { 280 | mstGraph.add(edge); 281 | edge.mst = true; 282 | } 283 | } 284 | 285 | for (RoomEdge edge : edges) { 286 | if (!edge.mst && MathUtils.random() < settings.getReconnectChance()) { 287 | edge.mst = true; 288 | edge.recon = true; 289 | } 290 | } 291 | 292 | createHallways(); 293 | } 294 | 295 | Array paths = new Array<>(); 296 | 297 | private void createHallways () { 298 | Array edges = graph.getEdges(); 299 | float grid = settings.getGridSize(); 300 | // offset mid position by half grid if the width is odd so we can easily find rooms we need for hallways 301 | int hallwaysWidth = settings.getHallwaysWidth(); 302 | float offset = (hallwaysWidth%2==1)?grid / 2:0; 303 | 304 | for (RoomEdge e : edges) { 305 | if (!e.mst) 306 | continue; 307 | HallwayPath path = new HallwayPath(grid, hallwaysWidth); 308 | path.recon = e.recon; 309 | Rectangle bA = e.roomA.bounds; 310 | Rectangle bB = e.roomB.bounds; 311 | float min, max, mid; 312 | // rooms cant overlap on both axis 313 | if (bA.x < bB.x + bB.width && bA.x + bA.width > bB.x) { 314 | // no need for 0 len hallway 315 | if (MathUtils.isEqual(bA.y, bB.y + bB.height) || MathUtils.isEqual(bA.y + bA.height, bB.y)) { 316 | continue; 317 | } 318 | min = (bA.x < bB.x) ? bB.x : bA.x; 319 | max = (bA.x + bA.width < bB.x + bB.width) ? bA.x + bA.width : bB.x + bB.width; 320 | mid = (min + max) / 2; 321 | mid = Utils.roundToSize(mid, grid) - offset; 322 | if (bA.y > bB.y) { 323 | path.set(mid, bA.y, mid, bB.y + bB.height); 324 | } else { 325 | path.set(mid, bA.y + bA.height, mid, bB.y); 326 | } 327 | } else if (bA.y < bB.y + bB.height && bA.y + bA.height > bB.y) { 328 | // no need for 0 len hallway 329 | if (MathUtils.isEqual(bA.x, bB.x + bB.width) || MathUtils.isEqual(bA.x + bA.width, bB.x)) { 330 | continue; 331 | } 332 | 333 | min = (bA.y < bB.y) ? bB.y : bA.y; 334 | max = (bA.y + bA.height < bB.y + bB.height) ? bA.y + bA.height : bB.y + bB.height; 335 | mid = (min + max) / 2; 336 | mid = Utils.roundToSize(mid, grid) - offset; 337 | if (bA.x > bB.x) { 338 | path.set(bA.x, mid, bB.x + bB.width, mid); 339 | } else { 340 | path.set(bA.x + bA.width, mid, bB.x, mid); 341 | } 342 | } else { 343 | // need to make a L shaped hallway 344 | float ax = bA.x; 345 | float ay = bA.y; 346 | float aw = bA.width; 347 | float ah = bA.height; 348 | float bx = bB.x; 349 | float by = bB.y; 350 | float bw = bB.width; 351 | float bh = bB.height; 352 | float mx, my; 353 | // pick a side of the bend 354 | // can we make this simpler? im dumb 355 | if (MathUtils.randomBoolean()) { 356 | mx = ax + aw / 2; 357 | my = by + bh / 2; 358 | mx = Utils.roundToSize(mx, grid) - offset; 359 | my = Utils.roundToSize(my, grid) - offset; 360 | if (ax < bx) { 361 | if (ay < by) { 362 | path.set(mx, ay + ah, mx, my, bx, my); 363 | } else { 364 | path.set(mx, ay, mx, my, bx, my); 365 | } 366 | } else { 367 | if (ay > by) { 368 | path.set(mx, ay, mx, my, bx + bw, my); 369 | } else { 370 | path.set(mx, ay + ah, mx, my, bx + bw, my); 371 | } 372 | } 373 | } else { 374 | mx = bx + bw / 2; 375 | my = ay + ah / 2; 376 | mx = Utils.roundToSize(mx, grid) - offset; 377 | my = Utils.roundToSize(my, grid) - offset; 378 | if (ax < bx) { 379 | if (ay < by) { 380 | path.set(ax + aw, my, mx, my, mx, by); 381 | } else { 382 | path.set(ax + aw, my, mx, my, mx, by + bh); 383 | } 384 | } else { 385 | if (ay > by) { 386 | path.set(ax, my, mx, my, mx, by + bh); 387 | } else { 388 | path.set(ax, my, mx, my, mx, by); 389 | } 390 | } 391 | } 392 | } 393 | path.roomA = e.roomA; 394 | path.roomB = e.roomB; 395 | paths.add(path); 396 | } 397 | 398 | addHallwayRooms(); 399 | } 400 | 401 | private void addHallwayRooms () { 402 | for (HallwayPath path : paths) { 403 | for (Room room : rooms) { 404 | if (room.isMain) 405 | continue; 406 | if (path.intersects(room)) { 407 | room.isHallway = true; 408 | } 409 | } 410 | } 411 | 412 | for (HallwayPath path : paths) { 413 | if (path.hasBend) { 414 | createRooms(path.hallA); 415 | createRooms(path.hallB); 416 | } else { 417 | createRooms(path.hallA); 418 | } 419 | } 420 | } 421 | 422 | private void createRooms (Rectangle r) { 423 | float grid = settings.getGridSize(); 424 | float x = Utils.roundToSize(r.x, grid); 425 | float w = Utils.roundToSize(r.width, grid); 426 | float y = Utils.roundToSize(r.y, grid); 427 | float h = Utils.roundToSize(r.height, grid); 428 | 429 | int gw = (int)(w / grid); 430 | int gh = (int)(h / grid); 431 | 432 | for (int rx = 0; rx < gw; rx++) { 433 | for (int ry = 0; ry < gh; ry++) { 434 | createRoom(x + rx * grid, y + ry * grid, grid); 435 | } 436 | } 437 | } 438 | 439 | private void createRoom (float x, float y, float size) { 440 | if (findRoom(x + size / 2, y + size / 2) != null) 441 | return; 442 | Room room = new Room(roomID++, size); 443 | room.bounds.set(x, y, size, size); 444 | room.isExtra = true; 445 | rooms.add(room); 446 | } 447 | 448 | private Room getRoom (float cx, float cy) { 449 | for (Room room : mainRooms) { 450 | if (MathUtils.isEqual(cx, room.cx()) && MathUtils.isEqual(cy, room.cy())) { 451 | return room; 452 | } 453 | } 454 | return null; 455 | } 456 | 457 | private Room findRoom (float tx, float ty) { 458 | for (Room room : rooms) { 459 | if (room.bounds.contains(tx, ty)) 460 | return room; 461 | } 462 | return null; 463 | } 464 | 465 | public void dispose () { 466 | b2d.dispose(); 467 | } 468 | 469 | public String toJson (JsonWriter.OutputType outputType, boolean pretty) { 470 | Json json = new Json(outputType); 471 | StringWriter writer = new StringWriter(); 472 | json.setWriter(writer); 473 | json.writeObjectStart(); 474 | json.writeValue("grid-size", settings.getGridSize()); 475 | json.writeArrayStart("rooms"); 476 | for (Room room : rooms) { 477 | if (room.isUnused()) 478 | continue; 479 | json.writeObjectStart(); 480 | json.writeValue("id", room.id); 481 | if (room.isMain) { 482 | json.writeValue("type", "main"); 483 | } else if (room.isHallway) { 484 | json.writeValue("type", "hallway"); 485 | } else if (room.isExtra) { 486 | json.writeValue("type", "extra"); 487 | } 488 | json.writeValue("bounds", room.bounds); 489 | json.writeObjectEnd(); 490 | } 491 | json.writeArrayEnd(); 492 | json.writeArrayStart("paths"); 493 | for (HallwayPath path : paths) { 494 | json.writeObjectStart(); 495 | json.writeValue("id", path.id); 496 | json.writeValue("start-room", path.roomA.id); 497 | json.writeValue("end-room", path.roomB.id); 498 | json.writeValue("start", path.start); 499 | if (path.hasBend) { 500 | json.writeValue("mid", path.bend); 501 | } 502 | json.writeValue("end", path.end); 503 | json.writeArrayStart("overlaps"); 504 | for (Room room : path.overlap) { 505 | json.writeValue(room.id); 506 | } 507 | json.writeArrayEnd(); 508 | json.writeObjectEnd(); 509 | } 510 | json.writeArrayEnd(); 511 | json.writeObjectEnd(); 512 | 513 | if (pretty) { 514 | return json.prettyPrint(writer.toString()); 515 | } else { 516 | return writer.toString(); 517 | } 518 | } 519 | } 520 | -------------------------------------------------------------------------------- /html/webapp/soundmanager2-jsmin.js: -------------------------------------------------------------------------------- 1 | /** @license 2 | 3 | 4 | SoundManager 2: JavaScript Sound for the Web 5 | ---------------------------------------------- 6 | http://schillmania.com/projects/soundmanager2/ 7 | 8 | Copyright (c) 2007, Scott Schiller. All rights reserved. 9 | Code provided under the BSD License: 10 | http://schillmania.com/projects/soundmanager2/license.txt 11 | 12 | V2.97a.20130512 13 | */ 14 | (function (h, g) { 15 | function fa(fa, wa) { 16 | function ga(b) { 17 | return c.preferFlash && H && !c.ignoreFlash && c.flash[b] !== g && c.flash[b] 18 | } 19 | 20 | function s(b) { 21 | return function (d) { 22 | var e = this._s; 23 | !e || !e._a ? (e && e.id ? c._wD(e.id + ": Ignoring " + d.type) : c._wD(rb + "Ignoring " + d.type), d = null) : d = b.call(this, d); 24 | return d 25 | } 26 | } 27 | 28 | this.setupOptions = { 29 | url: fa || null, 30 | flashVersion: 8, 31 | debugMode: !0, 32 | debugFlash: !1, 33 | useConsole: !0, 34 | consoleOnly: !0, 35 | waitForWindowLoad: !1, 36 | bgColor: "#ffffff", 37 | useHighPerformance: !1, 38 | flashPollingInterval: null, 39 | html5PollingInterval: null, 40 | flashLoadTimeout: 1E3, 41 | wmode: null, 42 | allowScriptAccess: "always", 43 | useFlashBlock: !1, 44 | useHTML5Audio: !0, 45 | html5Test: /^(probably|maybe)$/i, 46 | preferFlash: !0, 47 | noSWFCache: !1, 48 | idPrefix: "sound" 49 | }; 50 | this.defaultOptions = { 51 | autoLoad: !1, 52 | autoPlay: !1, 53 | from: null, 54 | loops: 1, 55 | onid3: null, 56 | onload: null, 57 | whileloading: null, 58 | onplay: null, 59 | onpause: null, 60 | onresume: null, 61 | whileplaying: null, 62 | onposition: null, 63 | onstop: null, 64 | onfailure: null, 65 | onfinish: null, 66 | multiShot: !0, 67 | multiShotEvents: !1, 68 | position: null, 69 | pan: 0, 70 | stream: !0, 71 | to: null, 72 | type: null, 73 | usePolicyFile: !1, 74 | volume: 100 75 | }; 76 | this.flash9Options = { 77 | isMovieStar: null, 78 | usePeakData: !1, useWaveformData: !1, useEQData: !1, onbufferchange: null, ondataerror: null 79 | }; 80 | this.movieStarOptions = {bufferTime: 3, serverURL: null, onconnect: null, duration: null}; 81 | this.audioFormats = { 82 | mp3: { 83 | type: ['audio/mpeg; codecs\x3d"mp3"', "audio/mpeg", "audio/mp3", "audio/MPA", "audio/mpa-robust"], 84 | required: !0 85 | }, 86 | mp4: { 87 | related: ["aac", "m4a", "m4b"], 88 | type: ['audio/mp4; codecs\x3d"mp4a.40.2"', "audio/aac", "audio/x-m4a", "audio/MP4A-LATM", "audio/mpeg4-generic"], 89 | required: !1 90 | }, 91 | ogg: {type: ["audio/ogg; codecs\x3dvorbis"], required: !1}, 92 | opus: {type: ["audio/ogg; codecs\x3dopus", "audio/opus"], required: !1}, 93 | wav: {type: ['audio/wav; codecs\x3d"1"', "audio/wav", "audio/wave", "audio/x-wav"], required: !1} 94 | }; 95 | this.movieID = "sm2-container"; 96 | this.id = wa || "sm2movie"; 97 | this.debugID = "soundmanager-debug"; 98 | this.debugURLParam = /([#?&])debug=1/i; 99 | this.versionNumber = "V2.97a.20130512"; 100 | this.altURL = this.movieURL = this.version = null; 101 | this.enabled = this.swfLoaded = !1; 102 | this.oMC = null; 103 | this.sounds = {}; 104 | this.soundIDs = []; 105 | this.didFlashBlock = this.muted = !1; 106 | this.filePattern = null; 107 | this.filePatterns = 108 | {flash8: /\.mp3(\?.*)?$/i, flash9: /\.mp3(\?.*)?$/i}; 109 | this.features = {buffering: !1, peakData: !1, waveformData: !1, eqData: !1, movieStar: !1}; 110 | this.sandbox = { 111 | type: null, 112 | types: { 113 | remote: "remote (domain-based) rules", 114 | localWithFile: "local with file access (no internet access)", 115 | localWithNetwork: "local with network (internet access only, no local access)", 116 | localTrusted: "local, trusted (local+internet access)" 117 | }, 118 | description: null, 119 | noRemote: null, 120 | noLocal: null 121 | }; 122 | this.html5 = {usingFlash: null}; 123 | this.flash = {}; 124 | this.ignoreFlash = this.html5Only = !1; 125 | var Ua, c = this, Va = null, k = null, rb = "HTML5::", A, t = navigator.userAgent, U = h.location.href.toString(), m = document, xa, Wa, ya, n, F = [], za = !0, C, V = !1, W = !1, q = !1, y = !1, ha = !1, p, sb = 0, X, B, Aa, O, Ba, M, P, Q, Xa, Ca, ia, I, ja, Da, R, Ea, Y, ka, la, S, Ya, Fa, Za = ["log", "info", "warn", "error"], $a, Ga, ab, Z = null, Ha = null, r, Ia, T, bb, ma, na, J, v, $ = !1, Ja = !1, cb, db, eb, oa = 0, aa = null, pa, N = [], qa, u = null, fb, ra, ba, K, sa, Ka, gb, w, hb = Array.prototype.slice, E = !1, La, H, Ma, ib, G, jb, Na, ta, kb = 0, ca = t.match(/(ipad|iphone|ipod)/i), lb = t.match(/android/i), L = t.match(/msie/i), 126 | tb = t.match(/webkit/i), ua = t.match(/safari/i) && !t.match(/chrome/i), Oa = t.match(/opera/i), ub = t.match(/firefox/i), Pa = t.match(/(mobile|pre\/|xoom)/i) || ca || lb, Qa = !U.match(/usehtml5audio/i) && !U.match(/sm2\-ignorebadua/i) && ua && !t.match(/silk/i) && t.match(/OS X 10_6_([3-7])/i), da = h.console !== g && console.log !== g, Ra = m.hasFocus !== g ? m.hasFocus() : null, va = ua && (m.hasFocus === g || !m.hasFocus()), mb = !va, nb = /(mp3|mp4|mpa|m4a|m4b)/i, ea = m.location ? m.location.protocol.match(/http/i) : null, ob = !ea ? "http://" : "", pb = /^\s*audio\/(?:x-)?(?:mpeg4|aac|flv|mov|mp4||m4v|m4a|m4b|mp4v|3gp|3g2)\s*(?:$|;)/i, 127 | qb = "mpeg4 aac flv mov mp4 m4v f4v m4a m4b mp4v 3gp 3g2".split(" "), vb = RegExp("\\.(" + qb.join("|") + ")(\\?.*)?$", "i"); 128 | this.mimePattern = /^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i; 129 | this.useAltURL = !ea; 130 | var Sa; 131 | try { 132 | Sa = Audio !== g && (Oa && opera !== g && 10 > opera.version() ? new Audio(null) : new Audio).canPlayType !== g 133 | } catch (wb) { 134 | Sa = !1 135 | } 136 | this.hasHTML5 = Sa; 137 | this.setup = function (b) { 138 | var d = !c.url; 139 | b !== g && (q && u && c.ok() && (b.flashVersion !== g || b.url !== g || b.html5Test !== g)) && J(r("setupLate")); 140 | Aa(b); 141 | b && (d && (Y && b.url !== g) && c.beginDelayedInit(), 142 | !Y && (b.url !== g && "complete" === m.readyState) && setTimeout(R, 1)); 143 | return c 144 | }; 145 | this.supported = this.ok = function () { 146 | return u ? q && !y : c.useHTML5Audio && c.hasHTML5 147 | }; 148 | this.getMovie = function (c) { 149 | return A(c) || m[c] || h[c] 150 | }; 151 | this.createSound = function (b, d) { 152 | function e() { 153 | f = ma(f); 154 | c.sounds[f.id] = new Ua(f); 155 | c.soundIDs.push(f.id); 156 | return c.sounds[f.id] 157 | } 158 | 159 | var a, f; 160 | a = null; 161 | a = "soundManager.createSound(): " + r(!q ? "notReady" : "notOK"); 162 | if (!q || !c.ok())return J(a), !1; 163 | d !== g && (b = {id: b, url: d}); 164 | f = B(b); 165 | f.url = pa(f.url); 166 | void 0 === f.id && (f.id = c.setupOptions.idPrefix + 167 | kb++); 168 | f.id.toString().charAt(0).match(/^[0-9]$/) && c._wD("soundManager.createSound(): " + r("badID", f.id), 2); 169 | c._wD("soundManager.createSound(): " + f.id + (f.url ? " (" + f.url + ")" : ""), 1); 170 | if (v(f.id, !0))return c._wD("soundManager.createSound(): " + f.id + " exists", 1), c.sounds[f.id]; 171 | if (ra(f))a = e(), c._wD(f.id + ": Using HTML5"), a._setup_html5(f); else { 172 | if (c.html5Only)return c._wD(f.id + ": No HTML5 support for this sound, and no Flash. Exiting."), e(); 173 | if (c.html5.usingFlash && f.url && f.url.match(/data\:/i))return c._wD(f.id + 174 | ": data: URIs not supported via Flash. Exiting."), e(); 175 | 8 < n && (null === f.isMovieStar && (f.isMovieStar = !(!f.serverURL && !(f.type && f.type.match(pb) || f.url && f.url.match(vb)))), f.isMovieStar && (c._wD("soundManager.createSound(): using MovieStar handling"), 1 < f.loops && p("noNSLoop"))); 176 | f = na(f, "soundManager.createSound(): "); 177 | a = e(); 178 | 8 === n ? k._createSound(f.id, f.loops || 1, f.usePolicyFile) : (k._createSound(f.id, f.url, f.usePeakData, f.useWaveformData, f.useEQData, f.isMovieStar, f.isMovieStar ? f.bufferTime : !1, f.loops || 1, f.serverURL, 179 | f.duration || null, f.autoPlay, !0, f.autoLoad, f.usePolicyFile), f.serverURL || (a.connected = !0, f.onconnect && f.onconnect.apply(a))); 180 | !f.serverURL && (f.autoLoad || f.autoPlay) && a.load(f) 181 | } 182 | !f.serverURL && f.autoPlay && a.play(); 183 | return a 184 | }; 185 | this.destroySound = function (b, d) { 186 | if (!v(b))return !1; 187 | var e = c.sounds[b], a; 188 | e._iO = {}; 189 | e.stop(); 190 | e.unload(); 191 | for (a = 0; a < c.soundIDs.length; a++)if (c.soundIDs[a] === b) { 192 | c.soundIDs.splice(a, 1); 193 | break 194 | } 195 | d || e.destruct(!0); 196 | delete c.sounds[b]; 197 | return !0 198 | }; 199 | this.load = function (b, d) { 200 | return !v(b) ? !1 : c.sounds[b].load(d) 201 | }; 202 | this.unload = function (b) { 203 | return !v(b) ? !1 : c.sounds[b].unload() 204 | }; 205 | this.onposition = this.onPosition = function (b, d, e, a) { 206 | return !v(b) ? !1 : c.sounds[b].onposition(d, e, a) 207 | }; 208 | this.clearOnPosition = function (b, d, e) { 209 | return !v(b) ? !1 : c.sounds[b].clearOnPosition(d, e) 210 | }; 211 | this.start = this.play = function (b, d) { 212 | var e = null, a = d && !(d instanceof Object); 213 | if (!q || !c.ok())return J("soundManager.play(): " + r(!q ? "notReady" : "notOK")), !1; 214 | if (v(b, a))a && (d = {url: d}); else { 215 | if (!a)return !1; 216 | a && (d = {url: d}); 217 | d && d.url && (c._wD('soundManager.play(): Attempting to create "' + 218 | b + '"', 1), d.id = b, e = c.createSound(d).play()) 219 | } 220 | null === e && (e = c.sounds[b].play(d)); 221 | return e 222 | }; 223 | this.setPosition = function (b, d) { 224 | return !v(b) ? !1 : c.sounds[b].setPosition(d) 225 | }; 226 | this.stop = function (b) { 227 | if (!v(b))return !1; 228 | c._wD("soundManager.stop(" + b + ")", 1); 229 | return c.sounds[b].stop() 230 | }; 231 | this.stopAll = function () { 232 | var b; 233 | c._wD("soundManager.stopAll()", 1); 234 | for (b in c.sounds)c.sounds.hasOwnProperty(b) && c.sounds[b].stop() 235 | }; 236 | this.pause = function (b) { 237 | return !v(b) ? !1 : c.sounds[b].pause() 238 | }; 239 | this.pauseAll = function () { 240 | var b; 241 | for (b = c.soundIDs.length - 242 | 1; 0 <= b; b--)c.sounds[c.soundIDs[b]].pause() 243 | }; 244 | this.resume = function (b) { 245 | return !v(b) ? !1 : c.sounds[b].resume() 246 | }; 247 | this.resumeAll = function () { 248 | var b; 249 | for (b = c.soundIDs.length - 1; 0 <= b; b--)c.sounds[c.soundIDs[b]].resume() 250 | }; 251 | this.togglePause = function (b) { 252 | return !v(b) ? !1 : c.sounds[b].togglePause() 253 | }; 254 | this.setPan = function (b, d) { 255 | return !v(b) ? !1 : c.sounds[b].setPan(d) 256 | }; 257 | this.setVolume = function (b, d) { 258 | return !v(b) ? !1 : c.sounds[b].setVolume(d) 259 | }; 260 | this.mute = function (b) { 261 | var d = 0; 262 | b instanceof String && (b = null); 263 | if (b) { 264 | if (!v(b))return !1; 265 | c._wD('soundManager.mute(): Muting "' + 266 | b + '"'); 267 | return c.sounds[b].mute() 268 | } 269 | c._wD("soundManager.mute(): Muting all sounds"); 270 | for (d = c.soundIDs.length - 1; 0 <= d; d--)c.sounds[c.soundIDs[d]].mute(); 271 | return c.muted = !0 272 | }; 273 | this.muteAll = function () { 274 | c.mute() 275 | }; 276 | this.unmute = function (b) { 277 | b instanceof String && (b = null); 278 | if (b) { 279 | if (!v(b))return !1; 280 | c._wD('soundManager.unmute(): Unmuting "' + b + '"'); 281 | return c.sounds[b].unmute() 282 | } 283 | c._wD("soundManager.unmute(): Unmuting all sounds"); 284 | for (b = c.soundIDs.length - 1; 0 <= b; b--)c.sounds[c.soundIDs[b]].unmute(); 285 | c.muted = !1; 286 | return !0 287 | }; 288 | this.unmuteAll = 289 | function () { 290 | c.unmute() 291 | }; 292 | this.toggleMute = function (b) { 293 | return !v(b) ? !1 : c.sounds[b].toggleMute() 294 | }; 295 | this.getMemoryUse = function () { 296 | var c = 0; 297 | k && 8 !== n && (c = parseInt(k._getMemoryUse(), 10)); 298 | return c 299 | }; 300 | this.disable = function (b) { 301 | var d; 302 | b === g && (b = !1); 303 | if (y)return !1; 304 | y = !0; 305 | p("shutdown", 1); 306 | for (d = c.soundIDs.length - 1; 0 <= d; d--)$a(c.sounds[c.soundIDs[d]]); 307 | X(b); 308 | w.remove(h, "load", P); 309 | return !0 310 | }; 311 | this.canPlayMIME = function (b) { 312 | var d; 313 | c.hasHTML5 && (d = ba({type: b})); 314 | !d && u && (d = b && c.ok() ? !!(8 < n && b.match(pb) || b.match(c.mimePattern)) : null); 315 | return d 316 | }; 317 | this.canPlayURL = function (b) { 318 | var d; 319 | c.hasHTML5 && (d = ba({url: b})); 320 | !d && u && (d = b && c.ok() ? !!b.match(c.filePattern) : null); 321 | return d 322 | }; 323 | this.canPlayLink = function (b) { 324 | return b.type !== g && b.type && c.canPlayMIME(b.type) ? !0 : c.canPlayURL(b.href) 325 | }; 326 | this.getSoundById = function (b, d) { 327 | if (!b)return null; 328 | var e = c.sounds[b]; 329 | !e && !d && c._wD('soundManager.getSoundById(): Sound "' + b + '" not found.', 2); 330 | return e 331 | }; 332 | this.onready = function (b, d) { 333 | if ("function" === typeof b)q && c._wD(r("queue", "onready")), d || (d = h), Ba("onready", b, d), M(); else throw r("needFunction", 334 | "onready"); 335 | return !0 336 | }; 337 | this.ontimeout = function (b, d) { 338 | if ("function" === typeof b)q && c._wD(r("queue", "ontimeout")), d || (d = h), Ba("ontimeout", b, d), M({type: "ontimeout"}); else throw r("needFunction", "ontimeout"); 339 | return !0 340 | }; 341 | this._writeDebug = function (b, d) { 342 | var e, a; 343 | if (!c.debugMode)return !1; 344 | if (da && c.useConsole) { 345 | if (d && "object" === typeof d)console.log(b, d); else if (Za[d] !== g)console[Za[d]](b); else console.log(b); 346 | if (c.consoleOnly)return !0 347 | } 348 | e = A("soundmanager-debug"); 349 | if (!e)return !1; 350 | a = m.createElement("div"); 351 | 0 === ++sb % 2 && (a.className = 352 | "sm2-alt"); 353 | d = d === g ? 0 : parseInt(d, 10); 354 | a.appendChild(m.createTextNode(b)); 355 | d && (2 <= d && (a.style.fontWeight = "bold"), 3 === d && (a.style.color = "#ff3333")); 356 | e.insertBefore(a, e.firstChild); 357 | return !0 358 | }; 359 | -1 !== U.indexOf("sm2-debug\x3dalert") && (this._writeDebug = function (c) { 360 | h.alert(c) 361 | }); 362 | this._wD = this._writeDebug; 363 | this._debug = function () { 364 | var b, d; 365 | p("currentObj", 1); 366 | b = 0; 367 | for (d = c.soundIDs.length; b < d; b++)c.sounds[c.soundIDs[b]]._debug() 368 | }; 369 | this.reboot = function (b, d) { 370 | c.soundIDs.length && c._wD("Destroying " + c.soundIDs.length + " SMSound object" + 371 | (1 !== c.soundIDs.length ? "s" : "") + "..."); 372 | var e, a, f; 373 | for (e = c.soundIDs.length - 1; 0 <= e; e--)c.sounds[c.soundIDs[e]].destruct(); 374 | if (k)try { 375 | L && (Ha = k.innerHTML), Z = k.parentNode.removeChild(k) 376 | } catch (g) { 377 | p("badRemove", 2) 378 | } 379 | Ha = Z = u = k = null; 380 | c.enabled = Y = q = $ = Ja = V = W = y = E = c.swfLoaded = !1; 381 | c.soundIDs = []; 382 | c.sounds = {}; 383 | kb = 0; 384 | if (b)F = []; else for (e in F)if (F.hasOwnProperty(e)) { 385 | a = 0; 386 | for (f = F[e].length; a < f; a++)F[e][a].fired = !1 387 | } 388 | d || c._wD("soundManager: Rebooting..."); 389 | c.html5 = {usingFlash: null}; 390 | c.flash = {}; 391 | c.html5Only = !1; 392 | c.ignoreFlash = !1; 393 | h.setTimeout(function () { 394 | Da(); 395 | d || c.beginDelayedInit() 396 | }, 20); 397 | return c 398 | }; 399 | this.reset = function () { 400 | p("reset"); 401 | return c.reboot(!0, !0) 402 | }; 403 | this.getMoviePercent = function () { 404 | return k && "PercentLoaded"in k ? k.PercentLoaded() : null 405 | }; 406 | this.beginDelayedInit = function () { 407 | ha = !0; 408 | R(); 409 | setTimeout(function () { 410 | if (Ja)return !1; 411 | la(); 412 | ja(); 413 | return Ja = !0 414 | }, 20); 415 | Q() 416 | }; 417 | this.destruct = function () { 418 | c._wD("soundManager.destruct()"); 419 | c.disable(!0) 420 | }; 421 | Ua = function (b) { 422 | var d, e, a = this, f, h, z, l, m, q, s = !1, D = [], t = 0, Ta, y, u = null, A; 423 | e = d = null; 424 | this.sID = this.id = b.id; 425 | this.url = b.url; 426 | this._iO = this.instanceOptions = 427 | this.options = B(b); 428 | this.pan = this.options.pan; 429 | this.volume = this.options.volume; 430 | this.isHTML5 = !1; 431 | this._a = null; 432 | A = this.url ? !1 : !0; 433 | this.id3 = {}; 434 | this._debug = function () { 435 | c._wD(a.id + ": Merged options:", a.options) 436 | }; 437 | this.load = function (b) { 438 | var d = null, e; 439 | b !== g ? a._iO = B(b, a.options) : (b = a.options, a._iO = b, u && u !== a.url && (p("manURL"), a._iO.url = a.url, a.url = null)); 440 | a._iO.url || (a._iO.url = a.url); 441 | a._iO.url = pa(a._iO.url); 442 | e = a.instanceOptions = a._iO; 443 | c._wD(a.id + ": load (" + e.url + ")"); 444 | if (!e.url && !a.url)return c._wD(a.id + ": load(): url is unassigned. Exiting.", 445 | 2), a; 446 | !a.isHTML5 && (8 === n && !a.url && !e.autoPlay) && c._wD(a.id + ": Flash 8 load() limitation: Wait for onload() before calling play().", 1); 447 | if (e.url === a.url && 0 !== a.readyState && 2 !== a.readyState)return p("onURL", 1), 3 === a.readyState && e.onload && ta(a, function () { 448 | e.onload.apply(a, [!!a.duration]) 449 | }), a; 450 | a.loaded = !1; 451 | a.readyState = 1; 452 | a.playState = 0; 453 | a.id3 = {}; 454 | if (ra(e))d = a._setup_html5(e), d._called_load ? c._wD(a.id + ": Ignoring request to load again") : (a._html5_canplay = !1, a.url !== e.url && (c._wD(p("manURL") + ": " + e.url), a._a.src = 455 | e.url, a.setPosition(0)), a._a.autobuffer = "auto", a._a.preload = "auto", a._a._called_load = !0, e.autoPlay && a.play()); else { 456 | if (c.html5Only)return c._wD(a.id + ": No flash support. Exiting."), a; 457 | if (a._iO.url && a._iO.url.match(/data\:/i))return c._wD(a.id + ": data: URIs not supported via Flash. Exiting."), a; 458 | try { 459 | a.isHTML5 = !1, a._iO = na(ma(e)), e = a._iO, 8 === n ? k._load(a.id, e.url, e.stream, e.autoPlay, e.usePolicyFile) : k._load(a.id, e.url, !!e.stream, !!e.autoPlay, e.loops || 1, !!e.autoLoad, e.usePolicyFile) 460 | } catch (f) { 461 | p("smError", 462 | 2), C("onload", !1), S({type: "SMSOUND_LOAD_JS_EXCEPTION", fatal: !0}) 463 | } 464 | } 465 | a.url = e.url; 466 | return a 467 | }; 468 | this.unload = function () { 469 | 0 !== a.readyState && (c._wD(a.id + ": unload()"), a.isHTML5 ? (l(), a._a && (a._a.pause(), u = sa(a._a))) : 8 === n ? k._unload(a.id, "about:blank") : k._unload(a.id), f()); 470 | return a 471 | }; 472 | this.destruct = function (b) { 473 | c._wD(a.id + ": Destruct"); 474 | a.isHTML5 ? (l(), a._a && (a._a.pause(), sa(a._a), E || z(), a._a._s = null, a._a = null)) : (a._iO.onfailure = null, k._destroySound(a.id)); 475 | b || c.destroySound(a.id, !0) 476 | }; 477 | this.start = this.play = function (b, 478 | d) { 479 | var e, f, l, z, h, x = !0, x = null; 480 | e = a.id + ": play(): "; 481 | d = d === g ? !0 : d; 482 | b || (b = {}); 483 | a.url && (a._iO.url = a.url); 484 | a._iO = B(a._iO, a.options); 485 | a._iO = B(b, a._iO); 486 | a._iO.url = pa(a._iO.url); 487 | a.instanceOptions = a._iO; 488 | if (!a.isHTML5 && a._iO.serverURL && !a.connected)return a.getAutoPlay() || (c._wD(e + " Netstream not connected yet - setting autoPlay"), a.setAutoPlay(!0)), a; 489 | ra(a._iO) && (a._setup_html5(a._iO), m()); 490 | 1 === a.playState && !a.paused && ((f = a._iO.multiShot) ? c._wD(e + "Already playing (multi-shot)", 1) : (c._wD(e + "Already playing (one-shot)", 491 | 1), a.isHTML5 && a.setPosition(a._iO.position), x = a)); 492 | if (null !== x)return x; 493 | b.url && b.url !== a.url && (!a.readyState && !a.isHTML5 && 8 === n && A ? A = !1 : a.load(a._iO)); 494 | a.loaded ? c._wD(e.substr(0, e.lastIndexOf(":"))) : 0 === a.readyState ? (c._wD(e + "Attempting to load"), !a.isHTML5 && !c.html5Only ? (a._iO.autoPlay = !0, a.load(a._iO)) : a.isHTML5 ? a.load(a._iO) : (c._wD(e + "Unsupported type. Exiting."), x = a), a.instanceOptions = a._iO) : 2 === a.readyState ? (c._wD(e + "Could not load - exiting", 2), x = a) : c._wD(e + "Loading - attempting to play..."); 495 | if (null !== x)return x; 496 | !a.isHTML5 && (9 === n && 0 < a.position && a.position === a.duration) && (c._wD(e + "Sound at end, resetting to position:0"), b.position = 0); 497 | if (a.paused && 0 <= a.position && (!a._iO.serverURL || 0 < a.position))c._wD(e + "Resuming from paused state", 1), a.resume(); else { 498 | a._iO = B(b, a._iO); 499 | if (null !== a._iO.from && null !== a._iO.to && 0 === a.instanceCount && 0 === a.playState && !a._iO.serverURL) { 500 | f = function () { 501 | a._iO = B(b, a._iO); 502 | a.play(a._iO) 503 | }; 504 | if (a.isHTML5 && !a._html5_canplay)c._wD(e + "Beginning load for from/to case"), a.load({oncanplay: f}), 505 | x = !1; else if (!a.isHTML5 && !a.loaded && (!a.readyState || 2 !== a.readyState))c._wD(e + "Preloading for from/to case"), a.load({onload: f}), x = !1; 506 | if (null !== x)return x; 507 | a._iO = y() 508 | } 509 | (!a.instanceCount || a._iO.multiShotEvents || a.isHTML5 && a._iO.multiShot && !E || !a.isHTML5 && 8 < n && !a.getAutoPlay()) && a.instanceCount++; 510 | a._iO.onposition && 0 === a.playState && q(a); 511 | a.playState = 1; 512 | a.paused = !1; 513 | a.position = a._iO.position !== g && !isNaN(a._iO.position) ? a._iO.position : 0; 514 | a.isHTML5 || (a._iO = na(ma(a._iO))); 515 | a._iO.onplay && d && (a._iO.onplay.apply(a), 516 | s = !0); 517 | a.setVolume(a._iO.volume, !0); 518 | a.setPan(a._iO.pan, !0); 519 | a.isHTML5 ? 2 > a.instanceCount ? (m(), e = a._setup_html5(), a.setPosition(a._iO.position), e.play()) : (c._wD(a.id + ": Cloning Audio() for instance #" + a.instanceCount + "..."), l = new Audio(a._iO.url), z = function () { 520 | w.remove(l, "onended", z); 521 | a._onfinish(a); 522 | sa(l); 523 | l = null 524 | }, h = function () { 525 | w.remove(l, "canplay", h); 526 | try { 527 | l.currentTime = a._iO.position / 1E3 528 | } catch (c) { 529 | J(a.id + ": multiShot play() failed to apply position of " + a._iO.position / 1E3) 530 | } 531 | l.play() 532 | }, w.add(l, "ended", z), a._iO.position ? 533 | w.add(l, "canplay", h) : l.play()) : (x = k._start(a.id, a._iO.loops || 1, 9 === n ? a.position : a.position / 1E3, a._iO.multiShot || !1), 9 === n && !x && (c._wD(e + "No sound hardware, or 32-sound ceiling hit", 2), a._iO.onplayerror && a._iO.onplayerror.apply(a))) 534 | } 535 | return a 536 | }; 537 | this.stop = function (b) { 538 | var d = a._iO; 539 | 1 === a.playState && (c._wD(a.id + ": stop()"), a._onbufferchange(0), a._resetOnPosition(0), a.paused = !1, a.isHTML5 || (a.playState = 0), Ta(), d.to && a.clearOnPosition(d.to), a.isHTML5 ? a._a && (b = a.position, a.setPosition(0), a.position = b, a._a.pause(), 540 | a.playState = 0, a._onTimer(), l()) : (k._stop(a.id, b), d.serverURL && a.unload()), a.instanceCount = 0, a._iO = {}, d.onstop && d.onstop.apply(a)); 541 | return a 542 | }; 543 | this.setAutoPlay = function (b) { 544 | c._wD(a.id + ": Autoplay turned " + (b ? "on" : "off")); 545 | a._iO.autoPlay = b; 546 | a.isHTML5 || (k._setAutoPlay(a.id, b), b && (!a.instanceCount && 1 === a.readyState) && (a.instanceCount++, c._wD(a.id + ": Incremented instance count to " + a.instanceCount))) 547 | }; 548 | this.getAutoPlay = function () { 549 | return a._iO.autoPlay 550 | }; 551 | this.setPosition = function (b) { 552 | b === g && (b = 0); 553 | var d = a.isHTML5 ? 554 | Math.max(b, 0) : Math.min(a.duration || a._iO.duration, Math.max(b, 0)); 555 | a.position = d; 556 | b = a.position / 1E3; 557 | a._resetOnPosition(a.position); 558 | a._iO.position = d; 559 | if (a.isHTML5) { 560 | if (a._a) { 561 | if (a._html5_canplay) { 562 | if (a._a.currentTime !== b) { 563 | c._wD(a.id + ": setPosition(" + b + ")"); 564 | try { 565 | a._a.currentTime = b, (0 === a.playState || a.paused) && a._a.pause() 566 | } catch (e) { 567 | c._wD(a.id + ": setPosition(" + b + ") failed: " + e.message, 2) 568 | } 569 | } 570 | } else if (b)return c._wD(a.id + ": setPosition(" + b + "): Cannot seek yet, sound not ready", 2), a; 571 | a.paused && a._onTimer(!0) 572 | } 573 | } else b = 574 | 9 === n ? a.position : b, a.readyState && 2 !== a.readyState && k._setPosition(a.id, b, a.paused || !a.playState, a._iO.multiShot); 575 | return a 576 | }; 577 | this.pause = function (b) { 578 | if (a.paused || 0 === a.playState && 1 !== a.readyState)return a; 579 | c._wD(a.id + ": pause()"); 580 | a.paused = !0; 581 | a.isHTML5 ? (a._setup_html5().pause(), l()) : (b || b === g) && k._pause(a.id, a._iO.multiShot); 582 | a._iO.onpause && a._iO.onpause.apply(a); 583 | return a 584 | }; 585 | this.resume = function () { 586 | var b = a._iO; 587 | if (!a.paused)return a; 588 | c._wD(a.id + ": resume()"); 589 | a.paused = !1; 590 | a.playState = 1; 591 | a.isHTML5 ? (a._setup_html5().play(), 592 | m()) : (b.isMovieStar && !b.serverURL && a.setPosition(a.position), k._pause(a.id, b.multiShot)); 593 | !s && b.onplay ? (b.onplay.apply(a), s = !0) : b.onresume && b.onresume.apply(a); 594 | return a 595 | }; 596 | this.togglePause = function () { 597 | c._wD(a.id + ": togglePause()"); 598 | if (0 === a.playState)return a.play({position: 9 === n && !a.isHTML5 ? a.position : a.position / 1E3}), a; 599 | a.paused ? a.resume() : a.pause(); 600 | return a 601 | }; 602 | this.setPan = function (b, c) { 603 | b === g && (b = 0); 604 | c === g && (c = !1); 605 | a.isHTML5 || k._setPan(a.id, b); 606 | a._iO.pan = b; 607 | c || (a.pan = b, a.options.pan = b); 608 | return a 609 | }; 610 | this.setVolume = 611 | function (b, d) { 612 | b === g && (b = 100); 613 | d === g && (d = !1); 614 | a.isHTML5 ? a._a && (a._a.volume = Math.max(0, Math.min(1, b / 100))) : k._setVolume(a.id, c.muted && !a.muted || a.muted ? 0 : b); 615 | a._iO.volume = b; 616 | d || (a.volume = b, a.options.volume = b); 617 | return a 618 | }; 619 | this.mute = function () { 620 | a.muted = !0; 621 | a.isHTML5 ? a._a && (a._a.muted = !0) : k._setVolume(a.id, 0); 622 | return a 623 | }; 624 | this.unmute = function () { 625 | a.muted = !1; 626 | var b = a._iO.volume !== g; 627 | a.isHTML5 ? a._a && (a._a.muted = !1) : k._setVolume(a.id, b ? a._iO.volume : a.options.volume); 628 | return a 629 | }; 630 | this.toggleMute = function () { 631 | return a.muted ? a.unmute() : 632 | a.mute() 633 | }; 634 | this.onposition = this.onPosition = function (b, c, d) { 635 | D.push({position: parseInt(b, 10), method: c, scope: d !== g ? d : a, fired: !1}); 636 | return a 637 | }; 638 | this.clearOnPosition = function (a, b) { 639 | var c; 640 | a = parseInt(a, 10); 641 | if (isNaN(a))return !1; 642 | for (c = 0; c < D.length; c++)if (a === D[c].position && (!b || b === D[c].method))D[c].fired && t--, D.splice(c, 1) 643 | }; 644 | this._processOnPosition = function () { 645 | var b, c; 646 | b = D.length; 647 | if (!b || !a.playState || t >= b)return !1; 648 | for (b -= 1; 0 <= b; b--)c = D[b], !c.fired && a.position >= c.position && (c.fired = !0, t++, c.method.apply(c.scope, [c.position])); 649 | return !0 650 | }; 651 | this._resetOnPosition = function (a) { 652 | var b, c; 653 | b = D.length; 654 | if (!b)return !1; 655 | for (b -= 1; 0 <= b; b--)c = D[b], c.fired && a <= c.position && (c.fired = !1, t--); 656 | return !0 657 | }; 658 | y = function () { 659 | var b = a._iO, d = b.from, e = b.to, f, g; 660 | g = function () { 661 | c._wD(a.id + ': "To" time of ' + e + " reached."); 662 | a.clearOnPosition(e, g); 663 | a.stop() 664 | }; 665 | f = function () { 666 | c._wD(a.id + ': Playing "from" ' + d); 667 | if (null !== e && !isNaN(e))a.onPosition(e, g) 668 | }; 669 | null !== d && !isNaN(d) && (b.position = d, b.multiShot = !1, f()); 670 | return b 671 | }; 672 | q = function () { 673 | var b, c = a._iO.onposition; 674 | if (c)for (b in c)if (c.hasOwnProperty(b))a.onPosition(parseInt(b, 675 | 10), c[b]) 676 | }; 677 | Ta = function () { 678 | var b, c = a._iO.onposition; 679 | if (c)for (b in c)c.hasOwnProperty(b) && a.clearOnPosition(parseInt(b, 10)) 680 | }; 681 | m = function () { 682 | a.isHTML5 && cb(a) 683 | }; 684 | l = function () { 685 | a.isHTML5 && db(a) 686 | }; 687 | f = function (b) { 688 | b || (D = [], t = 0); 689 | s = !1; 690 | a._hasTimer = null; 691 | a._a = null; 692 | a._html5_canplay = !1; 693 | a.bytesLoaded = null; 694 | a.bytesTotal = null; 695 | a.duration = a._iO && a._iO.duration ? a._iO.duration : null; 696 | a.durationEstimate = null; 697 | a.buffered = []; 698 | a.eqData = []; 699 | a.eqData.left = []; 700 | a.eqData.right = []; 701 | a.failures = 0; 702 | a.isBuffering = !1; 703 | a.instanceOptions = {}; 704 | a.instanceCount = 705 | 0; 706 | a.loaded = !1; 707 | a.metadata = {}; 708 | a.readyState = 0; 709 | a.muted = !1; 710 | a.paused = !1; 711 | a.peakData = {left: 0, right: 0}; 712 | a.waveformData = {left: [], right: []}; 713 | a.playState = 0; 714 | a.position = null; 715 | a.id3 = {} 716 | }; 717 | f(); 718 | this._onTimer = function (b) { 719 | var c, f = !1, g = {}; 720 | if (a._hasTimer || b) { 721 | if (a._a && (b || (0 < a.playState || 1 === a.readyState) && !a.paused))c = a._get_html5_duration(), c !== d && (d = c, a.duration = c, f = !0), a.durationEstimate = a.duration, c = 1E3 * a._a.currentTime || 0, c !== e && (e = c, f = !0), (f || b) && a._whileplaying(c, g, g, g, g); 722 | return f 723 | } 724 | }; 725 | this._get_html5_duration = function () { 726 | var b = 727 | a._iO; 728 | return (b = a._a && a._a.duration ? 1E3 * a._a.duration : b && b.duration ? b.duration : null) && !isNaN(b) && Infinity !== b ? b : null 729 | }; 730 | this._apply_loop = function (a, b) { 731 | !a.loop && 1 < b && c._wD("Note: Native HTML5 looping is infinite.", 1); 732 | a.loop = 1 < b ? "loop" : "" 733 | }; 734 | this._setup_html5 = function (b) { 735 | b = B(a._iO, b); 736 | var c = E ? Va : a._a, d = decodeURI(b.url), e; 737 | E ? d === decodeURI(La) && (e = !0) : d === decodeURI(u) && (e = !0); 738 | if (c) { 739 | if (c._s)if (E)c._s && (c._s.playState && !e) && c._s.stop(); else if (!E && d === decodeURI(u))return a._apply_loop(c, b.loops), c; 740 | e || (f(!1), c.src = 741 | b.url, La = u = a.url = b.url, c._called_load = !1) 742 | } else a._a = b.autoLoad || b.autoPlay ? new Audio(b.url) : Oa && 10 > opera.version() ? new Audio(null) : new Audio, c = a._a, c._called_load = !1, E && (Va = c); 743 | a.isHTML5 = !0; 744 | a._a = c; 745 | c._s = a; 746 | h(); 747 | a._apply_loop(c, b.loops); 748 | b.autoLoad || b.autoPlay ? a.load() : (c.autobuffer = !1, c.preload = "auto"); 749 | return c 750 | }; 751 | h = function () { 752 | if (a._a._added_events)return !1; 753 | var b; 754 | a._a._added_events = !0; 755 | for (b in G)G.hasOwnProperty(b) && a._a && a._a.addEventListener(b, G[b], !1); 756 | return !0 757 | }; 758 | z = function () { 759 | var b; 760 | c._wD(a.id + ": Removing event listeners"); 761 | a._a._added_events = !1; 762 | for (b in G)G.hasOwnProperty(b) && a._a && a._a.removeEventListener(b, G[b], !1) 763 | }; 764 | this._onload = function (b) { 765 | var d = !!b || !a.isHTML5 && 8 === n && a.duration; 766 | b = a.id + ": "; 767 | c._wD(b + (d ? "onload()" : "Failed to load / invalid sound?" + (!a.duration ? " Zero-length duration reported." : " -") + " (" + a.url + ")"), d ? 1 : 2); 768 | !d && !a.isHTML5 && (!0 === c.sandbox.noRemote && c._wD(b + r("noNet"), 1), !0 === c.sandbox.noLocal && c._wD(b + r("noLocal"), 1)); 769 | a.loaded = d; 770 | a.readyState = d ? 3 : 2; 771 | a._onbufferchange(0); 772 | a._iO.onload && ta(a, function () { 773 | a._iO.onload.apply(a, 774 | [d]) 775 | }); 776 | return !0 777 | }; 778 | this._onbufferchange = function (b) { 779 | if (0 === a.playState || b && a.isBuffering || !b && !a.isBuffering)return !1; 780 | a.isBuffering = 1 === b; 781 | a._iO.onbufferchange && (c._wD(a.id + ": Buffer state change: " + b), a._iO.onbufferchange.apply(a)); 782 | return !0 783 | }; 784 | this._onsuspend = function () { 785 | a._iO.onsuspend && (c._wD(a.id + ": Playback suspended"), a._iO.onsuspend.apply(a)); 786 | return !0 787 | }; 788 | this._onfailure = function (b, d, e) { 789 | a.failures++; 790 | c._wD(a.id + ": Failures \x3d " + a.failures); 791 | if (a._iO.onfailure && 1 === a.failures)a._iO.onfailure(a, b, d, e); 792 | else c._wD(a.id + ": Ignoring failure") 793 | }; 794 | this._onfinish = function () { 795 | var b = a._iO.onfinish; 796 | a._onbufferchange(0); 797 | a._resetOnPosition(0); 798 | if (a.instanceCount && (a.instanceCount--, a.instanceCount || (Ta(), a.playState = 0, a.paused = !1, a.instanceCount = 0, a.instanceOptions = {}, a._iO = {}, l(), a.isHTML5 && (a.position = 0)), (!a.instanceCount || a._iO.multiShotEvents) && b))c._wD(a.id + ": onfinish()"), ta(a, function () { 799 | b.apply(a) 800 | }) 801 | }; 802 | this._whileloading = function (b, c, d, e) { 803 | var f = a._iO; 804 | a.bytesLoaded = b; 805 | a.bytesTotal = c; 806 | a.duration = Math.floor(d); 807 | a.bufferLength = e; 808 | a.durationEstimate = !a.isHTML5 && !f.isMovieStar ? f.duration ? a.duration > f.duration ? a.duration : f.duration : parseInt(a.bytesTotal / a.bytesLoaded * a.duration, 10) : a.duration; 809 | a.isHTML5 || (a.buffered = [{start: 0, end: a.duration}]); 810 | (3 !== a.readyState || a.isHTML5) && f.whileloading && f.whileloading.apply(a) 811 | }; 812 | this._whileplaying = function (b, c, d, e, f) { 813 | var l = a._iO; 814 | if (isNaN(b) || null === b)return !1; 815 | a.position = Math.max(0, b); 816 | a._processOnPosition(); 817 | !a.isHTML5 && 8 < n && (l.usePeakData && (c !== g && c) && (a.peakData = { 818 | left: c.leftPeak, 819 | right: c.rightPeak 820 | }), l.useWaveformData && (d !== g && d) && (a.waveformData = { 821 | left: d.split(","), 822 | right: e.split(",") 823 | }), l.useEQData && (f !== g && f && f.leftEQ) && (b = f.leftEQ.split(","), a.eqData = b, a.eqData.left = b, f.rightEQ !== g && f.rightEQ && (a.eqData.right = f.rightEQ.split(",")))); 824 | 1 === a.playState && (!a.isHTML5 && (8 === n && !a.position && a.isBuffering) && a._onbufferchange(0), l.whileplaying && l.whileplaying.apply(a)); 825 | return !0 826 | }; 827 | this._oncaptiondata = function (b) { 828 | c._wD(a.id + ": Caption data received."); 829 | a.captiondata = b; 830 | a._iO.oncaptiondata && 831 | a._iO.oncaptiondata.apply(a, [b]) 832 | }; 833 | this._onmetadata = function (b, d) { 834 | c._wD(a.id + ": Metadata received."); 835 | var e = {}, f, g; 836 | f = 0; 837 | for (g = b.length; f < g; f++)e[b[f]] = d[f]; 838 | a.metadata = e; 839 | a._iO.onmetadata && a._iO.onmetadata.apply(a) 840 | }; 841 | this._onid3 = function (b, d) { 842 | c._wD(a.id + ": ID3 data received."); 843 | var e = [], f, g; 844 | f = 0; 845 | for (g = b.length; f < g; f++)e[b[f]] = d[f]; 846 | a.id3 = B(a.id3, e); 847 | a._iO.onid3 && a._iO.onid3.apply(a) 848 | }; 849 | this._onconnect = function (b) { 850 | b = 1 === b; 851 | c._wD(a.id + ": " + (b ? "Connected." : "Failed to connect? - " + a.url), b ? 1 : 2); 852 | if (a.connected = b)a.failures = 853 | 0, v(a.id) && (a.getAutoPlay() ? a.play(g, a.getAutoPlay()) : a._iO.autoLoad && a.load()), a._iO.onconnect && a._iO.onconnect.apply(a, [b]) 854 | }; 855 | this._ondataerror = function (b) { 856 | 0 < a.playState && (c._wD(a.id + ": Data error: " + b), a._iO.ondataerror && a._iO.ondataerror.apply(a)) 857 | }; 858 | this._debug() 859 | }; 860 | ka = function () { 861 | return m.body || m._docElement || m.getElementsByTagName("div")[0] 862 | }; 863 | A = function (b) { 864 | return m.getElementById(b) 865 | }; 866 | B = function (b, d) { 867 | var e = b || {}, a, f; 868 | a = d === g ? c.defaultOptions : d; 869 | for (f in a)a.hasOwnProperty(f) && e[f] === g && (e[f] = "object" !== typeof a[f] || null === a[f] ? a[f] : B(e[f], a[f])); 870 | return e 871 | }; 872 | ta = function (b, c) { 873 | !b.isHTML5 && 8 === n ? h.setTimeout(c, 0) : c() 874 | }; 875 | O = {onready: 1, ontimeout: 1, defaultOptions: 1, flash9Options: 1, movieStarOptions: 1}; 876 | Aa = function (b, d) { 877 | var e, a = !0, f = d !== g, x = c.setupOptions; 878 | if (b === g) { 879 | a = []; 880 | for (e in x)x.hasOwnProperty(e) && a.push(e); 881 | for (e in O)O.hasOwnProperty(e) && ("object" === typeof c[e] ? a.push(e + ": {...}") : c[e]instanceof Function ? a.push(e + ": function() {...}") : a.push(e)); 882 | c._wD(r("setup", a.join(", "))); 883 | return !1 884 | } 885 | for (e in b)if (b.hasOwnProperty(e))if ("object" !== typeof b[e] || null === b[e] || b[e]instanceof Array || b[e]instanceof RegExp)f && O[d] !== g ? c[d][e] = b[e] : x[e] !== g ? (c.setupOptions[e] = b[e], c[e] = b[e]) : O[e] === g ? (J(r(c[e] === g ? "setupUndef" : "setupError", e), 2), a = !1) : c[e]instanceof Function ? c[e].apply(c, b[e]instanceof Array ? b[e] : [b[e]]) : c[e] = b[e]; else if (O[e] === g)J(r(c[e] === g ? "setupUndef" : "setupError", e), 2), a = !1; else return Aa(b[e], e); 886 | return a 887 | }; 888 | w = function () { 889 | function b(a) { 890 | a = hb.call(a); 891 | var b = a.length; 892 | e ? (a[1] = "on" + a[1], 3 < b && a.pop()) : 3 === b && a.push(!1); 893 | return a 894 | } 895 | 896 | function c(b, 897 | d) { 898 | var g = b.shift(), l = [a[d]]; 899 | if (e)g[l](b[0], b[1]); else g[l].apply(g, b) 900 | } 901 | 902 | var e = h.attachEvent, a = { 903 | add: e ? "attachEvent" : "addEventListener", 904 | remove: e ? "detachEvent" : "removeEventListener" 905 | }; 906 | return { 907 | add: function () { 908 | c(b(arguments), "add") 909 | }, remove: function () { 910 | c(b(arguments), "remove") 911 | } 912 | } 913 | }(); 914 | G = { 915 | abort: s(function () { 916 | c._wD(this._s.id + ": abort") 917 | }), canplay: s(function () { 918 | var b = this._s, d; 919 | if (b._html5_canplay)return !0; 920 | b._html5_canplay = !0; 921 | c._wD(b.id + ": canplay"); 922 | b._onbufferchange(0); 923 | d = b._iO.position !== g && !isNaN(b._iO.position) ? b._iO.position / 924 | 1E3 : null; 925 | if (b.position && this.currentTime !== d) { 926 | c._wD(b.id + ": canplay: Setting position to " + d); 927 | try { 928 | this.currentTime = d 929 | } catch (e) { 930 | c._wD(b.id + ": canplay: Setting position of " + d + " failed: " + e.message, 2) 931 | } 932 | } 933 | b._iO._oncanplay && b._iO._oncanplay() 934 | }), canplaythrough: s(function () { 935 | var b = this._s; 936 | b.loaded || (b._onbufferchange(0), b._whileloading(b.bytesLoaded, b.bytesTotal, b._get_html5_duration()), b._onload(!0)) 937 | }), ended: s(function () { 938 | var b = this._s; 939 | c._wD(b.id + ": ended"); 940 | b._onfinish() 941 | }), error: s(function () { 942 | c._wD(this._s.id + 943 | ": HTML5 error, code " + this.error.code); 944 | this._s._onload(!1) 945 | }), loadeddata: s(function () { 946 | var b = this._s; 947 | c._wD(b.id + ": loadeddata"); 948 | !b._loaded && !ua && (b.duration = b._get_html5_duration()) 949 | }), loadedmetadata: s(function () { 950 | c._wD(this._s.id + ": loadedmetadata") 951 | }), loadstart: s(function () { 952 | c._wD(this._s.id + ": loadstart"); 953 | this._s._onbufferchange(1) 954 | }), play: s(function () { 955 | this._s._onbufferchange(0) 956 | }), playing: s(function () { 957 | c._wD(this._s.id + ": playing"); 958 | this._s._onbufferchange(0) 959 | }), progress: s(function (b) { 960 | var d = this._s, e, a, 961 | f; 962 | e = 0; 963 | var g = "progress" === b.type, z = b.target.buffered, l = b.loaded || 0, h = b.total || 1; 964 | d.buffered = []; 965 | if (z && z.length) { 966 | e = 0; 967 | for (a = z.length; e < a; e++)d.buffered.push({start: 1E3 * z.start(e), end: 1E3 * z.end(e)}); 968 | e = 1E3 * (z.end(0) - z.start(0)); 969 | l = Math.min(1, e / (1E3 * b.target.duration)); 970 | if (g && 1 < z.length) { 971 | f = []; 972 | a = z.length; 973 | for (e = 0; e < a; e++)f.push(1E3 * b.target.buffered.start(e) + "-" + 1E3 * b.target.buffered.end(e)); 974 | c._wD(this._s.id + ": progress, timeRanges: " + f.join(", ")) 975 | } 976 | g && !isNaN(l) && c._wD(this._s.id + ": progress, " + Math.floor(100 * 977 | l) + "% loaded") 978 | } 979 | isNaN(l) || (d._onbufferchange(0), d._whileloading(l, h, d._get_html5_duration()), l && (h && l === h) && G.canplaythrough.call(this, b)) 980 | }), ratechange: s(function () { 981 | c._wD(this._s.id + ": ratechange") 982 | }), suspend: s(function (b) { 983 | var d = this._s; 984 | c._wD(this._s.id + ": suspend"); 985 | G.progress.call(this, b); 986 | d._onsuspend() 987 | }), stalled: s(function () { 988 | c._wD(this._s.id + ": stalled") 989 | }), timeupdate: s(function () { 990 | this._s._onTimer() 991 | }), waiting: s(function () { 992 | var b = this._s; 993 | c._wD(this._s.id + ": waiting"); 994 | b._onbufferchange(1) 995 | }) 996 | }; 997 | ra = function (b) { 998 | return !b || 999 | !b.type && !b.url && !b.serverURL ? !1 : b.serverURL || b.type && ga(b.type) ? !1 : b.type ? ba({type: b.type}) : ba({url: b.url}) || c.html5Only || b.url.match(/data\:/i) 1000 | }; 1001 | sa = function (b) { 1002 | var c; 1003 | b && (c = ua && !ca ? null : ub ? "about:blank" : null, b.src = c, void 0 !== b._called_unload && (b._called_load = !1)); 1004 | E && (La = null); 1005 | return c 1006 | }; 1007 | ba = function (b) { 1008 | if (!c.useHTML5Audio || !c.hasHTML5)return !1; 1009 | var d = b.url || null; 1010 | b = b.type || null; 1011 | var e = c.audioFormats, a; 1012 | if (b && c.html5[b] !== g)return c.html5[b] && !ga(b); 1013 | if (!K) { 1014 | K = []; 1015 | for (a in e)e.hasOwnProperty(a) && (K.push(a), 1016 | e[a].related && (K = K.concat(e[a].related))); 1017 | K = RegExp("\\.(" + K.join("|") + ")(\\?.*)?$", "i") 1018 | } 1019 | a = d ? d.toLowerCase().match(K) : null; 1020 | !a || !a.length ? b && (d = b.indexOf(";"), a = (-1 !== d ? b.substr(0, d) : b).substr(6)) : a = a[1]; 1021 | a && c.html5[a] !== g ? d = c.html5[a] && !ga(a) : (b = "audio/" + a, d = c.html5.canPlayType({type: b}), d = (c.html5[a] = d) && c.html5[b] && !ga(b)); 1022 | return d 1023 | }; 1024 | gb = function () { 1025 | function b(a) { 1026 | var b, e, f = b = !1; 1027 | if (!d || "function" !== typeof d.canPlayType)return b; 1028 | if (a instanceof Array) { 1029 | b = 0; 1030 | for (e = a.length; b < e; b++)if (c.html5[a[b]] || d.canPlayType(a[b]).match(c.html5Test))f = !0, c.html5[a[b]] = !0, c.flash[a[b]] = !!a[b].match(nb); 1031 | b = f 1032 | } else a = d && "function" === typeof d.canPlayType ? d.canPlayType(a) : !1, b = !(!a || !a.match(c.html5Test)); 1033 | return b 1034 | } 1035 | 1036 | if (!c.useHTML5Audio || !c.hasHTML5)return u = c.html5.usingFlash = !0, !1; 1037 | var d = Audio !== g ? Oa && 10 > opera.version() ? new Audio(null) : new Audio : null, e, a, f = {}, h; 1038 | h = c.audioFormats; 1039 | for (e in h)if (h.hasOwnProperty(e) && (a = "audio/" + e, f[e] = b(h[e].type), f[a] = f[e], e.match(nb) ? (c.flash[e] = !0, c.flash[a] = !0) : (c.flash[e] = !1, c.flash[a] = !1), h[e] && h[e].related))for (a = h[e].related.length - 1040 | 1; 0 <= a; a--)f["audio/" + h[e].related[a]] = f[e], c.html5[h[e].related[a]] = f[e], c.flash[h[e].related[a]] = f[e]; 1041 | f.canPlayType = d ? b : null; 1042 | c.html5 = B(c.html5, f); 1043 | c.html5.usingFlash = fb(); 1044 | u = c.html5.usingFlash; 1045 | return !0 1046 | }; 1047 | I = { 1048 | notReady: "Unavailable - wait until onready() has fired.", 1049 | notOK: "Audio support is not available.", 1050 | domError: "soundManagerexception caught while appending SWF to DOM.", 1051 | spcWmode: "Removing wmode, preventing known SWF loading issue(s)", 1052 | swf404: "soundManager: Verify that %s is a valid path.", 1053 | tryDebug: "Try soundManager.debugFlash \x3d true for more security details (output goes to SWF.)", 1054 | checkSWF: "See SWF output for more debug info.", 1055 | localFail: "soundManager: Non-HTTP page (" + m.location.protocol + " URL?) Review Flash player security settings for this special case:\nhttp://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html\nMay need to add/allow path, eg. c:/sm2/ or /users/me/sm2/", 1056 | waitFocus: "soundManager: Special case: Waiting for SWF to load with window focus...", 1057 | waitForever: "soundManager: Waiting indefinitely for Flash (will recover if unblocked)...", 1058 | waitSWF: "soundManager: Waiting for 100% SWF load...", 1059 | needFunction: "soundManager: Function object expected for %s", 1060 | badID: 'Sound ID "%s" should be a string, starting with a non-numeric character', 1061 | currentObj: "soundManager: _debug(): Current sound objects", 1062 | waitOnload: "soundManager: Waiting for window.onload()", 1063 | docLoaded: "soundManager: Document already loaded", 1064 | onload: "soundManager: initComplete(): calling soundManager.onload()", 1065 | onloadOK: "soundManager.onload() complete", 1066 | didInit: "soundManager: init(): Already called?", 1067 | secNote: "Flash security note: Network/internet URLs will not load due to security restrictions. Access can be configured via Flash Player Global Security Settings Page: http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html", 1068 | badRemove: "soundManager: Failed to remove Flash node.", 1069 | shutdown: "soundManager.disable(): Shutting down", 1070 | queue: "soundManager: Queueing %s handler", 1071 | smError: "SMSound.load(): Exception: JS-Flash communication failed, or JS error.", 1072 | fbTimeout: "No flash response, applying .swf_timedout CSS...", 1073 | fbLoaded: "Flash loaded", 1074 | fbHandler: "soundManager: flashBlockHandler()", 1075 | manURL: "SMSound.load(): Using manually-assigned URL", 1076 | onURL: "soundManager.load(): current URL already assigned.", 1077 | badFV: 'soundManager.flashVersion must be 8 or 9. "%s" is invalid. Reverting to %s.', 1078 | as2loop: "Note: Setting stream:false so looping can work (flash 8 limitation)", 1079 | noNSLoop: "Note: Looping not implemented for MovieStar formats", 1080 | needfl9: "Note: Switching to flash 9, required for MP4 formats.", 1081 | mfTimeout: "Setting flashLoadTimeout \x3d 0 (infinite) for off-screen, mobile flash case", 1082 | needFlash: "soundManager: Fatal error: Flash is needed to play some required formats, but is not available.", 1083 | gotFocus: "soundManager: Got window focus.", 1084 | policy: "Enabling usePolicyFile for data access", 1085 | setup: "soundManager.setup(): allowed parameters: %s", 1086 | setupError: 'soundManager.setup(): "%s" cannot be assigned with this method.', 1087 | setupUndef: 'soundManager.setup(): Could not find option "%s"', 1088 | setupLate: "soundManager.setup(): url, flashVersion and html5Test property changes will not take effect until reboot().", 1089 | noURL: "soundManager: Flash URL required. Call soundManager.setup({url:...}) to get started.", 1090 | sm2Loaded: "SoundManager 2: Ready.", 1091 | reset: "soundManager.reset(): Removing event callbacks", 1092 | mobileUA: "Mobile UA detected, preferring HTML5 by default.", 1093 | globalHTML5: "Using singleton HTML5 Audio() pattern for this device." 1094 | }; 1095 | r = function () { 1096 | var b = hb.call(arguments), c = b.shift(), c = I && I[c] ? I[c] : "", e, a; 1097 | if (c && b && b.length) { 1098 | e = 0; 1099 | for (a = b.length; e < a; e++)c = c.replace("%s", b[e]) 1100 | } 1101 | return c 1102 | }; 1103 | ma = function (b) { 1104 | 8 === n && (1 < b.loops && b.stream) && 1105 | (p("as2loop"), b.stream = !1); 1106 | return b 1107 | }; 1108 | na = function (b, d) { 1109 | if (b && !b.usePolicyFile && (b.onid3 || b.usePeakData || b.useWaveformData || b.useEQData))c._wD((d || "") + r("policy")), b.usePolicyFile = !0; 1110 | return b 1111 | }; 1112 | J = function (b) { 1113 | da && console.warn !== g ? console.warn(b) : c._wD(b) 1114 | }; 1115 | xa = function () { 1116 | return !1 1117 | }; 1118 | $a = function (b) { 1119 | for (var c in b)b.hasOwnProperty(c) && "function" === typeof b[c] && (b[c] = xa) 1120 | }; 1121 | Ga = function (b) { 1122 | b === g && (b = !1); 1123 | (y || b) && c.disable(b) 1124 | }; 1125 | ab = function (b) { 1126 | var d = null; 1127 | if (b)if (b.match(/\.swf(\?.*)?$/i)) { 1128 | if (d = b.substr(b.toLowerCase().lastIndexOf(".swf?") + 1129 | 4))return b 1130 | } else b.lastIndexOf("/") !== b.length - 1 && (b += "/"); 1131 | b = (b && -1 !== b.lastIndexOf("/") ? b.substr(0, b.lastIndexOf("/") + 1) : "./") + c.movieURL; 1132 | c.noSWFCache && (b += "?ts\x3d" + (new Date).getTime()); 1133 | return b 1134 | }; 1135 | Ca = function () { 1136 | n = parseInt(c.flashVersion, 10); 1137 | 8 !== n && 9 !== n && (c._wD(r("badFV", n, 8)), c.flashVersion = n = 8); 1138 | var b = c.debugMode || c.debugFlash ? "_debug.swf" : ".swf"; 1139 | c.useHTML5Audio && (!c.html5Only && c.audioFormats.mp4.required && 9 > n) && (c._wD(r("needfl9")), c.flashVersion = n = 9); 1140 | c.version = c.versionNumber + (c.html5Only ? " (HTML5-only mode)" : 1141 | 9 === n ? " (AS3/Flash 9)" : " (AS2/Flash 8)"); 1142 | 8 < n ? (c.defaultOptions = B(c.defaultOptions, c.flash9Options), c.features.buffering = !0, c.defaultOptions = B(c.defaultOptions, c.movieStarOptions), c.filePatterns.flash9 = RegExp("\\.(mp3|" + qb.join("|") + ")(\\?.*)?$", "i"), c.features.movieStar = !0) : c.features.movieStar = !1; 1143 | c.filePattern = c.filePatterns[8 !== n ? "flash9" : "flash8"]; 1144 | c.movieURL = (8 === n ? "soundmanager2.swf" : "soundmanager2_flash9.swf").replace(".swf", b); 1145 | c.features.peakData = c.features.waveformData = c.features.eqData = 8 < 1146 | n 1147 | }; 1148 | Ya = function (b, c) { 1149 | if (!k)return !1; 1150 | k._setPolling(b, c) 1151 | }; 1152 | Fa = function () { 1153 | c.debugURLParam.test(U) && (c.debugMode = !0); 1154 | if (A(c.debugID))return !1; 1155 | var b, d, e, a; 1156 | if (c.debugMode && !A(c.debugID) && (!da || !c.useConsole || !c.consoleOnly)) { 1157 | b = m.createElement("div"); 1158 | b.id = c.debugID + "-toggle"; 1159 | d = { 1160 | position: "fixed", 1161 | bottom: "0px", 1162 | right: "0px", 1163 | width: "1.2em", 1164 | height: "1.2em", 1165 | lineHeight: "1.2em", 1166 | margin: "2px", 1167 | textAlign: "center", 1168 | border: "1px solid #999", 1169 | cursor: "pointer", 1170 | background: "#fff", 1171 | color: "#333", 1172 | zIndex: 10001 1173 | }; 1174 | b.appendChild(m.createTextNode("-")); 1175 | b.onclick = bb; 1176 | b.title = "Toggle SM2 debug console"; 1177 | t.match(/msie 6/i) && (b.style.position = "absolute", b.style.cursor = "hand"); 1178 | for (a in d)d.hasOwnProperty(a) && (b.style[a] = d[a]); 1179 | d = m.createElement("div"); 1180 | d.id = c.debugID; 1181 | d.style.display = c.debugMode ? "block" : "none"; 1182 | if (c.debugMode && !A(b.id)) { 1183 | try { 1184 | e = ka(), e.appendChild(b) 1185 | } catch (f) { 1186 | throw Error(r("domError") + " \n" + f.toString()); 1187 | } 1188 | e.appendChild(d) 1189 | } 1190 | } 1191 | }; 1192 | v = this.getSoundById; 1193 | p = function (b, d) { 1194 | return !b ? "" : c._wD(r(b), d) 1195 | }; 1196 | bb = function () { 1197 | var b = A(c.debugID), d = A(c.debugID + "-toggle"); 1198 | if (!b)return !1; 1199 | za ? (d.innerHTML = "+", b.style.display = "none") : (d.innerHTML = "-", b.style.display = "block"); 1200 | za = !za 1201 | }; 1202 | C = function (b, c, e) { 1203 | if (h.sm2Debugger !== g)try { 1204 | sm2Debugger.handleEvent(b, c, e) 1205 | } catch (a) { 1206 | return !1 1207 | } 1208 | return !0 1209 | }; 1210 | T = function () { 1211 | var b = []; 1212 | c.debugMode && b.push("sm2_debug"); 1213 | c.debugFlash && b.push("flash_debug"); 1214 | c.useHighPerformance && b.push("high_performance"); 1215 | return b.join(" ") 1216 | }; 1217 | Ia = function () { 1218 | var b = r("fbHandler"), d = c.getMoviePercent(), e = {type: "FLASHBLOCK"}; 1219 | if (c.html5Only)return !1; 1220 | c.ok() ? (c.didFlashBlock && c._wD(b + 1221 | ": Unblocked"), c.oMC && (c.oMC.className = [T(), "movieContainer", "swf_loaded" + (c.didFlashBlock ? " swf_unblocked" : "")].join(" "))) : (u && (c.oMC.className = T() + " movieContainer " + (null === d ? "swf_timedout" : "swf_error"), c._wD(b + ": " + r("fbTimeout") + (d ? " (" + r("fbLoaded") + ")" : ""))), c.didFlashBlock = !0, M({ 1222 | type: "ontimeout", 1223 | ignoreInit: !0, 1224 | error: e 1225 | }), S(e)) 1226 | }; 1227 | Ba = function (b, c, e) { 1228 | F[b] === g && (F[b] = []); 1229 | F[b].push({method: c, scope: e || null, fired: !1}) 1230 | }; 1231 | M = function (b) { 1232 | b || (b = {type: c.ok() ? "onready" : "ontimeout"}); 1233 | if (!q && b && !b.ignoreInit || 1234 | "ontimeout" === b.type && (c.ok() || y && !b.ignoreInit))return !1; 1235 | var d = {success: b && b.ignoreInit ? c.ok() : !y}, e = b && b.type ? F[b.type] || [] : [], a = [], f, d = [d], g = u && !c.ok(); 1236 | b.error && (d[0].error = b.error); 1237 | b = 0; 1238 | for (f = e.length; b < f; b++)!0 !== e[b].fired && a.push(e[b]); 1239 | if (a.length) { 1240 | b = 0; 1241 | for (f = a.length; b < f; b++)a[b].scope ? a[b].method.apply(a[b].scope, d) : a[b].method.apply(this, d), g || (a[b].fired = !0) 1242 | } 1243 | return !0 1244 | }; 1245 | P = function () { 1246 | h.setTimeout(function () { 1247 | c.useFlashBlock && Ia(); 1248 | M(); 1249 | "function" === typeof c.onload && (p("onload", 1), c.onload.apply(h), 1250 | p("onloadOK", 1)); 1251 | c.waitForWindowLoad && w.add(h, "load", P) 1252 | }, 1) 1253 | }; 1254 | Ma = function () { 1255 | if (H !== g)return H; 1256 | var b = !1, c = navigator, e = c.plugins, a, f = h.ActiveXObject; 1257 | if (e && e.length)(c = c.mimeTypes) && (c["application/x-shockwave-flash"] && c["application/x-shockwave-flash"].enabledPlugin && c["application/x-shockwave-flash"].enabledPlugin.description) && (b = !0); else if (f !== g && !t.match(/MSAppHost/i)) { 1258 | try { 1259 | a = new f("ShockwaveFlash.ShockwaveFlash") 1260 | } catch (m) { 1261 | a = null 1262 | } 1263 | b = !!a 1264 | } 1265 | return H = b 1266 | }; 1267 | fb = function () { 1268 | var b, d, e = c.audioFormats; 1269 | if (ca && t.match(/os (1|2|3_0|3_1)/i))c.hasHTML5 = !1, c.html5Only = !0, c.oMC && (c.oMC.style.display = "none"); else if (c.useHTML5Audio) { 1270 | if (!c.html5 || !c.html5.canPlayType)c._wD("SoundManager: No HTML5 Audio() support detected."), c.hasHTML5 = !1; 1271 | Qa && c._wD("soundManager: Note: Buggy HTML5 Audio in Safari on this OS X release, see https://bugs.webkit.org/show_bug.cgi?id\x3d32159 - " + (!H ? " would use flash fallback for MP3/MP4, but none detected." : "will use flash fallback for MP3/MP4, if available"), 1) 1272 | } 1273 | if (c.useHTML5Audio && c.hasHTML5)for (d in qa = !0, e)if (e.hasOwnProperty(d) && 1274 | e[d].required)if (c.html5.canPlayType(e[d].type)) { 1275 | if (c.preferFlash && (c.flash[d] || c.flash[e[d].type]))b = !0 1276 | } else qa = !1, b = !0; 1277 | c.ignoreFlash && (b = !1, qa = !0); 1278 | c.html5Only = c.hasHTML5 && c.useHTML5Audio && !b; 1279 | return !c.html5Only 1280 | }; 1281 | pa = function (b) { 1282 | var d, e, a = 0; 1283 | if (b instanceof Array) { 1284 | d = 0; 1285 | for (e = b.length; d < e; d++)if (b[d]instanceof Object) { 1286 | if (c.canPlayMIME(b[d].type)) { 1287 | a = d; 1288 | break 1289 | } 1290 | } else if (c.canPlayURL(b[d])) { 1291 | a = d; 1292 | break 1293 | } 1294 | b[a].url && (b[a] = b[a].url); 1295 | b = b[a] 1296 | } 1297 | return b 1298 | }; 1299 | cb = function (b) { 1300 | b._hasTimer || (b._hasTimer = !0, !Pa && c.html5PollingInterval && 1301 | (null === aa && 0 === oa && (aa = setInterval(eb, c.html5PollingInterval)), oa++)) 1302 | }; 1303 | db = function (b) { 1304 | b._hasTimer && (b._hasTimer = !1, !Pa && c.html5PollingInterval && oa--) 1305 | }; 1306 | eb = function () { 1307 | var b; 1308 | if (null !== aa && !oa)return clearInterval(aa), aa = null, !1; 1309 | for (b = c.soundIDs.length - 1; 0 <= b; b--)c.sounds[c.soundIDs[b]].isHTML5 && c.sounds[c.soundIDs[b]]._hasTimer && c.sounds[c.soundIDs[b]]._onTimer() 1310 | }; 1311 | S = function (b) { 1312 | b = b !== g ? b : {}; 1313 | "function" === typeof c.onerror && c.onerror.apply(h, [{type: b.type !== g ? b.type : null}]); 1314 | b.fatal !== g && b.fatal && c.disable() 1315 | }; 1316 | ib = function () { 1317 | if (!Qa || !Ma())return !1; 1318 | var b = c.audioFormats, d, e; 1319 | for (e in b)if (b.hasOwnProperty(e) && ("mp3" === e || "mp4" === e))if (c._wD("soundManager: Using flash fallback for " + e + " format"), c.html5[e] = !1, b[e] && b[e].related)for (d = b[e].related.length - 1; 0 <= d; d--)c.html5[b[e].related[d]] = !1 1320 | }; 1321 | this._setSandboxType = function (b) { 1322 | var d = c.sandbox; 1323 | d.type = b; 1324 | d.description = d.types[d.types[b] !== g ? b : "unknown"]; 1325 | "localWithFile" === d.type ? (d.noRemote = !0, d.noLocal = !1, p("secNote", 2)) : "localWithNetwork" === d.type ? (d.noRemote = !1, 1326 | d.noLocal = !0) : "localTrusted" === d.type && (d.noRemote = !1, d.noLocal = !1) 1327 | }; 1328 | this._externalInterfaceOK = function (b) { 1329 | if (c.swfLoaded)return !1; 1330 | var d; 1331 | C("swf", !0); 1332 | C("flashtojs", !0); 1333 | c.swfLoaded = !0; 1334 | va = !1; 1335 | Qa && ib(); 1336 | if (!b || b.replace(/\+dev/i, "") !== c.versionNumber.replace(/\+dev/i, ""))return d = 'soundManager: Fatal: JavaScript file build "' + c.versionNumber + '" does not match Flash SWF build "' + b + '" at ' + c.url + ". Ensure both are up-to-date.", setTimeout(function () { 1337 | throw Error(d); 1338 | }, 0), !1; 1339 | setTimeout(ya, L ? 100 : 1) 1340 | }; 1341 | la = function (b, 1342 | d) { 1343 | function e() { 1344 | var a = [], b, d = []; 1345 | b = "SoundManager " + c.version + (!c.html5Only && c.useHTML5Audio ? c.hasHTML5 ? " + HTML5 audio" : ", no HTML5 audio support" : ""); 1346 | c.html5Only ? c.html5PollingInterval && a.push("html5PollingInterval (" + c.html5PollingInterval + "ms)") : (c.preferFlash && a.push("preferFlash"), c.useHighPerformance && a.push("useHighPerformance"), c.flashPollingInterval && a.push("flashPollingInterval (" + c.flashPollingInterval + "ms)"), c.html5PollingInterval && a.push("html5PollingInterval (" + c.html5PollingInterval + 1347 | "ms)"), c.wmode && a.push("wmode (" + c.wmode + ")"), c.debugFlash && a.push("debugFlash"), c.useFlashBlock && a.push("flashBlock")); 1348 | a.length && (d = d.concat([a.join(" + ")])); 1349 | c._wD(b + (d.length ? " + " + d.join(", ") : ""), 1); 1350 | jb() 1351 | } 1352 | 1353 | function a(a, b) { 1354 | return '\x3cparam name\x3d"' + a + '" value\x3d"' + b + '" /\x3e' 1355 | } 1356 | 1357 | if (V && W)return !1; 1358 | if (c.html5Only)return Ca(), e(), c.oMC = A(c.movieID), ya(), W = V = !0, !1; 1359 | var f = d || c.url, h = c.altURL || f, k = ka(), l = T(), n = null, n = m.getElementsByTagName("html")[0], p, s, q, n = n && n.dir && n.dir.match(/rtl/i); 1360 | b = b === g ? c.id : b; 1361 | Ca(); 1362 | c.url = ab(ea ? f : h); 1363 | d = c.url; 1364 | c.wmode = !c.wmode && c.useHighPerformance ? "transparent" : c.wmode; 1365 | if (null !== c.wmode && (t.match(/msie 8/i) || !L && !c.useHighPerformance) && navigator.platform.match(/win32|win64/i))N.push(I.spcWmode), c.wmode = null; 1366 | k = { 1367 | name: b, 1368 | id: b, 1369 | src: d, 1370 | quality: "high", 1371 | allowScriptAccess: c.allowScriptAccess, 1372 | bgcolor: c.bgColor, 1373 | pluginspage: ob + "www.macromedia.com/go/getflashplayer", 1374 | title: "JS/Flash audio component (SoundManager 2)", 1375 | type: "application/x-shockwave-flash", 1376 | wmode: c.wmode, 1377 | hasPriority: "true" 1378 | }; 1379 | c.debugFlash && 1380 | (k.FlashVars = "debug\x3d1"); 1381 | c.wmode || delete k.wmode; 1382 | if (L)f = m.createElement("div"), s = ['\x3cobject id\x3d"' + b + '" data\x3d"' + d + '" type\x3d"' + k.type + '" title\x3d"' + k.title + '" classid\x3d"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase\x3d"' + ob + 'download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version\x3d6,0,40,0"\x3e', a("movie", d), a("AllowScriptAccess", c.allowScriptAccess), a("quality", k.quality), c.wmode ? a("wmode", c.wmode) : "", a("bgcolor", c.bgColor), a("hasPriority", "true"), c.debugFlash ? 1383 | a("FlashVars", k.FlashVars) : "", "\x3c/object\x3e"].join(""); else for (p in f = m.createElement("embed"), k)k.hasOwnProperty(p) && f.setAttribute(p, k[p]); 1384 | Fa(); 1385 | l = T(); 1386 | if (k = ka())if (c.oMC = A(c.movieID) || m.createElement("div"), c.oMC.id)q = c.oMC.className, c.oMC.className = (q ? q + " " : "movieContainer") + (l ? " " + l : ""), c.oMC.appendChild(f), L && (p = c.oMC.appendChild(m.createElement("div")), p.className = "sm2-object-box", p.innerHTML = s), W = !0; else { 1387 | c.oMC.id = c.movieID; 1388 | c.oMC.className = "movieContainer " + l; 1389 | p = l = null; 1390 | c.useFlashBlock || (c.useHighPerformance ? 1391 | l = { 1392 | position: "fixed", 1393 | width: "8px", 1394 | height: "8px", 1395 | bottom: "0px", 1396 | left: "0px", 1397 | overflow: "hidden" 1398 | } : (l = { 1399 | position: "absolute", 1400 | width: "6px", 1401 | height: "6px", 1402 | top: "-9999px", 1403 | left: "-9999px" 1404 | }, n && (l.left = Math.abs(parseInt(l.left, 10)) + "px"))); 1405 | tb && (c.oMC.style.zIndex = 1E4); 1406 | if (!c.debugFlash)for (q in l)l.hasOwnProperty(q) && (c.oMC.style[q] = l[q]); 1407 | try { 1408 | L || c.oMC.appendChild(f), k.appendChild(c.oMC), L && (p = c.oMC.appendChild(m.createElement("div")), p.className = "sm2-object-box", p.innerHTML = s), W = !0 1409 | } catch (u) { 1410 | throw Error(r("domError") + " \n" + 1411 | u.toString()); 1412 | } 1413 | } 1414 | V = !0; 1415 | e(); 1416 | return !0 1417 | }; 1418 | ja = function () { 1419 | if (c.html5Only)return la(), !1; 1420 | if (k)return !1; 1421 | if (!c.url)return p("noURL"), !1; 1422 | k = c.getMovie(c.id); 1423 | k || (Z ? (L ? c.oMC.innerHTML = Ha : c.oMC.appendChild(Z), Z = null, V = !0) : la(c.id, c.url), k = c.getMovie(c.id)); 1424 | "function" === typeof c.oninitmovie && setTimeout(c.oninitmovie, 1); 1425 | Na(); 1426 | return !0 1427 | }; 1428 | Q = function () { 1429 | setTimeout(Xa, 1E3) 1430 | }; 1431 | Xa = function () { 1432 | var b, d = !1; 1433 | if (!c.url || $)return !1; 1434 | $ = !0; 1435 | w.remove(h, "load", Q); 1436 | if (va && !Ra)return p("waitFocus"), !1; 1437 | q || (b = c.getMoviePercent(), 0 < b && 100 > b && (d = !0)); 1438 | setTimeout(function () { 1439 | b = c.getMoviePercent(); 1440 | if (d)return $ = !1, c._wD(r("waitSWF")), h.setTimeout(Q, 1), !1; 1441 | q || (c._wD("soundManager: No Flash response within expected time. Likely causes: " + (0 === b ? "SWF load failed, " : "") + "Flash blocked or JS-Flash security error." + (c.debugFlash ? " " + r("checkSWF") : ""), 2), !ea && b && (p("localFail", 2), c.debugFlash || p("tryDebug", 2)), 0 === b && c._wD(r("swf404", c.url), 1), C("flashtojs", !1, ": Timed out" + ea ? " (Check flash security or flash blockers)" : " (No plugin/missing SWF?)")); 1442 | !q && mb && (null === b ? c.useFlashBlock || 0 === c.flashLoadTimeout ? (c.useFlashBlock && Ia(), p("waitForever")) : !c.useFlashBlock && qa ? h.setTimeout(function () { 1443 | J("soundManager: useFlashBlock is false, 100% HTML5 mode is possible. Rebooting with preferFlash: false..."); 1444 | c.setup({preferFlash: !1}).reboot(); 1445 | c.didFlashBlock = !0; 1446 | c.beginDelayedInit() 1447 | }, 1) : (p("waitForever"), M({ 1448 | type: "ontimeout", 1449 | ignoreInit: !0 1450 | })) : 0 === c.flashLoadTimeout ? p("waitForever") : Ga(!0)) 1451 | }, c.flashLoadTimeout) 1452 | }; 1453 | ia = function () { 1454 | if (Ra || !va)return w.remove(h, "focus", 1455 | ia), !0; 1456 | Ra = mb = !0; 1457 | p("gotFocus"); 1458 | $ = !1; 1459 | Q(); 1460 | w.remove(h, "focus", ia); 1461 | return !0 1462 | }; 1463 | Na = function () { 1464 | N.length && (c._wD("SoundManager 2: " + N.join(" "), 1), N = []) 1465 | }; 1466 | jb = function () { 1467 | Na(); 1468 | var b, d = []; 1469 | if (c.useHTML5Audio && c.hasHTML5) { 1470 | for (b in c.audioFormats)c.audioFormats.hasOwnProperty(b) && d.push(b + " \x3d " + c.html5[b] + (!c.html5[b] && u && c.flash[b] ? " (using flash)" : c.preferFlash && c.flash[b] && u ? " (preferring flash)" : !c.html5[b] ? " (" + (c.audioFormats[b].required ? "required, " : "") + "and no flash support)" : "")); 1471 | c._wD("SoundManager 2 HTML5 support: " + 1472 | d.join(", "), 1) 1473 | } 1474 | }; 1475 | X = function (b) { 1476 | if (q)return !1; 1477 | if (c.html5Only)return p("sm2Loaded"), q = !0, P(), C("onload", !0), !0; 1478 | var d = !0, e; 1479 | if (!c.useFlashBlock || !c.flashLoadTimeout || c.getMoviePercent())q = !0, y && (e = {type: !H && u ? "NO_FLASH" : "INIT_TIMEOUT"}); 1480 | c._wD("SoundManager 2 " + (y ? "failed to load" : "loaded") + " (" + (y ? "Flash security/load error" : "OK") + ")", y ? 2 : 1); 1481 | y || b ? (c.useFlashBlock && c.oMC && (c.oMC.className = T() + " " + (null === c.getMoviePercent() ? "swf_timedout" : "swf_error")), M({ 1482 | type: "ontimeout", 1483 | error: e, 1484 | ignoreInit: !0 1485 | }), C("onload", 1486 | !1), S(e), d = !1) : C("onload", !0); 1487 | y || (c.waitForWindowLoad && !ha ? (p("waitOnload"), w.add(h, "load", P)) : (c.waitForWindowLoad && ha && p("docLoaded"), P())); 1488 | return d 1489 | }; 1490 | Wa = function () { 1491 | var b, d = c.setupOptions; 1492 | for (b in d)d.hasOwnProperty(b) && (c[b] === g ? c[b] = d[b] : c[b] !== d[b] && (c.setupOptions[b] = c[b])) 1493 | }; 1494 | ya = function () { 1495 | if (q)return p("didInit"), !1; 1496 | if (c.html5Only)return q || (w.remove(h, "load", c.beginDelayedInit), c.enabled = !0, X()), !0; 1497 | ja(); 1498 | try { 1499 | k._externalInterfaceTest(!1), Ya(!0, c.flashPollingInterval || (c.useHighPerformance ? 10 : 1500 | 50)), c.debugMode || k._disableDebug(), c.enabled = !0, C("jstoflash", !0), c.html5Only || w.add(h, "unload", xa) 1501 | } catch (b) { 1502 | return c._wD("js/flash exception: " + b.toString()), C("jstoflash", !1), S({ 1503 | type: "JS_TO_FLASH_EXCEPTION", 1504 | fatal: !0 1505 | }), Ga(!0), X(), !1 1506 | } 1507 | X(); 1508 | w.remove(h, "load", c.beginDelayedInit); 1509 | return !0 1510 | }; 1511 | R = function () { 1512 | if (Y)return !1; 1513 | Y = !0; 1514 | Wa(); 1515 | Fa(); 1516 | var b = null, b = null, d = U.toLowerCase(); 1517 | -1 !== d.indexOf("sm2-usehtml5audio\x3d") && (b = "1" === d.charAt(d.indexOf("sm2-usehtml5audio\x3d") + 18), da && console.log((b ? "Enabling " : "Disabling ") + 1518 | "useHTML5Audio via URL parameter"), c.setup({useHTML5Audio: b})); 1519 | -1 !== d.indexOf("sm2-preferflash\x3d") && (b = "1" === d.charAt(d.indexOf("sm2-preferflash\x3d") + 16), da && console.log((b ? "Enabling " : "Disabling ") + "preferFlash via URL parameter"), c.setup({preferFlash: b})); 1520 | !H && c.hasHTML5 && (c._wD("SoundManager: No Flash detected" + (!c.useHTML5Audio ? ", enabling HTML5." : ". Trying HTML5-only mode."), 1), c.setup({ 1521 | useHTML5Audio: !0, 1522 | preferFlash: !1 1523 | })); 1524 | gb(); 1525 | !H && u && (N.push(I.needFlash), c.setup({flashLoadTimeout: 1})); 1526 | m.removeEventListener && 1527 | m.removeEventListener("DOMContentLoaded", R, !1); 1528 | ja(); 1529 | return !0 1530 | }; 1531 | Ka = function () { 1532 | "complete" === m.readyState && (R(), m.detachEvent("onreadystatechange", Ka)); 1533 | return !0 1534 | }; 1535 | Ea = function () { 1536 | ha = !0; 1537 | w.remove(h, "load", Ea) 1538 | }; 1539 | Da = function () { 1540 | if (Pa && ((!c.setupOptions.useHTML5Audio || c.setupOptions.preferFlash) && N.push(I.mobileUA), c.setupOptions.useHTML5Audio = !0, c.setupOptions.preferFlash = !1, ca || lb && !t.match(/android\s2\.3/i)))N.push(I.globalHTML5), ca && (c.ignoreFlash = !0), E = !0 1541 | }; 1542 | Da(); 1543 | Ma(); 1544 | w.add(h, "focus", ia); 1545 | w.add(h, "load", Q); 1546 | w.add(h, 1547 | "load", Ea); 1548 | m.addEventListener ? m.addEventListener("DOMContentLoaded", R, !1) : m.attachEvent ? m.attachEvent("onreadystatechange", Ka) : (C("onload", !1), S({ 1549 | type: "NO_DOM2_EVENTS", 1550 | fatal: !0 1551 | })) 1552 | } 1553 | 1554 | var wa = null; 1555 | if (void 0 === h.SM2_DEFER || !SM2_DEFER)wa = new fa; 1556 | h.SoundManager = fa; 1557 | h.soundManager = wa 1558 | })(window); 1559 | --------------------------------------------------------------------------------