├── .gitignore ├── README.md ├── android ├── AndroidManifest.xml ├── assets │ └── badlogic.jpg ├── build.gradle ├── ic_launcher-web.png ├── proguard-rules.pro ├── project.properties ├── res │ ├── drawable-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_foreground.xml │ ├── drawable-hdpi │ │ └── ic_launcher.png │ ├── drawable-mdpi │ │ └── ic_launcher.png │ ├── drawable-xhdpi │ │ └── ic_launcher.png │ ├── drawable-xxhdpi │ │ └── ic_launcher.png │ ├── drawable-xxxhdpi │ │ └── ic_launcher.png │ └── values │ │ ├── color.xml │ │ ├── strings.xml │ │ └── styles.xml └── src │ └── com │ └── gdx │ └── cellular │ └── AndroidLauncher.java ├── build.gradle ├── core ├── assets │ ├── badlogic.jpg │ ├── customphysicsobjects │ │ ├── halfcircle │ │ ├── rectangle │ │ ├── square │ │ └── trapezoid │ ├── default.fnt │ ├── default.png │ ├── elementtextures │ │ ├── Brick.png │ │ ├── Player0.png │ │ ├── Player1.png │ │ ├── Stone.png │ │ ├── StoneBig.png │ │ └── Wood.png │ ├── save │ │ ├── Blood.ser │ │ ├── Sand.ser │ │ ├── boid.ser │ │ ├── cem.ser │ │ ├── e.ser │ │ ├── ex.ser │ │ ├── house.ser │ │ └── w.ser │ ├── textures │ │ └── light.png │ ├── uiskin.atlas │ ├── uiskin.json │ └── uiskin.png ├── build.gradle ├── out │ └── production │ │ └── classes │ │ └── META-INF │ │ └── GDX.core.kotlin_module └── src │ ├── CellularAutomaton.gwt.xml │ └── com │ └── gdx │ └── cellular │ ├── CellularAutomaton.java │ ├── CellularMatrix.java │ ├── boids │ └── Boid.java │ ├── box2d │ ├── PhysicsElementActor.java │ ├── ShapeFactory.java │ ├── douglaspeucker │ │ ├── EpsilonHelper.java │ │ ├── Line.java │ │ ├── Point.java │ │ ├── PointImpl.java │ │ ├── RecursiveApproach.java │ │ └── SeriesReducer.java │ ├── linesimplification │ │ └── Visvalingam.java │ └── marchingsquares │ │ ├── MooreNeighborTracing.java │ │ └── Pavlidis.java │ ├── effects │ └── EffectColors.java │ ├── elements │ ├── ColorConstants.java │ ├── Element.java │ ├── ElementType.java │ ├── EmptyCell.java │ ├── gas │ │ ├── ExplosionSpark.java │ │ ├── FlammableGas.java │ │ ├── Gas.java │ │ ├── Smoke.java │ │ ├── Spark.java │ │ └── Steam.java │ ├── liquid │ │ ├── Acid.java │ │ ├── Blood.java │ │ ├── Cement.java │ │ ├── Lava.java │ │ ├── Liquid.java │ │ ├── Oil.java │ │ └── Water.java │ ├── player │ │ └── PlayerMeat.java │ └── solid │ │ ├── Solid.java │ │ ├── immoveable │ │ ├── Brick.java │ │ ├── Ground.java │ │ ├── ImmovableSolid.java │ │ ├── SlimeMold.java │ │ ├── Stone.java │ │ ├── Titanium.java │ │ └── Wood.java │ │ └── movable │ │ ├── Coal.java │ │ ├── Dirt.java │ │ ├── Ember.java │ │ ├── Gunpowder.java │ │ ├── MovableSolid.java │ │ ├── Sand.java │ │ └── Snow.java │ ├── input │ ├── Cursor.java │ ├── InputElement.java │ ├── InputManager.java │ ├── InputProcessors.java │ ├── MouseMode.java │ └── processors │ │ ├── CreatorInputProcessor.java │ │ ├── MenuInputProcessor.java │ │ └── PlayerInputProcessor.java │ ├── particles │ ├── Explosion.java │ └── Particle.java │ ├── player │ └── Player.java │ ├── spouts │ ├── ElementSpout.java │ ├── ParticleSpout.java │ └── Spout.java │ ├── ui │ ├── ControlsMenu.java │ ├── CreatorMenu.java │ ├── CursorActor.java │ ├── MatrixActor.java │ ├── ModeActor.java │ └── Skins.java │ └── util │ ├── Assets.java │ ├── Chunk.java │ ├── ElementColumnStepper.java │ ├── ElementRowDrawer.java │ ├── ElementRowStepper.java │ ├── GameManager.java │ ├── MaterialMap.java │ ├── TextInputHandler.java │ └── WeatherSystem.java ├── desktop ├── build.gradle └── src │ └── com │ └── gdx │ └── cellular │ └── desktop │ └── DesktopLauncher.java ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── html ├── build.gradle ├── src │ └── com │ │ └── gdx │ │ └── cellular │ │ ├── GdxDefinition.gwt.xml │ │ ├── GdxDefinitionSuperdev.gwt.xml │ │ └── client │ │ └── HtmlLauncher.java └── webapp │ ├── WEB-INF │ └── web.xml │ ├── index.html │ ├── refresh.png │ ├── soundmanager2-jsmin.js │ ├── soundmanager2-setup.js │ └── styles.css ├── media ├── Box2DScene.gif ├── ExplosionScene.gif ├── SandScene.gif └── housescene.gif └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | ## Java 2 | 3 | *.class 4 | *.war 5 | *.ear 6 | hs_err_pid* 7 | 8 | ## Robovm 9 | /ios/robovm-build/ 10 | 11 | ## GWT 12 | /html/war/ 13 | /html/gwt-unitCache/ 14 | .apt_generated/ 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/arm64-v8a/ 24 | /android/libs/x86/ 25 | /android/libs/x86_64/ 26 | /android/gen/ 27 | .idea/ 28 | *.ipr 29 | *.iws 30 | *.iml 31 | /android/out/ 32 | com_crashlytics_export_strings.xml 33 | 34 | ## Eclipse 35 | 36 | .classpath 37 | .project 38 | .metadata/ 39 | /android/bin/ 40 | /core/bin/ 41 | /desktop/bin/ 42 | /html/bin/ 43 | /ios/bin/ 44 | /ios-moe/bin/ 45 | *.tmp 46 | *.bak 47 | *.swp 48 | *~.nib 49 | .settings/ 50 | .loadpath 51 | .externalToolBuilders/ 52 | *.launch 53 | 54 | ## NetBeans 55 | 56 | /nbproject/private/ 57 | /android/nbproject/private/ 58 | /core/nbproject/private/ 59 | /desktop/nbproject/private/ 60 | /html/nbproject/private/ 61 | /ios/nbproject/private/ 62 | /ios-moe/nbproject/private/ 63 | 64 | /build/ 65 | /android/build/ 66 | /core/build/ 67 | /desktop/build/ 68 | /html/build/ 69 | /ios/build/ 70 | /ios-moe/build/ 71 | 72 | /nbbuild/ 73 | /android/nbbuild/ 74 | /core/nbbuild/ 75 | /desktop/nbbuild/ 76 | /html/nbbuild/ 77 | /ios/nbbuild/ 78 | /ios-moe/nbbuild/ 79 | 80 | /dist/ 81 | /android/dist/ 82 | /core/dist/ 83 | /desktop/dist/ 84 | /html/dist/ 85 | /ios/dist/ 86 | /ios-moe/dist/ 87 | 88 | /nbdist/ 89 | /android/nbdist/ 90 | /core/nbdist/ 91 | /desktop/nbdist/ 92 | /html/nbdist/ 93 | /ios/nbdist/ 94 | /ios-moe/nbdist/ 95 | 96 | nbactions.xml 97 | nb-configuration.xml 98 | 99 | ## Gradle 100 | 101 | /local.properties 102 | .gradle/ 103 | gradle-app.setting 104 | /build/ 105 | /android/build/ 106 | /core/build/ 107 | /desktop/build/ 108 | /html/build/ 109 | /ios/build/ 110 | /ios-moe/build/ 111 | 112 | ## OS Specific 113 | .DS_Store 114 | Thumbs.db 115 | 116 | ## iOS 117 | /ios/xcode/*.xcodeproj/* 118 | !/ios/xcode/*.xcodeproj/xcshareddata 119 | !/ios/xcode/*.xcodeproj/project.pbxproj 120 | /ios/xcode/native/ 121 | 122 | /ios-moe/xcode/*.xcodeproj/* 123 | !/ios-moe/xcode/*.xcodeproj/xcshareddata 124 | !/ios-moe/xcode/*.xcodeproj/project.pbxproj 125 | /ios-moe/xcode/native/ 126 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FallingSandJava 2 | Falling sand simulation written in Java and LIBGDX 3 | 4 | YouTube video tutorial on how to build this: https://youtu.be/5Ka3tbbT-9E 5 | 6 | ![](media/SandScene.gif) 7 | 8 | ## Overview:
9 | Inspired by classic falling sand games I am making one of my own. The intent is to build and release a falling sand 10 | simulation simlar to the ones from the early 2000's. Plans past that are to create a local multiplayer combat game 11 | within the falling sand simulation taking influence from [Duck Game](https://store.steampowered.com/app/312530/Duck_Game/0) 12 | and integrating the falling sand simulation with [Box2D](https://box2d.org/) taking influence from [Noita](https://noitagame.com/). 13 | 14 | Online multiplayer would require extremely sophisticated systems to allow for smooth gameplay when each game object is 15 | one pixel square. This would be too much to synchronize with basic online implementations. However, With recent 16 | improvements in streaming online multiplayer should be possible through 17 | [Steam Remote Play](https://store.steampowered.com/streaming/) or [Parsec](https://parsecgaming.com/). 18 | 19 | ![](media/HouseScene.gif) 20 | 21 | ![](media/ExplosionScene.gif) 22 | 23 | ## Integrating Box2D 24 | Integrating Box2D with a falling sand simulation presents unique technical challenges. 25 | The Noita developers have gone into some detail in their video [Exploring the Tech and Design of Noita](https://youtu.be/prXuyMCgbTc?t=322) 26 | 27 | The basic steps are: 28 | 29 | * Take a 2D array of elements and use marching squares algorithm to get the contour 30 | * Use a Douglas-Peucker line simplification algorithm to reduce the amount of vertices 31 | * Pass the simplified set of vertices to a triangulation algorithm 32 | * Create a Box2D rigidbody from all the resulting triangles 33 | * If any elements in the rigidbody are destory repeat the process 34 | 35 | ![](media/Box2DScene.gif) 36 | 37 | 38 | -------------------------------------------------------------------------------- /android/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /android/assets/badlogic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidMcLaughlin208/FallingSandJava/6d1b95086b64443a5dea3b32377b2cc84efab024/android/assets/badlogic.jpg -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | android { 2 | buildToolsVersion "30.0.2" 3 | compileSdkVersion 30 4 | sourceSets { 5 | main { 6 | manifest.srcFile 'AndroidManifest.xml' 7 | java.srcDirs = ['src'] 8 | aidl.srcDirs = ['src'] 9 | renderscript.srcDirs = ['src'] 10 | res.srcDirs = ['res'] 11 | assets.srcDirs = ['assets'] 12 | jniLibs.srcDirs = ['libs'] 13 | } 14 | 15 | } 16 | packagingOptions { 17 | exclude 'META-INF/robovm/ios/robovm.xml' 18 | } 19 | defaultConfig { 20 | applicationId "com.gdx.cellular" 21 | minSdkVersion 14 22 | targetSdkVersion 30 23 | versionCode 1 24 | versionName "1.0" 25 | } 26 | buildTypes { 27 | release { 28 | minifyEnabled false 29 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 30 | } 31 | } 32 | } 33 | 34 | 35 | // called every time gradle gets executed, takes the native dependencies of 36 | // the natives configuration, and extracts them to the proper libs/ folders 37 | // so they get packed with the APK. 38 | task copyAndroidNatives { 39 | doFirst { 40 | file("libs/armeabi/").mkdirs() 41 | file("libs/armeabi-v7a/").mkdirs() 42 | file("libs/arm64-v8a/").mkdirs() 43 | file("libs/x86_64/").mkdirs() 44 | file("libs/x86/").mkdirs() 45 | 46 | configurations.natives.files.each { jar -> 47 | def outputDir = null 48 | if (jar.name.endsWith("natives-arm64-v8a.jar")) outputDir = file("libs/arm64-v8a") 49 | if (jar.name.endsWith("natives-armeabi-v7a.jar")) outputDir = file("libs/armeabi-v7a") 50 | if(jar.name.endsWith("natives-armeabi.jar")) outputDir = file("libs/armeabi") 51 | if(jar.name.endsWith("natives-x86_64.jar")) outputDir = file("libs/x86_64") 52 | if(jar.name.endsWith("natives-x86.jar")) outputDir = file("libs/x86") 53 | if(outputDir != null) { 54 | copy { 55 | from zipTree(jar) 56 | into outputDir 57 | include "*.so" 58 | } 59 | } 60 | } 61 | } 62 | } 63 | 64 | tasks.whenTaskAdded { packageTask -> 65 | if (packageTask.name.contains("package")) { 66 | packageTask.dependsOn 'copyAndroidNatives' 67 | } 68 | } 69 | 70 | task run(type: Exec) { 71 | def path 72 | def localProperties = project.file("../local.properties") 73 | if (localProperties.exists()) { 74 | Properties properties = new Properties() 75 | localProperties.withInputStream { instr -> 76 | properties.load(instr) 77 | } 78 | def sdkDir = properties.getProperty('sdk.dir') 79 | if (sdkDir) { 80 | path = sdkDir 81 | } else { 82 | path = "$System.env.ANDROID_HOME" 83 | } 84 | } else { 85 | path = "$System.env.ANDROID_HOME" 86 | } 87 | 88 | def adb = path + "/platform-tools/adb" 89 | commandLine "$adb", 'shell', 'am', 'start', '-n', 'com.gdx.cellular/com.gdx.cellular.AndroidLauncher' 90 | } 91 | 92 | eclipse.project.name = appName + "-android" 93 | -------------------------------------------------------------------------------- /android/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidMcLaughlin208/FallingSandJava/6d1b95086b64443a5dea3b32377b2cc84efab024/android/ic_launcher-web.png -------------------------------------------------------------------------------- /android/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | 22 | -verbose 23 | 24 | -dontwarn android.support.** 25 | -dontwarn com.badlogic.gdx.backends.android.AndroidFragmentApplication 26 | -dontwarn com.badlogic.gdx.utils.GdxBuild 27 | -dontwarn com.badlogic.gdx.physics.box2d.utils.Box2DBuild 28 | -dontwarn com.badlogic.gdx.jnigen.BuildTarget* 29 | -dontwarn com.badlogic.gdx.graphics.g2d.freetype.FreetypeBuild 30 | 31 | -keep class com.badlogic.gdx.controllers.android.AndroidControllers 32 | 33 | -keepclassmembers class com.badlogic.gdx.backends.android.AndroidInput* { 34 | (com.badlogic.gdx.Application, android.content.Context, java.lang.Object, com.badlogic.gdx.backends.android.AndroidApplicationConfiguration); 35 | } 36 | 37 | -keepclassmembers class com.badlogic.gdx.physics.box2d.World { 38 | boolean contactFilter(long, long); 39 | void beginContact(long); 40 | void endContact(long); 41 | void preSolve(long, long); 42 | void postSolve(long, long); 43 | boolean reportFixture(long); 44 | float reportRayFixture(long, float, float, float, float, float); 45 | } 46 | -------------------------------------------------------------------------------- /android/project.properties: -------------------------------------------------------------------------------- 1 | # This file is used by the Eclipse ADT plugin. It is unnecessary for IDEA and Android Studio projects, which 2 | # configure Proguard and the Android target via the build.gradle file. 3 | 4 | # To enable ProGuard to work with Eclipse ADT, uncomment this (available properties: sdk.dir, user.home) 5 | # and ensure proguard.jar in the Android SDK is up to date (or alternately reduce the android target to 23 or lower): 6 | # proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-rules.pro 7 | 8 | # Project target. 9 | target=android-19 10 | -------------------------------------------------------------------------------- /android/res/drawable-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /android/res/drawable-anydpi-v26/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 6 | 11 | 16 | 21 | 26 | 31 | 36 | 40 | 41 | -------------------------------------------------------------------------------- /android/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidMcLaughlin208/FallingSandJava/6d1b95086b64443a5dea3b32377b2cc84efab024/android/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidMcLaughlin208/FallingSandJava/6d1b95086b64443a5dea3b32377b2cc84efab024/android/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidMcLaughlin208/FallingSandJava/6d1b95086b64443a5dea3b32377b2cc84efab024/android/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidMcLaughlin208/FallingSandJava/6d1b95086b64443a5dea3b32377b2cc84efab024/android/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/res/drawable-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidMcLaughlin208/FallingSandJava/6d1b95086b64443a5dea3b32377b2cc84efab024/android/res/drawable-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/res/values/color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFFFFFFF 4 | 5 | -------------------------------------------------------------------------------- /android/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | AndroidVersion 5 | 6 | 7 | -------------------------------------------------------------------------------- /android/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /android/src/com/gdx/cellular/AndroidLauncher.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular; 2 | 3 | import android.os.Bundle; 4 | 5 | import com.badlogic.gdx.backends.android.AndroidApplication; 6 | import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration; 7 | import com.gdx.cellular.CellularAutomaton; 8 | 9 | public class AndroidLauncher extends AndroidApplication { 10 | @Override 11 | protected void onCreate (Bundle savedInstanceState) { 12 | super.onCreate(savedInstanceState); 13 | AndroidApplicationConfiguration config = new AndroidApplicationConfiguration(); 14 | initialize(new CellularAutomaton(), config); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | 3 | 4 | repositories { 5 | mavenLocal() 6 | mavenCentral() 7 | maven { url "https://plugins.gradle.org/m2/" } 8 | maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } 9 | jcenter() 10 | google() 11 | } 12 | dependencies { 13 | classpath 'org.wisepersist:gwt-gradle-plugin:1.0.6' 14 | 15 | 16 | } 17 | } 18 | 19 | allprojects { 20 | apply plugin: "eclipse" 21 | apply plugin: "idea" 22 | 23 | version = '1.0' 24 | ext { 25 | appName = "CellularAutomaton" 26 | gdxVersion = '1.9.9' 27 | roboVMVersion = '2.3.6' 28 | box2DLightsVersion = '1.4' 29 | ashleyVersion = '1.7.0' 30 | aiVersion = '1.8.0' 31 | } 32 | 33 | repositories { 34 | mavenLocal() 35 | mavenCentral() 36 | jcenter() 37 | google() 38 | maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } 39 | maven { url "https://oss.sonatype.org/content/repositories/releases/" } 40 | } 41 | } 42 | 43 | project(":desktop") { 44 | apply plugin: "java" 45 | 46 | 47 | dependencies { 48 | compile project(":core") 49 | compile "com.badlogicgames.gdx:gdx-backend-lwjgl:$gdxVersion" 50 | compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop" 51 | compile "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-desktop" 52 | compile "org.locationtech.jts:jts-core:1.17.0" 53 | compile "org.dyn4j:dyn4j:3.4.0" 54 | 55 | } 56 | } 57 | 58 | project(":html") { 59 | apply plugin: "gwt" 60 | apply plugin: "war" 61 | 62 | 63 | dependencies { 64 | compile project(":core") 65 | compile "com.badlogicgames.gdx:gdx-backend-gwt:$gdxVersion" 66 | compile "com.badlogicgames.gdx:gdx:$gdxVersion:sources" 67 | compile "com.badlogicgames.gdx:gdx-backend-gwt:$gdxVersion:sources" 68 | compile "com.badlogicgames.gdx:gdx-box2d:$gdxVersion:sources" 69 | compile "com.badlogicgames.gdx:gdx-box2d-gwt:$gdxVersion:sources" 70 | compile "com.badlogicgames.box2dlights:box2dlights:$box2DLightsVersion:sources" 71 | 72 | } 73 | } 74 | 75 | project(":core") { 76 | apply plugin: "java" 77 | 78 | 79 | dependencies { 80 | compile "com.badlogicgames.gdx:gdx:$gdxVersion" 81 | compile "com.badlogicgames.gdx:gdx-box2d:$gdxVersion" 82 | compile "com.badlogicgames.box2dlights:box2dlights:$box2DLightsVersion" 83 | compile "org.dyn4j:dyn4j:3.4.0" 84 | compile "org.locationtech.jts:jts-core:1.17.0" 85 | 86 | } 87 | } 88 | 89 | tasks.eclipse.doLast { 90 | delete ".project" 91 | } -------------------------------------------------------------------------------- /core/assets/badlogic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidMcLaughlin208/FallingSandJava/6d1b95086b64443a5dea3b32377b2cc84efab024/core/assets/badlogic.jpg -------------------------------------------------------------------------------- /core/assets/customphysicsobjects/halfcircle: -------------------------------------------------------------------------------- 1 | null, null, null, Stone, Stone, Stone, Stone, 2 | null, null, null, Stone, Stone, Stone, Stone, 3 | null, null, Stone, Stone, Stone, Stone, null, 4 | null, Stone, Stone, Stone, Stone, null, null, 5 | Stone, Stone, Stone, Stone, null, null, null, 6 | Stone, Stone, Stone, null, null, null, null, 7 | Stone, Stone, Stone, null, null, null, null, 8 | Stone, Stone, Stone, Stone, null, null, null, 9 | null, Stone, Stone, Stone, Stone, null, null, 10 | null, null, Stone, Stone, Stone, Stone, null, 11 | null, null, null, Stone, Stone, Stone, Stone, 12 | null, null, null, Stone, Stone, Stone, Stone, 13 | null, null, null, Stone, Stone, Stone, Stone, 14 | null, null, null, Stone, Stone, Stone, Stone, 15 | null, null, Stone, Stone, Stone, Stone, null, 16 | null, Stone, Stone, Stone, Stone, null, null, 17 | Stone, Stone, Stone, Stone, null, null, null, 18 | Stone, Stone, Stone, null, null, null, null, 19 | Stone, Stone, Stone, null, null, null, null, 20 | Stone, Stone, Stone, Stone, null, null, null, 21 | null, Stone, Stone, Stone, Stone, null, null, 22 | null, null, Stone, Stone, Stone, Stone, null, 23 | null, null, null, Stone, Stone, Stone, Stone, 24 | null, null, null, Stone, Stone, Stone, Stone, 25 | -------------------------------------------------------------------------------- /core/assets/customphysicsobjects/rectangle: -------------------------------------------------------------------------------- 1 | null, null, null, null, null, Stone, Stone, Stone, Stone, Stone, null, null, null, null 2 | null, null, null, null, null, Stone, Stone, Stone, Stone, Stone, null, null, null, null 3 | null, null, null, null, null, Stone, Stone, Stone, Stone, Stone, null, null, null, null 4 | null, null, null, null, null, Stone, Stone, Stone, Stone, Stone, null, null, null, null 5 | null, null, null, null, null, Stone, Stone, Stone, Stone, Stone, null, null, null, null 6 | null, null, null, null, null, Stone, Stone, Stone, Stone, Stone, null, null, null, null 7 | null, null, null, null, null, Stone, Stone, Stone, Stone, Stone, null, null, null, null 8 | null, null, null, null, null, Stone, Stone, Stone, Stone, Stone, null, null, null, null 9 | null, null, null, null, null, Stone, Stone, Stone, Stone, Stone, null, null, null, null 10 | null, null, null, null, null, Stone, Stone, Stone, Stone, Stone, null, null, null, null -------------------------------------------------------------------------------- /core/assets/customphysicsobjects/square: -------------------------------------------------------------------------------- 1 | null, null, null, null, null, Stone, Stone, null, Stone, Stone, null, null, null, null 2 | null, null, null, null, null, Stone, Stone, Stone, Stone, Stone, null, null, null, null 3 | null, null, null, null, null, Stone, Stone, Stone, Stone, Stone, null, null, null, null 4 | null, null, null, null, null, Stone, Stone, Stone, Stone, Stone, null, null, null, null 5 | null, null, null, null, null, Stone, Stone, Stone, Stone, Stone, null, null, null, null -------------------------------------------------------------------------------- /core/assets/customphysicsobjects/trapezoid: -------------------------------------------------------------------------------- 1 | null, null, null, null, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, null, null, null, null 2 | null, null, null, null, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, null, null, null, null 3 | null, null, null, null, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, null, null, null, null 4 | null, null, null, null, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, null, null, null, null 5 | null, null, null, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, null, null, null 6 | null, null, null, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, null, null, null 7 | null, null, null, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, null, null, null 8 | null, null, null, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, null, null, null 9 | null, null, null, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, null, null, null 10 | null, null, null, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, null, null, null 11 | null, null, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, null, null 12 | null, null, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, null, null 13 | null, null, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, null, null 14 | null, null, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, null, null 15 | null, null, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, null, null 16 | null, null, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, null, null 17 | null, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, null 18 | null, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, null 19 | null, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, null 20 | null, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, null 21 | null, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, null 22 | null, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, null 23 | null, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, null 24 | null, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, Stone, null 25 | -------------------------------------------------------------------------------- /core/assets/default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidMcLaughlin208/FallingSandJava/6d1b95086b64443a5dea3b32377b2cc84efab024/core/assets/default.png -------------------------------------------------------------------------------- /core/assets/elementtextures/Brick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidMcLaughlin208/FallingSandJava/6d1b95086b64443a5dea3b32377b2cc84efab024/core/assets/elementtextures/Brick.png -------------------------------------------------------------------------------- /core/assets/elementtextures/Player0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidMcLaughlin208/FallingSandJava/6d1b95086b64443a5dea3b32377b2cc84efab024/core/assets/elementtextures/Player0.png -------------------------------------------------------------------------------- /core/assets/elementtextures/Player1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidMcLaughlin208/FallingSandJava/6d1b95086b64443a5dea3b32377b2cc84efab024/core/assets/elementtextures/Player1.png -------------------------------------------------------------------------------- /core/assets/elementtextures/Stone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidMcLaughlin208/FallingSandJava/6d1b95086b64443a5dea3b32377b2cc84efab024/core/assets/elementtextures/Stone.png -------------------------------------------------------------------------------- /core/assets/elementtextures/StoneBig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidMcLaughlin208/FallingSandJava/6d1b95086b64443a5dea3b32377b2cc84efab024/core/assets/elementtextures/StoneBig.png -------------------------------------------------------------------------------- /core/assets/elementtextures/Wood.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidMcLaughlin208/FallingSandJava/6d1b95086b64443a5dea3b32377b2cc84efab024/core/assets/elementtextures/Wood.png -------------------------------------------------------------------------------- /core/assets/save/Sand.ser: -------------------------------------------------------------------------------- 1 | 480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,29,EmptyCell,390,Stone,61,EmptyCell,0,|,89,EmptyCell,260,Sand,131,EmptyCell,0,|,92,EmptyCell,244,Sand,10,EmptyCell,1,Sand,133,EmptyCell,0,|,92,EmptyCell,1,Sand,1,EmptyCell,1,Sand,1,EmptyCell,235,Sand,1,EmptyCell,3,Sand,145,EmptyCell,0,|,96,EmptyCell,1,Sand,3,EmptyCell,1,Sand,1,EmptyCell,224,Sand,154,EmptyCell,0,|,106,EmptyCell,217,Sand,157,EmptyCell,0,|,108,EmptyCell,213,Sand,159,EmptyCell,0,|,110,EmptyCell,210,Sand,160,EmptyCell,0,|,110,EmptyCell,1,Sand,2,EmptyCell,202,Sand,1,EmptyCell,2,Sand,162,EmptyCell,0,|,114,EmptyCell,200,Sand,166,EmptyCell,0,|,116,EmptyCell,196,Sand,168,EmptyCell,0,|,118,EmptyCell,190,Sand,172,EmptyCell,0,|,119,EmptyCell,187,Sand,174,EmptyCell,0,|,120,EmptyCell,185,Sand,175,EmptyCell,0,|,121,EmptyCell,182,Sand,177,EmptyCell,0,|,124,EmptyCell,1,Sand,1,EmptyCell,176,Sand,178,EmptyCell,0,|,127,EmptyCell,1,Sand,3,EmptyCell,167,Sand,182,EmptyCell,0,|,136,EmptyCell,161,Sand,183,EmptyCell,0,|,140,EmptyCell,155,Sand,185,EmptyCell,0,|,141,EmptyCell,1,Sand,2,EmptyCell,148,Sand,188,EmptyCell,0,|,146,EmptyCell,1,Sand,2,EmptyCell,133,Sand,1,EmptyCell,1,Sand,2,EmptyCell,1,Sand,1,EmptyCell,1,Sand,191,EmptyCell,0,|,150,EmptyCell,1,Sand,1,EmptyCell,121,Sand,1,EmptyCell,1,Sand,2,EmptyCell,1,Sand,202,EmptyCell,0,|,160,EmptyCell,61,Sand,1,EmptyCell,3,Sand,1,EmptyCell,3,Sand,1,EmptyCell,3,Sand,2,EmptyCell,1,Sand,2,EmptyCell,1,Sand,3,EmptyCell,2,Sand,1,EmptyCell,1,Sand,4,EmptyCell,1,Sand,4,EmptyCell,3,Sand,2,EmptyCell,1,Sand,219,EmptyCell,0,|,162,EmptyCell,1,Sand,1,EmptyCell,1,Sand,1,EmptyCell,41,Sand,1,EmptyCell,3,Sand,1,EmptyCell,1,Sand,5,EmptyCell,1,Sand,261,EmptyCell,0,|,169,EmptyCell,3,Sand,1,EmptyCell,25,Sand,1,EmptyCell,1,Sand,1,EmptyCell,1,Sand,278,EmptyCell,0,|,176,EmptyCell,1,Sand,4,EmptyCell,3,Sand,1,EmptyCell,2,Sand,1,EmptyCell,2,Sand,3,EmptyCell,1,Sand,286,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,240,EmptyCell,5,PlayerMeat,235,EmptyCell,0,|,240,EmptyCell,5,PlayerMeat,235,EmptyCell,0,|,240,EmptyCell,5,PlayerMeat,235,EmptyCell,0,|,240,EmptyCell,5,PlayerMeat,235,EmptyCell,0,|,240,EmptyCell,5,PlayerMeat,235,EmptyCell,0,|,240,EmptyCell,5,PlayerMeat,235,EmptyCell,0,|,240,EmptyCell,5,PlayerMeat,235,EmptyCell,0,|,240,EmptyCell,5,PlayerMeat,235,EmptyCell,0,|,240,EmptyCell,5,PlayerMeat,235,EmptyCell,0,|,240,EmptyCell,5,PlayerMeat,235,EmptyCell,0,|,240,EmptyCell,5,PlayerMeat,235,EmptyCell,0,|,240,EmptyCell,5,PlayerMeat,235,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|,480,EmptyCell,0,|, -------------------------------------------------------------------------------- /core/assets/textures/light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidMcLaughlin208/FallingSandJava/6d1b95086b64443a5dea3b32377b2cc84efab024/core/assets/textures/light.png -------------------------------------------------------------------------------- /core/assets/uiskin.atlas: -------------------------------------------------------------------------------- 1 | 2 | uiskin.png 3 | size: 256,128 4 | format: RGBA8888 5 | filter: Linear,Linear 6 | repeat: none 7 | check-off 8 | rotate: false 9 | xy: 11, 5 10 | size: 14, 14 11 | orig: 14, 14 12 | offset: 0, 0 13 | index: -1 14 | textfield 15 | rotate: false 16 | xy: 11, 5 17 | size: 14, 14 18 | split: 3, 3, 3, 3 19 | orig: 14, 14 20 | offset: 0, 0 21 | index: -1 22 | check-on 23 | rotate: false 24 | xy: 125, 35 25 | size: 14, 14 26 | orig: 14, 14 27 | offset: 0, 0 28 | index: -1 29 | cursor 30 | rotate: false 31 | xy: 23, 1 32 | size: 3, 3 33 | split: 1, 1, 1, 1 34 | orig: 3, 3 35 | offset: 0, 0 36 | index: -1 37 | default 38 | rotate: false 39 | xy: 1, 50 40 | size: 254, 77 41 | orig: 254, 77 42 | offset: 0, 0 43 | index: -1 44 | default-pane 45 | rotate: false 46 | xy: 11, 1 47 | size: 5, 3 48 | split: 1, 1, 1, 1 49 | orig: 5, 3 50 | offset: 0, 0 51 | index: -1 52 | default-rect-pad 53 | rotate: false 54 | xy: 11, 1 55 | size: 5, 3 56 | split: 1, 1, 1, 1 57 | orig: 5, 3 58 | offset: 0, 0 59 | index: -1 60 | default-pane-noborder 61 | rotate: false 62 | xy: 170, 44 63 | size: 1, 1 64 | split: 0, 0, 0, 0 65 | orig: 1, 1 66 | offset: 0, 0 67 | index: -1 68 | default-rect 69 | rotate: false 70 | xy: 38, 25 71 | size: 3, 3 72 | split: 1, 1, 1, 1 73 | orig: 3, 3 74 | offset: 0, 0 75 | index: -1 76 | default-rect-down 77 | rotate: false 78 | xy: 170, 46 79 | size: 3, 3 80 | split: 1, 1, 1, 1 81 | orig: 3, 3 82 | offset: 0, 0 83 | index: -1 84 | default-round 85 | rotate: false 86 | xy: 112, 29 87 | size: 12, 20 88 | split: 5, 5, 5, 4 89 | pad: 4, 4, 1, 1 90 | orig: 12, 20 91 | offset: 0, 0 92 | index: -1 93 | default-round-down 94 | rotate: false 95 | xy: 99, 29 96 | size: 12, 20 97 | split: 5, 5, 5, 4 98 | pad: 4, 4, 1, 1 99 | orig: 12, 20 100 | offset: 0, 0 101 | index: -1 102 | default-round-large 103 | rotate: false 104 | xy: 57, 29 105 | size: 20, 20 106 | split: 5, 5, 5, 4 107 | orig: 20, 20 108 | offset: 0, 0 109 | index: -1 110 | default-scroll 111 | rotate: false 112 | xy: 78, 29 113 | size: 20, 20 114 | split: 2, 2, 2, 2 115 | orig: 20, 20 116 | offset: 0, 0 117 | index: -1 118 | default-select 119 | rotate: false 120 | xy: 29, 29 121 | size: 27, 20 122 | split: 4, 14, 4, 4 123 | orig: 27, 20 124 | offset: 0, 0 125 | index: -1 126 | default-select-selection 127 | rotate: false 128 | xy: 26, 16 129 | size: 3, 3 130 | split: 1, 1, 1, 1 131 | orig: 3, 3 132 | offset: 0, 0 133 | index: -1 134 | default-slider 135 | rotate: false 136 | xy: 29, 20 137 | size: 8, 8 138 | split: 2, 2, 2, 2 139 | orig: 8, 8 140 | offset: 0, 0 141 | index: -1 142 | default-slider-knob 143 | rotate: false 144 | xy: 1, 1 145 | size: 9, 18 146 | orig: 9, 18 147 | offset: 0, 0 148 | index: -1 149 | default-splitpane 150 | rotate: false 151 | xy: 17, 1 152 | size: 5, 3 153 | split: 0, 5, 0, 0 154 | orig: 5, 3 155 | offset: 0, 0 156 | index: -1 157 | default-splitpane-vertical 158 | rotate: false 159 | xy: 125, 29 160 | size: 3, 5 161 | split: 0, 0, 0, 5 162 | orig: 3, 5 163 | offset: 0, 0 164 | index: -1 165 | default-window 166 | rotate: false 167 | xy: 1, 20 168 | size: 27, 29 169 | split: 4, 3, 20, 3 170 | orig: 27, 29 171 | offset: 0, 0 172 | index: -1 173 | selection 174 | rotate: false 175 | xy: 174, 48 176 | size: 1, 1 177 | orig: 1, 1 178 | offset: 0, 0 179 | index: -1 180 | tree-minus 181 | rotate: false 182 | xy: 140, 35 183 | size: 14, 14 184 | orig: 14, 14 185 | offset: 0, 0 186 | index: -1 187 | tree-plus 188 | rotate: false 189 | xy: 155, 35 190 | size: 14, 14 191 | orig: 14, 14 192 | offset: 0, 0 193 | index: -1 194 | white 195 | rotate: false 196 | xy: 129, 31 197 | size: 3, 3 198 | orig: 3, 3 199 | offset: 0, 0 200 | index: -1 -------------------------------------------------------------------------------- /core/assets/uiskin.json: -------------------------------------------------------------------------------- 1 | { 2 | BitmapFont: { default-font: { file: default.fnt } }, 3 | Color: { 4 | green: { a: 1, b: 0, g: 1, r: 0 }, 5 | white: { a: 1, b: 1, g: 1, r: 1 }, 6 | red: { a: 1, b: 0, g: 0, r: 1 }, 7 | black: { a: 1, b: 0, g: 0, r: 0 }, 8 | }, 9 | TintedDrawable: { 10 | dialogDim: { name: white, color: { r: 0, g: 0, b: 0, a: 0.45 } }, 11 | }, 12 | ButtonStyle: { 13 | default: { down: default-round-down, up: default-round }, 14 | toggle: { parent: default, checked: default-round-down } 15 | }, 16 | TextButtonStyle: { 17 | default: { parent: default, font: default-font, fontColor: white }, 18 | toggle: { parent: default, checked: default-round-down, downFontColor: red } 19 | }, 20 | ScrollPaneStyle: { 21 | default: { vScroll: default-scroll, hScrollKnob: default-round-large, background: default-rect, hScroll: default-scroll, vScrollKnob: default-round-large } 22 | }, 23 | SelectBoxStyle: { 24 | default: { 25 | font: default-font, fontColor: white, background: default-select, 26 | scrollStyle: default, 27 | listStyle: { font: default-font, selection: default-select-selection } 28 | } 29 | }, 30 | SplitPaneStyle: { 31 | default-vertical: { handle: default-splitpane-vertical }, 32 | default-horizontal: { handle: default-splitpane } 33 | }, 34 | WindowStyle: { 35 | default: { titleFont: default-font, background: default-window, titleFontColor: white }, 36 | dialog: { parent: default, stageBackground: dialogDim } 37 | }, 38 | ProgressBarStyle: { 39 | default-horizontal: { background: default-slider, knob: default-slider-knob }, 40 | default-vertical: { background: default-slider, knob: default-round-large } 41 | }, 42 | SliderStyle: { 43 | default-horizontal: { parent: default-horizontal }, 44 | default-vertical: { parent: default-vertical } 45 | }, 46 | LabelStyle: { 47 | default: { font: default-font, fontColor: white } 48 | }, 49 | TextFieldStyle: { 50 | default: { selection: selection, background: textfield, font: default-font, fontColor: white, cursor: cursor } 51 | }, 52 | CheckBoxStyle: { 53 | default: { checkboxOn: check-on, checkboxOff: check-off, font: default-font, fontColor: white } 54 | }, 55 | ListStyle: { 56 | default: { fontColorUnselected: white, selection: selection, fontColorSelected: white, font: default-font } 57 | }, 58 | TouchpadStyle: { 59 | default: { background: default-pane, knob: default-round-large } 60 | }, 61 | TreeStyle: { 62 | default: { minus: tree-minus, plus: tree-plus, selection: default-select-selection } 63 | }, 64 | TextTooltipStyle: { 65 | default: { 66 | label: { font: default-font, fontColor: white }, 67 | background: default-pane, wrapWidth: 150 68 | } 69 | }, 70 | } -------------------------------------------------------------------------------- /core/assets/uiskin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidMcLaughlin208/FallingSandJava/6d1b95086b64443a5dea3b32377b2cc84efab024/core/assets/uiskin.png -------------------------------------------------------------------------------- /core/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "java" 2 | 3 | sourceCompatibility = 1.8 4 | [compileJava, compileTestJava]*.options*.encoding = 'UTF-8' 5 | 6 | sourceSets.main.java.srcDirs = [ "src/" ] 7 | 8 | 9 | eclipse.project { 10 | name = appName + "-core" 11 | } 12 | -------------------------------------------------------------------------------- /core/out/production/classes/META-INF/GDX.core.kotlin_module: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /core/src/CellularAutomaton.gwt.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/CellularAutomaton.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular; 2 | 3 | import com.badlogic.gdx.ApplicationAdapter; 4 | import com.badlogic.gdx.Gdx; 5 | import com.badlogic.gdx.graphics.*; 6 | import com.badlogic.gdx.graphics.glutils.ShapeRenderer; 7 | import com.badlogic.gdx.math.Vector2; 8 | import com.badlogic.gdx.math.Vector3; 9 | import com.badlogic.gdx.physics.box2d.*; 10 | import com.badlogic.gdx.scenes.scene2d.Stage; 11 | import com.badlogic.gdx.utils.Array; 12 | import com.badlogic.gdx.utils.viewport.FitViewport; 13 | import com.badlogic.gdx.utils.viewport.Viewport; 14 | import com.gdx.cellular.box2d.ShapeFactory; 15 | import com.gdx.cellular.elements.ElementType; 16 | import com.gdx.cellular.input.InputManager; 17 | import com.gdx.cellular.input.InputProcessors; 18 | import com.gdx.cellular.ui.MatrixActor; 19 | import com.gdx.cellular.util.ElementColumnStepper; 20 | import com.gdx.cellular.util.GameManager; 21 | 22 | import java.util.ArrayList; 23 | import java.util.BitSet; 24 | import java.util.List; 25 | 26 | 27 | public class CellularAutomaton extends ApplicationAdapter { 28 | public static int screenWidth = 1280; // 480; 29 | public static int screenHeight = 800; //800; 30 | public static int pixelSizeModifier = 6; 31 | public static int box2dSizeModifier = 10; 32 | public static Vector3 gravity = new Vector3(0f, -5f, 0f); 33 | public static BitSet stepped = new BitSet(1); 34 | 35 | private ShapeRenderer shapeRenderer; 36 | public CellularMatrix matrix; 37 | private OrthographicCamera camera; 38 | 39 | private int numThreads = 12; 40 | private boolean useMultiThreading = true; 41 | 42 | private InputManager inputManager; 43 | 44 | private FPSLogger fpsLogger; 45 | public static int frameCount = 0; 46 | public boolean useChunks = true; 47 | public World b2dWorld; 48 | public Box2DDebugRenderer debugRenderer; 49 | public InputProcessors inputProcessors; 50 | public Stage matrixStage; 51 | public GameManager gameManager; 52 | 53 | @Override 54 | public void create () { 55 | Gdx.gl.glEnable(GL20.GL_BLEND); 56 | fpsLogger = new FPSLogger(); 57 | 58 | camera = new OrthographicCamera(); 59 | camera.setToOrtho(false, screenWidth, screenHeight); 60 | camera.zoom = 1f; 61 | 62 | shapeRenderer = new ShapeRenderer(); 63 | shapeRenderer.setProjectionMatrix(camera.combined); 64 | shapeRenderer.setAutoShapeType(true); 65 | 66 | stepped.set(0, true); 67 | 68 | Viewport viewport = new FitViewport(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), camera); 69 | inputManager = new InputManager(camera, viewport, shapeRenderer); 70 | 71 | b2dWorld = new World(new Vector2(0, -100), true); 72 | 73 | matrix = new CellularMatrix(screenWidth, screenHeight, pixelSizeModifier, b2dWorld); 74 | matrix.generateShuffledIndexesForThreads(numThreads); 75 | 76 | matrixStage = new Stage(viewport); 77 | matrixStage.addActor(new MatrixActor(shapeRenderer, matrix)); 78 | 79 | ShapeFactory.initialize(b2dWorld); 80 | debugRenderer = new Box2DDebugRenderer(); 81 | 82 | setUpBasicBodies(); 83 | 84 | this.gameManager = new GameManager(this); 85 | gameManager.createPlayer(matrix.innerArraySize/2, matrix.outerArraySize/2); 86 | inputProcessors = new InputProcessors(inputManager, matrix, camera, gameManager); 87 | } 88 | 89 | @Override 90 | public void render () { 91 | Gdx.gl.glClearColor(0, 0, 0, 1); 92 | Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); 93 | 94 | fpsLogger.log(); 95 | stepped.flip(0); 96 | incrementFrameCount(); 97 | 98 | if (useChunks) { 99 | matrix.resetChunks(); 100 | } 101 | 102 | // Detect and act on input 103 | numThreads = inputManager.adjustThreadCount(numThreads); 104 | useMultiThreading = inputManager.toggleThreads(useMultiThreading); 105 | useChunks = inputManager.toggleChunks(useChunks); 106 | inputManager.save(matrix); 107 | inputManager.load(matrix); 108 | 109 | matrix.reshuffleXIndexes(); 110 | matrix.reshuffleThreadXIndexes(numThreads); 111 | matrix.calculateAndSetThreadedXIndexOffset(); 112 | 113 | boolean isPaused = inputManager.getIsPaused(); 114 | if (isPaused) { 115 | matrix.useChunks = false; 116 | useChunks = false; 117 | matrixStage.draw(); 118 | matrix.drawPhysicsElementActors(shapeRenderer); 119 | Array bodies = new Array<>(); 120 | b2dWorld.getBodies(bodies); 121 | matrix.drawBox2d(shapeRenderer, bodies); 122 | debugRenderer.render(b2dWorld, camera.combined); 123 | return; 124 | } 125 | 126 | matrix.spawnFromSpouts(); 127 | matrix.useChunks = useChunks; 128 | 129 | if (!useMultiThreading) { 130 | matrix.stepAndDrawAll(shapeRenderer); 131 | } else { 132 | matrix.reshuffleThreadXIndexes(numThreads); 133 | List threads = new ArrayList<>(numThreads); 134 | 135 | for (int t = 0; t < numThreads; t++) { 136 | Thread newThread = new Thread(new ElementColumnStepper(matrix, t)); 137 | threads.add(newThread); 138 | } 139 | if (stepped.get(0)) { 140 | startAndWaitOnOddThreads(threads); 141 | startAndWaitOnEvenThreads(threads); 142 | } else { 143 | startAndWaitOnEvenThreads(threads); 144 | startAndWaitOnOddThreads(threads); 145 | } 146 | // matrix.drawAll(shapeRenderer); 147 | 148 | } 149 | 150 | matrix.executeExplosions(); 151 | 152 | b2dWorld.step(1/120f, 10, 6); 153 | b2dWorld.step(1/120f, 10, 6); 154 | matrix.stepPhysicsElementActors(); 155 | 156 | matrixStage.draw(); 157 | matrix.drawPhysicsElementActors(shapeRenderer); 158 | 159 | Array bodies = new Array<>(); 160 | b2dWorld.getBodies(bodies); 161 | matrix.drawBox2d(shapeRenderer, bodies); 162 | debugRenderer.render(b2dWorld, camera.combined); 163 | 164 | inputManager.drawMenu(); 165 | inputManager.drawCursor(); 166 | 167 | inputManager.weatherSystem.enact(this.matrix); 168 | gameManager.stepPlayers(this.matrix); 169 | } 170 | 171 | @Override 172 | public void resize (int width, int height) { 173 | matrixStage.getViewport().update(width, height, true); 174 | inputManager.cursorStage.getViewport().update(width, height, true); 175 | inputManager.modeStage.getViewport().update(width, height, true); 176 | } 177 | 178 | private void incrementFrameCount() { 179 | frameCount = frameCount == 3 ? 0 : frameCount + 1; 180 | } 181 | 182 | private void setUpBasicBodies() { 183 | BodyDef groundBodyDef = new BodyDef(); 184 | 185 | inputManager.spawnPhysicsRect(matrix, new Vector3((camera.viewportWidth/2/box2dSizeModifier/8) * 10, 150, 0), 186 | new Vector3((camera.viewportWidth/2/box2dSizeModifier - camera.viewportWidth/2/box2dSizeModifier/8) * 20, 50, 0), 187 | ElementType.STONE, 188 | BodyDef.BodyType.StaticBody); 189 | } 190 | 191 | private void startAndWaitOnEvenThreads(List threads) { 192 | try { 193 | for (int t = 0; t < threads.size(); t++) { 194 | if (t % 2 == 0) { 195 | threads.get(t).start(); 196 | } 197 | } 198 | for (int t = 0; t < threads.size(); t++) { 199 | if (t % 2 == 0) { 200 | threads.get(t).join(); 201 | } 202 | } 203 | } catch (InterruptedException e) { 204 | e.printStackTrace(); 205 | } 206 | } 207 | 208 | private void startAndWaitOnOddThreads(List threads) { 209 | try { 210 | for (int t = 0; t < threads.size(); t++) { 211 | if (t % 2 != 0) { 212 | threads.get(t).start(); 213 | } 214 | } 215 | for (int t = 0; t < threads.size(); t++) { 216 | if (t % 2 == 0) { 217 | threads.get(t).join(); 218 | } 219 | } 220 | } catch (InterruptedException e) { 221 | e.printStackTrace(); 222 | } 223 | } 224 | 225 | @Override 226 | public void dispose () { 227 | shapeRenderer.dispose(); 228 | } 229 | 230 | } 231 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/boids/Boid.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.boids; 2 | 3 | import com.badlogic.gdx.math.Vector3; 4 | import com.badlogic.gdx.utils.Array; 5 | import com.gdx.cellular.CellularAutomaton; 6 | import com.gdx.cellular.CellularMatrix; 7 | import com.gdx.cellular.elements.Element; 8 | import com.gdx.cellular.elements.ElementType; 9 | import com.gdx.cellular.elements.EmptyCell; 10 | import com.gdx.cellular.elements.liquid.Liquid; 11 | import com.gdx.cellular.elements.solid.Solid; 12 | import com.gdx.cellular.util.Chunk; 13 | 14 | import java.util.HashMap; 15 | import java.util.List; 16 | import java.util.Map; 17 | 18 | public class Boid extends Element { 19 | 20 | private static final int SCAN_DISTANCE = 15; 21 | public static int neighborDistance = 15; 22 | public static int maxNeighbors = 25; 23 | private static final int noiseFactor = 7; 24 | private static final float coheseFactor = 8; 25 | private static final float alignmentFactor = 10f; 26 | private static final float avoidFactor = 5f; 27 | private static final String ALIGNMENT = "alignment"; 28 | private static final String COHESE = "cohese"; 29 | private static final String AVOID = "avoid"; 30 | private final Map vectorMap = new HashMap<>(); 31 | private Chunk chunk; 32 | 33 | public Boid(int x, int y, Vector3 velocity) { 34 | super(x, y); 35 | vel = velocity; 36 | vectorMap.put(ALIGNMENT, new Vector3(0, 0, 0)); 37 | vectorMap.put(COHESE, new Vector3(0, 0, 0)); 38 | vectorMap.put(AVOID, new Vector3(0, 0, 0)); 39 | } 40 | 41 | @Override 42 | public void step(CellularMatrix matrix) { 43 | if (stepped.get(0) == CellularAutomaton.stepped.get(0)) return; 44 | stepped.flip(0); 45 | 46 | // List neighbors = matrix.getBoidNeighbors(getMatrixX(), getMatrixY()); 47 | Array neighbors = matrix.getBoidNeighbors(getMatrixX(), getMatrixY()); 48 | 49 | calculateVelocities(neighbors); 50 | Vector3 alignmentForce = vectorMap.get(ALIGNMENT); 51 | Vector3 cohese = vectorMap.get(COHESE); 52 | Vector3 avoid = vectorMap.get(AVOID); 53 | float noiseX = 1 - (float) Math.random() * 2; 54 | float noiseY = 1 - (float) Math.random() * 2; 55 | Vector3 noise = new Vector3(noiseX * noiseFactor, noiseY * noiseFactor, 0); 56 | 57 | this.vel.add(alignmentForce.scl(1/alignmentFactor)); 58 | this.vel.add(cohese.scl(1/coheseFactor)); 59 | this.vel.add(avoid.scl(1/avoidFactor)); 60 | this.vel.add(noise); 61 | 62 | this.vel.limit(75); 63 | 64 | int yModifier = vel.y < 0 ? -1 : 1; 65 | int xModifier = vel.x < 0 ? -1 : 1; 66 | float velYDeltaTimeFloat = (Math.abs(vel.y) * 1/60); 67 | float velXDeltaTimeFloat = (Math.abs(vel.x) * 1/60); 68 | int velXDeltaTime; 69 | int velYDeltaTime; 70 | if (velXDeltaTimeFloat < 1) { 71 | xThreshold += velXDeltaTimeFloat; 72 | velXDeltaTime = (int) xThreshold; 73 | if (Math.abs(velXDeltaTime) > 0) { 74 | xThreshold = 0; 75 | } 76 | } else { 77 | xThreshold = 0; 78 | velXDeltaTime = (int) velXDeltaTimeFloat; 79 | } 80 | if (velYDeltaTimeFloat < 1) { 81 | yThreshold += velYDeltaTimeFloat; 82 | velYDeltaTime = (int) yThreshold; 83 | if (Math.abs(velYDeltaTime) > 0) { 84 | yThreshold = 0; 85 | } 86 | } else { 87 | yThreshold = 0; 88 | velYDeltaTime = (int) velYDeltaTimeFloat; 89 | } 90 | 91 | boolean xDiffIsLarger = Math.abs(velXDeltaTime) > Math.abs(velYDeltaTime); 92 | 93 | int upperBound = Math.max(Math.abs(velXDeltaTime), Math.abs(velYDeltaTime)); 94 | int min = Math.min(Math.abs(velXDeltaTime), Math.abs(velYDeltaTime)); 95 | float slope = (min == 0 || upperBound == 0) ? 0 : ((float) (min + 1) / (upperBound + 1)); 96 | 97 | int smallerCount; 98 | Vector3 formerLocation = new Vector3(getMatrixX(), getMatrixY(), 0); 99 | Vector3 lastValidLocation = new Vector3(getMatrixX(), getMatrixY(), 0); 100 | boolean onlyCheckingObstacles = false; 101 | int scanVariation = SCAN_DISTANCE + (int) (Math.random() * 10); 102 | for (int i = 1; i <= upperBound + scanVariation; i++) { 103 | if (i > upperBound) { 104 | onlyCheckingObstacles = true; 105 | } 106 | smallerCount = (int) Math.floor(i * slope); 107 | 108 | int yIncrease, xIncrease; 109 | if (xDiffIsLarger) { 110 | xIncrease = i; 111 | yIncrease = smallerCount; 112 | } else { 113 | yIncrease = i; 114 | xIncrease = smallerCount; 115 | } 116 | 117 | int modifiedMatrixY = getMatrixY() + (yIncrease * yModifier); 118 | int modifiedMatrixX = getMatrixX() + (xIncrease * xModifier); 119 | if (matrix.isWithinBounds(modifiedMatrixX, modifiedMatrixY)) { 120 | Element neighbor = matrix.get(modifiedMatrixX, modifiedMatrixY); 121 | if (onlyCheckingObstacles) { 122 | if (neighbor instanceof Solid || neighbor instanceof Liquid) { 123 | float distance = (int) Math.ceil(Math.sqrt(Math.pow(getMatrixX() - modifiedMatrixX, 2) + Math.pow(getMatrixY() - modifiedMatrixY, 2))); 124 | int modifier = Math.random() > 0.5f ? -1 : 1; 125 | // int modifier = getAvoidModifier(); 126 | Vector3 newVel = new Vector3(vel.y, vel.x, 0).scl((1/distance) * 15 * modifier); 127 | vel.add(newVel); 128 | } 129 | continue; 130 | } 131 | if (neighbor == this) continue; 132 | boolean stopped = actOnNeighboringElement(neighbor, modifiedMatrixX, modifiedMatrixY, matrix, i == upperBound, i == 1, lastValidLocation, 0); 133 | if (stopped) { 134 | break; 135 | } 136 | lastValidLocation.x = modifiedMatrixX; 137 | lastValidLocation.y = modifiedMatrixY; 138 | 139 | } else { 140 | if (onlyCheckingObstacles) { 141 | float distance = (int) Math.ceil(Math.sqrt(Math.pow(getMatrixX() - modifiedMatrixX, 2) + Math.pow(getMatrixY() - modifiedMatrixY, 2))); 142 | int modifier = Math.random() > 0.5f ? -1 : 1; 143 | // int modifier = getAvoidModifier(); 144 | Vector3 newVel = new Vector3(vel.y, vel.x, 0).scl((1/distance) * 15 * modifier); 145 | vel.add(newVel); 146 | break; 147 | } else { 148 | if (xDiffIsLarger) { 149 | vel.x *= -1; 150 | } else { 151 | vel.y *= -1; 152 | } 153 | break; 154 | } 155 | } 156 | this.chunk = matrix.addBoidToChunk(this, this.chunk); 157 | } 158 | } 159 | 160 | private int getAvoidModifier() { 161 | if (vel.y > 0 && vel.x > 0) { 162 | return -1; 163 | } else if (vel.y < 0 && vel.x > 0) { 164 | return 1; 165 | } else if (vel.y > 0 && vel.x < 0) { 166 | return 1; 167 | } else if (vel.y < 0 && vel.x < 0) { 168 | return -1; 169 | } 170 | return 1; 171 | } 172 | 173 | private void calculateVelocities(Array neighbors) { 174 | // Avoid variables 175 | Vector3 avoid = new Vector3(); 176 | Vector3 location = new Vector3(getMatrixX(), getMatrixY(), 0); 177 | 178 | // Cohese variables 179 | int totalX = 0; 180 | int totalY = 0; 181 | Vector3 cohese = new Vector3(0, 0, 0); 182 | 183 | // Alignment variables 184 | Vector3 alignment = new Vector3(0,0,0); 185 | 186 | for (Boid neighbor : neighbors) { 187 | // Avoid logic 188 | Vector3 otherLocationn = new Vector3(neighbor.getMatrixX(), neighbor.getMatrixY(), 0); 189 | float distance = location.dst(otherLocationn); 190 | 191 | Vector3 diff = location.cpy().sub(otherLocationn); 192 | diff.nor(); 193 | if (distance > 0) { 194 | diff.scl(1 / distance); 195 | avoid.add(diff); 196 | } 197 | 198 | // Cohese logic 199 | totalX += neighbor.getMatrixX(); 200 | totalY += neighbor.getMatrixY(); 201 | 202 | // Alignment logic 203 | alignment.add(neighbor.vel); 204 | } 205 | // Cohesion post processing 206 | if (neighbors.size > 0) { 207 | float avgX = totalX / (float) neighbors.size; 208 | float avgY = totalY / (float) neighbors.size; 209 | float desiredX = avgX - this.getMatrixX(); 210 | float desiredY = avgY - this.getMatrixY(); 211 | cohese = new Vector3(desiredX, desiredY, 0); 212 | } 213 | 214 | // Alignment post processing 215 | if (neighbors.size > 0) { 216 | alignment.scl(1f / (float) neighbors.size); 217 | } 218 | 219 | this.vectorMap.put(ALIGNMENT, alignment); 220 | this.vectorMap.put(COHESE, cohese); 221 | this.vectorMap.put(AVOID, avoid); 222 | } 223 | 224 | @Override 225 | protected boolean actOnNeighboringElement(Element neighbor, int modifiedMatrixX, int modifiedMatrixY, CellularMatrix matrix, boolean isFinal, boolean isFirst, Vector3 lastValidLocation, int depth) { 226 | if (neighbor instanceof EmptyCell || neighbor instanceof Boid) { 227 | if (isFinal) { 228 | swapPositions(matrix, neighbor, modifiedMatrixX, modifiedMatrixY); 229 | return false; 230 | } 231 | } else if (neighbor instanceof Solid || neighbor instanceof Liquid) { 232 | vel.scl(-1); 233 | return true; 234 | } 235 | return false; 236 | } 237 | 238 | @Override 239 | public void dieAndReplace(CellularMatrix matrix, ElementType type) { 240 | super.dieAndReplace(matrix, type); 241 | matrix.removeBoidFromChunk(this); 242 | } 243 | 244 | @Override 245 | public void die(CellularMatrix matrix) { 246 | super.die(matrix); 247 | matrix.removeBoidFromChunk(this); 248 | } 249 | } 250 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/box2d/douglaspeucker/EpsilonHelper.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.box2d.douglaspeucker; 2 | 3 | import java.util.List; 4 | 5 | public class EpsilonHelper { 6 | 7 | /** 8 | * For each 3 consecutive points in the list this function calculates the distance 9 | * from the middle point to a line defined by the first and third point. 10 | * 11 | * The result may be used to find a proper epsilon by calculating 12 | * maximum {@link #max(double[])} or average {@link #avg(double[])} from 13 | * all deviations. 14 | */ 15 | public static

double[] deviations(List

points) { 16 | double[] deviations = new double[Math.max(0, points.size() - 2)]; 17 | for (int i = 2; i < points.size(); i++) { 18 | P p1 = points.get(i-2); 19 | P p2 = points.get(i-1); 20 | P p3 = points.get(i); 21 | double dev = new Line

(p1, p3).distance(p2); 22 | deviations[i-2] = dev; 23 | } 24 | return deviations; 25 | } 26 | 27 | public static double sum(double[] values) { 28 | double sum = 0.0; 29 | for (int i = 0; i < values.length; i++) { 30 | sum += values[i]; 31 | } 32 | return sum; 33 | } 34 | 35 | 36 | public static double avg(double[] values) { 37 | if (values.length > 0) { 38 | return sum(values)/values.length; 39 | } else { 40 | return 0.0; 41 | } 42 | } 43 | 44 | public static double max(double[] values) { 45 | double max = 0.0; 46 | for (int i = 0; i < values.length; i++) { 47 | if (values[i] > max) { 48 | max = values[i]; 49 | } 50 | } 51 | return max; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/box2d/douglaspeucker/Line.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.box2d.douglaspeucker; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | public class Line

{ 7 | 8 | private P start; 9 | private P end; 10 | 11 | private double dx; 12 | private double dy; 13 | private double sxey; 14 | private double exsy; 15 | private double length; 16 | 17 | public Line(P start, P end) { 18 | this.start = start; 19 | this.end = end; 20 | dx = start.getX() - end.getX(); 21 | dy = start.getY() - end.getY(); 22 | sxey = start.getX() * end.getY(); 23 | exsy = end.getX() * start.getY(); 24 | length = Math.sqrt(dx*dx + dy*dy); 25 | } 26 | 27 | @SuppressWarnings("unchecked") 28 | public List

asList() { 29 | return Arrays.asList(start, end); 30 | } 31 | 32 | double distance(P p) { 33 | return Math.abs(dy * p.getX() - dx * p.getY() + sxey - exsy) / length; 34 | } 35 | } 36 | 37 | 38 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/box2d/douglaspeucker/Point.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.box2d.douglaspeucker; 2 | 3 | import com.badlogic.gdx.math.Vector2; 4 | 5 | /** 6 | * Represents a point on a plane. A point consists of 2 coordinates - x and y. 7 | */ 8 | public interface Point { 9 | 10 | double getX(); 11 | 12 | double getY(); 13 | 14 | Vector2 getPosition(); 15 | } 16 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/box2d/douglaspeucker/PointImpl.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.box2d.douglaspeucker; 2 | 3 | import com.badlogic.gdx.math.Vector2; 4 | 5 | public class PointImpl implements Point { 6 | 7 | private double x; 8 | 9 | private double y; 10 | 11 | private Vector2 position; 12 | 13 | public PointImpl(double x, double y) { 14 | this.x = x; 15 | this.y = y; 16 | this.position = new Vector2((float) x, (float) y); 17 | } 18 | 19 | public PointImpl(Vector2 position) { 20 | this.x = position.x; 21 | this.y = position.y; 22 | this.position = position; 23 | } 24 | 25 | public static Point p(double x, double y) { 26 | return new PointImpl(x, y); 27 | } 28 | 29 | public static Point p(Vector2 position) { 30 | return new PointImpl(position); 31 | } 32 | 33 | public double getX() { 34 | return x; 35 | } 36 | 37 | public void setX(double x) { 38 | this.x = x; 39 | } 40 | 41 | public double getY() { 42 | return y; 43 | } 44 | 45 | @Override 46 | public Vector2 getPosition() { 47 | return position; 48 | } 49 | 50 | public void setY(double y) { 51 | this.y = y; 52 | } 53 | 54 | @Override 55 | public int hashCode() { 56 | final int prime = 31; 57 | int result = 1; 58 | long temp; 59 | temp = Double.doubleToLongBits(x); 60 | result = prime * result + (int) (temp ^ (temp >>> 32)); 61 | temp = Double.doubleToLongBits(y); 62 | result = prime * result + (int) (temp ^ (temp >>> 32)); 63 | return result; 64 | } 65 | 66 | @Override 67 | public boolean equals(Object obj) { 68 | if (this == obj) 69 | return true; 70 | if (obj == null) 71 | return false; 72 | if (getClass() != obj.getClass()) 73 | return false; 74 | PointImpl other = (PointImpl) obj; 75 | if (Double.doubleToLongBits(x) != Double.doubleToLongBits(other.x)) 76 | return false; 77 | if (Double.doubleToLongBits(y) != Double.doubleToLongBits(other.y)) 78 | return false; 79 | return true; 80 | } 81 | 82 | @Override 83 | public String toString() { 84 | return "[" + x + ", " + y + "]"; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/box2d/douglaspeucker/SeriesReducer.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.box2d.douglaspeucker; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class SeriesReducer { 7 | 8 | /** 9 | * Reduces number of points in given series using Ramer-Douglas-Peucker algorithm. 10 | * 11 | * @param points 12 | * initial, ordered list of points (objects implementing the {@link Point} interface) 13 | * @param epsilon 14 | * allowed margin of the resulting curve, has to be > 0 15 | */ 16 | public static

List

reduce(List

points, double epsilon) { 17 | if (epsilon < 0) { 18 | throw new IllegalArgumentException("Epsilon cannot be less then 0."); 19 | } 20 | double furthestPointDistance = 0.0; 21 | int furthestPointIndex = 0; 22 | Line

line = new Line

(points.get(0), points.get(points.size() - 1)); 23 | for (int i = 1; i < points.size() - 1; i++) { 24 | double distance = line.distance(points.get(i)); 25 | if (distance > furthestPointDistance ) { 26 | furthestPointDistance = distance; 27 | furthestPointIndex = i; 28 | } 29 | } 30 | if (furthestPointDistance > epsilon) { 31 | List

reduced1 = reduce(points.subList(0, furthestPointIndex+1), epsilon); 32 | List

reduced2 = reduce(points.subList(furthestPointIndex, points.size()), epsilon); 33 | List

result = new ArrayList

(reduced1); 34 | result.addAll(reduced2.subList(1, reduced2.size())); 35 | return result; 36 | } else { 37 | return line.asList(); 38 | } 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/box2d/linesimplification/Visvalingam.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.box2d.linesimplification; 2 | 3 | import com.badlogic.gdx.math.Vector2; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | public class Visvalingam { 9 | 10 | private static final float DEFAULT_THRESHOLD = .4f; 11 | 12 | private Visvalingam() { throw new IllegalStateException("Should not instantiate Visvalingam"); } 13 | 14 | public static List simplify(List verts) { 15 | List simplifiedOnce = simplify(verts, DEFAULT_THRESHOLD); 16 | // return simplifiedOnce; 17 | // List simplifiedTwice = simplify(simplifiedOnce, DEFAULT_THRESHOLD); 18 | return simplify(simplifiedOnce, 1.8f); 19 | // return simplify(simplifiedTwice, DEFAULT_THRESHOLD); 20 | } 21 | 22 | public static List simplify(List verts, float threshold) { 23 | if (verts.size() <= 3) { 24 | return verts; 25 | } 26 | List simplifiedVerts = new ArrayList<>(); 27 | int skippedCount = 0; 28 | int vertsSize = verts.size(); 29 | calculateTriangleAreaAndAddPointToVerts(verts.get(vertsSize - 1), verts.get(0), verts.get(1), simplifiedVerts, threshold); 30 | for (int i = 0; i < verts.size() - 2; i++) { 31 | Vector2 point1 = verts.get(i); 32 | Vector2 point2 = verts.get(i + 1); 33 | Vector2 point3 = verts.get(i + 2); 34 | boolean added = calculateTriangleAreaAndAddPointToVerts(point1, point2, point3, simplifiedVerts, threshold); 35 | // if (added) { 36 | // skippedCount = 0; 37 | // } else { 38 | // if (skippedCount > 11) { 39 | // int index = simplifiedVerts.size(); 40 | // simplifiedVerts.add(index, verts.get(i - (2*(skippedCount / 3)))); 41 | // simplifiedVerts.add(index + 1, verts.get(i - (skippedCount / 3))); 42 | // skippedCount = 0; 43 | // 44 | // } else { 45 | // skippedCount++; 46 | // } 47 | // } 48 | 49 | } 50 | calculateTriangleAreaAndAddPointToVerts(verts.get(vertsSize - 2), verts.get(vertsSize - 1), verts.get(0), simplifiedVerts, threshold); 51 | return simplifiedVerts; 52 | 53 | } 54 | 55 | private static boolean calculateTriangleAreaAndAddPointToVerts(Vector2 point1, Vector2 point2, Vector2 point3, List simplifiedVerts, float threshold) { 56 | float area = Math.abs(((point1.x * (point2.y - point3.y)) + (point2.x * (point3.y - point1.y)) + (point3.x * (point1.y - point2.y))) / 2f); 57 | if (area > threshold) { 58 | simplifiedVerts.add(point2.cpy()); 59 | return true; 60 | } else { 61 | return false; 62 | } 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/box2d/marchingsquares/MooreNeighborTracing.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.box2d.marchingsquares; 2 | 3 | import com.badlogic.gdx.math.Vector2; 4 | import com.badlogic.gdx.utils.Array; 5 | import com.gdx.cellular.elements.Element; 6 | 7 | import java.util.ArrayList; 8 | import java.util.HashMap; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | public class MooreNeighborTracing { 13 | 14 | private MooreNeighborTracing() { throw new IllegalStateException("Cannot instantiate MooreNeighborTracing"); } 15 | 16 | private static final Map neighborRelativeLocationMap = new HashMap<>(); 17 | private static final Map directionIndexOffsetMap = new HashMap<>(); 18 | private static final Map newRelativeDirectionMap = new HashMap<>(); 19 | 20 | static { 21 | neighborRelativeLocationMap.put(1, new Vector2(0, -1)); 22 | neighborRelativeLocationMap.put(2, new Vector2(1, -1)); 23 | neighborRelativeLocationMap.put(3, new Vector2(1, 0)); 24 | neighborRelativeLocationMap.put(4, new Vector2(1, 1)); 25 | neighborRelativeLocationMap.put(5, new Vector2(0, 1)); 26 | neighborRelativeLocationMap.put(6, new Vector2(-1, 1)); 27 | neighborRelativeLocationMap.put(7, new Vector2(-1, 0)); 28 | neighborRelativeLocationMap.put(8, new Vector2(-1, -1)); 29 | 30 | directionIndexOffsetMap.put(IncomingDirection.North, 0); 31 | directionIndexOffsetMap.put(IncomingDirection.West, 2); 32 | directionIndexOffsetMap.put(IncomingDirection.South, 4); 33 | directionIndexOffsetMap.put(IncomingDirection.East, 6); 34 | 35 | newRelativeDirectionMap.put(1, IncomingDirection.East); 36 | newRelativeDirectionMap.put(2, IncomingDirection.East); 37 | newRelativeDirectionMap.put(3, IncomingDirection.North); 38 | newRelativeDirectionMap.put(4, IncomingDirection.North); 39 | newRelativeDirectionMap.put(5, IncomingDirection.West); 40 | newRelativeDirectionMap.put(6, IncomingDirection.West); 41 | newRelativeDirectionMap.put(7, IncomingDirection.South); 42 | newRelativeDirectionMap.put(8, IncomingDirection.South); 43 | 44 | } 45 | 46 | public static List getOutliningVerts(Array> elements) { 47 | List outliningVerts = new ArrayList<>(); 48 | Element startingPoint = null; 49 | Vector2 startingVector = null; 50 | // Brute force from the bottom left of the matrix to find starting element 51 | for (int y = elements.size - 1; y >= 0; y--) { 52 | if (startingVector != null) break; 53 | Array row = elements.get(y); 54 | for (int x = 0; x < row.size; x++) { 55 | Element element = row.get(x); 56 | if (element != null) { 57 | startingPoint = element; 58 | startingVector = new Vector2(x, y); 59 | outliningVerts.add(startingVector.cpy()); 60 | break; 61 | } 62 | } 63 | } 64 | if (startingPoint == null) { 65 | return outliningVerts; 66 | } 67 | // List elementList = new ArrayList<>(); 68 | Element currentElement; 69 | Vector2 currentLocation = startingVector.cpy(); 70 | IncomingDirection currentIncomingDirection = IncomingDirection.East; 71 | boolean endConditionMet = false; 72 | IncomingDirection incomingDirectionToFinalPoint = null; 73 | int neighborsVisited = 0; 74 | while (!endConditionMet) { 75 | if (neighborsVisited >= 10000) { 76 | System.out.println("Stuck in infinite loop"); 77 | return outliningVerts; 78 | } 79 | neighborsVisited++; 80 | for (int i = 1; i <= 8; i++) { 81 | Vector2 neighborLocation = getNeighboringElementLocationForIndexAndDirection(i, currentIncomingDirection, currentLocation, elements); 82 | Element neighbor = getNeighboringElement(neighborLocation, elements); 83 | if (neighbor == null) { 84 | if (i == 8) { 85 | // Element is an island 86 | endConditionMet = true; 87 | break; 88 | } 89 | continue; 90 | } 91 | currentElement = neighbor; 92 | currentLocation = neighborLocation.cpy(); 93 | currentIncomingDirection = getNewIncomingDirection(i, currentIncomingDirection); 94 | if (currentElement == startingPoint) { 95 | endConditionMet = true; 96 | break; 97 | } 98 | int indexOfCurrentLocation = outliningVerts.indexOf(currentLocation); 99 | if (indexOfCurrentLocation == -1) { 100 | outliningVerts.add(neighborLocation.cpy()); 101 | // elementList.add(currentElement); 102 | } else { 103 | outliningVerts.remove(indexOfCurrentLocation); 104 | } 105 | break; 106 | } 107 | } 108 | return outliningVerts; 109 | } 110 | 111 | private static IncomingDirection getNewIncomingDirection(int i, IncomingDirection currentIncomingDirection) { 112 | int offsetIndex = getOffsetIndex(i, currentIncomingDirection); 113 | return newRelativeDirectionMap.get(offsetIndex); 114 | } 115 | 116 | private static Vector2 getNeighboringElementLocationForIndexAndDirection(int i, IncomingDirection currentIncomingDirection, Vector2 currentLocation, Array> elements) { 117 | int offsetIndex = getOffsetIndex(i, currentIncomingDirection); 118 | return getNeighborLocation(offsetIndex, currentLocation); 119 | } 120 | 121 | private static Element getNeighboringElement(Vector2 neighborLocation, Array> elements) { 122 | if (neighborLocation.y >= elements.size || neighborLocation.y < 0 || neighborLocation.x >= elements.get((int) neighborLocation.y).size || neighborLocation.x < 0) { 123 | return null; 124 | } else { 125 | return elements.get((int) neighborLocation.y).get((int) neighborLocation.x); 126 | } 127 | } 128 | 129 | private static Vector2 getNeighborLocation(int offsetIndex, Vector2 currentLocation) { 130 | Vector2 offsetVector = neighborRelativeLocationMap.get(offsetIndex); 131 | return new Vector2(currentLocation.x + offsetVector.x, currentLocation.y + offsetVector.y); 132 | } 133 | 134 | private static int getOffsetIndex(int i, IncomingDirection currentIncomingDirection) { 135 | int newIndex = i + directionIndexOffsetMap.get(currentIncomingDirection); 136 | if (newIndex > 8) { 137 | return newIndex - 8; 138 | } else { 139 | return newIndex; 140 | } 141 | } 142 | 143 | private enum IncomingDirection { 144 | North, 145 | South, 146 | East, 147 | West 148 | } 149 | 150 | } 151 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/box2d/marchingsquares/Pavlidis.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.box2d.marchingsquares; 2 | 3 | import com.badlogic.gdx.math.Vector2; 4 | import com.badlogic.gdx.utils.Array; 5 | import com.gdx.cellular.elements.Element; 6 | 7 | import java.util.ArrayList; 8 | import java.util.HashMap; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | public class Pavlidis { 13 | 14 | private Pavlidis() { throw new IllegalStateException("Cannot instantiate Pavlidis"); } 15 | 16 | private static final Map> directionMap = new HashMap<>(); 17 | private static final Map rotateDirectionMap = new HashMap<>(); 18 | 19 | static { 20 | // This is used to determine the next relative direction when moving to a found element 21 | directionMap.put(Direction.North, new HashMap<>()); 22 | Map northMap = directionMap.get(Direction.North); 23 | northMap.put(DirectionalVector.UpLeft, Direction.West); 24 | northMap.put(DirectionalVector.Up, Direction.North); 25 | northMap.put(DirectionalVector.UpRight, Direction.East); 26 | 27 | directionMap.put(Direction.East, new HashMap<>()); 28 | Map eastMap = directionMap.get(Direction.East); 29 | eastMap.put(DirectionalVector.UpLeft, Direction.North); 30 | eastMap.put(DirectionalVector.Up, Direction.East); 31 | eastMap.put(DirectionalVector.UpRight, Direction.South); 32 | directionMap.put(Direction.South, new HashMap<>()); 33 | 34 | Map southMap = directionMap.get(Direction.South); 35 | southMap.put(DirectionalVector.UpLeft, Direction.East); 36 | southMap.put(DirectionalVector.Up, Direction.South); 37 | southMap.put(DirectionalVector.UpRight, Direction.West); 38 | 39 | directionMap.put(Direction.West, new HashMap<>()); 40 | Map westMap = directionMap.get(Direction.West); 41 | westMap.put(DirectionalVector.UpLeft, Direction.South); 42 | westMap.put(DirectionalVector.Up, Direction.West); 43 | westMap.put(DirectionalVector.UpRight, Direction.North); 44 | 45 | // This is used to rotate direction if no element is found at upLeft, up, or upRight 46 | rotateDirectionMap.put(Direction.North, Direction.East); 47 | rotateDirectionMap.put(Direction.East, Direction.South); 48 | rotateDirectionMap.put(Direction.South, Direction.West); 49 | rotateDirectionMap.put(Direction.West, Direction.North); 50 | } 51 | 52 | 53 | public static List getOutliningVerts(Array> elements) { 54 | List outliningVerts = new ArrayList<>(); 55 | Element startingPoint = null; 56 | Vector2 startingVector = null; 57 | // Brute force from the bottom left of the matrix to find starting element 58 | for (int y = elements.size - 1; y >= 0; y--) { 59 | if (startingVector != null) break; 60 | Array row = elements.get(y); 61 | for (int x = 0; x < row.size; x++) { 62 | Element element = row.get(x); 63 | if (element != null) { 64 | startingPoint = element; 65 | startingVector = new Vector2(x, y); 66 | outliningVerts.add(startingVector.cpy()); 67 | break; 68 | } 69 | } 70 | } 71 | if (startingPoint == null) { 72 | return outliningVerts; 73 | } 74 | Element currentElement = null; 75 | Vector2 currentLocation = startingVector.cpy(); 76 | Direction currentDirection = Direction.North; 77 | Vector2 upLeftVector, upVector, upRightVector; 78 | Element upLeft, up, upRight; 79 | while (currentElement != startingPoint) { 80 | upLeftVector = getDirectionalVector(currentLocation, currentDirection, DirectionalVector.UpLeft); 81 | upLeft = getFromArray(upLeftVector, elements); 82 | if (upLeft != null) { 83 | currentElement = upLeft; 84 | currentLocation.set(upLeftVector); 85 | outliningVerts.add(currentLocation.cpy()); 86 | currentDirection = getNewRelativeDirection(currentDirection, DirectionalVector.UpLeft); 87 | continue; 88 | } 89 | upVector = getDirectionalVector(currentLocation, currentDirection, DirectionalVector.Up); 90 | up = getFromArray(upVector, elements); 91 | if (up != null) { 92 | currentElement = up; 93 | currentLocation.set(upVector); 94 | outliningVerts.add(currentLocation.cpy()); 95 | currentDirection = getNewRelativeDirection(currentDirection, DirectionalVector.Up); 96 | continue; 97 | } 98 | upRightVector = getDirectionalVector(currentLocation, currentDirection, DirectionalVector.UpRight); 99 | upRight = getFromArray(upRightVector, elements); 100 | if (upRight != null) { 101 | currentElement = upRight; 102 | currentLocation.set(upRightVector); 103 | outliningVerts.add(currentLocation.cpy()); 104 | currentDirection = getNewRelativeDirection(currentDirection, DirectionalVector.UpRight); 105 | continue; 106 | } 107 | currentDirection = rotateDirectionMap.get(currentDirection); 108 | 109 | } 110 | outliningVerts.remove(outliningVerts.size() - 1); 111 | return outliningVerts; 112 | } 113 | 114 | private static Direction getNewRelativeDirection(Direction currentDirection, DirectionalVector directionalVector) { 115 | return directionMap.get(currentDirection).get(directionalVector); 116 | } 117 | 118 | private static Vector2 getDirectionalVector(Vector2 current, Direction direction, DirectionalVector directionalVector) { 119 | switch (direction) { 120 | case North: 121 | switch (directionalVector) { 122 | case UpLeft: 123 | return new Vector2(current.x - 1, current.y - 1); 124 | case Up: 125 | return new Vector2(current.x, current.y - 1); 126 | case UpRight: 127 | return new Vector2(current.x + 1, current.y - 1); 128 | } 129 | case East: 130 | switch (directionalVector) { 131 | case UpLeft: 132 | return new Vector2(current.x + 1, current.y - 1); 133 | case Up: 134 | return new Vector2(current.x + 1, current.y); 135 | case UpRight: 136 | return new Vector2(current.x + 1, current.y + 1); 137 | } 138 | case South: 139 | switch (directionalVector) { 140 | case UpLeft: 141 | return new Vector2(current.x + 1, current.y + 1); 142 | case Up: 143 | return new Vector2(current.x, current.y + 1); 144 | case UpRight: 145 | return new Vector2(current.x - 1, current.y + 1); 146 | } 147 | case West: 148 | switch (directionalVector) { 149 | case UpLeft: 150 | return new Vector2(current.x - 1, current.y + 1); 151 | case Up: 152 | return new Vector2(current.x - 1, current.y); 153 | case UpRight: 154 | return new Vector2(current.x - 1, current.y - 1); 155 | } 156 | default: 157 | throw new IllegalStateException("Impossible combination of Direction and DirectionalVector"); 158 | } 159 | } 160 | 161 | private static Element getFromArray(Vector2 cur, Array> elements) { 162 | if (cur.y >= elements.size || cur.y < 0 || cur.x >= elements.get((int) cur.y).size || cur.x < 0) { 163 | return null; 164 | } 165 | return elements.get((int) cur.y).get((int) cur.x); 166 | } 167 | 168 | private enum Direction { 169 | North, 170 | East, 171 | South, 172 | West 173 | } 174 | 175 | private enum DirectionalVector { 176 | UpLeft, 177 | Up, 178 | UpRight 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/effects/EffectColors.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.effects; 2 | 3 | 4 | import com.badlogic.gdx.graphics.Color; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | public class EffectColors { 10 | 11 | private static ListfireColors = new ArrayList<>(); 12 | 13 | static { 14 | fireColors.add(Color.RED); 15 | fireColors.add(Color.YELLOW); 16 | fireColors.add(Color.YELLOW); 17 | fireColors.add(Color.ORANGE); 18 | fireColors.add(Color.ORANGE); 19 | fireColors.add(Color.ORANGE); 20 | } 21 | 22 | public static Color getRandomFireColor() { 23 | return fireColors.get((int) Math.floor(Math.random() * fireColors.size())); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/elements/ElementType.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.elements; 2 | 3 | import com.badlogic.gdx.graphics.Color; 4 | import com.badlogic.gdx.math.Vector3; 5 | import com.gdx.cellular.CellularMatrix; 6 | import com.gdx.cellular.boids.Boid; 7 | import com.gdx.cellular.elements.gas.*; 8 | import com.gdx.cellular.elements.liquid.*; 9 | import com.gdx.cellular.elements.player.PlayerMeat; 10 | import com.gdx.cellular.elements.solid.immoveable.*; 11 | import com.gdx.cellular.elements.solid.movable.*; 12 | import com.gdx.cellular.particles.Particle; 13 | 14 | import java.util.*; 15 | import java.util.stream.Collectors; 16 | 17 | public enum ElementType { 18 | EMPTYCELL(EmptyCell.class, ClassType.EMPTYCELL) { 19 | @Override 20 | public Element createElementByMatrix(int x, int y) { 21 | return EmptyCell.getInstance(); 22 | } 23 | }, 24 | GROUND(Ground.class, ClassType.IMMOVABLESOLID) { 25 | @Override 26 | public Element createElementByMatrix(int x, int y) { 27 | return new Ground(x, y); 28 | } 29 | }, 30 | STONE(Stone.class, ClassType.IMMOVABLESOLID) { 31 | @Override 32 | public Element createElementByMatrix(int x, int y) { 33 | return new Stone(x, y); 34 | } 35 | }, 36 | BRICK(Brick.class, ClassType.IMMOVABLESOLID) { 37 | @Override 38 | public Element createElementByMatrix(int x, int y) { 39 | return new Brick(x, y); 40 | } 41 | }, 42 | SAND(Sand.class, ClassType.MOVABLESOLID) { 43 | @Override 44 | public Element createElementByMatrix(int x, int y) { 45 | return new Sand(x, y); 46 | } 47 | }, 48 | SNOW(Snow.class, ClassType.MOVABLESOLID) { 49 | @Override 50 | public Element createElementByMatrix(int x, int y) { 51 | return new Snow(x, y); 52 | } 53 | }, 54 | DIRT(Dirt.class, ClassType.MOVABLESOLID) { 55 | @Override 56 | public Element createElementByMatrix(int x, int y) { 57 | return new Dirt(x, y); 58 | } 59 | }, 60 | GUNPOWDER(Gunpowder.class, ClassType.MOVABLESOLID) { 61 | @Override 62 | public Element createElementByMatrix(int x, int y) { 63 | return new Gunpowder(x, y); 64 | } 65 | }, 66 | WATER(Water.class, ClassType.LIQUID) { 67 | @Override 68 | public Element createElementByMatrix(int x, int y) { 69 | return new Water(x, y); 70 | } 71 | }, 72 | CEMENT(Cement.class, ClassType.LIQUID) { 73 | @Override 74 | public Element createElementByMatrix(int x, int y) { 75 | return new Cement(x, y); 76 | } 77 | }, 78 | OIL(Oil.class, ClassType.LIQUID) { 79 | @Override 80 | public Element createElementByMatrix(int x, int y) { 81 | return new Oil(x, y); 82 | } 83 | }, 84 | ACID(Acid.class, ClassType.LIQUID) { 85 | @Override 86 | public Element createElementByMatrix(int x, int y) { 87 | return new Acid(x, y); 88 | } 89 | }, 90 | WOOD(Wood.class, ClassType.IMMOVABLESOLID) { 91 | @Override 92 | public Element createElementByMatrix(int x, int y) { 93 | return new Wood(x, y); 94 | } 95 | }, 96 | TITANIUM(Titanium.class, ClassType.IMMOVABLESOLID) { 97 | @Override 98 | public Element createElementByMatrix(int x, int y) { 99 | return new Titanium(x, y); 100 | } 101 | }, 102 | SPARK(Spark.class, ClassType.GAS) { 103 | @Override 104 | public Element createElementByMatrix(int x, int y) { 105 | return new Spark(x, y); 106 | } 107 | }, 108 | EXPLOSIONSPARK(ExplosionSpark.class, ClassType.GAS) { 109 | @Override 110 | public Element createElementByMatrix(int x, int y) { 111 | return new ExplosionSpark(x, y); 112 | } 113 | }, 114 | EMBER(Ember.class, ClassType.MOVABLESOLID) { 115 | @Override 116 | public Element createElementByMatrix(int x, int y) { 117 | return new Ember(x, y); 118 | } 119 | }, 120 | LAVA(Lava.class, ClassType.LIQUID) { 121 | @Override 122 | public Element createElementByMatrix(int x, int y) { 123 | return new Lava(x, y); 124 | } 125 | }, 126 | COAL(Coal.class, ClassType.MOVABLESOLID) { 127 | @Override 128 | public Element createElementByMatrix(int x, int y) { 129 | return new Coal(x, y); 130 | } 131 | }, 132 | SMOKE(Smoke.class, ClassType.GAS) { 133 | @Override 134 | public Element createElementByMatrix(int x, int y) { 135 | return new Smoke(x, y); 136 | } 137 | }, 138 | FLAMMABLEGAS(FlammableGas.class, ClassType.GAS) { 139 | @Override 140 | public Element createElementByMatrix(int x, int y) { 141 | return new FlammableGas(x, y); 142 | } 143 | }, 144 | BLOOD(Blood.class, ClassType.LIQUID) { 145 | @Override 146 | public Element createElementByMatrix(int x, int y) { 147 | return new Blood(x, y); 148 | } 149 | }, 150 | SLIMEMOLD(SlimeMold.class, ClassType.IMMOVABLESOLID) { 151 | @Override 152 | public Element createElementByMatrix(int x, int y) { 153 | return new SlimeMold(x, y); 154 | } 155 | }, 156 | STEAM(Steam.class, ClassType.GAS) { 157 | @Override 158 | public Element createElementByMatrix(int x, int y) { 159 | return new Steam(x, y); 160 | } 161 | }, 162 | PLAYERMEAT(PlayerMeat.class, ClassType.PLAYER) { 163 | @Override 164 | public Element createElementByMatrix(int x, int y) { 165 | return new PlayerMeat(x, y); 166 | } 167 | }, 168 | PARTICLE(Particle.class, ClassType.PARTICLE) { 169 | @Override 170 | public Element createElementByMatrix(int x, int y) { 171 | throw new IllegalStateException(); 172 | } 173 | }, 174 | BOID(Boid.class, ClassType.PARTICLE) { 175 | @Override 176 | public Element createElementByMatrix(int x, int y) { 177 | throw new IllegalStateException(); 178 | } 179 | }; 180 | 181 | public final Class clazz; 182 | public final ClassType classType; 183 | public static List IMMOVABLE_SOLIDS; 184 | public static List MOVABLE_SOLIDS; 185 | public static List SOLIDS; 186 | public static List LIQUIDS; 187 | public static List GASSES; 188 | 189 | ElementType(Class clazz, ClassType classType) { 190 | this.clazz = clazz; 191 | this.classType = classType; 192 | } 193 | 194 | public abstract Element createElementByMatrix(int x, int y); 195 | 196 | public static Element createParticleByMatrix(CellularMatrix matrix, int x, int y, Vector3 vector3, ElementType elementType, Color color, boolean isIgnited) { 197 | if (matrix.isWithinBounds(x, y)) { 198 | Element newElement = new Particle(x, y, vector3, elementType, color, isIgnited); 199 | matrix.setElementAtIndex(x, y, newElement); 200 | return newElement; 201 | } 202 | return null; 203 | } 204 | 205 | public static Boid createBoidByMatrix(CellularMatrix matrix, int x, int y, Vector3 velocity) { 206 | if (matrix.isWithinBounds(x, y)) { 207 | Boid boid = new Boid(x, y, velocity); 208 | matrix.addBoid(boid); 209 | matrix.setElementAtIndex(x, y, boid); 210 | return boid; 211 | } 212 | return null; 213 | } 214 | 215 | public static List getMovableSolids() { 216 | if (MOVABLE_SOLIDS == null) { 217 | MOVABLE_SOLIDS = initializeList(ClassType.MOVABLESOLID); 218 | MOVABLE_SOLIDS.sort(Comparator.comparing(Enum::toString)); 219 | } 220 | return Collections.unmodifiableList(MOVABLE_SOLIDS); 221 | } 222 | 223 | public static List getImmovableSolids() { 224 | if (IMMOVABLE_SOLIDS == null) { 225 | IMMOVABLE_SOLIDS = initializeList(ClassType.IMMOVABLESOLID); 226 | IMMOVABLE_SOLIDS.sort(Comparator.comparing(Enum::toString)); 227 | } 228 | return Collections.unmodifiableList(IMMOVABLE_SOLIDS); 229 | } 230 | 231 | public static List getSolids() { 232 | if (SOLIDS == null) { 233 | List immovables = new ArrayList<>(getImmovableSolids()); 234 | immovables.addAll(getMovableSolids()); 235 | SOLIDS = immovables; 236 | immovables.sort(Comparator.comparing(Enum::toString)); 237 | } 238 | return Collections.unmodifiableList(SOLIDS); 239 | } 240 | 241 | public static List getLiquids() { 242 | if (LIQUIDS == null) { 243 | LIQUIDS = initializeList(ClassType.LIQUID); 244 | LIQUIDS.sort(Comparator.comparing(Enum::toString)); 245 | } 246 | return Collections.unmodifiableList(LIQUIDS); 247 | } 248 | 249 | public static List getGasses() { 250 | if (GASSES == null) { 251 | GASSES = initializeList(ClassType.GAS); 252 | GASSES.sort(Comparator.comparing(Enum::toString)); 253 | } 254 | return Collections.unmodifiableList(GASSES); 255 | } 256 | 257 | private static List initializeList(ClassType classType) { 258 | return Arrays.stream(ElementType.values()).filter(elementType -> elementType.classType.equals(classType)).collect(Collectors.toList()); 259 | } 260 | 261 | 262 | public static Element createParticleByMatrix(CellularMatrix matrix, int x, int y, Vector3 vector3, Element sourceElement) { 263 | if (matrix.isWithinBounds(x, y)) { 264 | Element newElement = new Particle(x, y, vector3, sourceElement); 265 | matrix.setElementAtIndex(x, y, newElement); 266 | return newElement; 267 | } 268 | return null; 269 | } 270 | 271 | public enum ClassType { 272 | MOVABLESOLID, 273 | IMMOVABLESOLID, 274 | LIQUID, 275 | GAS, 276 | PARTICLE, 277 | EMPTYCELL, 278 | PLAYER; 279 | 280 | } 281 | } 282 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/elements/EmptyCell.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.elements; 2 | 3 | import com.badlogic.gdx.graphics.Color; 4 | import com.badlogic.gdx.math.Vector2; 5 | import com.badlogic.gdx.math.Vector3; 6 | import com.gdx.cellular.CellularMatrix; 7 | 8 | public class EmptyCell extends Element { 9 | private static Element element; 10 | 11 | private EmptyCell(int x, int y) { 12 | super(x, y); 13 | } 14 | 15 | public static Element getInstance() { 16 | if (element == null) { 17 | element = new EmptyCell(-1, -1); 18 | } 19 | return element; 20 | } 21 | 22 | @Override 23 | public void step(CellularMatrix matrix) { 24 | 25 | } 26 | 27 | @Override 28 | protected boolean actOnNeighboringElement(Element neighbor, int modifiedMatrixX, int modifiedMatrixY, CellularMatrix matrix, boolean isFinal, boolean isFirst, Vector3 lastValidLocation, int depth) { 29 | return true; 30 | } 31 | 32 | @Override 33 | public boolean corrode(CellularMatrix matrix) { 34 | return false; 35 | } 36 | 37 | @Override 38 | public boolean receiveHeat(CellularMatrix matrix, int heat) { 39 | return false; 40 | } 41 | 42 | @Override 43 | public void setCoordinatesByMatrix(Vector2 pos) { } 44 | 45 | @Override 46 | public void setCoordinatesByMatrix(int providedX, int providedY) { } 47 | 48 | @Override 49 | public void setSecondaryCoordinatesByMatrix(int providedX, int providedY) { } 50 | 51 | @Override 52 | public void setXByMatrix(int providedVal) { } 53 | 54 | @Override 55 | public void setYByMatrix(int providedVal) { } 56 | 57 | @Override 58 | public boolean infect(CellularMatrix matrix) { 59 | return false; 60 | } 61 | 62 | @Override 63 | public void darkenColor() { } 64 | 65 | @Override 66 | public void darkenColor(float factor) { } 67 | 68 | @Override 69 | public boolean stain(float r, float g, float b, float a) { 70 | return false; 71 | } 72 | 73 | @Override 74 | public boolean stain(Color color) { 75 | return false; 76 | } 77 | 78 | 79 | } 80 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/elements/gas/ExplosionSpark.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.elements.gas; 2 | 3 | import com.badlogic.gdx.math.Vector3; 4 | import com.gdx.cellular.CellularMatrix; 5 | import com.gdx.cellular.effects.EffectColors; 6 | import com.gdx.cellular.elements.Element; 7 | import com.gdx.cellular.elements.EmptyCell; 8 | import com.gdx.cellular.elements.liquid.Liquid; 9 | import com.gdx.cellular.elements.solid.Solid; 10 | 11 | public class ExplosionSpark extends Gas { 12 | 13 | public ExplosionSpark(int x, int y) { 14 | super(x, y); 15 | vel = new Vector3(0,64f,0); 16 | inertialResistance = 0; 17 | mass = 10; 18 | frictionFactor = 1f; 19 | density = 4; 20 | dispersionRate = 4; 21 | flammabilityResistance = 25; 22 | isIgnited = true; 23 | lifeSpan = getRandomInt(20); 24 | temperature = 3; 25 | } 26 | 27 | @Override 28 | public void step(CellularMatrix matrix) { 29 | super.step(matrix); 30 | this.color = EffectColors.getRandomFireColor(); 31 | } 32 | 33 | @Override 34 | protected boolean actOnNeighboringElement(Element neighbor, int modifiedMatrixX, int modifiedMatrixY, CellularMatrix matrix, boolean isFinal, boolean isFirst, Vector3 lastValidLocation, int depth) { 35 | boolean acted = actOnOther(neighbor, matrix); 36 | if (acted) return true; 37 | if (neighbor instanceof EmptyCell) { 38 | if (isFinal) { 39 | swapPositions(matrix, neighbor, modifiedMatrixX, modifiedMatrixY); 40 | } else { 41 | return false; 42 | } 43 | } else if (neighbor instanceof Spark) { 44 | return false; 45 | } else if (neighbor instanceof Smoke) { 46 | neighbor.die(matrix); 47 | return false; 48 | } else if (neighbor instanceof Liquid || neighbor instanceof Solid || neighbor instanceof Gas) { 49 | neighbor.receiveHeat(matrix, heatFactor); 50 | die(matrix); 51 | return true; 52 | } 53 | return false; 54 | } 55 | 56 | @Override 57 | public boolean receiveHeat(CellularMatrix matrix, int heat) { 58 | return false; 59 | } 60 | 61 | @Override 62 | public void modifyColor() { } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/elements/gas/FlammableGas.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.elements.gas; 2 | 3 | 4 | import com.badlogic.gdx.math.Vector3; 5 | 6 | public class FlammableGas extends Gas { 7 | 8 | public FlammableGas(int x, int y) { 9 | super(x, y); 10 | health = 100; 11 | vel = new Vector3(0,124f,0); 12 | inertialResistance = 0; 13 | mass = 1; 14 | frictionFactor = 1f; 15 | density = 1; 16 | dispersionRate = 2; 17 | lifeSpan = getRandomInt(500) + 3000; 18 | flammabilityResistance = 10; 19 | resetFlammabilityResistance = 10; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/elements/gas/Smoke.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.elements.gas; 2 | 3 | import com.badlogic.gdx.math.Vector3; 4 | import com.gdx.cellular.CellularMatrix; 5 | 6 | public class Smoke extends Gas{ 7 | 8 | public Smoke(int x, int y) { 9 | super(x, y); 10 | vel = new Vector3(0,124f,0); 11 | inertialResistance = 0; 12 | mass = 1; 13 | frictionFactor = 1f; 14 | density = 3; 15 | dispersionRate = 2; 16 | lifeSpan = getRandomInt(250) + 450; 17 | } 18 | 19 | @Override 20 | public boolean receiveHeat(CellularMatrix matrix, int heat) { 21 | return false; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/elements/gas/Spark.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.elements.gas; 2 | 3 | import com.badlogic.gdx.math.Vector3; 4 | import com.gdx.cellular.CellularMatrix; 5 | import com.gdx.cellular.elements.Element; 6 | import com.gdx.cellular.elements.EmptyCell; 7 | import com.gdx.cellular.elements.solid.Solid; 8 | import com.gdx.cellular.elements.liquid.Liquid; 9 | 10 | public class Spark extends Gas { 11 | 12 | public Spark(int x, int y) { 13 | super(x, y); 14 | vel = new Vector3(0,124f,0); 15 | inertialResistance = 0; 16 | mass = 10; 17 | frictionFactor = 1f; 18 | density = 4; 19 | dispersionRate = 4; 20 | flammabilityResistance = 25; 21 | isIgnited = true; 22 | lifeSpan = getRandomInt(20); 23 | temperature = 3; 24 | } 25 | 26 | @Override 27 | protected boolean actOnNeighboringElement(Element neighbor, int modifiedMatrixX, int modifiedMatrixY, CellularMatrix matrix, boolean isFinal, boolean isFirst, Vector3 lastValidLocation, int depth) { 28 | boolean acted = actOnOther(neighbor, matrix); 29 | if (acted) return true; 30 | if (neighbor instanceof EmptyCell) { 31 | if (isFinal) { 32 | swapPositions(matrix, neighbor, modifiedMatrixX, modifiedMatrixY); 33 | } else { 34 | return false; 35 | } 36 | } else if (neighbor instanceof Spark) { 37 | return false; 38 | } else if (neighbor instanceof Smoke) { 39 | neighbor.die(matrix); 40 | return false; 41 | } else if (neighbor instanceof Liquid || neighbor instanceof Solid || neighbor instanceof Gas) { 42 | neighbor.receiveHeat(matrix, heatFactor); 43 | die(matrix); 44 | return true; 45 | } 46 | return false; 47 | } 48 | 49 | @Override 50 | public boolean receiveHeat(CellularMatrix matrix, int heat) { 51 | return false; 52 | } 53 | 54 | 55 | } 56 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/elements/gas/Steam.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.elements.gas; 2 | 3 | import com.badlogic.gdx.math.Vector3; 4 | import com.gdx.cellular.CellularMatrix; 5 | import com.gdx.cellular.elements.ElementType; 6 | 7 | public class Steam extends Gas { 8 | 9 | public Steam(int x, int y) { 10 | super(x, y); 11 | vel = new Vector3(0,124f,0); 12 | inertialResistance = 0; 13 | mass = 1; 14 | frictionFactor = 1f; 15 | density = 5; 16 | dispersionRate = 2; 17 | lifeSpan = getRandomInt(2000) + 1000; 18 | } 19 | 20 | @Override 21 | public void checkLifeSpan(CellularMatrix matrix) { 22 | if (lifeSpan != null) { 23 | lifeSpan--; 24 | if (lifeSpan <= 0) { 25 | if (Math.random() > 0.5) { 26 | die(matrix); 27 | } else { 28 | dieAndReplace(matrix, ElementType.WATER); 29 | } 30 | } 31 | } 32 | } 33 | 34 | @Override 35 | public boolean receiveHeat(CellularMatrix matrix, int heat) { 36 | return false; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/elements/liquid/Acid.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.elements.liquid; 2 | 3 | import com.badlogic.gdx.math.Vector3; 4 | import com.gdx.cellular.CellularMatrix; 5 | import com.gdx.cellular.elements.Element; 6 | import com.gdx.cellular.elements.ElementType; 7 | 8 | public class Acid extends Liquid { 9 | 10 | public int corrosionCount = 3; 11 | public Acid(int x, int y) { 12 | super(x, y); 13 | vel = new Vector3(0,-124f,0); 14 | inertialResistance = 0; 15 | mass = 50; 16 | frictionFactor = 1f; 17 | density = 2; 18 | dispersionRate = 2; 19 | } 20 | 21 | @Override 22 | public boolean actOnOther(Element other, CellularMatrix matrix) { 23 | other.stain(-1, 1, -1, 0); 24 | if (!isReactionFrame() || other == null) return false; 25 | boolean corroded = other.corrode(matrix); 26 | if (corroded) corrosionCount -= 1; 27 | if (corrosionCount <= 0) { 28 | dieAndReplace(matrix, ElementType.FLAMMABLEGAS); 29 | return true; 30 | } 31 | return false; 32 | } 33 | 34 | @Override 35 | public boolean corrode(CellularMatrix matrix) { 36 | return false; 37 | } 38 | 39 | @Override 40 | public boolean receiveHeat(CellularMatrix matrix, int heat) { 41 | return false; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/elements/liquid/Blood.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.elements.liquid; 2 | 3 | import com.badlogic.gdx.graphics.Color; 4 | import com.badlogic.gdx.math.Vector3; 5 | import com.gdx.cellular.CellularMatrix; 6 | import com.gdx.cellular.elements.Element; 7 | 8 | public class Blood extends Liquid { 9 | 10 | public Blood(int x, int y) { 11 | super(x, y); 12 | vel = new Vector3(0,-124f,0); 13 | inertialResistance = 0; 14 | mass = 100; 15 | frictionFactor = 1f; 16 | density = 6; 17 | dispersionRate = 5; 18 | coolingFactor = 5; 19 | } 20 | 21 | @Override 22 | public boolean receiveHeat(CellularMatrix matrix, int heat) { 23 | return false; 24 | } 25 | 26 | @Override 27 | public boolean actOnOther(Element other, CellularMatrix matrix) { 28 | other.stain(new Color(0.5f, 0, 0, 1)); 29 | if (other.shouldApplyHeat()) { 30 | other.receiveCooling(matrix, coolingFactor); 31 | coolingFactor--; 32 | if (coolingFactor <= 0) { 33 | die(matrix); 34 | return true; 35 | } 36 | return false; 37 | } 38 | return false; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/elements/liquid/Cement.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.elements.liquid; 2 | 3 | import com.badlogic.gdx.math.Vector3; 4 | import com.gdx.cellular.CellularMatrix; 5 | import com.gdx.cellular.elements.Element; 6 | import com.gdx.cellular.elements.ElementType; 7 | 8 | public class Cement extends Liquid { 9 | 10 | public Cement(int x, int y) { 11 | super(x, y); 12 | vel = new Vector3(0,-124f,0); 13 | inertialResistance = 0; 14 | mass = 100; 15 | frictionFactor = 1f; 16 | density = 9; 17 | dispersionRate = 1; 18 | coolingFactor = 5; 19 | stoppedMovingThreshold = 900; 20 | } 21 | 22 | @Override 23 | public void step(CellularMatrix matrix) { 24 | super.step(matrix); 25 | if (stoppedMovingCount >= stoppedMovingThreshold) { 26 | dieAndReplace(matrix, ElementType.STONE); 27 | } 28 | } 29 | 30 | @Override 31 | public boolean receiveHeat(CellularMatrix matrix, int heat) { 32 | return false; 33 | } 34 | 35 | @Override 36 | public boolean actOnOther(Element other, CellularMatrix matrix) { 37 | return false; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/elements/liquid/Lava.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.elements.liquid; 2 | 3 | import com.badlogic.gdx.math.Vector3; 4 | import com.gdx.cellular.CellularMatrix; 5 | import com.gdx.cellular.elements.Element; 6 | import com.gdx.cellular.elements.ElementType; 7 | 8 | public class Lava extends Liquid { 9 | 10 | int magmatizeDamage; 11 | 12 | public Lava(int x, int y) { 13 | super(x, y); 14 | vel = new Vector3(0,-124f,0); 15 | inertialResistance = 0; 16 | mass = 100; 17 | frictionFactor = 1f; 18 | density = 10; 19 | dispersionRate = 1; 20 | temperature = 10; 21 | heated = true; 22 | magmatizeDamage = (int) (Math.random() * 10); 23 | } 24 | 25 | @Override 26 | public boolean receiveHeat(CellularMatrix matrix, int heat) { 27 | return false; 28 | } 29 | 30 | @Override 31 | public void checkIfDead(CellularMatrix matrix) { 32 | if (this.temperature <= 0) { 33 | dieAndReplace(matrix, ElementType.STONE); 34 | for (int x = -1; x <= 1; x++) { 35 | for (int y = -1; y <= 1; y++) { 36 | if (x == 0 && y == 0) continue; 37 | Element element = matrix.get(this.getMatrixX() + x, this.getMatrixY() + y); 38 | if (element instanceof Liquid) { 39 | element.dieAndReplace(matrix, ElementType.STONE); 40 | } 41 | } 42 | } 43 | } 44 | if (this.health <= 0) { 45 | die(matrix); 46 | } 47 | } 48 | 49 | @Override 50 | public boolean actOnOther(Element other, CellularMatrix matrix) { 51 | other.magmatize(matrix, this.magmatizeDamage); 52 | return false; 53 | } 54 | 55 | @Override 56 | public void magmatize(CellularMatrix matrix, int damage) { } 57 | 58 | @Override 59 | public boolean receiveCooling(CellularMatrix matrix, int cooling) { 60 | this.temperature -= cooling; 61 | checkIfDead(matrix); 62 | return true; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/elements/liquid/Oil.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.elements.liquid; 2 | 3 | import com.badlogic.gdx.graphics.Color; 4 | import com.badlogic.gdx.math.Vector3; 5 | 6 | public class Oil extends Liquid { 7 | 8 | public Oil(int x, int y) { 9 | super(x, y); 10 | vel = new Vector3(0,-124f,0); 11 | inertialResistance = 0; 12 | mass = 75; 13 | frictionFactor = 1f; 14 | density = 4; 15 | dispersionRate = 4; 16 | flammabilityResistance = 5; 17 | resetFlammabilityResistance = 2; 18 | fireDamage = 10; 19 | temperature = 10; 20 | health = 1000; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/elements/liquid/Water.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.elements.liquid; 2 | 3 | import com.badlogic.gdx.math.Vector3; 4 | import com.gdx.cellular.CellularMatrix; 5 | import com.gdx.cellular.elements.Element; 6 | import com.gdx.cellular.elements.ElementType; 7 | 8 | public class Water extends Liquid { 9 | 10 | public Water(int x, int y) { 11 | super(x, y); 12 | vel = new Vector3(0,-124f,0); 13 | inertialResistance = 0; 14 | mass = 100; 15 | frictionFactor = 1f; 16 | density = 5; 17 | dispersionRate = 5; 18 | coolingFactor = 5; 19 | explosionResistance = 0; 20 | } 21 | 22 | @Override 23 | public boolean receiveHeat(CellularMatrix matrix, int heat) { 24 | dieAndReplace(matrix, ElementType.STEAM); 25 | return true; 26 | } 27 | 28 | @Override 29 | public boolean actOnOther(Element other, CellularMatrix matrix) { 30 | other.cleanColor(); 31 | if (other.shouldApplyHeat()) { 32 | other.receiveCooling(matrix, coolingFactor); 33 | coolingFactor--; 34 | if (coolingFactor <= 0) { 35 | dieAndReplace(matrix, ElementType.STEAM); 36 | return true; 37 | } 38 | return false; 39 | } 40 | return false; 41 | } 42 | 43 | @Override 44 | public boolean explode(CellularMatrix matrix, int strength) { 45 | if (explosionResistance < strength) { 46 | dieAndReplace(matrix, ElementType.STEAM); 47 | return true; 48 | } else { 49 | return false; 50 | } 51 | } 52 | 53 | 54 | } 55 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/elements/player/PlayerMeat.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.elements.player; 2 | 3 | import com.badlogic.gdx.math.Vector3; 4 | import com.gdx.cellular.CellularMatrix; 5 | import com.gdx.cellular.elements.Element; 6 | import com.gdx.cellular.elements.ElementType; 7 | import com.gdx.cellular.elements.EmptyCell; 8 | import com.gdx.cellular.elements.gas.Gas; 9 | import com.gdx.cellular.elements.liquid.Liquid; 10 | import com.gdx.cellular.elements.solid.immoveable.ImmovableSolid; 11 | import com.gdx.cellular.elements.solid.movable.MovableSolid; 12 | import com.gdx.cellular.particles.Particle; 13 | import com.gdx.cellular.player.Player; 14 | 15 | public class PlayerMeat extends ImmovableSolid { 16 | 17 | private Player owningPlayer; 18 | 19 | public PlayerMeat(int x, int y) { 20 | super(x, y); 21 | mass = 200; 22 | flammabilityResistance = 100; 23 | resetFlammabilityResistance = 100; 24 | frictionFactor = 0.5f; 25 | inertialResistance = 1.1f; 26 | vel = new Vector3(0f, 0f,0f); 27 | } 28 | 29 | @Override 30 | public void step(CellularMatrix matrix) { 31 | } 32 | 33 | private void stepAsPartOfPhysicsBody(CellularMatrix matrix) { 34 | applyHeatToNeighborsIfIgnited(matrix); 35 | spawnSparkIfIgnited(matrix); 36 | modifyColor(); 37 | } 38 | 39 | @Override 40 | protected boolean actOnNeighboringElement(Element neighbor, int modifiedMatrixX, int modifiedMatrixY, CellularMatrix matrix, boolean isFinal, boolean isFirst, Vector3 lastValidLocation, int depth) { 41 | return false; 42 | } 43 | 44 | public boolean stepAsPlayer(CellularMatrix matrix, int xOffset, int yOffset) { 45 | if (matrix.isWithinBounds(getMatrixX() + xOffset, getMatrixY() + yOffset)) { 46 | Element neighbor = matrix.get(getMatrixX() + xOffset, getMatrixY() + yOffset); 47 | if (neighbor instanceof EmptyCell || neighbor instanceof Particle || neighbor instanceof Liquid || neighbor instanceof Gas) { 48 | return true; 49 | } else if (neighbor instanceof MovableSolid){ 50 | if (neighbor.isFreeFalling) { 51 | return true; 52 | } 53 | return false; 54 | } else if (neighbor instanceof PlayerMeat) { 55 | PlayerMeat otherMeat = (PlayerMeat) neighbor; 56 | if (otherMeat.getOwningPlayer() == this.getOwningPlayer()) { 57 | return true; 58 | } 59 | return false; 60 | } else if (neighbor instanceof ImmovableSolid) { 61 | return false; 62 | } 63 | } 64 | return true; 65 | } 66 | 67 | public boolean moveToLocation(CellularMatrix matrix, int x, int y) { 68 | matrix.setElementAtIndex(getMatrixX(), getMatrixY(), ElementType.EMPTYCELL.createElementByMatrix(getMatrixX(), getMatrixY())); 69 | matrix.setElementAtIndex(x, y, this); 70 | return true; 71 | } 72 | 73 | public Player getOwningPlayer() { 74 | return owningPlayer; 75 | } 76 | 77 | public void setOwningPlayer(Player owningPlayer) { 78 | this.owningPlayer = owningPlayer; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/elements/solid/Solid.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.elements.solid; 2 | 3 | import com.gdx.cellular.elements.Element; 4 | 5 | public abstract class Solid extends Element { 6 | 7 | public Solid(int x, int y) { 8 | super(x, y); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/elements/solid/immoveable/Brick.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.elements.solid.immoveable; 2 | 3 | import com.badlogic.gdx.math.Vector3; 4 | import com.gdx.cellular.CellularMatrix; 5 | 6 | public class Brick extends ImmovableSolid { 7 | 8 | public Brick(int x, int y) { 9 | super(x, y); 10 | vel = new Vector3(0f, 0f,0f); 11 | frictionFactor = 0.5f; 12 | inertialResistance = 1.1f; 13 | mass = 500; 14 | explosionResistance = 4; 15 | } 16 | 17 | @Override 18 | public boolean receiveHeat(CellularMatrix matrix, int heat) { 19 | return false; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/elements/solid/immoveable/Ground.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.elements.solid.immoveable; 2 | 3 | import com.badlogic.gdx.graphics.Color; 4 | import com.badlogic.gdx.math.Vector3; 5 | import com.gdx.cellular.CellularMatrix; 6 | import com.gdx.cellular.elements.ColorConstants; 7 | import com.gdx.cellular.elements.Element; 8 | import com.gdx.cellular.elements.EmptyCell; 9 | 10 | public class Ground extends ImmovableSolid{ 11 | 12 | public Ground(int x, int y) { 13 | super(x, y); 14 | vel = new Vector3(0f, 0f,0f); 15 | frictionFactor = 0.5f; 16 | inertialResistance = 1.1f; 17 | mass = 200; 18 | health = 250; 19 | } 20 | 21 | @Override 22 | public boolean receiveHeat(CellularMatrix matrix, int heat) { 23 | return false; 24 | } 25 | 26 | @Override 27 | public void customElementFunctions(CellularMatrix matrix) { 28 | // Element above = matrix.get(matrixX, matrixY + 1); 29 | // if (above == null || above instanceof EmptyCell) { 30 | // this.color = ColorConstants.getColorByName("Grass"); 31 | // } else { 32 | // this.color = ColorConstants.getColorForElementType(this.elementType); 33 | // } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/elements/solid/immoveable/ImmovableSolid.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.elements.solid.immoveable; 2 | 3 | import com.badlogic.gdx.math.Vector3; 4 | import com.gdx.cellular.CellularMatrix; 5 | import com.gdx.cellular.elements.Element; 6 | import com.gdx.cellular.elements.solid.Solid; 7 | 8 | public abstract class ImmovableSolid extends Solid { 9 | 10 | public ImmovableSolid(int x, int y) { 11 | super(x, y); 12 | isFreeFalling = false; 13 | } 14 | 15 | // @Override 16 | // public void draw(ShapeRenderer sr) { 17 | // sr.setColor(color); 18 | // sr.rect(pixelX, pixelY, CellularAutomaton.pixelSizeModifier, CellularAutomaton.pixelSizeModifier); 19 | // } 20 | 21 | @Override 22 | public void step(CellularMatrix matrix) { 23 | applyHeatToNeighborsIfIgnited(matrix); 24 | takeEffectsDamage(matrix); 25 | spawnSparkIfIgnited(matrix); 26 | modifyColor(); 27 | customElementFunctions(matrix); 28 | } 29 | 30 | @Override 31 | protected boolean actOnNeighboringElement(Element neighbor, int modifiedMatrixX, int modifiedMatrixY, CellularMatrix matrix, boolean isFinal, boolean isFirst, Vector3 lastValidLocation, int depth) { 32 | return true; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/elements/solid/immoveable/SlimeMold.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.elements.solid.immoveable; 2 | 3 | import com.badlogic.gdx.math.Vector3; 4 | import com.gdx.cellular.CellularMatrix; 5 | import com.gdx.cellular.effects.EffectColors; 6 | import com.gdx.cellular.elements.ColorConstants; 7 | import com.gdx.cellular.elements.Element; 8 | import com.gdx.cellular.elements.ElementType; 9 | 10 | public class SlimeMold extends ImmovableSolid { 11 | 12 | public SlimeMold(int x, int y) { 13 | super(x, y); 14 | vel = new Vector3(0f, 0f,0f); 15 | frictionFactor = 0.5f; 16 | inertialResistance = 1.1f; 17 | mass = 500; 18 | flammabilityResistance = 10; 19 | resetFlammabilityResistance = 0; 20 | health = 40; 21 | } 22 | 23 | @Override 24 | public void step(CellularMatrix matrix) { 25 | super.step(matrix); 26 | infectNeighbors(matrix); 27 | } 28 | 29 | private boolean infectNeighbors(CellularMatrix matrix) { 30 | if (!isEffectsFrame() || isIgnited) return false; 31 | for (int x = getMatrixX() - 1; x <= getMatrixX() + 1; x++) { 32 | for (int y = getMatrixY() - 1; y <= getMatrixY() + 1; y++) { 33 | if (!(x == 0 && y == 0)) { 34 | Element neighbor = matrix.get(x, y); 35 | if (neighbor != null) { 36 | neighbor.infect(matrix); 37 | } 38 | } 39 | } 40 | } 41 | return true; 42 | } 43 | 44 | @Override 45 | public void takeFireDamage(CellularMatrix matrix) { 46 | health -= fireDamage; 47 | } 48 | 49 | public boolean infect(CellularMatrix matrix) { 50 | return false; 51 | } 52 | 53 | @Override 54 | public void modifyColor() { 55 | if (isIgnited) { 56 | color = EffectColors.getRandomFireColor(); 57 | } else { 58 | color = ColorConstants.getColorForElementType(ElementType.SLIMEMOLD, this.getMatrixX(), this.getMatrixY()); 59 | } 60 | } 61 | 62 | 63 | } 64 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/elements/solid/immoveable/Stone.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.elements.solid.immoveable; 2 | 3 | import com.badlogic.gdx.math.Vector3; 4 | import com.gdx.cellular.CellularMatrix; 5 | 6 | public class Stone extends ImmovableSolid { 7 | 8 | public Stone(int x, int y) { 9 | super(x, y); 10 | vel = new Vector3(0f, 0f,0f); 11 | frictionFactor = 0.5f; 12 | inertialResistance = 1.1f; 13 | mass = 500; 14 | explosionResistance = 4; 15 | } 16 | 17 | @Override 18 | public boolean receiveHeat(CellularMatrix matrix, int heat) { 19 | return false; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/elements/solid/immoveable/Titanium.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.elements.solid.immoveable; 2 | 3 | import com.badlogic.gdx.math.Vector3; 4 | import com.gdx.cellular.CellularMatrix; 5 | 6 | public class Titanium extends ImmovableSolid { 7 | 8 | public Titanium(int x, int y) { 9 | super(x, y); 10 | vel = new Vector3(0f, 0f,0f); 11 | frictionFactor = 0.5f; 12 | inertialResistance = 1.1f; 13 | mass = 1000; 14 | explosionResistance = 5; 15 | } 16 | 17 | @Override 18 | public boolean receiveHeat(CellularMatrix matrix, int heat) { 19 | return false; 20 | } 21 | 22 | @Override 23 | public boolean corrode(CellularMatrix matrix) { 24 | return false; 25 | } 26 | 27 | @Override 28 | public boolean infect(CellularMatrix matrix) { 29 | return false; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/elements/solid/immoveable/Wood.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.elements.solid.immoveable; 2 | 3 | import com.badlogic.gdx.graphics.Color; 4 | import com.badlogic.gdx.math.Vector3; 5 | import com.gdx.cellular.CellularMatrix; 6 | import com.gdx.cellular.elements.ElementType; 7 | 8 | public class Wood extends ImmovableSolid { 9 | 10 | public Wood(int x, int y) { 11 | super(x, y); 12 | vel = new Vector3(0f, 0f,0f); 13 | frictionFactor = 0.5f; 14 | inertialResistance = 1.1f; 15 | mass = 500; 16 | health = getRandomInt(100) + 100; 17 | flammabilityResistance = 40; 18 | resetFlammabilityResistance = 25; 19 | } 20 | 21 | @Override 22 | public void checkIfDead(CellularMatrix matrix) { 23 | if (this.health <= 0) { 24 | if (isIgnited && Math.random() > .95f) { 25 | dieAndReplace(matrix, ElementType.EMBER); 26 | } else { 27 | die(matrix); 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/elements/solid/movable/Coal.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.elements.solid.movable; 2 | 3 | import com.badlogic.gdx.graphics.Color; 4 | import com.badlogic.gdx.math.Vector3; 5 | import com.gdx.cellular.CellularMatrix; 6 | 7 | 8 | public class Coal extends MovableSolid { 9 | 10 | public Coal(int x, int y) { 11 | super(x, y); 12 | vel = new Vector3(0f, -124f,0f); 13 | frictionFactor = .4f; 14 | inertialResistance = .8f; 15 | mass = 200; 16 | flammabilityResistance = 100; 17 | resetFlammabilityResistance = 35; 18 | } 19 | 20 | @Override 21 | public void spawnSparkIfIgnited(CellularMatrix matrix) { 22 | if (getRandomInt(20) > 2) return; 23 | super.spawnSparkIfIgnited(matrix); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/elements/solid/movable/Dirt.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.elements.solid.movable; 2 | 3 | import com.badlogic.gdx.math.Vector3; 4 | import com.gdx.cellular.CellularMatrix; 5 | 6 | public class Dirt extends MovableSolid { 7 | 8 | public Dirt(int x, int y) { 9 | super(x, y); 10 | vel = new Vector3(0f, -124f,0f); 11 | frictionFactor = .6f; 12 | inertialResistance = .8f; 13 | mass = 200; 14 | } 15 | 16 | @Override 17 | public boolean receiveHeat(CellularMatrix matrix, int heat) { 18 | return false; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/elements/solid/movable/Ember.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.elements.solid.movable; 2 | 3 | import com.badlogic.gdx.math.Vector3; 4 | import com.gdx.cellular.CellularMatrix; 5 | 6 | public class Ember extends MovableSolid { 7 | 8 | public Ember(int x, int y) { 9 | super(x, y); 10 | vel = new Vector3(0f, -124f,0f); 11 | frictionFactor = .9f; 12 | inertialResistance = .99f; 13 | mass = 200; 14 | isIgnited = true; 15 | health = getRandomInt(100) + 250; 16 | temperature = 5; 17 | flammabilityResistance = 0; 18 | resetFlammabilityResistance = 20; 19 | } 20 | 21 | @Override 22 | public boolean infect(CellularMatrix matrix) { 23 | return false; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/elements/solid/movable/Gunpowder.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.elements.solid.movable; 2 | 3 | import com.badlogic.gdx.math.Vector3; 4 | import com.gdx.cellular.CellularMatrix; 5 | 6 | public class Gunpowder extends MovableSolid { 7 | 8 | private int ignitedCount = 0; 9 | private final int ignitedThreshold = 7; 10 | 11 | public Gunpowder(int x, int y) { 12 | super(x, y); 13 | vel = new Vector3(0f, -124f,0f); 14 | frictionFactor = .4f; 15 | inertialResistance = .8f; 16 | mass = 200; 17 | flammabilityResistance = 10; 18 | resetFlammabilityResistance = 35; 19 | explosionRadius = 15; 20 | fireDamage = 3; 21 | } 22 | 23 | public void step(CellularMatrix matrix) { 24 | super.step(matrix); 25 | if (isIgnited) { 26 | ignitedCount++; 27 | } 28 | if (ignitedCount >= ignitedThreshold) { 29 | matrix.addExplosion(15, 10, this); 30 | } 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/elements/solid/movable/Sand.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.elements.solid.movable; 2 | 3 | import com.badlogic.gdx.math.Vector3; 4 | import com.gdx.cellular.CellularMatrix; 5 | 6 | public class Sand extends MovableSolid { 7 | 8 | public Sand(int x, int y) { 9 | super(x, y); 10 | vel = new Vector3(Math.random() > 0.5 ? -1 : 1, -124f,0f); 11 | frictionFactor = 0.9f; 12 | inertialResistance = .1f; 13 | mass = 150; 14 | } 15 | 16 | @Override 17 | public boolean receiveHeat(CellularMatrix matrix, int heat) { 18 | return false; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/elements/solid/movable/Snow.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.elements.solid.movable; 2 | 3 | import com.badlogic.gdx.math.Vector3; 4 | import com.gdx.cellular.CellularMatrix; 5 | import com.gdx.cellular.elements.ElementType; 6 | 7 | public class Snow extends MovableSolid { 8 | 9 | public Snow(int x, int y) { 10 | super(x, y); 11 | vel = new Vector3(0f, -62f,0f); 12 | frictionFactor = .4f; 13 | inertialResistance = .8f; 14 | mass = 200; 15 | flammabilityResistance = 100; 16 | resetFlammabilityResistance = 35; 17 | } 18 | 19 | @Override 20 | public boolean receiveHeat(CellularMatrix matrix, int heat) { 21 | if (heat > 0) { 22 | dieAndReplace(matrix, ElementType.WATER); 23 | return true; 24 | } 25 | return false; 26 | } 27 | 28 | @Override 29 | public void step(CellularMatrix matrix) { 30 | super.step(matrix); 31 | if (vel.y < -62) { 32 | vel.y = Math.random() > 0.3 ? -62 : -124; 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/input/Cursor.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.input; 2 | 3 | import com.badlogic.gdx.Gdx; 4 | import com.badlogic.gdx.graphics.Color; 5 | import com.badlogic.gdx.graphics.OrthographicCamera; 6 | import com.badlogic.gdx.graphics.glutils.ShapeRenderer; 7 | import com.badlogic.gdx.math.Vector3; 8 | import com.gdx.cellular.CellularAutomaton; 9 | 10 | import static com.gdx.cellular.input.MouseMode.*; 11 | 12 | public class Cursor { 13 | 14 | public InputManager inputManager; 15 | 16 | public Cursor(InputManager inputManager) { 17 | this.inputManager = inputManager; 18 | } 19 | 20 | public void draw(ShapeRenderer sr) { 21 | MouseMode mode = inputManager.getMouseMode(); 22 | Vector3 touchPos = inputManager.getTouchPos(); 23 | int pixelX = (int) touchPos.x; 24 | int pixelY = (int) touchPos.y; 25 | int brushSize = inputManager.brushSize; 26 | InputManager.BRUSHTYPE brushtype = inputManager.brushType; 27 | switch(mode) { 28 | case EXPLOSION: 29 | sr.begin(); 30 | sr.set(ShapeRenderer.ShapeType.Line); 31 | sr.setColor(Color.RED); 32 | sr.circle(pixelX, pixelY, brushSize - 2); 33 | sr.end(); 34 | break; 35 | case SPAWN: 36 | case BOID: 37 | case HEAT: 38 | case PARTICALIZE: 39 | case PARTICLE: 40 | if (brushtype == InputManager.BRUSHTYPE.CIRCLE) { 41 | sr.begin(); 42 | sr.set(ShapeRenderer.ShapeType.Line); 43 | sr.setColor(Color.RED); 44 | sr.circle(pixelX, pixelY, brushSize - 2); 45 | sr.end(); 46 | } else if (brushtype == InputManager.BRUSHTYPE.SQUARE) { 47 | sr.begin(); 48 | sr.set(ShapeRenderer.ShapeType.Line); 49 | sr.setColor(Color.RED); 50 | sr.rect(pixelX - brushSize, pixelY - brushSize, brushSize*2, brushSize*2); 51 | sr.end(); 52 | } else if (brushtype == InputManager.BRUSHTYPE.RECTANGLE) { 53 | if (inputManager.touchedLastFrame) { 54 | int width = (int) Math.abs(inputManager.rectStartPos.x - touchPos.x); 55 | int height = (int) Math.abs(inputManager.rectStartPos.y - touchPos.y); 56 | int xOrigin = (int) Math.min(inputManager.rectStartPos.x, touchPos.x); 57 | int yOrigin = (int) Math.min(inputManager.rectStartPos.y, touchPos.y); 58 | sr.begin(); 59 | sr.set(ShapeRenderer.ShapeType.Line); 60 | sr.setColor(Color.RED); 61 | sr.rect(xOrigin, yOrigin, width, height); 62 | sr.end(); 63 | } 64 | } 65 | break; 66 | case RECTANGLE: 67 | if (inputManager.touchedLastFrame) { 68 | int width = (int) Math.abs(inputManager.rectStartPos.x - touchPos.x); 69 | int height = (int) Math.abs(inputManager.rectStartPos.y - touchPos.y); 70 | int xOrigin = (int) Math.min(inputManager.rectStartPos.x, touchPos.x); 71 | int yOrigin = (int) Math.min(inputManager.rectStartPos.y, touchPos.y); 72 | sr.begin(); 73 | sr.set(ShapeRenderer.ShapeType.Line); 74 | sr.setColor(Color.RED); 75 | sr.rect(xOrigin, yOrigin, width, height); 76 | sr.end(); 77 | } 78 | break; 79 | default: 80 | } 81 | 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/input/InputElement.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.input; 2 | 3 | import com.badlogic.gdx.Input; 4 | import com.gdx.cellular.elements.ElementType; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | public class InputElement { 10 | 11 | Map elementMap; 12 | private static final InputElement inputElement; 13 | static { 14 | inputElement = new InputElement(); 15 | } 16 | 17 | private InputElement() { 18 | elementMap = new HashMap<>(); 19 | elementMap.put(Input.Keys.NUM_1, ElementType.STONE); 20 | elementMap.put(Input.Keys.NUM_2, ElementType.SAND); 21 | elementMap.put(Input.Keys.NUM_3, ElementType.DIRT); 22 | elementMap.put(Input.Keys.NUM_4, ElementType.WATER); 23 | elementMap.put(Input.Keys.NUM_5, ElementType.OIL); 24 | elementMap.put(Input.Keys.NUM_6, ElementType.ACID); 25 | elementMap.put(Input.Keys.NUM_7, ElementType.WOOD); 26 | elementMap.put(Input.Keys.NUM_8, ElementType.TITANIUM); 27 | elementMap.put(Input.Keys.NUM_9, ElementType.EMPTYCELL); 28 | elementMap.put(Input.Keys.E, ElementType.EMBER); 29 | elementMap.put(Input.Keys.O, ElementType.COAL); 30 | elementMap.put(Input.Keys.L, ElementType.LAVA); 31 | elementMap.put(Input.Keys.B, ElementType.BLOOD); 32 | elementMap.put(Input.Keys.G, ElementType.FLAMMABLEGAS); 33 | elementMap.put(Input.Keys.F, ElementType.SPARK); 34 | elementMap.put(Input.Keys.N, ElementType.SNOW); 35 | elementMap.put(Input.Keys.COMMA, ElementType.SLIMEMOLD); 36 | } 37 | 38 | public static ElementType getElementForKeycode(int keycode) { 39 | return inputElement.elementMap.get(keycode); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/input/InputProcessors.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.input; 2 | 3 | import com.badlogic.gdx.Gdx; 4 | import com.badlogic.gdx.InputProcessor; 5 | import com.badlogic.gdx.graphics.OrthographicCamera; 6 | import com.gdx.cellular.CellularMatrix; 7 | import com.gdx.cellular.input.processors.CreatorInputProcessor; 8 | import com.gdx.cellular.input.processors.MenuInputProcessor; 9 | import com.gdx.cellular.input.processors.PlayerInputProcessor; 10 | import com.gdx.cellular.util.GameManager; 11 | 12 | public class InputProcessors { 13 | 14 | private final InputManager inputManager; 15 | private final InputProcessor creatorInputProcessor; 16 | private final InputProcessor playerInputProcessor; 17 | 18 | public InputProcessors(InputManager inputManager, CellularMatrix matrix, OrthographicCamera camera, GameManager gameManager) { 19 | this.inputManager = inputManager; 20 | this.playerInputProcessor = new PlayerInputProcessor(this, gameManager); 21 | this.creatorInputProcessor = new CreatorInputProcessor(this, inputManager, camera, matrix); 22 | this.inputManager.setCreatorInputProcessor(creatorInputProcessor); 23 | Gdx.input.setInputProcessor(creatorInputProcessor); 24 | } 25 | 26 | public void setPlayerProcessor() { 27 | Gdx.input.setInputProcessor(playerInputProcessor); 28 | } 29 | 30 | public void setCreatorInputProcessor() { 31 | Gdx.input.setInputProcessor(creatorInputProcessor); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/input/MouseMode.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.input; 2 | 3 | public enum MouseMode { 4 | SPAWN, 5 | BOID, 6 | EXPLOSION, 7 | HEAT, 8 | PARTICLE, 9 | PARTICALIZE, 10 | PHYSICSOBJ, 11 | RECTANGLE 12 | } 13 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/input/processors/CreatorInputProcessor.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.input.processors; 2 | 3 | import com.badlogic.gdx.Input; 4 | import com.badlogic.gdx.InputProcessor; 5 | import com.badlogic.gdx.graphics.OrthographicCamera; 6 | import com.badlogic.gdx.math.Vector3; 7 | import com.gdx.cellular.CellularMatrix; 8 | import com.gdx.cellular.elements.ElementType; 9 | import com.gdx.cellular.input.InputElement; 10 | import com.gdx.cellular.input.InputManager; 11 | import com.gdx.cellular.input.InputProcessors; 12 | 13 | 14 | public class CreatorInputProcessor implements InputProcessor { 15 | 16 | private final InputManager inputManager; 17 | private final OrthographicCamera camera; 18 | private final CellularMatrix matrix; 19 | private final InputProcessors parent; 20 | 21 | public CreatorInputProcessor(InputProcessors inputProcessors, InputManager inputManager, OrthographicCamera camera, CellularMatrix matrix) { 22 | this.parent = inputProcessors; 23 | this.inputManager = inputManager; 24 | this.camera = camera; 25 | this.matrix = matrix; 26 | } 27 | 28 | @Override 29 | public boolean keyDown(int keycode) { 30 | if (keycode == Input.Keys.ENTER) { 31 | this.parent.setPlayerProcessor(); 32 | } 33 | if (keycode == Input.Keys.EQUALS) { 34 | inputManager.calculateNewBrushSize(2); 35 | } 36 | if (keycode == Input.Keys.MINUS) { 37 | inputManager.calculateNewBrushSize(-2); 38 | } 39 | ElementType elementType = InputElement.getElementForKeycode(keycode); 40 | if (elementType != null) { 41 | inputManager.setCurrentlySelectedElement(elementType); 42 | } 43 | if (keycode == Input.Keys.SPACE) { 44 | inputManager.placeSpout(matrix); 45 | } 46 | if (keycode == Input.Keys.C) { 47 | inputManager.clearMatrix(matrix); 48 | inputManager.clearBox2dActors(); 49 | } 50 | if (keycode == Input.Keys.P) { 51 | inputManager.togglePause(); 52 | } 53 | if (keycode == Input.Keys.M) { 54 | inputManager.cycleBrushType(); 55 | } 56 | return false; 57 | } 58 | 59 | @Override 60 | public boolean scrolled(int amount) { 61 | inputManager.calculateNewBrushSize(amount * -2); 62 | return true; 63 | } 64 | 65 | @Override 66 | public boolean keyUp(int keycode) { 67 | return false; 68 | } 69 | 70 | @Override 71 | public boolean keyTyped(char character) { 72 | return false; 73 | } 74 | 75 | @Override 76 | public boolean touchDown(int screenX, int screenY, int pointer, int button) { 77 | if (button == Input.Buttons.LEFT && !inputManager.drawMenu) { 78 | inputManager.spawnElementByInput(matrix); 79 | } else if (button == Input.Buttons.RIGHT) { 80 | inputManager.setTouchedLastFrame(false); 81 | Vector3 pos = camera.unproject(new Vector3(screenX, screenY, 0)); 82 | inputManager.setDrawMenuAndLocation(pos.x, pos.y); 83 | } 84 | return false; 85 | } 86 | 87 | @Override 88 | public boolean touchUp(int screenX, int screenY, int pointer, int button) { 89 | if (button == Input.Buttons.LEFT) { 90 | inputManager.setTouchedLastFrame(false); 91 | inputManager.touchUpLMB(matrix); 92 | } 93 | return false; 94 | } 95 | 96 | @Override 97 | public boolean touchDragged(int screenX, int screenY, int pointer) { 98 | if (!inputManager.drawMenu) { 99 | inputManager.spawnElementByInput(matrix); 100 | } 101 | return false; 102 | } 103 | 104 | @Override 105 | public boolean mouseMoved(int screenX, int screenY) { 106 | return false; 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/input/processors/MenuInputProcessor.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.input.processors; 2 | 3 | import com.badlogic.gdx.Input; 4 | import com.badlogic.gdx.InputProcessor; 5 | import com.badlogic.gdx.graphics.OrthographicCamera; 6 | import com.badlogic.gdx.math.Vector3; 7 | import com.gdx.cellular.CellularMatrix; 8 | import com.gdx.cellular.input.InputManager; 9 | import com.gdx.cellular.input.InputProcessors; 10 | 11 | public class MenuInputProcessor implements InputProcessor { 12 | 13 | 14 | private boolean showMenu = false; 15 | 16 | private final InputManager inputManager; 17 | private final OrthographicCamera camera; 18 | private final CellularMatrix matrix; 19 | private final InputProcessors parent; 20 | 21 | 22 | public MenuInputProcessor(InputProcessors inputProcessors, InputManager inputManager, OrthographicCamera camera, CellularMatrix matrix) { 23 | super(); 24 | this.parent = inputProcessors; 25 | this.inputManager = inputManager; 26 | this.camera = camera; 27 | this.matrix = matrix; 28 | } 29 | 30 | @Override 31 | public boolean keyDown(int keycode) { 32 | return false; 33 | } 34 | 35 | @Override 36 | public boolean keyUp(int keycode) { 37 | return false; 38 | } 39 | 40 | @Override 41 | public boolean keyTyped(char character) { 42 | return false; 43 | } 44 | 45 | @Override 46 | public boolean touchDown(int screenX, int screenY, int pointer, int button) { 47 | if (button == Input.Buttons.RIGHT) { 48 | Vector3 pos = camera.unproject(new Vector3(screenX, screenY, 0)); 49 | inputManager.setDrawMenuAndLocation(pos.x, pos.y); 50 | } 51 | return false; 52 | } 53 | 54 | @Override 55 | public boolean touchUp(int screenX, int screenY, int pointer, int button) { 56 | return false; 57 | } 58 | 59 | @Override 60 | public boolean touchDragged(int screenX, int screenY, int pointer) { 61 | return false; 62 | } 63 | 64 | @Override 65 | public boolean mouseMoved(int screenX, int screenY) { 66 | return false; 67 | } 68 | 69 | @Override 70 | public boolean scrolled(int amount) { 71 | return false; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/input/processors/PlayerInputProcessor.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.input.processors; 2 | 3 | import com.badlogic.gdx.Input; 4 | import com.badlogic.gdx.InputProcessor; 5 | import com.gdx.cellular.input.InputProcessors; 6 | import com.gdx.cellular.player.Player; 7 | import com.gdx.cellular.util.GameManager; 8 | 9 | public class PlayerInputProcessor implements InputProcessor { 10 | 11 | private GameManager gameManager; 12 | private InputProcessors parent; 13 | 14 | public PlayerInputProcessor(InputProcessors inputProcessors, GameManager gameManager) { 15 | this.parent = inputProcessors; 16 | this.gameManager = gameManager; 17 | } 18 | 19 | 20 | 21 | @Override 22 | public boolean keyDown(int keycode) { 23 | if (keycode == Input.Keys.ENTER) { 24 | this.parent.setCreatorInputProcessor(); 25 | return true; 26 | } 27 | Player player1 = gameManager.getPlayer(0); 28 | if (keycode == Input.Keys.A) { 29 | player1.setXVelocity(-62); 30 | } else if (keycode == Input.Keys.D) { 31 | player1.setXVelocity(62); 32 | } else if (keycode == Input.Keys.W) { 33 | player1.setYVelocity(250); 34 | } 35 | return true; 36 | } 37 | 38 | @Override 39 | public boolean keyUp(int keycode) { 40 | Player player1 = gameManager.getPlayer(0); 41 | if (keycode == Input.Keys.A) { 42 | player1.setXVelocity(0); 43 | } else if (keycode == Input.Keys.D) { 44 | player1.setXVelocity(0); 45 | } else if (keycode == Input.Keys.W) { 46 | player1.setYVelocity(0); 47 | } 48 | return true; 49 | } 50 | 51 | @Override 52 | public boolean keyTyped(char character) { 53 | return false; 54 | } 55 | 56 | @Override 57 | public boolean touchDown(int screenX, int screenY, int pointer, int button) { 58 | return false; 59 | } 60 | 61 | @Override 62 | public boolean touchUp(int screenX, int screenY, int pointer, int button) { 63 | return false; 64 | } 65 | 66 | @Override 67 | public boolean touchDragged(int screenX, int screenY, int pointer) { 68 | return false; 69 | } 70 | 71 | @Override 72 | public boolean mouseMoved(int screenX, int screenY) { 73 | return false; 74 | } 75 | 76 | @Override 77 | public boolean scrolled(int amount) { 78 | return false; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/particles/Explosion.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.particles; 2 | 3 | import com.badlogic.gdx.math.Vector2; 4 | import com.badlogic.gdx.math.Vector3; 5 | import com.gdx.cellular.CellularMatrix; 6 | import com.gdx.cellular.elements.Element; 7 | import com.gdx.cellular.elements.ElementType; 8 | import com.gdx.cellular.elements.EmptyCell; 9 | import com.gdx.cellular.elements.gas.Gas; 10 | import com.gdx.cellular.elements.liquid.Liquid; 11 | import com.gdx.cellular.elements.solid.immoveable.ImmovableSolid; 12 | import com.gdx.cellular.elements.solid.movable.MovableSolid; 13 | 14 | import java.util.ArrayList; 15 | import java.util.HashMap; 16 | import java.util.List; 17 | import java.util.Map; 18 | 19 | public class Explosion { 20 | 21 | private final CellularMatrix matrix; 22 | public int radius; 23 | public int strength; 24 | public Element sourceElement; 25 | int matrixX; 26 | int matrixY; 27 | 28 | public Explosion(CellularMatrix matrix, int radius, int strength, Element sourceElement) { 29 | this.matrix = matrix; 30 | this.radius = radius; 31 | this.strength = strength; 32 | this.sourceElement = sourceElement; 33 | this.matrixX = sourceElement.getMatrixX(); 34 | this.matrixY = sourceElement.getMatrixY(); 35 | } 36 | 37 | public Explosion(CellularMatrix matrix, int radius, int strength, int matrixX, int matrixY) { 38 | this.matrix = matrix; 39 | this.radius = radius; 40 | this.strength = strength; 41 | this.matrixX = matrixX; 42 | this.matrixY = matrixY; 43 | } 44 | 45 | public List enact() { 46 | int matrixX; 47 | int matrixY; 48 | if (sourceElement != null) { 49 | matrixX = sourceElement.getMatrixX(); 50 | matrixY = sourceElement.getMatrixY(); 51 | } else { 52 | matrixX = this.matrixX; 53 | matrixY = this.matrixY; 54 | } 55 | if (sourceElement != null && sourceElement.isDead()) { 56 | return new ArrayList<>(); 57 | } 58 | Map coordinatesCache = new HashMap<>(); 59 | for (int x = radius; x >= radius * -1; x--) { 60 | for (int y = radius; y >= radius * -1; y--) { 61 | if (Math.abs(x) == radius || Math.abs(y) == radius) { 62 | //if (Math.random() < 0.05) 63 | iterateBetweenTwoPoints(matrixX, matrixY, matrixX + x, matrixY + y, strength, coordinatesCache, matrix); 64 | } 65 | } 66 | } 67 | return null; 68 | } 69 | 70 | private void iterateBetweenTwoPoints(int matrixX, int matrixY, int newX, int newY, int strength, Map cache, CellularMatrix matrix) { 71 | int matrixX1 = matrixX; 72 | int matrixY1 = matrixY; 73 | int matrixX2 = newX; 74 | int matrixY2 = newY; 75 | 76 | int localRadius = radius + getRandomVariation(radius); 77 | 78 | // If the two points are the same no need to iterate. Just run the provided function 79 | 80 | int xDiff = matrixX1 - matrixX2; 81 | int yDiff = matrixY1 - matrixY2; 82 | boolean xDiffIsLarger = Math.abs(xDiff) > Math.abs(yDiff); 83 | 84 | int xModifier = xDiff < 0 ? 1 : -1; 85 | int yModifier = yDiff < 0 ? 1 : -1; 86 | 87 | boolean onlyDarken = false; 88 | 89 | int upperBound = Math.max(Math.abs(xDiff), Math.abs(yDiff)); 90 | int min = Math.min(Math.abs(xDiff), Math.abs(yDiff)); 91 | float slope = (min == 0 || upperBound == 0) ? 0 : ((float) (min + 1) / (upperBound + 1)); 92 | 93 | int smallerCount; 94 | for (int i = 0; i <= upperBound; i++) { 95 | smallerCount = (int) Math.floor(i * slope); 96 | int yIncrease, xIncrease; 97 | if (xDiffIsLarger) { 98 | xIncrease = i; 99 | yIncrease = smallerCount; 100 | } else { 101 | yIncrease = i; 102 | xIncrease = smallerCount; 103 | } 104 | int currentY = matrixY1 + (yIncrease * yModifier); 105 | int currentX = matrixX1 + (xIncrease * xModifier); 106 | // If these coordinates have been visited previously we can 'continue if the result was 107 | // true (explosion not stopped) and break if false (explosion stopped at these coordinates previously) 108 | String cachedResult = cache.get(String.valueOf(currentX) + currentY); 109 | if (cachedResult != null && cachedResult.equals(String.valueOf(true))) { 110 | continue; 111 | } else if (cachedResult != null && cachedResult.equals(String.valueOf(false))) { 112 | onlyDarken = true; 113 | continue; 114 | } 115 | if (!matrix.isWithinBounds(currentX, currentY)) { 116 | cache.put(String.valueOf(currentX) + currentY, String.valueOf(false)); 117 | break; 118 | } 119 | int distance = matrix.distanceBetweenTwoPoints(matrixX1, currentX, matrixY1, currentY); 120 | if (distance < localRadius/2) { 121 | if (onlyDarken) { 122 | Element element = matrix.get(currentX, currentY); 123 | darkenElement(element, ((float) distance)/localRadius); 124 | cache.put(String.valueOf(currentX) + currentY, String.valueOf(false)); 125 | if (Math.random() > .8) { 126 | break; 127 | } 128 | continue; 129 | } 130 | Element element = matrix.get(currentX, currentY); 131 | if (element instanceof EmptyCell) { 132 | if (Math.random() > 0.5) { 133 | matrix.setElementAtIndex(currentX, currentY, ElementType.EXPLOSIONSPARK.createElementByMatrix(currentX, currentY)); 134 | } 135 | cache.put(String.valueOf(currentX) + currentY, String.valueOf(true)); 136 | } else { 137 | boolean unstopped = element.explode(matrix, strength); 138 | cache.put(String.valueOf(currentX) + currentY, String.valueOf(unstopped)); 139 | if (!unstopped) { 140 | element.receiveHeat(matrix, 300); 141 | darkenElement(element, ((float) distance)/localRadius); 142 | onlyDarken = true; 143 | continue; 144 | } 145 | } 146 | } else if (distance < (localRadius/2 + Math.max(localRadius/4, 1))) { 147 | if (onlyDarken) { 148 | Element element = matrix.get(currentX, currentY); 149 | element.darkenColor(((float) distance)/localRadius); 150 | cache.put(String.valueOf(currentX) + currentY, String.valueOf(false)); 151 | if (Math.random() > .6) { 152 | break; 153 | } 154 | continue; 155 | } 156 | Element element = matrix.get(currentX, currentY); 157 | if (element instanceof EmptyCell) { 158 | if (Math.random() > 0.5) { 159 | matrix.setElementAtIndex(currentX, currentY, ElementType.EXPLOSIONSPARK.createElementByMatrix(currentX, currentY)); 160 | } 161 | cache.put(String.valueOf(currentX) + currentY, String.valueOf(true)); 162 | continue; 163 | } 164 | darkenElement(element, ((float) distance)/(localRadius)*1.5f); 165 | element.receiveHeat(matrix, 300); 166 | Vector2 center = new Vector2(matrixX, matrixY); 167 | Vector2 newPoint = new Vector2(currentX, currentY); 168 | newPoint.sub(center).nor(); 169 | matrix.particalizeByMatrix(currentX, currentY, new Vector3(newPoint.x * radius * 5, newPoint.y * radius * 5, 0)); 170 | if (Math.random() > .8) { 171 | break; 172 | } 173 | } 174 | } 175 | } 176 | 177 | private int getRandomVariation(int radius) { 178 | if (Math.random() > 0.5f) { 179 | return 1; 180 | } else { 181 | return -1; 182 | } 183 | // if (Math.random() > 0.5f) { 184 | // return (int) (Math.random() * (Math.max(radius/5, 1))); 185 | // } else { 186 | // return (int) (Math.random() * -(Math.max(radius/5, 1))); 187 | // } 188 | } 189 | 190 | // Intellij says the casts to subclasses are redundant. But the overriden method definition 191 | // in the subclass is not called unless the cast is performed. 192 | private void darkenElement(Element element, float factor) { 193 | if (element instanceof MovableSolid) { 194 | ((MovableSolid) element).darkenColor(factor); 195 | } else if (element instanceof Liquid) { 196 | ((Liquid) element).darkenColor(factor); 197 | } else if (element instanceof ImmovableSolid) { 198 | ((ImmovableSolid) element).darkenColor(factor); 199 | } else if (element instanceof Gas) { 200 | ((Gas) element).darkenColor(factor); 201 | } 202 | } 203 | 204 | } 205 | 206 | 207 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/particles/Particle.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.particles; 2 | 3 | import com.badlogic.gdx.Gdx; 4 | import com.badlogic.gdx.graphics.Color; 5 | import com.badlogic.gdx.math.Vector3; 6 | import com.gdx.cellular.CellularAutomaton; 7 | import com.gdx.cellular.CellularMatrix; 8 | import com.gdx.cellular.elements.Element; 9 | import com.gdx.cellular.elements.ElementType; 10 | import com.gdx.cellular.elements.EmptyCell; 11 | import com.gdx.cellular.elements.gas.Gas; 12 | import com.gdx.cellular.elements.liquid.Liquid; 13 | import com.gdx.cellular.elements.solid.Solid; 14 | 15 | public class Particle extends Element { 16 | 17 | public ElementType containedElementType; 18 | 19 | public Particle(int x, int y, Vector3 vel, ElementType elementType, Color color, boolean isIgnited) { 20 | super(x, y); 21 | if (ElementType.PARTICLE.equals(elementType)) { 22 | throw new IllegalStateException("Containing element cannot be particle"); 23 | } 24 | this.containedElementType = elementType; 25 | this.vel = new Vector3(); 26 | Vector3 localVel = vel == null ? new Vector3(0, -124, 0) : vel; 27 | this.vel.x = localVel.x; 28 | this.vel.y = localVel.y; 29 | this.color = color; 30 | this.isIgnited = isIgnited; 31 | if (isIgnited) { 32 | this.flammabilityResistance = 0; 33 | } 34 | } 35 | 36 | public Particle(int x, int y, Vector3 vel, Element sourceElement) { 37 | super(x, y); 38 | if (ElementType.PARTICLE.equals(sourceElement.elementType)) { 39 | throw new IllegalStateException("Containing element cannot be particle"); 40 | } 41 | this.containedElementType = sourceElement.elementType; 42 | this.vel = new Vector3(); 43 | Vector3 localVel = vel == null ? new Vector3(0, -124, 0) : vel; 44 | this.vel.x = localVel.x; 45 | this.vel.y = localVel.y; 46 | this.color = sourceElement.color; 47 | this.isIgnited = sourceElement.isIgnited; 48 | if (isIgnited) { 49 | this.flammabilityResistance = 0; 50 | } 51 | } 52 | 53 | @Override 54 | public boolean receiveHeat(CellularMatrix matrix, int heat) { 55 | return false; 56 | } 57 | 58 | @Override 59 | public void dieAndReplace(CellularMatrix matrix, ElementType elementType) { 60 | particleDeathAndSpawn(matrix); 61 | } 62 | 63 | private void particleDeathAndSpawn(CellularMatrix matrix) { 64 | Element currentLocation = matrix.get(this.getMatrixX(), this.getMatrixY()); 65 | if (currentLocation == this || currentLocation instanceof EmptyCell) { 66 | die(matrix); 67 | Element newElement = containedElementType.createElementByMatrix(getMatrixX(), getMatrixY()); 68 | newElement.color = this.color; 69 | newElement.isIgnited = this.isIgnited; 70 | if (newElement.isIgnited) { 71 | newElement.flammabilityResistance = 0; 72 | } 73 | matrix.setElementAtIndex(getMatrixX(), getMatrixY(), newElement); 74 | matrix.reportToChunkActive(getMatrixX(), getMatrixY()); 75 | } else { 76 | int yIndex = 0; 77 | while (true) { 78 | Element elementAtNewPos = matrix.get(getMatrixX(), getMatrixY() + yIndex); 79 | if (elementAtNewPos == null) { 80 | break; 81 | } else if (elementAtNewPos instanceof EmptyCell) { 82 | die(matrix); 83 | matrix.setElementAtIndex(getMatrixX(), getMatrixY() + yIndex, containedElementType.createElementByMatrix(getMatrixX(), getMatrixY() + yIndex)); 84 | matrix.reportToChunkActive(getMatrixX(), getMatrixY() + yIndex); 85 | break; 86 | } 87 | yIndex++; 88 | } 89 | } 90 | } 91 | 92 | @Override 93 | public void step(CellularMatrix matrix) { 94 | if (stepped.get(0) == CellularAutomaton.stepped.get(0)) return; 95 | stepped.flip(0); 96 | if (vel.y > -64 && vel.y < 32) { 97 | vel.y = -64; 98 | } 99 | vel.add(CellularAutomaton.gravity); 100 | if (vel.y < -500) { 101 | vel.y = -500; 102 | } else if (vel.y > 500) { 103 | vel.y = 500; 104 | } 105 | 106 | int yModifier = vel.y < 0 ? -1 : 1; 107 | int xModifier = vel.x < 0 ? -1 : 1; 108 | int velYDeltaTime = (int) (Math.abs(vel.y) * Gdx.graphics.getDeltaTime()); 109 | int velXDeltaTime = (int) (Math.abs(vel.x) * Gdx.graphics.getDeltaTime()); 110 | 111 | boolean xDiffIsLarger = Math.abs(velXDeltaTime) > Math.abs(velYDeltaTime); 112 | 113 | int upperBound = Math.max(Math.abs(velXDeltaTime), Math.abs(velYDeltaTime)); 114 | int min = Math.min(Math.abs(velXDeltaTime), Math.abs(velYDeltaTime)); 115 | float slope = (min == 0 || upperBound == 0) ? 0 : ((float) (min + 1) / (upperBound + 1)); 116 | 117 | int smallerCount; 118 | Vector3 lastValidLocation = new Vector3(getMatrixX(), getMatrixY(), 0); 119 | for (int i = 1; i <= upperBound; i++) { 120 | smallerCount = (int) Math.floor(i * slope); 121 | 122 | int yIncrease, xIncrease; 123 | if (xDiffIsLarger) { 124 | xIncrease = i; 125 | yIncrease = smallerCount; 126 | } else { 127 | yIncrease = i; 128 | xIncrease = smallerCount; 129 | } 130 | 131 | int modifiedMatrixY = getMatrixY() + (yIncrease * yModifier); 132 | int modifiedMatrixX = getMatrixX() + (xIncrease * xModifier); 133 | if (matrix.isWithinBounds(modifiedMatrixX, modifiedMatrixY)) { 134 | Element neighbor = matrix.get(modifiedMatrixX, modifiedMatrixY); 135 | if (neighbor == this) continue; 136 | boolean stopped = actOnNeighboringElement(neighbor, modifiedMatrixX, modifiedMatrixY, matrix, i == upperBound, i == 1, lastValidLocation, 0); 137 | if (stopped) { 138 | break; 139 | } 140 | lastValidLocation.x = modifiedMatrixX; 141 | lastValidLocation.y = modifiedMatrixY; 142 | 143 | } else { 144 | matrix.setElementAtIndex(getMatrixX(), getMatrixY(), ElementType.EMPTYCELL.createElementByMatrix(getMatrixX(), getMatrixY())); 145 | return; 146 | } 147 | } 148 | modifyColor(); 149 | } 150 | 151 | @Override 152 | protected boolean actOnNeighboringElement(Element neighbor, int modifiedMatrixX, int modifiedMatrixY, CellularMatrix matrix, boolean isFinal, boolean isFirst, Vector3 lastValidLocation, int depth) { 153 | if (neighbor instanceof EmptyCell || neighbor instanceof Particle) { 154 | if (isFinal) { 155 | swapPositions(matrix, neighbor, modifiedMatrixX, modifiedMatrixY); 156 | } else { 157 | return false; 158 | } 159 | } else if (neighbor instanceof Liquid || neighbor instanceof Solid) { 160 | moveToLastValid(matrix, lastValidLocation); 161 | dieAndReplace(matrix, containedElementType); 162 | return true; 163 | } else if (neighbor instanceof Gas) { 164 | if (isFinal) { 165 | moveToLastValidAndSwap(matrix, neighbor, modifiedMatrixX, modifiedMatrixY, lastValidLocation); 166 | return true; 167 | } 168 | return false; 169 | } 170 | return false; 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/player/Player.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.player; 2 | 3 | import com.badlogic.gdx.graphics.Color; 4 | import com.badlogic.gdx.graphics.Pixmap; 5 | import com.badlogic.gdx.math.Vector3; 6 | import com.badlogic.gdx.utils.Array; 7 | import com.gdx.cellular.CellularAutomaton; 8 | import com.gdx.cellular.CellularMatrix; 9 | import com.gdx.cellular.elements.Element; 10 | import com.gdx.cellular.elements.ElementType; 11 | import com.gdx.cellular.elements.EmptyCell; 12 | import com.gdx.cellular.elements.gas.Gas; 13 | import com.gdx.cellular.elements.liquid.Liquid; 14 | import com.gdx.cellular.elements.player.PlayerMeat; 15 | import com.gdx.cellular.elements.solid.movable.MovableSolid; 16 | import com.gdx.cellular.util.Assets; 17 | import com.gdx.cellular.util.MaterialMap; 18 | 19 | public class Player { 20 | 21 | Array> bodyMeat; 22 | MaterialMap playerTexture; 23 | Vector3 vel; 24 | private int matrixX; 25 | private int matrixY; 26 | private float yThreshold = 0; 27 | private float xThreshold = 0; 28 | 29 | public Player(int x, int y, int playerIndex, CellularMatrix matrix) { 30 | this.bodyMeat = createBody(x, y, playerIndex, matrix); 31 | this.vel = new Vector3(0,-124,0); 32 | this.matrixX = x; 33 | this.matrixY = y; 34 | } 35 | 36 | public void addVelocity(Vector3 velToAdd) { 37 | this.vel.add(velToAdd); 38 | } 39 | 40 | public void addVelocity(float x, float y) { 41 | this.vel.x += x; 42 | this.vel.y += y; 43 | } 44 | 45 | public void setVelocity(Vector3 velToTake) { 46 | this.vel.x = velToTake.x; 47 | this.vel.y = velToTake.y; 48 | } 49 | 50 | public void setVelocity(float x, float y) { 51 | this.vel.x = x; 52 | this.vel.y = y; 53 | } 54 | 55 | public void setXVelocity(int x) { 56 | this.vel.x = x; 57 | } 58 | 59 | public void setYVelocity(int y) { 60 | this.vel.y = y; 61 | } 62 | 63 | public void step(CellularMatrix matrix) { 64 | addVelocity(CellularAutomaton.gravity); 65 | 66 | int yModifier = vel.y < 0 ? -1 : 1; 67 | int xModifier = vel.x < 0 ? -1 : 1; 68 | float velYDeltaTimeFloat = (Math.abs(vel.y) * 1/60); 69 | float velXDeltaTimeFloat = (Math.abs(vel.x) * 1/60); 70 | int velXDeltaTime; 71 | int velYDeltaTime; 72 | if (velXDeltaTimeFloat < 1) { 73 | xThreshold += velXDeltaTimeFloat; 74 | velXDeltaTime = (int) xThreshold; 75 | if (Math.abs(velXDeltaTime) > 0) { 76 | xThreshold = 0; 77 | } 78 | } else { 79 | xThreshold = 0; 80 | velXDeltaTime = (int) velXDeltaTimeFloat; 81 | } 82 | if (velYDeltaTimeFloat < 1) { 83 | yThreshold += velYDeltaTimeFloat; 84 | velYDeltaTime = (int) yThreshold; 85 | if (Math.abs(velYDeltaTime) > 0) { 86 | yThreshold = 0; 87 | } 88 | } else { 89 | yThreshold = 0; 90 | velYDeltaTime = (int) velYDeltaTimeFloat; 91 | } 92 | 93 | boolean xDiffIsLarger = Math.abs(velXDeltaTime) > Math.abs(velYDeltaTime); 94 | 95 | int upperBound = Math.max(Math.abs(velXDeltaTime), Math.abs(velYDeltaTime)); 96 | int min = Math.min(Math.abs(velXDeltaTime), Math.abs(velYDeltaTime)); 97 | float floatFreq = (min == 0 || upperBound == 0) ? 0 : ((float) min / upperBound); 98 | int freqThreshold = 0; 99 | float freqCounter = 0; 100 | 101 | int smallerCount = 0; 102 | Vector3 formerLocation = new Vector3(getMatrixX(), getMatrixY(), 0); 103 | Vector3 lastValidLocation = new Vector3(getMatrixX(), getMatrixY(), 0); 104 | for (int i = 1; i <= upperBound; i++) { 105 | freqCounter += floatFreq; 106 | boolean thresholdPassed = Math.floor(freqCounter) > freqThreshold; 107 | if (floatFreq != 0 && thresholdPassed && min >= smallerCount) { 108 | freqThreshold = (int) Math.floor(freqCounter); 109 | smallerCount += 1; 110 | } 111 | 112 | int yIncrease, xIncrease; 113 | if (xDiffIsLarger) { 114 | xIncrease = i; 115 | yIncrease = smallerCount; 116 | } else { 117 | yIncrease = i; 118 | xIncrease = smallerCount; 119 | } 120 | 121 | int xOffset = xIncrease * xModifier; 122 | int yOffset = yIncrease * yModifier; 123 | boolean unstopped; 124 | for (Array meatRow : this.bodyMeat) { 125 | for (Element meat : meatRow) { 126 | PlayerMeat playerMeat = (PlayerMeat) meat; 127 | unstopped = playerMeat.stepAsPlayer(matrix, xOffset, yOffset); 128 | if (!unstopped) { 129 | moveToLastValid(matrix, lastValidLocation); 130 | // this.vel.x = 0; 131 | this.vel.y = 0; 132 | return; 133 | } 134 | } 135 | } 136 | lastValidLocation.x = getMatrixX() + xOffset; 137 | lastValidLocation.y = getMatrixY() + yOffset; 138 | } 139 | moveToLastValid(matrix, lastValidLocation); 140 | } 141 | 142 | private void moveToLastValid(CellularMatrix matrix, Vector3 lastValidLocation) { 143 | if (getMatrixX() == (int) lastValidLocation.x && getMatrixY() == (int) lastValidLocation.y) { 144 | return; 145 | } 146 | for (Array meatRow : this.bodyMeat) { 147 | for (Element meat : meatRow) { 148 | matrix.setElementAtIndex(meat.getMatrixX(), meat.getMatrixY(), ElementType.EMPTYCELL.createElementByMatrix(0,0)); 149 | } 150 | } 151 | int xOffset = (int) lastValidLocation.x - getMatrixX(); 152 | int yOffset = (int) lastValidLocation.y - getMatrixY(); 153 | for (Array meatRow : this.bodyMeat) { 154 | for (Element meat : meatRow) { 155 | PlayerMeat playerMeat = (PlayerMeat) meat; 156 | int neighborX = playerMeat.getMatrixX() + xOffset; 157 | int neighborY = playerMeat.getMatrixY() + yOffset; 158 | if (matrix.isWithinBounds(neighborX, neighborY)) { 159 | Element neighbor = matrix.get(neighborX, neighborY); 160 | if (neighbor instanceof EmptyCell) { 161 | // playerMeat.swapPositions(matrix, neighbor, neighborX, neighborY); 162 | matrix.setElementAtIndex(neighborX, neighborY, playerMeat); 163 | } else if (neighbor instanceof Liquid || neighbor instanceof MovableSolid || neighbor instanceof Gas) { 164 | ElementType.createParticleByMatrix(matrix, neighborX, neighborY, CellularAutomaton.gravity.cpy().scl(-1), neighbor); 165 | matrix.setElementAtIndex(neighborX, neighborY, playerMeat); 166 | } else if (neighbor instanceof PlayerMeat) { 167 | playerMeat.moveToLocation(matrix, neighborX, neighborY); 168 | } 169 | } else { 170 | matrix.setElementAtIndex(playerMeat.getMatrixX(), playerMeat.getMatrixY(), ElementType.EMPTYCELL.createElementByMatrix(playerMeat.getMatrixX(), playerMeat.getMatrixY())); 171 | } 172 | } 173 | } 174 | this.setMatrixX((int) lastValidLocation.x); 175 | this.setMatrixY((int) lastValidLocation.y); 176 | } 177 | 178 | private Array> createBody(int worldX, int worldY, int playerIndex, CellularMatrix matrix) { 179 | Pixmap pixmap = Assets.getPixmap("elementtextures/Player0.png"); 180 | this.playerTexture = new MaterialMap(pixmap); 181 | Array> elements = new Array<>(); 182 | for (int y = 0; y < playerTexture.h; y++) { 183 | Array innerArray = new Array<>(); 184 | elements.add(innerArray); 185 | for (int x = 0; x < playerTexture.w; x++) { 186 | Element meat = ElementType.PLAYERMEAT.createElementByMatrix(worldX + x, worldY + y); 187 | matrix.setElementAtIndex(worldX + x, worldY + y, meat); 188 | ((PlayerMeat) meat).setOwningPlayer(this); 189 | int rgb = this.playerTexture.getRGB(x, y); 190 | Color color = new Color(); 191 | Color.rgba8888ToColor(color, rgb); 192 | meat.color = color; 193 | innerArray.add(meat); 194 | } 195 | } 196 | return elements; 197 | } 198 | 199 | 200 | public void delete(CellularMatrix matrix) { 201 | bodyMeat.forEach(arr -> arr.forEach(meat -> matrix.setElementAtIndex(meat.getMatrixX(), meat.getMatrixY(), ElementType.EMPTYCELL.createElementByMatrix(meat.getMatrixX(), meat.getMatrixY())))); 202 | } 203 | 204 | public int getMatrixX() { 205 | return matrixX; 206 | } 207 | 208 | public void setMatrixX(int matrixX) { 209 | this.matrixX = matrixX; 210 | } 211 | 212 | public int getMatrixY() { 213 | return matrixY; 214 | } 215 | 216 | public void setMatrixY(int matrixY) { 217 | this.matrixY = matrixY; 218 | } 219 | 220 | 221 | } 222 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/spouts/ElementSpout.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.spouts; 2 | 3 | import com.gdx.cellular.elements.ElementType; 4 | 5 | import java.util.function.Consumer; 6 | 7 | import com.gdx.cellular.CellularMatrix.FunctionInput; 8 | import com.gdx.cellular.input.InputManager; 9 | 10 | public class ElementSpout implements Spout { 11 | 12 | int matrixX; 13 | int matrixY; 14 | ElementType sourceElement; 15 | int brushSize; 16 | InputManager.BRUSHTYPE brushtype; 17 | Consumer function; 18 | 19 | public ElementSpout(ElementType sourceElement, int matrixX, int matrixY, int brushSize, InputManager.BRUSHTYPE brushtype, Consumer function) { 20 | this.matrixX = matrixX; 21 | this.matrixY = matrixY; 22 | this.sourceElement = sourceElement; 23 | this.brushSize = brushSize; 24 | this.brushtype = brushtype; 25 | this.function = function; 26 | } 27 | 28 | @Override 29 | public FunctionInput setFunctionInputs(FunctionInput functionInput) { 30 | functionInput.setInput(FunctionInput.X, matrixX); 31 | functionInput.setInput(FunctionInput.Y, matrixY); 32 | functionInput.setInput(FunctionInput.BRUSH_SIZE, brushSize); 33 | functionInput.setInput(FunctionInput.BRUSH_TYPE, brushtype); 34 | functionInput.setInput(FunctionInput.ELEMENT_TYPE, sourceElement); 35 | return functionInput; 36 | } 37 | 38 | @Override 39 | public Consumer getFunction() { 40 | return function; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/spouts/ParticleSpout.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.spouts; 2 | 3 | import com.badlogic.gdx.math.Vector3; 4 | import com.gdx.cellular.CellularMatrix.FunctionInput; 5 | import com.gdx.cellular.elements.ElementType; 6 | import com.gdx.cellular.input.InputManager; 7 | 8 | 9 | import java.util.concurrent.ThreadLocalRandom; 10 | import java.util.function.Consumer; 11 | 12 | public class ParticleSpout implements Spout { 13 | 14 | int matrixX; 15 | int matrixY; 16 | ElementType sourceElement; 17 | int brushSize; 18 | InputManager.BRUSHTYPE brushtype; 19 | Consumer function; 20 | 21 | public ParticleSpout(ElementType sourceElement, int matrixX, int matrixY, int brushSize, InputManager.BRUSHTYPE brushtype, Consumer function) { 22 | this.matrixX = matrixX; 23 | this.matrixY = matrixY; 24 | this.sourceElement = sourceElement; 25 | this.brushSize = brushSize; 26 | this.brushtype = brushtype; 27 | this.function = function; 28 | } 29 | 30 | @Override 31 | public FunctionInput setFunctionInputs(FunctionInput functionInput) { 32 | functionInput.setInput(FunctionInput.X, matrixX); 33 | functionInput.setInput(FunctionInput.Y, matrixY); 34 | functionInput.setInput(FunctionInput.BRUSH_SIZE, brushSize); 35 | functionInput.setInput(FunctionInput.BRUSH_TYPE, brushtype); 36 | functionInput.setInput(FunctionInput.ELEMENT_TYPE, sourceElement); 37 | functionInput.setInput(FunctionInput.VELOCITY, generateRandomVelocity()); 38 | return functionInput; 39 | } 40 | 41 | @Override 42 | public Consumer getFunction() { 43 | return function; 44 | } 45 | 46 | private Vector3 generateRandomVelocity() { 47 | int x = ThreadLocalRandom.current().nextInt(-500, 500); 48 | int y = ThreadLocalRandom.current().nextInt(-500, 500); 49 | return new Vector3( x, y, 0); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/spouts/Spout.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.spouts; 2 | 3 | import com.gdx.cellular.CellularMatrix; 4 | import com.gdx.cellular.CellularMatrix.FunctionInput; 5 | 6 | import java.util.function.Consumer; 7 | 8 | public interface Spout { 9 | 10 | FunctionInput setFunctionInputs(FunctionInput functionInput); 11 | 12 | Consumer getFunction(); 13 | } 14 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/ui/ControlsMenu.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.ui; 2 | 3 | import com.badlogic.gdx.scenes.scene2d.Stage; 4 | import com.badlogic.gdx.scenes.scene2d.ui.Skin; 5 | import com.badlogic.gdx.scenes.scene2d.ui.Table; 6 | import com.badlogic.gdx.utils.viewport.Viewport; 7 | import com.gdx.cellular.input.InputManager; 8 | 9 | public class ControlsMenu { 10 | 11 | private final InputManager inputManager; 12 | private final Viewport viewport; 13 | 14 | public ControlsMenu(InputManager inputManager, Viewport viewport) { 15 | this.inputManager = inputManager; 16 | this.viewport = viewport; 17 | createMenu(viewport); 18 | } 19 | 20 | private void createMenu(Viewport viewport) { 21 | Stage stage = new Stage(viewport); 22 | Skin skin = Skins.getSkin("uiskin"); 23 | } 24 | 25 | 26 | } 27 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/ui/CursorActor.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.ui; 2 | 3 | import com.badlogic.gdx.graphics.g2d.Batch; 4 | import com.badlogic.gdx.graphics.glutils.ShapeRenderer; 5 | import com.badlogic.gdx.scenes.scene2d.Actor; 6 | import com.gdx.cellular.input.Cursor; 7 | 8 | public class CursorActor extends Actor { 9 | 10 | private ShapeRenderer shapeRenderer; 11 | public Cursor cursor; 12 | 13 | public CursorActor(ShapeRenderer shapeRenderer, Cursor cursor) { 14 | this.shapeRenderer = shapeRenderer; 15 | this.cursor = cursor; 16 | } 17 | 18 | @Override 19 | public void draw(Batch batch, float parentAlpha) { 20 | batch.end(); 21 | shapeRenderer.setProjectionMatrix(getStage().getCamera().combined); 22 | cursor.draw(shapeRenderer); 23 | batch.begin(); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/ui/MatrixActor.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.ui; 2 | 3 | import com.badlogic.gdx.graphics.Pixmap; 4 | import com.badlogic.gdx.graphics.Texture; 5 | import com.badlogic.gdx.graphics.g2d.Batch; 6 | import com.badlogic.gdx.graphics.glutils.ShapeRenderer; 7 | import com.badlogic.gdx.scenes.scene2d.Actor; 8 | import com.gdx.cellular.CellularAutomaton; 9 | import com.gdx.cellular.CellularMatrix; 10 | import com.gdx.cellular.util.ElementColumnStepper; 11 | import com.gdx.cellular.util.ElementRowDrawer; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | public class MatrixActor extends Actor { 17 | 18 | private final ShapeRenderer shapeRenderer; 19 | private final CellularMatrix matrix; 20 | // private final List shapeRenderers = new ArrayList<>(); 21 | 22 | public MatrixActor(ShapeRenderer shapeRenderer, CellularMatrix matrix) { 23 | this.shapeRenderer = shapeRenderer; 24 | this.matrix = matrix; 25 | // for (int i = 0; i < matrix.drawThreadCount; i++) { 26 | // ShapeRenderer sr = new ShapeRenderer(); 27 | // sr.setAutoShapeType(true); 28 | // shapeRenderers.add(sr); 29 | // } 30 | } 31 | 32 | @Override 33 | public void draw (Batch batch, float parentAlpha) { 34 | batch.end(); 35 | shapeRenderer.setProjectionMatrix(getStage().getCamera().combined); 36 | matrix.drawAll(shapeRenderer); 37 | // int numThreads = matrix.drawThreadCount; 38 | // int rowsToDraw = matrix.outerArraySize / numThreads; 39 | // List threads = new ArrayList<>(numThreads); 40 | // for (int t = 0; t < numThreads; t++) { 41 | // int minRow = t * (rowsToDraw + 1); 42 | // int maxRow = (t +1) * rowsToDraw; 43 | // if (t == numThreads - 1) { 44 | // maxRow = matrix.outerArraySize - 1; 45 | // } 46 | // Thread newThread = new Thread(new ElementRowDrawer(matrix, minRow, maxRow, shapeRenderers.get(t))); 47 | // threads.add(newThread); 48 | // } 49 | // for (Thread thread : threads) { 50 | // thread.start(); 51 | // } 52 | // for (Thread thread : threads) { 53 | // try { 54 | // thread.join(); 55 | // } catch (InterruptedException e) { 56 | // e.printStackTrace(); 57 | // } 58 | // } 59 | batch.begin(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/ui/ModeActor.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.ui; 2 | 3 | import com.badlogic.gdx.Gdx; 4 | import com.badlogic.gdx.graphics.Color; 5 | import com.badlogic.gdx.graphics.g2d.Batch; 6 | import com.badlogic.gdx.scenes.scene2d.Actor; 7 | import com.badlogic.gdx.scenes.scene2d.EventListener; 8 | import com.badlogic.gdx.scenes.scene2d.InputEvent; 9 | import com.badlogic.gdx.scenes.scene2d.InputListener; 10 | import com.badlogic.gdx.scenes.scene2d.ui.Label; 11 | import com.badlogic.gdx.scenes.scene2d.ui.Skin; 12 | import com.gdx.cellular.input.InputManager; 13 | 14 | public class ModeActor extends Actor { 15 | 16 | public InputManager inputManager; 17 | public Skin skin; 18 | public Label modeLabel; 19 | public Label elementLabel; 20 | public Label weatherLabel; 21 | public int pixelX; 22 | public int pixelY; 23 | 24 | public ModeActor(InputManager inputManager, int x, int y) { 25 | this.inputManager = inputManager; 26 | this.skin = Skins.getSkin("uiskin"); 27 | this.modeLabel = new Label(inputManager.getMouseMode().toString(), skin); 28 | this.elementLabel = new Label(inputManager.currentlySelectedElement.toString(), skin); 29 | this.weatherLabel = new Label("Weather", skin); 30 | this.pixelX = x; 31 | this.pixelY = y; 32 | } 33 | 34 | @Override 35 | public void draw(Batch batch, float parentAlpha) { 36 | this.modeLabel.setText("Current Mode: " + this.inputManager.getMouseMode().toString()); 37 | this.modeLabel.setX(pixelX); 38 | this.modeLabel.setY(pixelY); 39 | this.modeLabel.draw(batch, 1); 40 | this.elementLabel.setText("Current Element: " + this.inputManager.currentlySelectedElement.toString()); 41 | this.elementLabel.setX(this.pixelX); 42 | this.elementLabel.setY(this.pixelY - this.modeLabel.getHeight()/1.5f); 43 | this.elementLabel.draw(batch, 1); 44 | String weatherString = this.inputManager.weatherSystem.disabled ? "OFF" : "ON"; 45 | this.weatherLabel.setText("Weather: " + weatherString + " Element: " + this.inputManager.weatherSystem.elementType.toString()); 46 | this.weatherLabel.setX(this.pixelX); 47 | this.weatherLabel.setY(this.pixelY - (this.modeLabel.getHeight()/1.5f) * 2); 48 | this.weatherLabel.draw(batch, 1); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/ui/Skins.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.ui; 2 | 3 | import com.badlogic.gdx.assets.AssetManager; 4 | import com.badlogic.gdx.assets.loaders.SkinLoader; 5 | import com.badlogic.gdx.graphics.g2d.TextureAtlas; 6 | import com.badlogic.gdx.scenes.scene2d.ui.Skin; 7 | 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | public class Skins { 12 | 13 | private static final Map skinMap = new HashMap<>(); 14 | private static final AssetManager assetManager = new AssetManager(); 15 | 16 | private Skins() { 17 | throw new IllegalStateException("Should not be instantiated"); 18 | } 19 | 20 | static public Skin getSkin(String skinName) { 21 | Skin skin = skinMap.get(skinName); 22 | if (skin == null) { 23 | assetManager.load(skinName + ".atlas", TextureAtlas.class); 24 | SkinLoader.SkinParameter parameter = new SkinLoader.SkinParameter(skinName + ".atlas"); 25 | assetManager.load(skinName + ".json", Skin.class, parameter); 26 | assetManager.finishLoading(); 27 | Skin loadedSkin = assetManager.get(skinName + ".json", Skin.class); 28 | skinMap.put(skinName, loadedSkin); 29 | skin = loadedSkin; 30 | } 31 | return skin; 32 | } 33 | 34 | 35 | } 36 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/util/Assets.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.util; 2 | 3 | import com.badlogic.gdx.assets.AssetManager; 4 | import com.badlogic.gdx.files.FileHandle; 5 | import com.badlogic.gdx.graphics.Pixmap; 6 | import com.badlogic.gdx.scenes.scene2d.ui.Skin; 7 | 8 | public class Assets { 9 | 10 | private static final AssetManager assetManager; 11 | 12 | private Assets() { 13 | throw new IllegalStateException("Should not be instantiated"); 14 | } 15 | 16 | static { 17 | assetManager = new AssetManager(); 18 | FileHandle texturesFolder = new FileHandle("elementtextures"); 19 | for (FileHandle fileHandle : texturesFolder.list()) { 20 | assetManager.load(texturesFolder.name() + "/" + fileHandle.name(), Pixmap.class); 21 | } 22 | assetManager.finishLoading(); 23 | } 24 | 25 | public static Pixmap getPixmap(String s) { 26 | if (assetManager.isLoaded(s)) { 27 | return assetManager.get(s); 28 | } else { 29 | return null; 30 | } 31 | } 32 | 33 | public static Skin getSkin(String s) { 34 | if (assetManager.isLoaded(s)) { 35 | return assetManager.get(s); 36 | } else { 37 | return null; 38 | } 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/util/Chunk.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.util; 2 | 3 | import com.badlogic.gdx.math.Vector3; 4 | import com.gdx.cellular.boids.Boid; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Enumeration; 8 | import java.util.List; 9 | import java.util.concurrent.ConcurrentHashMap; 10 | import java.util.stream.Collectors; 11 | 12 | public class Chunk { 13 | 14 | public static int size = 32; 15 | 16 | private boolean shouldStep = true; 17 | private boolean shouldStepNextFrame = true; 18 | private Vector3 topLeft; 19 | private Vector3 bottomRight; 20 | private ConcurrentHashMap boidMap = new ConcurrentHashMap<>(); 21 | 22 | public Chunk(Vector3 topLeft, Vector3 bottomRight) { 23 | this.topLeft = topLeft; 24 | this.bottomRight = bottomRight; 25 | } 26 | 27 | public Chunk() { 28 | 29 | } 30 | 31 | public void setTopLeft(Vector3 topLeft) { 32 | this.topLeft = topLeft; 33 | } 34 | 35 | public Vector3 getTopLeft() { 36 | return topLeft; 37 | } 38 | 39 | public void setShouldStep(boolean shouldStep) { 40 | this.shouldStep = shouldStep; 41 | } 42 | 43 | public boolean getShouldStep() { 44 | return this.shouldStep; 45 | } 46 | 47 | public void setShouldStepNextFrame(boolean shouldStepNextFrame) { 48 | this.shouldStepNextFrame = shouldStepNextFrame; 49 | } 50 | 51 | public boolean getShouldStepNextFrame() { 52 | return this.shouldStepNextFrame; 53 | } 54 | 55 | public void setBottomRight(Vector3 bottomRight) { 56 | this.bottomRight = bottomRight; 57 | } 58 | 59 | public Vector3 getBottomRight() { 60 | return bottomRight; 61 | } 62 | 63 | public void shiftShouldStepAndReset() { 64 | this.shouldStep = this.shouldStepNextFrame; 65 | this.shouldStepNextFrame = false; 66 | } 67 | 68 | public void addBoid(Boid boid) { 69 | this.boidMap.put(boid, ""); 70 | } 71 | 72 | public void removeBoid(Boid boid) { 73 | this.boidMap.remove(boid); 74 | } 75 | 76 | public List getAllBoids() { 77 | return new ArrayList<>(this.boidMap.keySet()); 78 | } 79 | 80 | public void removeAllBoids() { 81 | this.boidMap.clear(); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/util/ElementColumnStepper.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.util; 2 | 3 | import com.gdx.cellular.CellularMatrix; 4 | 5 | public class ElementColumnStepper implements Runnable { 6 | 7 | 8 | public CellularMatrix matrix; 9 | public int colIndex; 10 | 11 | public ElementColumnStepper(CellularMatrix matrix, int colIndex) { 12 | this.matrix = matrix; 13 | this.colIndex = colIndex; 14 | } 15 | 16 | @Override 17 | public void run() { 18 | matrix.stepProvidedColumns(colIndex); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/util/ElementRowDrawer.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.util; 2 | 3 | import com.badlogic.gdx.graphics.glutils.ShapeRenderer; 4 | import com.gdx.cellular.CellularMatrix; 5 | 6 | public class ElementRowDrawer implements Runnable { 7 | 8 | public CellularMatrix matrix; 9 | public int minRow; 10 | public int maxRow; 11 | public ShapeRenderer sr; 12 | 13 | public ElementRowDrawer(CellularMatrix matrix, int minRow, int maxRow, ShapeRenderer sr) { 14 | this.matrix = matrix; 15 | this.minRow = minRow; 16 | this.maxRow = maxRow; 17 | this.sr = sr; 18 | } 19 | 20 | @Override 21 | public void run() { 22 | matrix.drawProvidedRows(minRow, maxRow, sr); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/util/ElementRowStepper.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.util; 2 | 3 | import com.gdx.cellular.CellularMatrix; 4 | 5 | public class ElementRowStepper implements Runnable { 6 | 7 | public int minRow; 8 | public int maxRow; 9 | public CellularMatrix matrix; 10 | 11 | public ElementRowStepper(int minRow, int maxRow, CellularMatrix matrix) { 12 | this.minRow = minRow; 13 | this.maxRow = maxRow; 14 | this.matrix = matrix; 15 | } 16 | 17 | @Override 18 | public void run() { 19 | matrix.stepProvidedRows(minRow, maxRow); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/util/GameManager.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.util; 2 | 3 | import com.badlogic.gdx.utils.Array; 4 | import com.gdx.cellular.CellularAutomaton; 5 | import com.gdx.cellular.CellularMatrix; 6 | import com.gdx.cellular.player.Player; 7 | 8 | public class GameManager { 9 | 10 | public CellularAutomaton cellularAutomaton; 11 | public final int maxPlayers = 4; 12 | Array players = new Array<>(); 13 | 14 | public GameManager(CellularAutomaton cellularAutomaton) { 15 | this.cellularAutomaton = cellularAutomaton; 16 | for (int i = 0; i < maxPlayers; i++) { 17 | players.add(null); 18 | } 19 | } 20 | 21 | public void stepPlayers(CellularMatrix matrix) { 22 | for (int i = 0; i < players.size; i++) { 23 | Player player = players.get(i); 24 | if (player == null) { 25 | continue; 26 | } 27 | player.step(matrix); 28 | } 29 | } 30 | 31 | public Player createPlayer(int x, int y) { 32 | int index = -1; 33 | for (int i = 0; i < players.size; i++) { 34 | Player player = players.get(i); 35 | if (player == null) { 36 | index = i; 37 | break; 38 | } 39 | } 40 | if (index == -1) { 41 | return null; 42 | } 43 | Player newPlayer = new Player(x, y, index, cellularAutomaton.matrix); 44 | players.set(index, newPlayer); 45 | return newPlayer; 46 | } 47 | 48 | public void deletePlayer(int playerIndex) { 49 | this.players.get(playerIndex).delete(cellularAutomaton.matrix); 50 | this.players.set(playerIndex, null); 51 | } 52 | 53 | public Player getPlayer(int index) { 54 | if (index < 0 || index >= players.size) { 55 | return null; 56 | } 57 | return players.get(index); 58 | } 59 | 60 | 61 | } 62 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/util/MaterialMap.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.util; 2 | 3 | import com.badlogic.gdx.graphics.Pixmap; 4 | 5 | public class MaterialMap { 6 | 7 | Pixmap img; 8 | public int w; 9 | public int h; 10 | 11 | public MaterialMap(Pixmap img) { 12 | this.img = img; 13 | this.w = img.getWidth(); 14 | this.h = img.getHeight(); 15 | } 16 | 17 | public int getRGB(int x, int y) { 18 | int relativeX = x == 0 ? 0 : Math.abs(x) % w; 19 | int relativeY = y == 0 ? 0 : Math.abs(y) % h; 20 | return img.getPixel(relativeX, relativeY); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/util/TextInputHandler.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.util; 2 | 3 | import com.badlogic.gdx.Input; 4 | import com.gdx.cellular.input.InputManager; 5 | 6 | import java.util.function.Function; 7 | 8 | public class TextInputHandler implements Input.TextInputListener { 9 | private final Function function; 10 | private final InputManager inputManager; 11 | 12 | public TextInputHandler(InputManager inputManager, Function function) { 13 | this.inputManager = inputManager; 14 | this.function = function; 15 | 16 | } 17 | 18 | @Override 19 | public void input (String text) { 20 | String sanitizedInput = text.replaceAll("[^a-zA-Z0-9_]+", "_"); 21 | function.apply(sanitizedInput); 22 | } 23 | 24 | @Override 25 | public void canceled () { 26 | inputManager.setIsPaused(false); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /core/src/com/gdx/cellular/util/WeatherSystem.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.util; 2 | 3 | import com.badlogic.gdx.math.Vector3; 4 | import com.gdx.cellular.CellularMatrix; 5 | import com.gdx.cellular.elements.Element; 6 | import com.gdx.cellular.elements.ElementType; 7 | 8 | public class WeatherSystem { 9 | 10 | public ElementType elementType; 11 | public int weight; 12 | public boolean disabled = true; 13 | 14 | public WeatherSystem(ElementType elementType, int weight) { 15 | this.elementType = elementType; 16 | this.weight = weight; 17 | } 18 | 19 | public void enact(CellularMatrix matrix) { 20 | if (disabled) { 21 | return; 22 | } 23 | int numberToEmit = weight; 24 | for (int i = 0; i < numberToEmit; i++) { 25 | int x = (int) (Math.random() * (matrix.innerArraySize - 1)); 26 | Element newElement = elementType.createElementByMatrix(x, matrix.outerArraySize - 1); 27 | newElement.vel = new Vector3(30, -256, 0); 28 | matrix.setElementAtIndex(x, matrix.outerArraySize - 1, newElement); 29 | matrix.reportToChunkActive(x, matrix.outerArraySize - 1); 30 | } 31 | } 32 | 33 | public void setElementType(ElementType elementType) { 34 | this.elementType = elementType; 35 | } 36 | 37 | public void setWeight(int weight) { 38 | if (weight < 0) { 39 | this.weight = 0; 40 | return; 41 | } else if (weight > 20) { 42 | this.weight = 20; 43 | return; 44 | } 45 | this.weight = weight; 46 | } 47 | 48 | public void enable() { 49 | this.disabled = false; 50 | } 51 | 52 | public void disable() { 53 | this.disabled = true; 54 | } 55 | 56 | 57 | public void toggle() { 58 | this.disabled = !this.disabled; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /desktop/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "java" 2 | 3 | sourceCompatibility = 1.8 4 | sourceSets.main.java.srcDirs = [ "src/" ] 5 | 6 | project.ext.mainClassName = "com.gdx.cellular.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 debug(dependsOn: classes, type: JavaExec) { 18 | main = project.mainClassName 19 | classpath = sourceSets.main.runtimeClasspath 20 | standardInput = System.in 21 | workingDir = project.assetsDir 22 | ignoreExitValue = true 23 | debug = true 24 | } 25 | 26 | task dist(type: Jar) { 27 | from files(sourceSets.main.output.classesDir) 28 | from files(sourceSets.main.output.resourcesDir) 29 | from {configurations.compile.collect {zipTree(it)}} 30 | from files(project.assetsDir); 31 | 32 | manifest { 33 | attributes 'Main-Class': project.mainClassName 34 | } 35 | } 36 | 37 | dist.dependsOn classes 38 | 39 | eclipse { 40 | project { 41 | name = appName + "-desktop" 42 | linkedResource name: 'assets', type: '2', location: 'PARENT-1-PROJECT_LOC/core/assets' 43 | } 44 | } 45 | 46 | task afterEclipseImport(description: "Post processing after project generation", group: "IDE") { 47 | doLast { 48 | def classpath = new XmlParser().parse(file(".classpath")) 49 | new Node(classpath, "classpathentry", [ kind: 'src', path: 'assets' ]); 50 | def writer = new FileWriter(file(".classpath")) 51 | def printer = new XmlNodePrinter(new PrintWriter(writer)) 52 | printer.setPreserveWhitespace(true) 53 | printer.print(classpath) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /desktop/src/com/gdx/cellular/desktop/DesktopLauncher.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.desktop; 2 | 3 | import com.badlogic.gdx.backends.lwjgl.LwjglApplication; 4 | import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration; 5 | import com.gdx.cellular.CellularAutomaton; 6 | 7 | public class DesktopLauncher { 8 | public static void main (String[] arg) { 9 | LwjglApplicationConfiguration config = new LwjglApplicationConfiguration(); 10 | // config.vSyncEnabled = false; 11 | // config.foregroundFPS = 0; // Setting to 0 disables foreground fps throttling 12 | // config.backgroundFPS = 0; 13 | config.width = 1280; // 480; 14 | config.height = 800; //800; 15 | new LwjglApplication(new CellularAutomaton(), config); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.daemon=true 2 | org.gradle.jvmargs=-Xms128m -Xmx1500m 3 | org.gradle.configureondemand=false 4 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidMcLaughlin208/FallingSandJava/6d1b95086b64443a5dea3b32377b2cc84efab024/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon May 04 15:35:42 PDT 2020 2 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.8.1-all.zip 3 | distributionBase=GRADLE_USER_HOME 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 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 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /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 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 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 Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /html/build.gradle: -------------------------------------------------------------------------------- 1 | gwt { 2 | gwtVersion='2.8.0' // Should match the gwt version used for building the gwt backend 3 | maxHeapSize="1G" // Default 256m is not enough for gwt compiler. GWT is HUNGRY 4 | minHeapSize="1G" 5 | 6 | src = files(file("src/")) // Needs to be in front of "modules" below. 7 | modules 'com.gdx.cellular.GdxDefinition' 8 | devModules 'com.gdx.cellular.GdxDefinitionSuperdev' 9 | project.webAppDirName = 'webapp' 10 | 11 | compiler { 12 | strict = true; 13 | disableCastChecking = true; 14 | } 15 | } 16 | 17 | import org.wisepersist.gradle.plugins.gwt.GwtSuperDev 18 | 19 | def HttpFileServer server = null 20 | def httpFilePort = 8080 21 | 22 | task startHttpServer () { 23 | dependsOn draftCompileGwt 24 | 25 | String output = project.buildDir.path + "/gwt/draftOut" 26 | 27 | doLast { 28 | copy { 29 | from "webapp" 30 | into output 31 | } 32 | 33 | copy { 34 | from "war" 35 | into output 36 | } 37 | 38 | server = new SimpleHttpFileServerFactory().start(new File(output), httpFilePort) 39 | 40 | println "Server started in directory " + server.getContentRoot() + ", http://localhost:" + server.getPort() 41 | } 42 | } 43 | 44 | task superDev (type: GwtSuperDev) { 45 | dependsOn startHttpServer 46 | doFirst { 47 | gwt.modules = gwt.devModules 48 | } 49 | } 50 | 51 | 52 | task dist(dependsOn: [clean, compileGwt]) { 53 | doLast { 54 | file("build/dist").mkdirs() 55 | copy { 56 | from "build/gwt/out" 57 | into "build/dist" 58 | } 59 | copy { 60 | from "webapp" 61 | into "build/dist" 62 | } 63 | copy { 64 | from "war" 65 | into "build/dist" 66 | } 67 | } 68 | } 69 | 70 | task addSource { 71 | doLast { 72 | sourceSets.main.compileClasspath += files(project(':core').sourceSets.main.allJava.srcDirs) 73 | } 74 | } 75 | 76 | tasks.compileGwt.dependsOn(addSource) 77 | tasks.draftCompileGwt.dependsOn(addSource) 78 | 79 | sourceCompatibility = 1.8 80 | sourceSets.main.java.srcDirs = [ "src/" ] 81 | 82 | 83 | eclipse.project { 84 | name = appName + "-html" 85 | } 86 | -------------------------------------------------------------------------------- /html/src/com/gdx/cellular/GdxDefinition.gwt.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /html/src/com/gdx/cellular/GdxDefinitionSuperdev.gwt.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /html/src/com/gdx/cellular/client/HtmlLauncher.java: -------------------------------------------------------------------------------- 1 | package com.gdx.cellular.client; 2 | 3 | import com.badlogic.gdx.ApplicationListener; 4 | import com.badlogic.gdx.backends.gwt.GwtApplication; 5 | import com.badlogic.gdx.backends.gwt.GwtApplicationConfiguration; 6 | import com.gdx.cellular.CellularAutomaton; 7 | 8 | public class HtmlLauncher extends GwtApplication { 9 | 10 | // USE THIS CODE FOR A FIXED SIZE APPLICATION 11 | @Override 12 | public GwtApplicationConfiguration getConfig () { 13 | return new GwtApplicationConfiguration(480, 320); 14 | } 15 | // END CODE FOR FIXED SIZE APPLICATION 16 | 17 | // UNCOMMENT THIS CODE FOR A RESIZABLE APPLICATION 18 | // PADDING is to avoid scrolling in iframes, set to 20 if you have problems 19 | // private static final int PADDING = 0; 20 | // private GwtApplicationConfiguration cfg; 21 | // 22 | // @Override 23 | // public GwtApplicationConfiguration getConfig() { 24 | // int w = Window.getClientWidth() - PADDING; 25 | // int h = Window.getClientHeight() - PADDING; 26 | // cfg = new GwtApplicationConfiguration(w, h); 27 | // Window.enableScrolling(false); 28 | // Window.setMargin("0"); 29 | // Window.addResizeHandler(new ResizeListener()); 30 | // cfg.preferFlash = false; 31 | // return cfg; 32 | // } 33 | // 34 | // class ResizeListener implements ResizeHandler { 35 | // @Override 36 | // public void onResize(ResizeEvent event) { 37 | // int width = event.getWidth() - PADDING; 38 | // int height = event.getHeight() - PADDING; 39 | // getRootPanel().setWidth("" + width + "px"); 40 | // getRootPanel().setHeight("" + height + "px"); 41 | // getApplicationListener().resize(width, height); 42 | // Gdx.graphics.setWindowedMode(width, height); 43 | // } 44 | // } 45 | // END OF CODE FOR RESIZABLE APPLICATION 46 | 47 | @Override 48 | public ApplicationListener createApplicationListener () { 49 | return new CellularAutomaton(); 50 | } 51 | } -------------------------------------------------------------------------------- /html/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /html/webapp/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CellularAutomaton 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |

15 | 16 | 17 | 18 | 37 | 38 | -------------------------------------------------------------------------------- /html/webapp/refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidMcLaughlin208/FallingSandJava/6d1b95086b64443a5dea3b32377b2cc84efab024/html/webapp/refresh.png -------------------------------------------------------------------------------- /html/webapp/soundmanager2-setup.js: -------------------------------------------------------------------------------- 1 | window.SM2_DEFER = true; -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /media/Box2DScene.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidMcLaughlin208/FallingSandJava/6d1b95086b64443a5dea3b32377b2cc84efab024/media/Box2DScene.gif -------------------------------------------------------------------------------- /media/ExplosionScene.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidMcLaughlin208/FallingSandJava/6d1b95086b64443a5dea3b32377b2cc84efab024/media/ExplosionScene.gif -------------------------------------------------------------------------------- /media/SandScene.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidMcLaughlin208/FallingSandJava/6d1b95086b64443a5dea3b32377b2cc84efab024/media/SandScene.gif -------------------------------------------------------------------------------- /media/housescene.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidMcLaughlin208/FallingSandJava/6d1b95086b64443a5dea3b32377b2cc84efab024/media/housescene.gif -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include 'desktop', 'html', 'core' --------------------------------------------------------------------------------