diff --git a/RhythmBullet.sln b/RhythmBullet.sln
new file mode 100644
index 0000000..f8a44a5
--- /dev/null
+++ b/RhythmBullet.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.28010.2019
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RhythmBullet", "RhythmBullet\RhythmBullet.csproj", "{4242553D-40F9-40F0-9AE6-CB6771DD9CF9}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {4242553D-40F9-40F0-9AE6-CB6771DD9CF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4242553D-40F9-40F0-9AE6-CB6771DD9CF9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4242553D-40F9-40F0-9AE6-CB6771DD9CF9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4242553D-40F9-40F0-9AE6-CB6771DD9CF9}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {C7334E35-D9AE-4FF0-A8AE-DC3A1ED7CB86}
+ EndGlobalSection
+EndGlobal
diff --git a/RhythmBullet/Content/Content.mgcb b/RhythmBullet/Content/Content.mgcb
new file mode 100644
index 0000000..ddc4c36
--- /dev/null
+++ b/RhythmBullet/Content/Content.mgcb
@@ -0,0 +1,15 @@
+
+#----------------------------- Global Properties ----------------------------#
+
+/outputDir:bin/$(Platform)
+/intermediateDir:obj/$(Platform)
+/platform:DesktopGL
+/config:
+/profile:Reach
+/compress:False
+
+#-------------------------------- References --------------------------------#
+
+
+#---------------------------------- Content ---------------------------------#
+
diff --git a/RhythmBullet/Icon.bmp b/RhythmBullet/Icon.bmp
new file mode 100644
index 0000000..2b48165
Binary files /dev/null and b/RhythmBullet/Icon.bmp differ
diff --git a/RhythmBullet/Icon.ico b/RhythmBullet/Icon.ico
new file mode 100644
index 0000000..7d9dec1
Binary files /dev/null and b/RhythmBullet/Icon.ico differ
diff --git a/RhythmBullet/Program.cs b/RhythmBullet/Program.cs
new file mode 100644
index 0000000..1aff434
--- /dev/null
+++ b/RhythmBullet/Program.cs
@@ -0,0 +1,22 @@
+using System;
+
+namespace RhythmBullet
+{
+ ///
+ /// The main class.
+ ///
+ public static class Program
+ {
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ using (var game = new RhythmBulletGame())
+ {
+ game.Run();
+ }
+ }
+ }
+}
diff --git a/RhythmBullet/Properties/AssemblyInfo.cs b/RhythmBullet/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..33238ab
--- /dev/null
+++ b/RhythmBullet/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("RhythmBullet")]
+[assembly: AssemblyProduct("RhythmBullet")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyCopyright("Copyright © 2018")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("78eb6f5c-0f37-458a-9928-0fd0799c93a5")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/RhythmBullet/RhythmBullet.csproj b/RhythmBullet/RhythmBullet.csproj
new file mode 100644
index 0000000..d1e7e6b
--- /dev/null
+++ b/RhythmBullet/RhythmBullet.csproj
@@ -0,0 +1,123 @@
+
+
+
+
+ Debug
+ AnyCPU
+ 8.0.30703
+ 2.0
+ {4242553D-40F9-40F0-9AE6-CB6771DD9CF9}
+ WinExe
+ Properties
+ RhythmBullet
+ RhythmBullet
+ 512
+ DesktopGL
+ v4.5
+
+
+ true
+ bin\$(MonoGamePlatform)\$(Platform)\$(Configuration)\
+ DEBUG;TRACE;LINUX
+ full
+ AnyCPU
+ prompt
+ false
+ 4
+
+
+ bin\$(MonoGamePlatform)\$(Platform)\$(Configuration)\
+ TRACE;LINUX
+ true
+ pdbonly
+ AnyCPU
+ prompt
+ false
+ 4
+
+
+ Icon.ico
+
+
+ app.manifest
+
+
+
+
+
+
+
+
+
+
+
+ $(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\MonoGame.Framework.dll
+
+
+
+
+
+
+
+
+
+
+
+ x86\SDL2.dll
+ PreserveNewest
+
+
+ x64\SDL2.dll
+ PreserveNewest
+
+
+ x86\soft_oal.dll
+ PreserveNewest
+
+
+ x64\soft_oal.dll
+ PreserveNewest
+
+
+ x86\libSDL2-2.0.so.0
+ PreserveNewest
+
+
+ x64\libSDL2-2.0.so.0
+ PreserveNewest
+
+
+ x86\libopenal.so.1
+ PreserveNewest
+
+
+ x64\libopenal.so.1
+ PreserveNewest
+
+
+ libSDL2-2.0.0.dylib
+ PreserveNewest
+
+
+ libopenal.1.dylib
+ PreserveNewest
+
+
+ MonoGame.Framework.dll.config
+ PreserveNewest
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/RhythmBullet/RhythmBulletGame.cs b/RhythmBullet/RhythmBulletGame.cs
new file mode 100644
index 0000000..a8bff22
--- /dev/null
+++ b/RhythmBullet/RhythmBulletGame.cs
@@ -0,0 +1,85 @@
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+using Microsoft.Xna.Framework.Input;
+using RhythmBullet.Zer01HD.UI.Screen;
+
+namespace RhythmBullet
+{
+ ///
+ /// This is the main type for your game.
+ ///
+ public class RhythmBulletGame : Game
+ {
+ private Screen currentScreen;
+
+ GraphicsDeviceManager graphics;
+ SpriteBatch spriteBatch;
+
+ public RhythmBulletGame()
+ {
+ graphics = new GraphicsDeviceManager(this);
+ Content.RootDirectory = "Content";
+ graphics.PreferredBackBufferWidth = 1920;
+ graphics.PreferredBackBufferHeight = 1080;
+ }
+
+ ///
+ /// Allows the game to perform any initialization it needs to before starting to run.
+ /// This is where it can query for any required services and load any non-graphic
+ /// related content. Calling base.Initialize will enumerate through any components
+ /// and initialize them as well.
+ ///
+ protected override void Initialize()
+ {
+ // TODO: Add your initialization logic here
+ base.Initialize();
+ }
+
+ ///
+ /// LoadContent will be called once per game and is the place to load
+ /// all of your content.
+ ///
+ protected override void LoadContent()
+ {
+ // Create a new SpriteBatch, which can be used to draw textures.
+ spriteBatch = new SpriteBatch(GraphicsDevice);
+ // TODO: use this.Content to load your game content here
+ }
+
+ ///
+ /// UnloadContent will be called once per game and is the place to unload
+ /// game-specific content.
+ ///
+ protected override void UnloadContent()
+ {
+ // TODO: Unload any non ContentManager content here
+ }
+
+ ///
+ /// Allows the game to run logic such as updating the world,
+ /// checking for collisions, gathering input, and playing audio.
+ ///
+ /// Provides a snapshot of timing values.
+ protected override void Update(GameTime gameTime)
+ {
+ if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape)) Exit();
+
+ // TODO: Add your update logic here
+
+ base.Update(gameTime);
+ }
+
+ ///
+ /// This is called when the game should draw itself.
+ ///
+ /// Provides a snapshot of timing values.
+ protected override void Draw(GameTime gameTime)
+ {
+ GraphicsDevice.Clear(Color.CornflowerBlue);
+
+ // TODO: Add your drawing code here
+
+ base.Draw(gameTime);
+ }
+ }
+}
diff --git a/RhythmBullet/Zer01HD/UI/Page/Page.cs b/RhythmBullet/Zer01HD/UI/Page/Page.cs
new file mode 100644
index 0000000..8e39ab8
--- /dev/null
+++ b/RhythmBullet/Zer01HD/UI/Page/Page.cs
@@ -0,0 +1,29 @@
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace RhythmBullet.Zer01HD.UI
+{
+ class Page
+ {
+ private int x, y;
+ public Page()
+ {
+
+ }
+
+ public void Update(GameTime gameTime)
+ {
+
+ }
+
+ public void Draw(SpriteBatch batch)
+ {
+
+ }
+ }
+}
diff --git a/RhythmBullet/Zer01HD/UI/Page/PageManager.cs b/RhythmBullet/Zer01HD/UI/Page/PageManager.cs
new file mode 100644
index 0000000..df1e898
--- /dev/null
+++ b/RhythmBullet/Zer01HD/UI/Page/PageManager.cs
@@ -0,0 +1,31 @@
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace RhythmBullet.Zer01HD.UI
+{
+ class PageManager
+ {
+ private readonly List pages = new List();
+
+ public void Act(GameTime gameTime)
+ {
+ foreach (Page page in pages)
+ {
+ page.act(gameTime);
+ }
+ }
+
+ public void Draw(SpriteBatch spriteBatch)
+ {
+ foreach (Page page in pages)
+ {
+ page.draw(spriteBatch);
+ }
+ }
+ }
+}
diff --git a/RhythmBullet/Zer01HD/UI/Screen/Screen.cs b/RhythmBullet/Zer01HD/UI/Screen/Screen.cs
new file mode 100644
index 0000000..2bf3283
--- /dev/null
+++ b/RhythmBullet/Zer01HD/UI/Screen/Screen.cs
@@ -0,0 +1,33 @@
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace RhythmBullet.Zer01HD.UI.Screen
+{
+ class Screen
+ {
+ public void Update(GameTime gameTime)
+ {
+
+ }
+
+ public void Draw(SpriteBatch spriteBatch)
+ {
+
+ }
+
+ public void Show()
+ {
+
+ }
+
+ public void Hide()
+ {
+
+ }
+ }
+}
diff --git a/RhythmBullet/app.manifest b/RhythmBullet/app.manifest
new file mode 100644
index 0000000..ed00b80
--- /dev/null
+++ b/RhythmBullet/app.manifest
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true/pm
+
+
+
+
diff --git a/old/.classpath b/old/.classpath
new file mode 100644
index 0000000..e4d0db4
--- /dev/null
+++ b/old/.classpath
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/old/.gradle/4.6/fileChanges/last-build.bin b/old/.gradle/4.6/fileChanges/last-build.bin
new file mode 100644
index 0000000..f76dd23
Binary files /dev/null and b/old/.gradle/4.6/fileChanges/last-build.bin differ
diff --git a/old/.gradle/4.6/fileHashes/fileHashes.bin b/old/.gradle/4.6/fileHashes/fileHashes.bin
new file mode 100644
index 0000000..80d9885
Binary files /dev/null and b/old/.gradle/4.6/fileHashes/fileHashes.bin differ
diff --git a/old/.gradle/4.6/fileHashes/fileHashes.lock b/old/.gradle/4.6/fileHashes/fileHashes.lock
new file mode 100644
index 0000000..9ac3fd1
Binary files /dev/null and b/old/.gradle/4.6/fileHashes/fileHashes.lock differ
diff --git a/old/.gradle/4.6/taskHistory/taskHistory.bin b/old/.gradle/4.6/taskHistory/taskHistory.bin
new file mode 100644
index 0000000..c312825
Binary files /dev/null and b/old/.gradle/4.6/taskHistory/taskHistory.bin differ
diff --git a/old/.gradle/4.6/taskHistory/taskHistory.lock b/old/.gradle/4.6/taskHistory/taskHistory.lock
new file mode 100644
index 0000000..431ea0e
Binary files /dev/null and b/old/.gradle/4.6/taskHistory/taskHistory.lock differ
diff --git a/old/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/old/.gradle/buildOutputCleanup/buildOutputCleanup.lock
new file mode 100644
index 0000000..cc3c6b5
Binary files /dev/null and b/old/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ
diff --git a/old/.gradle/buildOutputCleanup/cache.properties b/old/.gradle/buildOutputCleanup/cache.properties
new file mode 100644
index 0000000..e905e7b
--- /dev/null
+++ b/old/.gradle/buildOutputCleanup/cache.properties
@@ -0,0 +1,2 @@
+#Mon Sep 10 00:40:35 CDT 2018
+gradle.version=4.6
diff --git a/old/.gradle/buildOutputCleanup/outputFiles.bin b/old/.gradle/buildOutputCleanup/outputFiles.bin
new file mode 100644
index 0000000..60d5744
Binary files /dev/null and b/old/.gradle/buildOutputCleanup/outputFiles.bin differ
diff --git a/old/.gradle/vcsWorkingDirs/gc.properties b/old/.gradle/vcsWorkingDirs/gc.properties
new file mode 100644
index 0000000..e69de29
diff --git a/old/.project b/old/.project
new file mode 100644
index 0000000..cb1ec43
--- /dev/null
+++ b/old/.project
@@ -0,0 +1,42 @@
+
+
+ RhythmBullet
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.springsource.ide.eclipse.gradle.core.nature
+ org.eclipse.jdt.core.javanature
+
+
+
+ 1536558856206
+
+ 26
+
+ org.eclipse.ui.ide.orFilterMatcher
+
+
+ org.eclipse.ui.ide.multiFilter
+ 1.0-projectRelativePath-equals-true-false-android
+
+
+ org.eclipse.ui.ide.multiFilter
+ 1.0-projectRelativePath-equals-true-false-core
+
+
+ org.eclipse.ui.ide.multiFilter
+ 1.0-projectRelativePath-equals-true-false-desktop
+
+
+
+
+
+
diff --git a/old/.settings/gradle/org.springsource.ide.eclipse.gradle.core.import.prefs b/old/.settings/gradle/org.springsource.ide.eclipse.gradle.core.import.prefs
new file mode 100644
index 0000000..528428a
--- /dev/null
+++ b/old/.settings/gradle/org.springsource.ide.eclipse.gradle.core.import.prefs
@@ -0,0 +1,9 @@
+#org.springsource.ide.eclipse.gradle.core.preferences.GradleImportPreferences
+#Mon Sep 10 00:40:31 CDT 2018
+addResourceFilters=true
+afterTasks=afterEclipseImport;
+beforeTasks=cleanEclipse;eclipse;
+enableAfterTasks=true
+enableBeforeTasks=true
+enableDependendencyManagement=true
+projects=;android;core;desktop;
diff --git a/old/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs b/old/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs
new file mode 100644
index 0000000..5ca5389
--- /dev/null
+++ b/old/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs
@@ -0,0 +1,5 @@
+#org.springsource.ide.eclipse.gradle.core.preferences.GradleProjectPreferences
+#Mon Sep 10 00:40:41 CDT 2018
+build.family.org.gradle.tooling.model.eclipse.HierarchicalEclipseProject=;android;core;desktop;
+org.springsource.ide.eclipse.gradle.linkedresources=
+org.springsource.ide.eclipse.gradle.rootprojectloc=
diff --git a/old/.settings/gradle/org.springsource.ide.eclipse.gradle.refresh.prefs b/old/.settings/gradle/org.springsource.ide.eclipse.gradle.refresh.prefs
new file mode 100644
index 0000000..fa38a70
--- /dev/null
+++ b/old/.settings/gradle/org.springsource.ide.eclipse.gradle.refresh.prefs
@@ -0,0 +1,8 @@
+#org.springsource.ide.eclipse.gradle.core.actions.GradleRefreshPreferences
+#Mon Sep 10 00:40:36 CDT 2018
+addResourceFilters=true
+afterTasks=afterEclipseImport;
+beforeTasks=cleanEclipse;eclipse;
+enableAfterTasks=true
+enableBeforeTasks=true
+useHierarchicalNames=false
diff --git a/old/android/.classpath b/old/android/.classpath
new file mode 100644
index 0000000..aafed56
--- /dev/null
+++ b/old/android/.classpath
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/old/android/.project b/old/android/.project
new file mode 100644
index 0000000..4336ea1
--- /dev/null
+++ b/old/android/.project
@@ -0,0 +1,34 @@
+
+
+ RhythmBullet-android
+
+
+
+
+
+ com.android.ide.eclipse.adt.ResourceManagerBuilder
+
+
+
+
+ com.android.ide.eclipse.adt.PreCompilerBuilder
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ com.android.ide.eclipse.adt.ApkBuilder
+
+
+
+
+
+ org.springsource.ide.eclipse.gradle.core.nature
+ org.eclipse.jdt.core.javanature
+ com.android.ide.eclipse.adt.AndroidNature
+
+
diff --git a/old/android/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs b/old/android/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs
new file mode 100644
index 0000000..82b46a5
--- /dev/null
+++ b/old/android/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs
@@ -0,0 +1,4 @@
+#org.springsource.ide.eclipse.gradle.core.preferences.GradleProjectPreferences
+#Mon Sep 10 00:40:48 CDT 2018
+org.springsource.ide.eclipse.gradle.linkedresources=
+org.springsource.ide.eclipse.gradle.rootprojectloc=..
diff --git a/old/android/.settings/gradle/org.springsource.ide.eclipse.gradle.refresh.prefs b/old/android/.settings/gradle/org.springsource.ide.eclipse.gradle.refresh.prefs
new file mode 100644
index 0000000..599cb88
--- /dev/null
+++ b/old/android/.settings/gradle/org.springsource.ide.eclipse.gradle.refresh.prefs
@@ -0,0 +1,8 @@
+#org.springsource.ide.eclipse.gradle.core.actions.GradleRefreshPreferences
+#Mon Sep 10 00:40:41 CDT 2018
+addResourceFilters=true
+afterTasks=afterEclipseImport;
+beforeTasks=cleanEclipse;eclipse;
+enableAfterTasks=true
+enableBeforeTasks=true
+useHierarchicalNames=false
diff --git a/old/android/.settings/org.eclipse.jdt.core.prefs b/old/android/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..67f499c
--- /dev/null
+++ b/old/android/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,13 @@
+#
+#Mon Sep 10 00:54:15 CDT 2018
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
diff --git a/old/android/AndroidManifest.xml b/old/android/AndroidManifest.xml
new file mode 100644
index 0000000..9919a07
--- /dev/null
+++ b/old/android/AndroidManifest.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/old/android/assets/1280x720/Shooter1.png b/old/android/assets/1280x720/Shooter1.png
new file mode 100644
index 0000000..12e54e3
Binary files /dev/null and b/old/android/assets/1280x720/Shooter1.png differ
diff --git a/old/android/assets/1280x720/Tech-Circle1.png b/old/android/assets/1280x720/Tech-Circle1.png
new file mode 100644
index 0000000..4229dfe
Binary files /dev/null and b/old/android/assets/1280x720/Tech-Circle1.png differ
diff --git a/old/android/assets/1280x720/backgrounds/mainBG.png b/old/android/assets/1280x720/backgrounds/mainBG.png
new file mode 100644
index 0000000..e93e249
Binary files /dev/null and b/old/android/assets/1280x720/backgrounds/mainBG.png differ
diff --git a/old/android/assets/1280x720/bar.png b/old/android/assets/1280x720/bar.png
new file mode 100644
index 0000000..606fd37
Binary files /dev/null and b/old/android/assets/1280x720/bar.png differ
diff --git a/old/android/assets/1280x720/cybercircle1.png b/old/android/assets/1280x720/cybercircle1.png
new file mode 100644
index 0000000..c40498d
Binary files /dev/null and b/old/android/assets/1280x720/cybercircle1.png differ
diff --git a/old/android/assets/1280x720/cybercircle3B.png b/old/android/assets/1280x720/cybercircle3B.png
new file mode 100644
index 0000000..a8a2dd6
Binary files /dev/null and b/old/android/assets/1280x720/cybercircle3B.png differ
diff --git a/old/android/assets/1280x720/flake.png b/old/android/assets/1280x720/flake.png
new file mode 100644
index 0000000..341d8a2
Binary files /dev/null and b/old/android/assets/1280x720/flake.png differ
diff --git a/old/android/assets/1280x720/laser.png b/old/android/assets/1280x720/laser.png
new file mode 100644
index 0000000..e5aa06b
Binary files /dev/null and b/old/android/assets/1280x720/laser.png differ
diff --git a/old/android/assets/1280x720/magic1.png b/old/android/assets/1280x720/magic1.png
new file mode 100644
index 0000000..e24db14
Binary files /dev/null and b/old/android/assets/1280x720/magic1.png differ
diff --git a/old/android/assets/1280x720/pellet.png b/old/android/assets/1280x720/pellet.png
new file mode 100644
index 0000000..a9e7562
Binary files /dev/null and b/old/android/assets/1280x720/pellet.png differ
diff --git a/old/android/assets/1280x720/polyjet-standard.png b/old/android/assets/1280x720/polyjet-standard.png
new file mode 100644
index 0000000..286ad5d
Binary files /dev/null and b/old/android/assets/1280x720/polyjet-standard.png differ
diff --git a/old/android/assets/1280x720/shard.png b/old/android/assets/1280x720/shard.png
new file mode 100644
index 0000000..d1574ea
Binary files /dev/null and b/old/android/assets/1280x720/shard.png differ
diff --git a/old/android/assets/1280x720/square.png b/old/android/assets/1280x720/square.png
new file mode 100644
index 0000000..ad1c849
Binary files /dev/null and b/old/android/assets/1280x720/square.png differ
diff --git a/old/android/assets/1280x720/title.png b/old/android/assets/1280x720/title.png
new file mode 100644
index 0000000..9be0ad6
Binary files /dev/null and b/old/android/assets/1280x720/title.png differ
diff --git a/old/android/assets/1280x720/tpSelector.png b/old/android/assets/1280x720/tpSelector.png
new file mode 100644
index 0000000..0796baf
Binary files /dev/null and b/old/android/assets/1280x720/tpSelector.png differ
diff --git a/old/android/assets/1280x720/void_circle.png b/old/android/assets/1280x720/void_circle.png
new file mode 100644
index 0000000..28a9e58
Binary files /dev/null and b/old/android/assets/1280x720/void_circle.png differ
diff --git a/old/android/assets/1280x800/Shooter1.png b/old/android/assets/1280x800/Shooter1.png
new file mode 100644
index 0000000..75878cb
Binary files /dev/null and b/old/android/assets/1280x800/Shooter1.png differ
diff --git a/old/android/assets/1280x800/Tech-Circle1.png b/old/android/assets/1280x800/Tech-Circle1.png
new file mode 100644
index 0000000..bd661d3
Binary files /dev/null and b/old/android/assets/1280x800/Tech-Circle1.png differ
diff --git a/old/android/assets/1280x800/backgrounds/mainBG.png b/old/android/assets/1280x800/backgrounds/mainBG.png
new file mode 100644
index 0000000..4c9d321
Binary files /dev/null and b/old/android/assets/1280x800/backgrounds/mainBG.png differ
diff --git a/old/android/assets/1280x800/bar.png b/old/android/assets/1280x800/bar.png
new file mode 100644
index 0000000..deb93bd
Binary files /dev/null and b/old/android/assets/1280x800/bar.png differ
diff --git a/old/android/assets/1280x800/cybercircle1.png b/old/android/assets/1280x800/cybercircle1.png
new file mode 100644
index 0000000..2edc4d1
Binary files /dev/null and b/old/android/assets/1280x800/cybercircle1.png differ
diff --git a/old/android/assets/1280x800/cybercircle3B.png b/old/android/assets/1280x800/cybercircle3B.png
new file mode 100644
index 0000000..6f5ab4e
Binary files /dev/null and b/old/android/assets/1280x800/cybercircle3B.png differ
diff --git a/old/android/assets/1280x800/flake.png b/old/android/assets/1280x800/flake.png
new file mode 100644
index 0000000..67076c3
Binary files /dev/null and b/old/android/assets/1280x800/flake.png differ
diff --git a/old/android/assets/1280x800/laser.png b/old/android/assets/1280x800/laser.png
new file mode 100644
index 0000000..5b82d55
Binary files /dev/null and b/old/android/assets/1280x800/laser.png differ
diff --git a/old/android/assets/1280x800/magic1.png b/old/android/assets/1280x800/magic1.png
new file mode 100644
index 0000000..22f3f3b
Binary files /dev/null and b/old/android/assets/1280x800/magic1.png differ
diff --git a/old/android/assets/1280x800/pellet.png b/old/android/assets/1280x800/pellet.png
new file mode 100644
index 0000000..7ea8abc
Binary files /dev/null and b/old/android/assets/1280x800/pellet.png differ
diff --git a/old/android/assets/1280x800/polyjet-standard.png b/old/android/assets/1280x800/polyjet-standard.png
new file mode 100644
index 0000000..63fe63d
Binary files /dev/null and b/old/android/assets/1280x800/polyjet-standard.png differ
diff --git a/old/android/assets/1280x800/shard.png b/old/android/assets/1280x800/shard.png
new file mode 100644
index 0000000..a29a60d
Binary files /dev/null and b/old/android/assets/1280x800/shard.png differ
diff --git a/old/android/assets/1280x800/square.png b/old/android/assets/1280x800/square.png
new file mode 100644
index 0000000..4759b27
Binary files /dev/null and b/old/android/assets/1280x800/square.png differ
diff --git a/old/android/assets/1280x800/title.png b/old/android/assets/1280x800/title.png
new file mode 100644
index 0000000..ca71aa0
Binary files /dev/null and b/old/android/assets/1280x800/title.png differ
diff --git a/old/android/assets/1280x800/tpSelector.png b/old/android/assets/1280x800/tpSelector.png
new file mode 100644
index 0000000..6228a48
Binary files /dev/null and b/old/android/assets/1280x800/tpSelector.png differ
diff --git a/old/android/assets/1280x800/void_circle.png b/old/android/assets/1280x800/void_circle.png
new file mode 100644
index 0000000..edca8e5
Binary files /dev/null and b/old/android/assets/1280x800/void_circle.png differ
diff --git a/old/android/assets/1366x768/Shooter1.png b/old/android/assets/1366x768/Shooter1.png
new file mode 100644
index 0000000..6632c4a
Binary files /dev/null and b/old/android/assets/1366x768/Shooter1.png differ
diff --git a/old/android/assets/1366x768/Tech-Circle1.png b/old/android/assets/1366x768/Tech-Circle1.png
new file mode 100644
index 0000000..bb78f62
Binary files /dev/null and b/old/android/assets/1366x768/Tech-Circle1.png differ
diff --git a/old/android/assets/1366x768/backgrounds/mainBG.png b/old/android/assets/1366x768/backgrounds/mainBG.png
new file mode 100644
index 0000000..75fd847
Binary files /dev/null and b/old/android/assets/1366x768/backgrounds/mainBG.png differ
diff --git a/old/android/assets/1366x768/bar.png b/old/android/assets/1366x768/bar.png
new file mode 100644
index 0000000..951f25b
Binary files /dev/null and b/old/android/assets/1366x768/bar.png differ
diff --git a/old/android/assets/1366x768/cybercircle1.png b/old/android/assets/1366x768/cybercircle1.png
new file mode 100644
index 0000000..2d205ef
Binary files /dev/null and b/old/android/assets/1366x768/cybercircle1.png differ
diff --git a/old/android/assets/1366x768/cybercircle3B.png b/old/android/assets/1366x768/cybercircle3B.png
new file mode 100644
index 0000000..8af9f1e
Binary files /dev/null and b/old/android/assets/1366x768/cybercircle3B.png differ
diff --git a/old/android/assets/1366x768/flake.png b/old/android/assets/1366x768/flake.png
new file mode 100644
index 0000000..78056c2
Binary files /dev/null and b/old/android/assets/1366x768/flake.png differ
diff --git a/old/android/assets/1366x768/laser.png b/old/android/assets/1366x768/laser.png
new file mode 100644
index 0000000..18034cc
Binary files /dev/null and b/old/android/assets/1366x768/laser.png differ
diff --git a/old/android/assets/1366x768/magic1.png b/old/android/assets/1366x768/magic1.png
new file mode 100644
index 0000000..ab2fefd
Binary files /dev/null and b/old/android/assets/1366x768/magic1.png differ
diff --git a/old/android/assets/1366x768/pellet.png b/old/android/assets/1366x768/pellet.png
new file mode 100644
index 0000000..a9e7562
Binary files /dev/null and b/old/android/assets/1366x768/pellet.png differ
diff --git a/old/android/assets/1366x768/polyjet-standard.png b/old/android/assets/1366x768/polyjet-standard.png
new file mode 100644
index 0000000..9a5c154
Binary files /dev/null and b/old/android/assets/1366x768/polyjet-standard.png differ
diff --git a/old/android/assets/1366x768/shard.png b/old/android/assets/1366x768/shard.png
new file mode 100644
index 0000000..97083d9
Binary files /dev/null and b/old/android/assets/1366x768/shard.png differ
diff --git a/old/android/assets/1366x768/square.png b/old/android/assets/1366x768/square.png
new file mode 100644
index 0000000..d2896d5
Binary files /dev/null and b/old/android/assets/1366x768/square.png differ
diff --git a/old/android/assets/1366x768/title.png b/old/android/assets/1366x768/title.png
new file mode 100644
index 0000000..cd4caf7
Binary files /dev/null and b/old/android/assets/1366x768/title.png differ
diff --git a/old/android/assets/1366x768/tpSelector.png b/old/android/assets/1366x768/tpSelector.png
new file mode 100644
index 0000000..d8eb20c
Binary files /dev/null and b/old/android/assets/1366x768/tpSelector.png differ
diff --git a/old/android/assets/1366x768/void_circle.png b/old/android/assets/1366x768/void_circle.png
new file mode 100644
index 0000000..eafeb24
Binary files /dev/null and b/old/android/assets/1366x768/void_circle.png differ
diff --git a/old/android/assets/1920x1080/Shooter1.png b/old/android/assets/1920x1080/Shooter1.png
new file mode 100644
index 0000000..59254c1
Binary files /dev/null and b/old/android/assets/1920x1080/Shooter1.png differ
diff --git a/old/android/assets/1920x1080/Tech-Circle1.png b/old/android/assets/1920x1080/Tech-Circle1.png
new file mode 100644
index 0000000..73d6ecd
Binary files /dev/null and b/old/android/assets/1920x1080/Tech-Circle1.png differ
diff --git a/old/android/assets/1920x1080/backgrounds/mainBG.png b/old/android/assets/1920x1080/backgrounds/mainBG.png
new file mode 100644
index 0000000..177ecec
Binary files /dev/null and b/old/android/assets/1920x1080/backgrounds/mainBG.png differ
diff --git a/old/android/assets/1920x1080/bar.png b/old/android/assets/1920x1080/bar.png
new file mode 100644
index 0000000..d384455
Binary files /dev/null and b/old/android/assets/1920x1080/bar.png differ
diff --git a/old/android/assets/1920x1080/cybercircle1.png b/old/android/assets/1920x1080/cybercircle1.png
new file mode 100644
index 0000000..f3c7512
Binary files /dev/null and b/old/android/assets/1920x1080/cybercircle1.png differ
diff --git a/old/android/assets/1920x1080/cybercircle3B.png b/old/android/assets/1920x1080/cybercircle3B.png
new file mode 100644
index 0000000..13f13ef
Binary files /dev/null and b/old/android/assets/1920x1080/cybercircle3B.png differ
diff --git a/old/android/assets/1920x1080/flake.png b/old/android/assets/1920x1080/flake.png
new file mode 100644
index 0000000..2da5d42
Binary files /dev/null and b/old/android/assets/1920x1080/flake.png differ
diff --git a/old/android/assets/1920x1080/laser.png b/old/android/assets/1920x1080/laser.png
new file mode 100644
index 0000000..c7e0405
Binary files /dev/null and b/old/android/assets/1920x1080/laser.png differ
diff --git a/old/android/assets/1920x1080/magic1.png b/old/android/assets/1920x1080/magic1.png
new file mode 100644
index 0000000..8d270ee
Binary files /dev/null and b/old/android/assets/1920x1080/magic1.png differ
diff --git a/old/android/assets/1920x1080/pellet.png b/old/android/assets/1920x1080/pellet.png
new file mode 100644
index 0000000..e578a10
Binary files /dev/null and b/old/android/assets/1920x1080/pellet.png differ
diff --git a/old/android/assets/1920x1080/polyjet-standard.png b/old/android/assets/1920x1080/polyjet-standard.png
new file mode 100644
index 0000000..cfec492
Binary files /dev/null and b/old/android/assets/1920x1080/polyjet-standard.png differ
diff --git a/old/android/assets/1920x1080/shard.png b/old/android/assets/1920x1080/shard.png
new file mode 100644
index 0000000..154e2b2
Binary files /dev/null and b/old/android/assets/1920x1080/shard.png differ
diff --git a/old/android/assets/1920x1080/square.png b/old/android/assets/1920x1080/square.png
new file mode 100644
index 0000000..f351e99
Binary files /dev/null and b/old/android/assets/1920x1080/square.png differ
diff --git a/old/android/assets/1920x1080/title.png b/old/android/assets/1920x1080/title.png
new file mode 100644
index 0000000..7885f48
Binary files /dev/null and b/old/android/assets/1920x1080/title.png differ
diff --git a/old/android/assets/1920x1080/tpSelector.png b/old/android/assets/1920x1080/tpSelector.png
new file mode 100644
index 0000000..da02f1e
Binary files /dev/null and b/old/android/assets/1920x1080/tpSelector.png differ
diff --git a/old/android/assets/1920x1080/void_circle.png b/old/android/assets/1920x1080/void_circle.png
new file mode 100644
index 0000000..9dad9e7
Binary files /dev/null and b/old/android/assets/1920x1080/void_circle.png differ
diff --git a/old/android/assets/1920x1200/Shooter1.png b/old/android/assets/1920x1200/Shooter1.png
new file mode 100644
index 0000000..9ccb7dc
Binary files /dev/null and b/old/android/assets/1920x1200/Shooter1.png differ
diff --git a/old/android/assets/1920x1200/Tech-Circle1.png b/old/android/assets/1920x1200/Tech-Circle1.png
new file mode 100644
index 0000000..973956b
Binary files /dev/null and b/old/android/assets/1920x1200/Tech-Circle1.png differ
diff --git a/old/android/assets/1920x1200/backgrounds/mainBG.png b/old/android/assets/1920x1200/backgrounds/mainBG.png
new file mode 100644
index 0000000..5bd56df
Binary files /dev/null and b/old/android/assets/1920x1200/backgrounds/mainBG.png differ
diff --git a/old/android/assets/1920x1200/bar.png b/old/android/assets/1920x1200/bar.png
new file mode 100644
index 0000000..738b095
Binary files /dev/null and b/old/android/assets/1920x1200/bar.png differ
diff --git a/old/android/assets/1920x1200/cybercircle1.png b/old/android/assets/1920x1200/cybercircle1.png
new file mode 100644
index 0000000..6938404
Binary files /dev/null and b/old/android/assets/1920x1200/cybercircle1.png differ
diff --git a/old/android/assets/1920x1200/cybercircle3B.png b/old/android/assets/1920x1200/cybercircle3B.png
new file mode 100644
index 0000000..de638f3
Binary files /dev/null and b/old/android/assets/1920x1200/cybercircle3B.png differ
diff --git a/old/android/assets/1920x1200/flake.png b/old/android/assets/1920x1200/flake.png
new file mode 100644
index 0000000..858ac5c
Binary files /dev/null and b/old/android/assets/1920x1200/flake.png differ
diff --git a/old/android/assets/1920x1200/laser.png b/old/android/assets/1920x1200/laser.png
new file mode 100644
index 0000000..1528938
Binary files /dev/null and b/old/android/assets/1920x1200/laser.png differ
diff --git a/old/android/assets/1920x1200/magic1.png b/old/android/assets/1920x1200/magic1.png
new file mode 100644
index 0000000..efcdacf
Binary files /dev/null and b/old/android/assets/1920x1200/magic1.png differ
diff --git a/old/android/assets/1920x1200/pellet.png b/old/android/assets/1920x1200/pellet.png
new file mode 100644
index 0000000..b7ffce2
Binary files /dev/null and b/old/android/assets/1920x1200/pellet.png differ
diff --git a/old/android/assets/1920x1200/polyjet-standard.png b/old/android/assets/1920x1200/polyjet-standard.png
new file mode 100644
index 0000000..c374e1a
Binary files /dev/null and b/old/android/assets/1920x1200/polyjet-standard.png differ
diff --git a/old/android/assets/1920x1200/shard.png b/old/android/assets/1920x1200/shard.png
new file mode 100644
index 0000000..f952746
Binary files /dev/null and b/old/android/assets/1920x1200/shard.png differ
diff --git a/old/android/assets/1920x1200/square.png b/old/android/assets/1920x1200/square.png
new file mode 100644
index 0000000..12edf25
Binary files /dev/null and b/old/android/assets/1920x1200/square.png differ
diff --git a/old/android/assets/1920x1200/title.png b/old/android/assets/1920x1200/title.png
new file mode 100644
index 0000000..1ada752
Binary files /dev/null and b/old/android/assets/1920x1200/title.png differ
diff --git a/old/android/assets/1920x1200/tpSelector.png b/old/android/assets/1920x1200/tpSelector.png
new file mode 100644
index 0000000..049d468
Binary files /dev/null and b/old/android/assets/1920x1200/tpSelector.png differ
diff --git a/old/android/assets/1920x1200/void_circle.png b/old/android/assets/1920x1200/void_circle.png
new file mode 100644
index 0000000..c4a71c2
Binary files /dev/null and b/old/android/assets/1920x1200/void_circle.png differ
diff --git a/old/android/assets/2560x1440/Shooter1.png b/old/android/assets/2560x1440/Shooter1.png
new file mode 100644
index 0000000..5c89fe0
Binary files /dev/null and b/old/android/assets/2560x1440/Shooter1.png differ
diff --git a/old/android/assets/2560x1440/Tech-Circle1.png b/old/android/assets/2560x1440/Tech-Circle1.png
new file mode 100644
index 0000000..076a8ca
Binary files /dev/null and b/old/android/assets/2560x1440/Tech-Circle1.png differ
diff --git a/old/android/assets/2560x1440/backgrounds/mainBG.png b/old/android/assets/2560x1440/backgrounds/mainBG.png
new file mode 100644
index 0000000..e155bc5
Binary files /dev/null and b/old/android/assets/2560x1440/backgrounds/mainBG.png differ
diff --git a/old/android/assets/2560x1440/bar.png b/old/android/assets/2560x1440/bar.png
new file mode 100644
index 0000000..c5b6b3a
Binary files /dev/null and b/old/android/assets/2560x1440/bar.png differ
diff --git a/old/android/assets/2560x1440/cybercircle1.png b/old/android/assets/2560x1440/cybercircle1.png
new file mode 100644
index 0000000..2771c97
Binary files /dev/null and b/old/android/assets/2560x1440/cybercircle1.png differ
diff --git a/old/android/assets/2560x1440/cybercircle3B.png b/old/android/assets/2560x1440/cybercircle3B.png
new file mode 100644
index 0000000..f66907f
Binary files /dev/null and b/old/android/assets/2560x1440/cybercircle3B.png differ
diff --git a/old/android/assets/2560x1440/flake.png b/old/android/assets/2560x1440/flake.png
new file mode 100644
index 0000000..6e50620
Binary files /dev/null and b/old/android/assets/2560x1440/flake.png differ
diff --git a/old/android/assets/2560x1440/laser.png b/old/android/assets/2560x1440/laser.png
new file mode 100644
index 0000000..6ea99f4
Binary files /dev/null and b/old/android/assets/2560x1440/laser.png differ
diff --git a/old/android/assets/2560x1440/magic1.png b/old/android/assets/2560x1440/magic1.png
new file mode 100644
index 0000000..5ac0cb7
Binary files /dev/null and b/old/android/assets/2560x1440/magic1.png differ
diff --git a/old/android/assets/2560x1440/pellet.png b/old/android/assets/2560x1440/pellet.png
new file mode 100644
index 0000000..cffc1ae
Binary files /dev/null and b/old/android/assets/2560x1440/pellet.png differ
diff --git a/old/android/assets/2560x1440/polyjet-standard.png b/old/android/assets/2560x1440/polyjet-standard.png
new file mode 100644
index 0000000..c2b6f32
Binary files /dev/null and b/old/android/assets/2560x1440/polyjet-standard.png differ
diff --git a/old/android/assets/2560x1440/shard.png b/old/android/assets/2560x1440/shard.png
new file mode 100644
index 0000000..10a036f
Binary files /dev/null and b/old/android/assets/2560x1440/shard.png differ
diff --git a/old/android/assets/2560x1440/splashlogo.png b/old/android/assets/2560x1440/splashlogo.png
new file mode 100644
index 0000000..f2fab6d
Binary files /dev/null and b/old/android/assets/2560x1440/splashlogo.png differ
diff --git a/old/android/assets/2560x1440/square.png b/old/android/assets/2560x1440/square.png
new file mode 100644
index 0000000..70fcf91
Binary files /dev/null and b/old/android/assets/2560x1440/square.png differ
diff --git a/old/android/assets/2560x1440/title.png b/old/android/assets/2560x1440/title.png
new file mode 100644
index 0000000..dc1274a
Binary files /dev/null and b/old/android/assets/2560x1440/title.png differ
diff --git a/old/android/assets/2560x1440/tpSelector.png b/old/android/assets/2560x1440/tpSelector.png
new file mode 100644
index 0000000..de16a8d
Binary files /dev/null and b/old/android/assets/2560x1440/tpSelector.png differ
diff --git a/old/android/assets/2560x1440/void_circle.png b/old/android/assets/2560x1440/void_circle.png
new file mode 100644
index 0000000..b8ad109
Binary files /dev/null and b/old/android/assets/2560x1440/void_circle.png differ
diff --git a/old/android/assets/3840x2160/Shooter1.png b/old/android/assets/3840x2160/Shooter1.png
new file mode 100644
index 0000000..fc4adc1
Binary files /dev/null and b/old/android/assets/3840x2160/Shooter1.png differ
diff --git a/old/android/assets/3840x2160/Tech-Circle1.png b/old/android/assets/3840x2160/Tech-Circle1.png
new file mode 100644
index 0000000..efad7f1
Binary files /dev/null and b/old/android/assets/3840x2160/Tech-Circle1.png differ
diff --git a/old/android/assets/3840x2160/backgrounds/mainBG.png b/old/android/assets/3840x2160/backgrounds/mainBG.png
new file mode 100644
index 0000000..2c83916
Binary files /dev/null and b/old/android/assets/3840x2160/backgrounds/mainBG.png differ
diff --git a/old/android/assets/3840x2160/bar.png b/old/android/assets/3840x2160/bar.png
new file mode 100644
index 0000000..aaf5f9c
Binary files /dev/null and b/old/android/assets/3840x2160/bar.png differ
diff --git a/old/android/assets/3840x2160/cybercircle1.png b/old/android/assets/3840x2160/cybercircle1.png
new file mode 100644
index 0000000..e63d232
Binary files /dev/null and b/old/android/assets/3840x2160/cybercircle1.png differ
diff --git a/old/android/assets/3840x2160/cybercircle3B.png b/old/android/assets/3840x2160/cybercircle3B.png
new file mode 100644
index 0000000..4129106
Binary files /dev/null and b/old/android/assets/3840x2160/cybercircle3B.png differ
diff --git a/old/android/assets/3840x2160/flake.png b/old/android/assets/3840x2160/flake.png
new file mode 100644
index 0000000..a0cb521
Binary files /dev/null and b/old/android/assets/3840x2160/flake.png differ
diff --git a/old/android/assets/3840x2160/laser.png b/old/android/assets/3840x2160/laser.png
new file mode 100644
index 0000000..f5d289f
Binary files /dev/null and b/old/android/assets/3840x2160/laser.png differ
diff --git a/old/android/assets/3840x2160/magic1.png b/old/android/assets/3840x2160/magic1.png
new file mode 100644
index 0000000..6229753
Binary files /dev/null and b/old/android/assets/3840x2160/magic1.png differ
diff --git a/old/android/assets/3840x2160/pellet.png b/old/android/assets/3840x2160/pellet.png
new file mode 100644
index 0000000..576da50
Binary files /dev/null and b/old/android/assets/3840x2160/pellet.png differ
diff --git a/old/android/assets/3840x2160/polyjet-standard.png b/old/android/assets/3840x2160/polyjet-standard.png
new file mode 100644
index 0000000..893c4fb
Binary files /dev/null and b/old/android/assets/3840x2160/polyjet-standard.png differ
diff --git a/old/android/assets/3840x2160/shard.png b/old/android/assets/3840x2160/shard.png
new file mode 100644
index 0000000..637a04d
Binary files /dev/null and b/old/android/assets/3840x2160/shard.png differ
diff --git a/old/android/assets/3840x2160/square.png b/old/android/assets/3840x2160/square.png
new file mode 100644
index 0000000..2868dca
Binary files /dev/null and b/old/android/assets/3840x2160/square.png differ
diff --git a/old/android/assets/3840x2160/title.png b/old/android/assets/3840x2160/title.png
new file mode 100644
index 0000000..998f2d9
Binary files /dev/null and b/old/android/assets/3840x2160/title.png differ
diff --git a/old/android/assets/3840x2160/tpSelector.png b/old/android/assets/3840x2160/tpSelector.png
new file mode 100644
index 0000000..465ef5d
Binary files /dev/null and b/old/android/assets/3840x2160/tpSelector.png differ
diff --git a/old/android/assets/3840x2160/void_circle.png b/old/android/assets/3840x2160/void_circle.png
new file mode 100644
index 0000000..396d5f1
Binary files /dev/null and b/old/android/assets/3840x2160/void_circle.png differ
diff --git a/old/android/assets/badlogic.jpg b/old/android/assets/badlogic.jpg
new file mode 100644
index 0000000..4390da6
Binary files /dev/null and b/old/android/assets/badlogic.jpg differ
diff --git a/old/android/assets/defaultCover.png b/old/android/assets/defaultCover.png
new file mode 100644
index 0000000..f6cc866
Binary files /dev/null and b/old/android/assets/defaultCover.png differ
diff --git a/old/android/assets/fonts/Gasalt-Regular.ttf b/old/android/assets/fonts/Gasalt-Regular.ttf
new file mode 100644
index 0000000..79ff0fa
Binary files /dev/null and b/old/android/assets/fonts/Gasalt-Regular.ttf differ
diff --git a/old/android/assets/fonts/darktech_ldr.ttf b/old/android/assets/fonts/darktech_ldr.ttf
new file mode 100644
index 0000000..273716f
Binary files /dev/null and b/old/android/assets/fonts/darktech_ldr.ttf differ
diff --git a/old/android/assets/fonts/maiden.TTF b/old/android/assets/fonts/maiden.TTF
new file mode 100644
index 0000000..cb4b9d9
Binary files /dev/null and b/old/android/assets/fonts/maiden.TTF differ
diff --git a/old/android/assets/keyboard.atlas b/old/android/assets/keyboard.atlas
new file mode 100644
index 0000000..f0df62f
--- /dev/null
+++ b/old/android/assets/keyboard.atlas
@@ -0,0 +1,650 @@
+
+keyboard.png
+size: 1024,1024
+format: RGBA8888
+filter: Nearest,Nearest
+repeat: none
+Keyboard_Black_0
+ rotate: false
+ xy: 2, 920
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_1
+ rotate: false
+ xy: 2, 818
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_2
+ rotate: false
+ xy: 104, 920
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_3
+ rotate: false
+ xy: 2, 716
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_4
+ rotate: false
+ xy: 104, 818
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_5
+ rotate: false
+ xy: 206, 920
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_6
+ rotate: false
+ xy: 2, 614
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_7
+ rotate: false
+ xy: 104, 716
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_8
+ rotate: false
+ xy: 206, 818
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_9
+ rotate: false
+ xy: 308, 920
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_F10
+ rotate: false
+ xy: 2, 512
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_F11
+ rotate: false
+ xy: 104, 614
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_F12
+ rotate: false
+ xy: 206, 716
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_A
+ rotate: false
+ xy: 308, 818
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Alt
+ rotate: false
+ xy: 410, 920
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Down
+ rotate: false
+ xy: 2, 410
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Left
+ rotate: false
+ xy: 104, 512
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Right
+ rotate: false
+ xy: 206, 614
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Up
+ rotate: false
+ xy: 308, 716
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Asterisk
+ rotate: false
+ xy: 410, 818
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_B
+ rotate: false
+ xy: 512, 920
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Backspace
+ rotate: false
+ xy: 2, 308
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Backspace_Alt
+ rotate: false
+ xy: 104, 410
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Bracket_Left
+ rotate: false
+ xy: 206, 512
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Bracket_Right
+ rotate: false
+ xy: 308, 614
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_C
+ rotate: false
+ xy: 410, 716
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Caps_Lock
+ rotate: false
+ xy: 512, 818
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Command
+ rotate: false
+ xy: 614, 920
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Ctrl
+ rotate: false
+ xy: 2, 206
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_D
+ rotate: false
+ xy: 104, 308
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Del
+ rotate: false
+ xy: 206, 410
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_E
+ rotate: false
+ xy: 308, 512
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_End
+ rotate: false
+ xy: 410, 614
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Enter
+ rotate: false
+ xy: 512, 716
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Enter_Alt
+ rotate: false
+ xy: 614, 818
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Enter_Tall
+ rotate: false
+ xy: 716, 920
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Escape
+ rotate: false
+ xy: 2, 104
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_F
+ rotate: false
+ xy: 104, 206
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_F1
+ rotate: false
+ xy: 206, 308
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_F2
+ rotate: false
+ xy: 308, 410
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_F3
+ rotate: false
+ xy: 410, 512
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_F4
+ rotate: false
+ xy: 512, 614
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_F5
+ rotate: false
+ xy: 614, 716
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_F6
+ rotate: false
+ xy: 716, 818
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_F7
+ rotate: false
+ xy: 818, 920
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_F8
+ rotate: false
+ xy: 2, 2
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_F9
+ rotate: false
+ xy: 104, 104
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_G
+ rotate: false
+ xy: 206, 206
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_H
+ rotate: false
+ xy: 308, 308
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Home
+ rotate: false
+ xy: 410, 410
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_I
+ rotate: false
+ xy: 512, 512
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Insert
+ rotate: false
+ xy: 614, 614
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_J
+ rotate: false
+ xy: 716, 716
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_K
+ rotate: false
+ xy: 818, 818
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_L
+ rotate: false
+ xy: 920, 920
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_M
+ rotate: false
+ xy: 104, 2
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Mark_Left
+ rotate: false
+ xy: 206, 104
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Mark_Right
+ rotate: false
+ xy: 308, 206
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Minus
+ rotate: false
+ xy: 410, 308
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Mouse_Left
+ rotate: false
+ xy: 512, 410
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Mouse_Middle
+ rotate: false
+ xy: 614, 512
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Mouse_Right
+ rotate: false
+ xy: 716, 614
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Mouse_Simple
+ rotate: false
+ xy: 818, 716
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_N
+ rotate: false
+ xy: 920, 818
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Num_Lock
+ rotate: false
+ xy: 206, 2
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_O
+ rotate: false
+ xy: 308, 104
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_P
+ rotate: false
+ xy: 410, 206
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Page_Down
+ rotate: false
+ xy: 512, 308
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Page_Up
+ rotate: false
+ xy: 614, 410
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Plus
+ rotate: false
+ xy: 716, 512
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Plus_Tall
+ rotate: false
+ xy: 818, 614
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Print_Screen
+ rotate: false
+ xy: 920, 716
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Q
+ rotate: false
+ xy: 308, 2
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Question
+ rotate: false
+ xy: 410, 104
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Quote
+ rotate: false
+ xy: 512, 206
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_R
+ rotate: false
+ xy: 614, 308
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_S
+ rotate: false
+ xy: 716, 410
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Semicolon
+ rotate: false
+ xy: 818, 512
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Shift
+ rotate: false
+ xy: 920, 614
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Shift_Alt
+ rotate: false
+ xy: 410, 2
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Slash
+ rotate: false
+ xy: 512, 104
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Space
+ rotate: false
+ xy: 614, 206
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_T
+ rotate: false
+ xy: 716, 308
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Tab
+ rotate: false
+ xy: 818, 410
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Tilda
+ rotate: false
+ xy: 920, 512
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_U
+ rotate: false
+ xy: 512, 2
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_V
+ rotate: false
+ xy: 614, 104
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_W
+ rotate: false
+ xy: 716, 206
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Win
+ rotate: false
+ xy: 818, 308
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_X
+ rotate: false
+ xy: 920, 410
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Y
+ rotate: false
+ xy: 614, 2
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
+Keyboard_Black_Z
+ rotate: false
+ xy: 716, 104
+ size: 100, 100
+ orig: 100, 100
+ offset: 0, 0
+ index: -1
diff --git a/old/android/assets/keyboard.png b/old/android/assets/keyboard.png
new file mode 100644
index 0000000..6dff14f
Binary files /dev/null and b/old/android/assets/keyboard.png differ
diff --git a/old/android/assets/music/Alan Walker - Spectre.mp3 b/old/android/assets/music/Alan Walker - Spectre.mp3
new file mode 100644
index 0000000..53f14af
Binary files /dev/null and b/old/android/assets/music/Alan Walker - Spectre.mp3 differ
diff --git a/old/android/assets/music/Beat_8.mp3 b/old/android/assets/music/Beat_8.mp3
new file mode 100644
index 0000000..83d0158
Binary files /dev/null and b/old/android/assets/music/Beat_8.mp3 differ
diff --git a/old/android/assets/particles/3pStar.png b/old/android/assets/particles/3pStar.png
new file mode 100644
index 0000000..fce6a34
Binary files /dev/null and b/old/android/assets/particles/3pStar.png differ
diff --git a/old/android/assets/particles/4PStar.png b/old/android/assets/particles/4PStar.png
new file mode 100644
index 0000000..1de8613
Binary files /dev/null and b/old/android/assets/particles/4PStar.png differ
diff --git a/old/android/assets/particles/beateffect.p b/old/android/assets/particles/beateffect.p
new file mode 100644
index 0000000..fcb5367
--- /dev/null
+++ b/old/android/assets/particles/beateffect.p
@@ -0,0 +1,149 @@
+main
+- Delay -
+active: false
+- Duration -
+lowMin: 150.0
+lowMax: 150.0
+- Count -
+min: 0
+max: 20
+- Emission -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 100.0
+highMax: 150.0
+relative: false
+scalingCount: 1
+scaling0: 1.0
+timelineCount: 1
+timeline0: 0.0
+- Life -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 2500.0
+highMax: 3000.0
+relative: false
+scalingCount: 2
+scaling0: 1.0
+scaling1: 1.0
+timelineCount: 2
+timeline0: 0.0
+timeline1: 1.0
+- Life Offset -
+active: false
+- X Offset -
+active: false
+- Y Offset -
+active: false
+- Spawn Shape -
+shape: line
+- Spawn Width -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 3840.0
+highMax: 3840.0
+relative: false
+scalingCount: 1
+scaling0: 1.0
+timelineCount: 1
+timeline0: 0.0
+- Spawn Height -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 0.0
+highMax: 0.0
+relative: false
+scalingCount: 1
+scaling0: 1.0
+timelineCount: 1
+timeline0: 0.0
+- Scale -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 45.0
+highMax: 135.0
+relative: false
+scalingCount: 3
+scaling0: 1.0
+scaling1: 1.0
+scaling2: 0.25490198
+timelineCount: 3
+timeline0: 0.0
+timeline1: 0.7876712
+timeline2: 1.0
+- Velocity -
+active: true
+lowMin: 0.0
+lowMax: 0.0
+highMin: 540.0
+highMax: 1080.0
+relative: false
+scalingCount: 3
+scaling0: 1.0
+scaling1: 1.0
+scaling2: 0.6666667
+timelineCount: 3
+timeline0: 0.0
+timeline1: 0.69863015
+timeline2: 0.9931507
+- Angle -
+active: true
+lowMin: 90.0
+lowMax: 90.0
+highMin: 45.0
+highMax: 135.0
+relative: false
+scalingCount: 3
+scaling0: 1.0
+scaling1: 0.43137255
+scaling2: 0.13725491
+timelineCount: 3
+timeline0: 0.0
+timeline1: 0.5684931
+timeline2: 0.8630137
+- Rotation -
+active: false
+- Wind -
+active: false
+- Gravity -
+active: false
+- Tint -
+colorsCount: 6
+colors0: 0.043137256
+colors1: 0.6392157
+colors2: 0.85490197
+colors3: 0.02745098
+colors4: 0.41960785
+colors5: 0.56078434
+timelineCount: 2
+timeline0: 0.0
+timeline1: 1.0
+- Transparency -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 1.0
+highMax: 1.0
+relative: false
+scalingCount: 6
+scaling0: 0.0
+scaling1: 0.19298245
+scaling2: 0.7719298
+scaling3: 1.0
+scaling4: 0.21052632
+scaling5: 0.0
+timelineCount: 6
+timeline0: 0.0
+timeline1: 0.23972602
+timeline2: 0.39726028
+timeline3: 0.60958904
+timeline4: 0.79452056
+timeline5: 1.0
+- Options -
+attached: false
+continuous: false
+aligned: false
+additive: true
+behind: false
+premultipliedAlpha: false
+- Image Path -
+glow-circle.png
diff --git a/old/android/assets/particles/explosion-s.p b/old/android/assets/particles/explosion-s.p
new file mode 100644
index 0000000..7f2ff3e
--- /dev/null
+++ b/old/android/assets/particles/explosion-s.p
@@ -0,0 +1,148 @@
+point1
+- Delay -
+active: false
+- Duration -
+lowMin: 50.0
+lowMax: 50.0
+- Count -
+min: 0
+max: 30
+- Emission -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 500.0
+highMax: 500.0
+relative: false
+scalingCount: 2
+scaling0: 1.0
+scaling1: 1.0
+timelineCount: 2
+timeline0: 0.0
+timeline1: 1.0
+- Life -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 250.0
+highMax: 500.0
+relative: false
+scalingCount: 3
+scaling0: 1.0
+scaling1: 1.0
+scaling2: 0.3
+timelineCount: 3
+timeline0: 0.0
+timeline1: 0.66
+timeline2: 1.0
+- Life Offset -
+active: false
+- X Offset -
+active: false
+- Y Offset -
+active: false
+- Spawn Shape -
+shape: point
+- Spawn Width -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 0.0
+highMax: 0.0
+relative: false
+scalingCount: 1
+scaling0: 1.0
+timelineCount: 1
+timeline0: 0.0
+- Spawn Height -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 0.0
+highMax: 0.0
+relative: false
+scalingCount: 1
+scaling0: 1.0
+timelineCount: 1
+timeline0: 0.0
+- Scale -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 0.5
+highMax: 2.0
+relative: false
+scalingCount: 1
+scaling0: 1.0
+timelineCount: 1
+timeline0: 0.0
+- Velocity -
+active: true
+lowMin: 0.0
+lowMax: 0.0
+highMin: 2.0
+highMax: 8.0
+relative: false
+scalingCount: 1
+scaling0: 1.0
+timelineCount: 1
+timeline0: 0.0
+- Angle -
+active: true
+lowMin: 90.0
+lowMax: 90.0
+highMin: 0.0
+highMax: 360.0
+relative: false
+scalingCount: 1
+scaling0: 1.0
+timelineCount: 1
+timeline0: 0.0
+- Rotation -
+active: true
+lowMin: 1.0
+lowMax: 360.0
+highMin: 180.0
+highMax: 180.0
+relative: false
+scalingCount: 2
+scaling0: 0.0
+scaling1: 1.0
+timelineCount: 2
+timeline0: 0.0
+timeline1: 1.0
+- Wind -
+active: false
+- Gravity -
+active: false
+- Tint -
+colorsCount: 6
+colors0: 1.0
+colors1: 0.047058824
+colors2: 0.047058824
+colors3: 1.0
+colors4: 0.92156863
+colors5: 0.047058824
+timelineCount: 2
+timeline0: 0.0
+timeline1: 1.0
+- Transparency -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 1.0
+highMax: 1.0
+relative: false
+scalingCount: 4
+scaling0: 0.0
+scaling1: 1.0
+scaling2: 0.31578946
+scaling3: 0.0
+timelineCount: 4
+timeline0: 0.0
+timeline1: 0.2
+timeline2: 0.74657536
+timeline3: 1.0
+- Options -
+attached: false
+continuous: false
+aligned: false
+additive: true
+behind: false
+premultipliedAlpha: false
+- Image Path -
+4PStar.png
diff --git a/old/android/assets/particles/firework-exp-s.p b/old/android/assets/particles/firework-exp-s.p
new file mode 100644
index 0000000..eeb443b
--- /dev/null
+++ b/old/android/assets/particles/firework-exp-s.p
@@ -0,0 +1,188 @@
+firework2
+- Delay -
+active: false
+- Duration -
+lowMin: 300.0
+lowMax: 300.0
+- Count -
+min: 20
+max: 150
+- Emission -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 500.0
+highMax: 500.0
+relative: false
+scalingCount: 4
+scaling0: 0.0
+scaling1: 0.0
+scaling2: 1.0
+scaling3: 1.0
+timelineCount: 4
+timeline0: 0.0
+timeline1: 0.5
+timeline2: 0.84246576
+timeline3: 1.0
+- Life -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 750.0
+highMax: 1200.0
+relative: false
+scalingCount: 2
+scaling0: 1.0
+scaling1: 1.0
+timelineCount: 2
+timeline0: 0.0
+timeline1: 1.0
+- Life Offset -
+active: true
+lowMin: 0.0
+lowMax: 0.0
+highMin: 0.0
+highMax: 0.0
+relative: false
+scalingCount: 1
+scaling0: 1.0
+timelineCount: 1
+timeline0: 0.0
+- X Offset -
+active: false
+- Y Offset -
+active: false
+- Spawn Shape -
+shape: point
+- Spawn Width -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 0.0
+highMax: 0.0
+relative: false
+scalingCount: 1
+scaling0: 1.0
+timelineCount: 1
+timeline0: 0.0
+- Spawn Height -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 0.0
+highMax: 0.0
+relative: false
+scalingCount: 1
+scaling0: 1.0
+timelineCount: 1
+timeline0: 0.0
+- Scale -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 0.5
+highMax: 1.5
+relative: false
+scalingCount: 1
+scaling0: 1.0
+timelineCount: 1
+timeline0: 0.0
+- Velocity -
+active: true
+lowMin: 0.0
+lowMax: 0.0
+highMin: 1.0
+highMax: 8.0
+relative: false
+scalingCount: 2
+scaling0: 0.0
+scaling1: 1.0
+timelineCount: 2
+timeline0: 0.0
+timeline1: 0.10273973
+- Angle -
+active: true
+lowMin: 0.0
+lowMax: 360.0
+highMin: 0.0
+highMax: 360.0
+relative: false
+scalingCount: 1
+scaling0: 0.0
+timelineCount: 1
+timeline0: 0.0
+- Rotation -
+active: true
+lowMin: 1.0
+lowMax: 360.0
+highMin: 180.0
+highMax: 180.0
+relative: false
+scalingCount: 2
+scaling0: 0.0
+scaling1: 1.0
+timelineCount: 2
+timeline0: 0.0
+timeline1: 1.0
+- Wind -
+active: false
+- Gravity -
+active: true
+lowMin: 0.0
+lowMax: 0.0
+highMin: -7.5
+highMax: -9.5
+relative: false
+scalingCount: 4
+scaling0: 0.0
+scaling1: 0.50980395
+scaling2: 0.78431374
+scaling3: 1.0
+timelineCount: 4
+timeline0: 0.0
+timeline1: 0.10958904
+timeline2: 0.25342464
+timeline3: 0.48630136
+- Tint -
+colorsCount: 15
+colors0: 1.0
+colors1: 0.047058824
+colors2: 0.047058824
+colors3: 0.047058824
+colors4: 0.047058824
+colors5: 1.0
+colors6: 0.047058824
+colors7: 1.0
+colors8: 0.2
+colors9: 1.0
+colors10: 0.972549
+colors11: 0.047058824
+colors12: 1.0
+colors13: 0.047058824
+colors14: 0.047058824
+timelineCount: 5
+timeline0: 0.0
+timeline1: 0.2897402
+timeline2: 0.5006605
+timeline3: 0.74372524
+timeline4: 1.0
+- Transparency -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 1.0
+highMax: 1.0
+relative: false
+scalingCount: 4
+scaling0: 0.64912283
+scaling1: 1.0
+scaling2: 0.75
+scaling3: 0.0
+timelineCount: 4
+timeline0: 0.0
+timeline1: 0.43150684
+timeline2: 0.8
+timeline3: 1.0
+- Options -
+attached: false
+continuous: false
+aligned: false
+additive: true
+behind: false
+premultipliedAlpha: false
+- Image Path -
+4PStar.png
diff --git a/old/android/assets/particles/firework-exp.p b/old/android/assets/particles/firework-exp.p
new file mode 100644
index 0000000..4efd16e
--- /dev/null
+++ b/old/android/assets/particles/firework-exp.p
@@ -0,0 +1,367 @@
+firework1
+- Delay -
+active: false
+- Duration -
+lowMin: 250.0
+lowMax: 250.0
+- Count -
+min: 20
+max: 150
+- Emission -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 600.0
+highMax: 600.0
+relative: false
+scalingCount: 3
+scaling0: 1.0
+scaling1: 1.0
+scaling2: 0.0
+timelineCount: 3
+timeline0: 0.0
+timeline1: 0.50022554
+timeline2: 1.0
+- Life -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 1000.0
+highMax: 1500.0
+relative: false
+scalingCount: 2
+scaling0: 1.0
+scaling1: 1.0
+timelineCount: 2
+timeline0: 0.0
+timeline1: 1.0
+- Life Offset -
+active: false
+- X Offset -
+active: false
+- Y Offset -
+active: false
+- Spawn Shape -
+shape: point
+- Spawn Width -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 0.0
+highMax: 0.0
+relative: false
+scalingCount: 1
+scaling0: 1.0
+timelineCount: 1
+timeline0: 0.0
+- Spawn Height -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 0.0
+highMax: 0.0
+relative: false
+scalingCount: 1
+scaling0: 1.0
+timelineCount: 1
+timeline0: 0.0
+- Scale -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 0.5
+highMax: 1.5
+relative: false
+scalingCount: 1
+scaling0: 1.0
+timelineCount: 1
+timeline0: 0.0
+- Velocity -
+active: true
+lowMin: 0.0
+lowMax: 0.0
+highMin: 6.0
+highMax: 14.0
+relative: false
+scalingCount: 2
+scaling0: 0.0
+scaling1: 1.0
+timelineCount: 2
+timeline0: 0.0
+timeline1: 0.10273973
+- Angle -
+active: true
+lowMin: 0.0
+lowMax: 360.0
+highMin: 0.0
+highMax: 360.0
+relative: false
+scalingCount: 1
+scaling0: 0.0
+timelineCount: 1
+timeline0: 0.0
+- Rotation -
+active: true
+lowMin: 1.0
+lowMax: 360.0
+highMin: 180.0
+highMax: 180.0
+relative: false
+scalingCount: 2
+scaling0: 0.0
+scaling1: 1.0
+timelineCount: 2
+timeline0: 0.0
+timeline1: 1.0
+- Wind -
+active: false
+- Gravity -
+active: true
+lowMin: 0.0
+lowMax: 0.0
+highMin: -7.5
+highMax: -9.5
+relative: false
+scalingCount: 4
+scaling0: 0.0
+scaling1: 0.50980395
+scaling2: 0.78431374
+scaling3: 1.0
+timelineCount: 4
+timeline0: 0.0
+timeline1: 0.10958904
+timeline2: 0.25342464
+timeline3: 0.48630136
+- Tint -
+colorsCount: 15
+colors0: 1.0
+colors1: 0.047058824
+colors2: 0.047058824
+colors3: 1.0
+colors4: 0.99607843
+colors5: 0.047058824
+colors6: 0.047058824
+colors7: 1.0
+colors8: 0.2
+colors9: 0.047058824
+colors10: 0.05490196
+colors11: 1.0
+colors12: 1.0
+colors13: 0.047058824
+colors14: 0.9843137
+timelineCount: 5
+timeline0: 0.0
+timeline1: 0.2897402
+timeline2: 0.5006605
+timeline3: 0.74372524
+timeline4: 1.0
+- Transparency -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 1.0
+highMax: 1.0
+relative: false
+scalingCount: 4
+scaling0: 0.64912283
+scaling1: 1.0
+scaling2: 0.75
+scaling3: 0.0
+timelineCount: 4
+timeline0: 0.0
+timeline1: 0.43150684
+timeline2: 0.8
+timeline3: 1.0
+- Options -
+attached: false
+continuous: false
+aligned: false
+additive: true
+behind: false
+premultipliedAlpha: false
+- Image Path -
+4PStar.png
+
+
+firework2
+- Delay -
+active: false
+- Duration -
+lowMin: 300.0
+lowMax: 300.0
+- Count -
+min: 20
+max: 150
+- Emission -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 500.0
+highMax: 500.0
+relative: false
+scalingCount: 4
+scaling0: 0.0
+scaling1: 0.0
+scaling2: 1.0
+scaling3: 1.0
+timelineCount: 4
+timeline0: 0.0
+timeline1: 0.5
+timeline2: 0.84246576
+timeline3: 1.0
+- Life -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 750.0
+highMax: 1200.0
+relative: false
+scalingCount: 2
+scaling0: 1.0
+scaling1: 1.0
+timelineCount: 2
+timeline0: 0.0
+timeline1: 1.0
+- Life Offset -
+active: true
+lowMin: 0.0
+lowMax: 0.0
+highMin: 0.0
+highMax: 0.0
+relative: false
+scalingCount: 1
+scaling0: 1.0
+timelineCount: 1
+timeline0: 0.0
+- X Offset -
+active: false
+- Y Offset -
+active: false
+- Spawn Shape -
+shape: point
+- Spawn Width -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 0.0
+highMax: 0.0
+relative: false
+scalingCount: 1
+scaling0: 1.0
+timelineCount: 1
+timeline0: 0.0
+- Spawn Height -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 0.0
+highMax: 0.0
+relative: false
+scalingCount: 1
+scaling0: 1.0
+timelineCount: 1
+timeline0: 0.0
+- Scale -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 0.5
+highMax: 1.5
+relative: false
+scalingCount: 1
+scaling0: 1.0
+timelineCount: 1
+timeline0: 0.0
+- Velocity -
+active: true
+lowMin: 0.0
+lowMax: 0.0
+highMin: 1.0
+highMax: 8.0
+relative: false
+scalingCount: 2
+scaling0: 0.0
+scaling1: 1.0
+timelineCount: 2
+timeline0: 0.0
+timeline1: 0.10273973
+- Angle -
+active: true
+lowMin: 0.0
+lowMax: 360.0
+highMin: 0.0
+highMax: 360.0
+relative: false
+scalingCount: 1
+scaling0: 0.0
+timelineCount: 1
+timeline0: 0.0
+- Rotation -
+active: true
+lowMin: 1.0
+lowMax: 360.0
+highMin: 180.0
+highMax: 180.0
+relative: false
+scalingCount: 2
+scaling0: 0.0
+scaling1: 1.0
+timelineCount: 2
+timeline0: 0.0
+timeline1: 1.0
+- Wind -
+active: false
+- Gravity -
+active: true
+lowMin: 0.0
+lowMax: 0.0
+highMin: -7.5
+highMax: -9.5
+relative: false
+scalingCount: 4
+scaling0: 0.0
+scaling1: 0.50980395
+scaling2: 0.78431374
+scaling3: 1.0
+timelineCount: 4
+timeline0: 0.0
+timeline1: 0.10958904
+timeline2: 0.25342464
+timeline3: 0.48630136
+- Tint -
+colorsCount: 15
+colors0: 1.0
+colors1: 0.047058824
+colors2: 0.047058824
+colors3: 0.047058824
+colors4: 0.047058824
+colors5: 1.0
+colors6: 0.047058824
+colors7: 1.0
+colors8: 0.2
+colors9: 1.0
+colors10: 0.972549
+colors11: 0.047058824
+colors12: 1.0
+colors13: 0.047058824
+colors14: 0.047058824
+timelineCount: 5
+timeline0: 0.0
+timeline1: 0.2897402
+timeline2: 0.5006605
+timeline3: 0.74372524
+timeline4: 1.0
+- Transparency -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 1.0
+highMax: 1.0
+relative: false
+scalingCount: 4
+scaling0: 0.64912283
+scaling1: 1.0
+scaling2: 0.75
+scaling3: 0.0
+timelineCount: 4
+timeline0: 0.0
+timeline1: 0.43150684
+timeline2: 0.8
+timeline3: 1.0
+- Options -
+attached: false
+continuous: false
+aligned: false
+additive: true
+behind: false
+premultipliedAlpha: false
+- Image Path -
+4PStar.png
diff --git a/old/android/assets/particles/glow-circle.png b/old/android/assets/particles/glow-circle.png
new file mode 100644
index 0000000..96f69a0
Binary files /dev/null and b/old/android/assets/particles/glow-circle.png differ
diff --git a/old/android/assets/particles/magic-tech.png b/old/android/assets/particles/magic-tech.png
new file mode 100644
index 0000000..ac4a4e1
Binary files /dev/null and b/old/android/assets/particles/magic-tech.png differ
diff --git a/old/android/assets/particles/square.png b/old/android/assets/particles/square.png
new file mode 100644
index 0000000..fc4c5ca
Binary files /dev/null and b/old/android/assets/particles/square.png differ
diff --git a/old/android/assets/particles/standard_thrust.p b/old/android/assets/particles/standard_thrust.p
new file mode 100644
index 0000000..fcfdb57
--- /dev/null
+++ b/old/android/assets/particles/standard_thrust.p
@@ -0,0 +1,154 @@
+thrust
+- Delay -
+active: false
+- Duration -
+lowMin: 0.0
+lowMax: 0.0
+- Count -
+min: 0
+max: 40
+- Emission -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 70.0
+highMax: 70.0
+relative: false
+scalingCount: 1
+scaling0: 1.0
+timelineCount: 1
+timeline0: 0.0
+- Life -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 400.0
+highMax: 300.0
+relative: false
+scalingCount: 1
+scaling0: 1.0
+timelineCount: 1
+timeline0: 0.0
+- Life Offset -
+active: false
+- X Offset -
+active: false
+- Y Offset -
+active: false
+- Spawn Shape -
+shape: point
+- Spawn Width -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 0.0
+highMax: 0.0
+relative: false
+scalingCount: 1
+scaling0: 1.0
+timelineCount: 1
+timeline0: 0.0
+- Spawn Height -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 0.0
+highMax: 0.0
+relative: false
+scalingCount: 1
+scaling0: 1.0
+timelineCount: 1
+timeline0: 0.0
+- Scale -
+lowMin: 0.0
+lowMax: 1.0
+highMin: 1.0
+highMax: 1.0
+relative: false
+scalingCount: 4
+scaling0: 1.0
+scaling1: 0.92156863
+scaling2: 0.627451
+scaling3: 0.0
+timelineCount: 4
+timeline0: 0.0
+timeline1: 0.5273973
+timeline2: 0.8082192
+timeline3: 1.0
+- Velocity -
+active: true
+lowMin: 0.0
+lowMax: 0.0
+highMin: 7.0
+highMax: 7.0
+relative: false
+scalingCount: 1
+scaling0: 1.0
+timelineCount: 1
+timeline0: 0.0
+- Angle -
+active: true
+lowMin: 60.0
+lowMax: 120.0
+highMin: 90.0
+highMax: 90.0
+relative: false
+scalingCount: 5
+scaling0: 0.0
+scaling1: 0.0
+scaling2: 0.23529412
+scaling3: 0.8235294
+scaling4: 1.0
+timelineCount: 5
+timeline0: 0.0
+timeline1: 0.2260274
+timeline2: 0.43835616
+timeline3: 0.82191783
+timeline4: 1.0
+- Rotation -
+active: true
+lowMin: 0.0
+lowMax: 0.0
+highMin: 4.0
+highMax: 120.0
+relative: false
+scalingCount: 1
+scaling0: 1.0
+timelineCount: 1
+timeline0: 0.0
+- Wind -
+active: false
+- Gravity -
+active: false
+- Tint -
+colorsCount: 3
+colors0: 0.15294118
+colors1: 0.8627451
+colors2: 1.0
+timelineCount: 1
+timeline0: 0.0
+- Transparency -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 1.0
+highMax: 1.0
+relative: false
+scalingCount: 6
+scaling0: 0.0
+scaling1: 0.3508772
+scaling2: 1.0
+scaling3: 0.84210527
+scaling4: 0.64912283
+scaling5: 0.40350878
+timelineCount: 6
+timeline0: 0.0
+timeline1: 0.12328767
+timeline2: 0.26027396
+timeline3: 0.63013697
+timeline4: 0.9246575
+timeline5: 1.0
+- Options -
+attached: false
+continuous: true
+aligned: false
+additive: true
+behind: false
+premultipliedAlpha: false
+- Image Path -
+square.png
diff --git a/old/android/assets/particles/teleport-cloak.p b/old/android/assets/particles/teleport-cloak.p
new file mode 100644
index 0000000..4b35fe9
--- /dev/null
+++ b/old/android/assets/particles/teleport-cloak.p
@@ -0,0 +1,138 @@
+hexagon
+- Delay -
+active: false
+- Duration -
+lowMin: 400.0
+lowMax: 400.0
+- Count -
+min: 0
+max: 25
+- Emission -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 45.0
+highMax: 45.0
+relative: false
+scalingCount: 1
+scaling0: 1.0
+timelineCount: 1
+timeline0: 0.0
+- Life -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 400.0
+highMax: 655.0
+relative: false
+scalingCount: 4
+scaling0: 0.8235294
+scaling1: 0.47058824
+scaling2: 0.50980395
+scaling3: 0.7254902
+timelineCount: 4
+timeline0: 0.0
+timeline1: 0.39726028
+timeline2: 0.5684931
+timeline3: 1.0
+- Life Offset -
+active: false
+- X Offset -
+active: false
+- Y Offset -
+active: false
+- Spawn Shape -
+shape: square
+- Spawn Width -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 3.0
+highMax: 3.0
+relative: false
+scalingCount: 3
+scaling0: 1.0
+scaling1: 1.0
+scaling2: 0.0
+timelineCount: 3
+timeline0: 0.0
+timeline1: 0.39923224
+timeline2: 0.59884834
+- Spawn Height -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 3.0
+highMax: 3.0
+relative: false
+scalingCount: 3
+scaling0: 1.0
+scaling1: 1.0
+scaling2: 0.0
+timelineCount: 3
+timeline0: 0.0
+timeline1: 0.40115163
+timeline2: 0.59692895
+- Scale -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 1.0
+highMax: 1.0
+relative: false
+scalingCount: 1
+scaling0: 1.0
+timelineCount: 1
+timeline0: 0.0
+- Velocity -
+active: false
+- Angle -
+active: true
+lowMin: 90.0
+lowMax: 90.0
+highMin: 45.0
+highMax: 135.0
+relative: false
+scalingCount: 2
+scaling0: 0.0
+scaling1: 0.0
+timelineCount: 2
+timeline0: 0.0
+timeline1: 1.0
+- Rotation -
+active: false
+- Wind -
+active: false
+- Gravity -
+active: false
+- Tint -
+colorsCount: 6
+colors0: 0.047058824
+colors1: 0.627451
+colors2: 1.0
+colors3: 0.078431375
+colors4: 0.047058824
+colors5: 1.0
+timelineCount: 2
+timeline0: 0.0
+timeline1: 1.0
+- Transparency -
+lowMin: 0.0
+lowMax: 0.0
+highMin: 1.0
+highMax: 1.0
+relative: false
+scalingCount: 4
+scaling0: 0.1754386
+scaling1: 0.7719298
+scaling2: 0.4385965
+scaling3: 0.21052632
+timelineCount: 4
+timeline0: 0.0
+timeline1: 0.25342464
+timeline2: 0.82191783
+timeline3: 1.0
+- Options -
+attached: true
+continuous: false
+aligned: false
+additive: true
+behind: false
+premultipliedAlpha: false
+- Image Path -
+magic-tech.png
diff --git a/old/android/assets/particles/triangle.png b/old/android/assets/particles/triangle.png
new file mode 100644
index 0000000..ab997c0
Binary files /dev/null and b/old/android/assets/particles/triangle.png differ
diff --git a/old/android/assets/shaders/basic.vsh b/old/android/assets/shaders/basic.vsh
new file mode 100644
index 0000000..639bc50
--- /dev/null
+++ b/old/android/assets/shaders/basic.vsh
@@ -0,0 +1,14 @@
+attribute vec4 a_position;
+attribute vec4 a_color;
+attribute vec2 a_texCoord0;
+
+uniform mat4 u_projTrans;
+
+varying vec4 vColor;
+varying vec2 vTexCoord;
+
+void main() {
+ vColor = a_color;
+ vTexCoord = a_texCoord0;
+ gl_Position = u_projTrans * a_position;
+}
diff --git a/old/android/assets/shaders/bright_filter.fsh b/old/android/assets/shaders/bright_filter.fsh
new file mode 100644
index 0000000..9129746
--- /dev/null
+++ b/old/android/assets/shaders/bright_filter.fsh
@@ -0,0 +1,22 @@
+#ifdef GL_ES
+#define LOWP lowp
+precision mediump float;
+#else
+#define LOWP
+#endif
+
+varying LOWP vec4 vColor;
+varying vec2 vTexCoord;
+
+uniform sampler2D u_texture;
+
+void main() {
+ vec4 color = texture(u_texture, vTexCoord);
+ float brightness = (color.r*0.2126) + (color.g*0.7152) + (color.b * 0.0722);
+
+ if (brightness > 0.6) {
+ gl_FragColor = color *0.75;
+ } else {
+ gl_FragColor = vec4(0.0);
+ }
+}
diff --git a/old/android/assets/shaders/chrome_abb.fsh b/old/android/assets/shaders/chrome_abb.fsh
new file mode 100644
index 0000000..e69de29
diff --git a/old/android/assets/shaders/combine.fsh b/old/android/assets/shaders/combine.fsh
new file mode 100644
index 0000000..11b8b7c
--- /dev/null
+++ b/old/android/assets/shaders/combine.fsh
@@ -0,0 +1,27 @@
+#ifdef GL_ES
+#define LOWP lowp
+precision mediump float;
+#else
+#define LOWP
+#endif
+
+varying LOWP vec4 vColor;
+varying vec2 vTexCoord;
+
+
+uniform sampler2D u_texture;
+uniform sampler2D u_texture1;
+
+void main() {
+ vec4 origColor = texture2D(u_texture, vTexCoord);
+ vec4 blurredColor = texture2D(u_texture1, vTexCoord);
+
+ vec4 result;
+ result = origColor + blurredColor;
+ result.a = vColor.a;
+ result.rgb *= vColor.rgb;
+ gl_FragColor = result;
+
+
+}
+
diff --git a/old/android/assets/shaders/gaussian_blur.fsh b/old/android/assets/shaders/gaussian_blur.fsh
new file mode 100644
index 0000000..e7145e5
--- /dev/null
+++ b/old/android/assets/shaders/gaussian_blur.fsh
@@ -0,0 +1,45 @@
+varying vec4 vColor;
+varying vec2 vTexCoord;
+
+uniform sampler2D u_texture;
+uniform vec2 resolution;
+uniform float radius;
+uniform int pass;
+
+void main() {
+ //this will be our RGBA sum
+ vec4 sum = vec4(0.0);
+
+ //our original texcoord for this fragment
+ vec2 tc = vTexCoord;
+
+ //the amount to blur, i.e. how far off center to sample from
+ //1.0 -> blur by one pixel
+ //2.0 -> blur by two pixels, etc.
+ float blur = radius/resolution.y;
+
+ //the direction of our blur
+ //(1.0, 0.0) -> x-axis blur
+ //(0.0, 1.0) -> y-axis blur
+ float hstep = 1.0;
+ float vstep = 0.0;
+
+ if (pass == 1) {
+ hstep = 0.0;
+ vstep = 1.0;
+ }
+
+ sum += texture2D(u_texture, vec2(tc.x - 5.0*blur*hstep, tc.y - 5.0*blur*vstep)) * 0.014374;
+ sum += texture2D(u_texture, vec2(tc.x - 4.0*blur*hstep, tc.y - 4.0*blur*vstep)) * 0.035855;
+ sum += texture2D(u_texture, vec2(tc.x - 3.0*blur*hstep, tc.y - 3.0*blur*vstep)) * 0.072994;
+ sum += texture2D(u_texture, vec2(tc.x - 2.0*blur*hstep, tc.y - 2.0*blur*vstep)) * 0.121281;
+ sum += texture2D(u_texture, vec2(tc.x - 1.0*blur*hstep, tc.y - 1.0*blur*vstep)) * 0.164472;
+
+ sum += texture2D(u_texture, vec2(tc.x + 1.0*blur*hstep, tc.y + 1.0*blur*vstep)) * 0.164472;
+ sum += texture2D(u_texture, vec2(tc.x + 2.0*blur*hstep, tc.y + 2.0*blur*vstep)) * 0.121281;
+ sum += texture2D(u_texture, vec2(tc.x + 3.0*blur*hstep, tc.y + 3.0*blur*vstep)) * 0.072994;
+ sum += texture2D(u_texture, vec2(tc.x + 4.0*blur*hstep, tc.y + 4.0*blur*vstep)) * 0.035855;
+ sum += texture2D(u_texture, vec2(tc.x + 5.0*blur*hstep, tc.y + 5.0*blur*vstep)) * 0.014374;
+
+ gl_FragColor = sum;
+}
\ No newline at end of file
diff --git a/old/android/assets/shaders/mesh.fsh b/old/android/assets/shaders/mesh.fsh
new file mode 100644
index 0000000..0a10a45
--- /dev/null
+++ b/old/android/assets/shaders/mesh.fsh
@@ -0,0 +1,10 @@
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+//input from vertex shader
+varying vec4 vColor;
+
+void main() {
+ gl_FragColor = vColor;
+}
\ No newline at end of file
diff --git a/old/android/assets/shaders/mesh.vsh b/old/android/assets/shaders/mesh.vsh
new file mode 100644
index 0000000..9a9b0ca
--- /dev/null
+++ b/old/android/assets/shaders/mesh.vsh
@@ -0,0 +1,13 @@
+attribute vec2 a_position;
+attribute vec4 a_color;
+
+//our camera matrix
+uniform mat4 u_projTrans;
+
+//send the color out to the fragment shader
+varying vec4 vColor;
+
+void main() {
+ vColor = a_color;
+ gl_Position = u_projTrans * vec4(a_position.xy, 0.0, 1.0);
+}
\ No newline at end of file
diff --git a/old/android/assets/sounds/disintegrate.ogg b/old/android/assets/sounds/disintegrate.ogg
new file mode 100644
index 0000000..affc432
Binary files /dev/null and b/old/android/assets/sounds/disintegrate.ogg differ
diff --git a/old/android/assets/sounds/explosion.ogg b/old/android/assets/sounds/explosion.ogg
new file mode 100644
index 0000000..9011613
Binary files /dev/null and b/old/android/assets/sounds/explosion.ogg differ
diff --git a/old/android/assets/sounds/laser.ogg b/old/android/assets/sounds/laser.ogg
new file mode 100644
index 0000000..e3ea3f5
Binary files /dev/null and b/old/android/assets/sounds/laser.ogg differ
diff --git a/old/android/assets/sounds/pop_close.ogg b/old/android/assets/sounds/pop_close.ogg
new file mode 100644
index 0000000..9efde8b
Binary files /dev/null and b/old/android/assets/sounds/pop_close.ogg differ
diff --git a/old/android/assets/sounds/pop_open.ogg b/old/android/assets/sounds/pop_open.ogg
new file mode 100644
index 0000000..8de88c5
Binary files /dev/null and b/old/android/assets/sounds/pop_open.ogg differ
diff --git a/old/android/assets/splash_texture.png b/old/android/assets/splash_texture.png
new file mode 100644
index 0000000..5f1fa4e
Binary files /dev/null and b/old/android/assets/splash_texture.png differ
diff --git a/old/android/assets/uiskin.atlas b/old/android/assets/uiskin.atlas
new file mode 100644
index 0000000..78c174f
--- /dev/null
+++ b/old/android/assets/uiskin.atlas
@@ -0,0 +1,403 @@
+
+uiskin.png
+size: 256,256
+format: RGBA8888
+filter: Linear,Linear
+repeat: none
+check-off
+ rotate: false
+ xy: 11, 5
+ size: 14, 14
+ split: 4, 4, 4, 4
+ orig: 14, 14
+ offset: 0, 0
+ index: -1
+check-on
+ rotate: false
+ xy: 125, 35
+ size: 14, 14
+ split: 5, 5, 5, 5
+ orig: 14, 14
+ offset: 0, 0
+ index: -1
+check-disabled
+ rotate: false
+ xy: 68, 14
+ size: 14, 14
+ split: 3, 3, 3, 3
+ orig: 14, 14
+ offset: 0, 0
+ index: -1
+textfield
+ rotate: false
+ xy: 11, 5
+ size: 14, 14
+ split: 3, 3, 3, 3
+ orig: 14, 14
+ offset: 0, 0
+ index: -1
+cursor
+ rotate: false
+ xy: 23, 1
+ size: 3, 3
+ split: 1, 1, 1, 1
+ orig: 3, 3
+ offset: 0, 0
+ index: -1
+default
+ rotate: false
+ xy: 1, 50
+ size: 254, 77
+ orig: 254, 77
+ offset: 0, 0
+ index: -1
+default-pane
+ rotate: false
+ xy: 11, 1
+ size: 5, 3
+ split: 1, 1, 1, 1
+ orig: 5, 3
+ offset: 0, 0
+ index: -1
+default-rect-pad
+ rotate: false
+ xy: 11, 1
+ size: 5, 3
+ split: 1, 1, 1, 1
+ orig: 5, 3
+ offset: 0, 0
+ index: -1
+default-pane-noborder
+ rotate: false
+ xy: 170, 44
+ size: 1, 1
+ split: 0, 0, 0, 0
+ orig: 1, 1
+ offset: 0, 0
+ index: -1
+default-rect
+ rotate: false
+ xy: 38, 25
+ size: 3, 3
+ split: 1, 1, 1, 1
+ orig: 3, 3
+ offset: 0, 0
+ index: -1
+default-rect-down
+ rotate: false
+ xy: 170, 46
+ size: 3, 3
+ split: 1, 1, 1, 1
+ orig: 3, 3
+ offset: 0, 0
+ index: -1
+default-round
+ rotate: false
+ xy: 112, 29
+ size: 12, 20
+ split: 5, 5, 5, 5
+ orig: 12, 20
+ offset: 0, 0
+ index: -1
+default-round-down
+ rotate: false
+ xy: 99, 29
+ size: 12, 20
+ split: 5, 5, 5, 5
+ orig: 12, 20
+ offset: 0, 0
+ index: -1
+default-round-disabled
+ rotate: false
+ xy: 89, 8
+ size: 12, 20
+ split: 5, 5, 5, 5
+ orig: 12, 20
+ offset: 0, 0
+ index: -1
+default-scroll
+ rotate: false
+ xy: 57, 29
+ size: 20, 20
+ split: 5, 5, 5, 4
+ orig: 20, 20
+ offset: 0, 0
+ index: -1
+default-round-large
+ rotate: false
+ xy: 78, 29
+ size: 20, 20
+ split: 2, 2, 2, 2
+ orig: 20, 20
+ offset: 0, 0
+ index: -1
+default-select
+ rotate: false
+ xy: 29, 29
+ size: 27, 20
+ split: 4, 14, 4, 4
+ orig: 27, 20
+ offset: 0, 0
+ index: -1
+default-select-selection
+ rotate: false
+ xy: 26, 16
+ size: 3, 3
+ split: 1, 1, 1, 1
+ orig: 3, 3
+ offset: 0, 0
+ index: -1
+default-slider
+ rotate: false
+ xy: 29, 20
+ size: 8, 8
+ split: 2, 2, 2, 2
+ orig: 8, 8
+ offset: 0, 0
+ index: -1
+default-slider-knob
+ rotate: false
+ xy: 1, 1
+ size: 9, 18
+ orig: 9, 18
+ offset: 0, 0
+ index: -1
+vertical-slider-knob
+ rotate: false
+ xy: 27, 1
+ size: 14, 5
+ orig: 14, 5
+ offset: 0, 0
+ index: -1
+progress-slider-knob
+ rotate: false
+ xy: 215, 1
+ size:9, 18
+ orig: 14, 5
+ offset: 0, 0
+ index: -1
+default-splitpane
+ rotate: false
+ xy: 17, 1
+ size: 5, 3
+ split: 0, 5, 0, 0
+ orig: 5, 3
+ offset: 0, 0
+ index: -1
+default-splitpane-vertical
+ rotate: false
+ xy: 125, 29
+ size: 3, 5
+ split: 0, 0, 0, 5
+ orig: 3, 5
+ offset: 0, 0
+ index: -1
+default-window
+ rotate: false
+ xy: 1, 20
+ size: 27, 29
+ split: 4, 3, 20, 3
+ orig: 27, 29
+ offset: 0, 0
+ index: -1
+tinted-window
+ rotate: false
+ xy: 154, 5
+ size: 27, 29
+ split: 4, 3, 20, 3
+ orig: 27, 29
+ offset: 0, 0
+ index: -1
+selection
+ rotate: false
+ xy: 174, 48
+ size: 1, 1
+ orig: 1, 1
+ offset: 0, 0
+ index: -1
+tree-minus
+ rotate: false
+ xy: 140, 35
+ size: 14, 14
+ orig: 14, 14
+ offset: 0, 0
+ index: -1
+tree-plus
+ rotate: false
+ xy: 155, 35
+ size: 14, 14
+ orig: 14, 14
+ offset: 0, 0
+ index: -1
+white
+ rotate: false
+ xy: 129, 31
+ size: 3, 3
+ orig: 3, 3
+ offset: 0, 0
+ index: -1
+pause
+ rotate: false
+ xy: 1, 50
+ size: 45, 45
+ orig: 45, 45
+ offset: 0, 0
+ index: -1
+pause-down
+ rotate: false
+ xy: 1, 96
+ size: 45, 45
+ orig: 45, 45
+ offset: 0, 0
+ index: -1
+bar-fill
+ rotate: false
+ xy: 105, 13
+ size: 13, 3
+ split: 0, 0, 0, 0
+ orig: 13, 3
+ offset: 0, 0
+ index: -1
+bar-empty
+ rotate: false
+ xy: 119, 13
+ size: 13, 3
+ split: 1, 1, 1, 1
+ orig: 13, 3
+ offset: 0, 0
+ index: -1
+left-button
+ rotate: false
+ xy: 42, 8
+ size: 12, 20
+ split: 1, 4, 3, 3
+ orig: 12, 20
+ offset: 0, 0
+ index: -1
+left-button-down
+ rotate: false
+ xy: 55, 8
+ size: 12, 20
+ split: 1, 4, 3, 3
+ orig: 12, 20
+ offset: 0, 0
+ index: -1
+play
+ rotate: false
+ xy: 47, 50
+ size: 45, 45
+ orig: 45, 45
+ offset: 0, 0
+ index: -1
+play-down
+ rotate: false
+ xy: 47, 96
+ size: 45, 45
+ orig: 45, 45
+ offset: 0, 0
+ index: -1
+fast-forward
+ rotate: false
+ xy: 93, 50
+ size: 45, 45
+ orig: 45, 45
+ offset: 0, 0
+ index: -1
+fast-forward-down
+ rotate: false
+ xy: 93, 96
+ size: 45, 45
+ orig: 45, 45
+ offset: 0, 0
+ index: -1
+rewind
+ rotate: false
+ xy: 139, 50
+ size: 45, 45
+ orig: 45, 45
+ offset: 0, 0
+ index: -1
+rewind-down
+ rotate: false
+ xy: 139, 96
+ size: 45, 45
+ orig: 45, 45
+ offset: 0, 0
+ index: -1
+shuffle
+ rotate: false
+ xy: 185, 50
+ size: 45, 45
+ orig: 45, 45
+ offset: 0, 0
+ index: -1
+shuffle-down
+ rotate: false;
+ xy: 185, 96
+ size: 45, 45
+ orig: 45, 45
+ offset: 0, 0
+ index: -1
+rotate
+ rotate: false;
+ xy: 47, 142
+ size: 45, 45
+ orig: 45, 45
+ offset: 0, 0
+ index: -1
+holo-pane
+ rotate: false
+ xy: 105, 17
+ size: 8, 8
+ split: 2, 2, 2, 2
+ orig: 8, 8
+ offset: 0, 0
+ index: -1
+holo-pane-down
+ rotate: false
+ xy: 133, 8
+ size: 20, 20
+ split: 2, 2, 2, 2
+ orig: 20, 20
+ offset: 0, 0
+ index: -1
+corner-panel
+ rotate: false
+ xy: 182, 1
+ size: 32, 32
+ split: 15, 15, 15, 15
+ orig: 32, 32
+ offset: 0, 0
+ index: -1
+rect
+ rotate: false
+ xy: 176, 35
+ size: 14, 14
+ split: 3, 3, 3, 3
+ orig: 14, 14
+ offset: 0, 0
+ index: -1
+rect-down
+ rotate: false
+ xy: 191, 35
+ size: 14, 14
+ split: 3, 3, 3, 3
+ orig: 14, 14
+ offset: 0, 0
+ index: -1
+rect-disabled
+ rotate: false
+ xy: 206, 35
+ size: 14, 14
+ split: 3, 3, 3, 3
+ orig: 14, 14
+ offset: 0, 0
+ index: -1
+side-bars
+ rotate: false
+ xy: 221, 35
+ size: 15, 14
+ split: 7, 7, 2, 2
+ orig: 15, 14
+ offset: 0, 0
+ index: -1
\ No newline at end of file
diff --git a/old/android/assets/uiskin.png b/old/android/assets/uiskin.png
new file mode 100644
index 0000000..aa8491d
Binary files /dev/null and b/old/android/assets/uiskin.png differ
diff --git a/old/android/assets/uiskin_legacy.png b/old/android/assets/uiskin_legacy.png
new file mode 100644
index 0000000..86e641f
Binary files /dev/null and b/old/android/assets/uiskin_legacy.png differ
diff --git a/old/android/assets/uiskin_legacyB.png b/old/android/assets/uiskin_legacyB.png
new file mode 100644
index 0000000..960d314
Binary files /dev/null and b/old/android/assets/uiskin_legacyB.png differ
diff --git a/old/android/build.gradle b/old/android/build.gradle
new file mode 100644
index 0000000..a4548d3
--- /dev/null
+++ b/old/android/build.gradle
@@ -0,0 +1,136 @@
+android {
+ buildToolsVersion "27.0.3"
+ compileSdkVersion 27
+ sourceSets {
+ main {
+ manifest.srcFile 'AndroidManifest.xml'
+ java.srcDirs = ['src']
+ aidl.srcDirs = ['src']
+ renderscript.srcDirs = ['src']
+ res.srcDirs = ['res']
+ assets.srcDirs = ['assets']
+ jniLibs.srcDirs = ['libs']
+ }
+
+ }
+ packagingOptions {
+ exclude 'META-INF/robovm/ios/robovm.xml'
+ }
+ defaultConfig {
+ applicationId "zero1hd.rhythmbullet"
+ minSdkVersion 9
+ targetSdkVersion 27
+ versionCode 1
+ versionName "1.0"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+
+// called every time gradle gets executed, takes the native dependencies of
+// the natives configuration, and extracts them to the proper libs/ folders
+// so they get packed with the APK.
+task copyAndroidNatives() {
+ file("libs/armeabi/").mkdirs();
+ file("libs/armeabi-v7a/").mkdirs();
+ file("libs/arm64-v8a/").mkdirs();
+ file("libs/x86_64/").mkdirs();
+ file("libs/x86/").mkdirs();
+
+ configurations.natives.files.each { jar ->
+ def outputDir = null
+ if(jar.name.endsWith("natives-arm64-v8a.jar")) outputDir = file("libs/arm64-v8a")
+ if(jar.name.endsWith("natives-armeabi-v7a.jar")) outputDir = file("libs/armeabi-v7a")
+ if(jar.name.endsWith("natives-armeabi.jar")) outputDir = file("libs/armeabi")
+ if(jar.name.endsWith("natives-x86_64.jar")) outputDir = file("libs/x86_64")
+ if(jar.name.endsWith("natives-x86.jar")) outputDir = file("libs/x86")
+ if(outputDir != null) {
+ copy {
+ from zipTree(jar)
+ into outputDir
+ include "*.so"
+ }
+ }
+ }
+}
+
+task run(type: Exec) {
+ def path
+ def localProperties = project.file("../local.properties")
+ if (localProperties.exists()) {
+ Properties properties = new Properties()
+ localProperties.withInputStream { instr ->
+ properties.load(instr)
+ }
+ def sdkDir = properties.getProperty('sdk.dir')
+ if (sdkDir) {
+ path = sdkDir
+ } else {
+ path = "$System.env.ANDROID_HOME"
+ }
+ } else {
+ path = "$System.env.ANDROID_HOME"
+ }
+
+ def adb = path + "/platform-tools/adb"
+ commandLine "$adb", 'shell', 'am', 'start', '-n', 'zero1hd.rhythmbullet/zero1hd.rhythmbullet.AndroidLauncher'
+}
+
+// sets up the Android Eclipse project, using the old Ant based build.
+eclipse {
+ // need to specify Java source sets explicitly, SpringSource Gradle Eclipse plugin
+ // ignores any nodes added in classpath.file.withXml
+ sourceSets {
+ main {
+ java.srcDirs "src", 'gen'
+ }
+ }
+
+ jdt {
+ sourceCompatibility = 1.6
+ targetCompatibility = 1.6
+ }
+
+ classpath {
+ plusConfigurations += [ project.configurations.compile ]
+ containers 'com.android.ide.eclipse.adt.ANDROID_FRAMEWORK', 'com.android.ide.eclipse.adt.LIBRARIES'
+ }
+
+ project {
+ name = appName + "-android"
+ natures 'com.android.ide.eclipse.adt.AndroidNature'
+ buildCommands.clear();
+ buildCommand "com.android.ide.eclipse.adt.ResourceManagerBuilder"
+ buildCommand "com.android.ide.eclipse.adt.PreCompilerBuilder"
+ buildCommand "org.eclipse.jdt.core.javabuilder"
+ buildCommand "com.android.ide.eclipse.adt.ApkBuilder"
+ }
+}
+
+// sets up the Android Idea project, using the old Ant based build.
+idea {
+ module {
+ sourceDirs += file("src");
+ scopes = [ COMPILE: [plus:[project.configurations.compile]]]
+
+ iml {
+ withXml {
+ def node = it.asNode()
+ def builder = NodeBuilder.newInstance();
+ builder.current = node;
+ builder.component(name: "FacetManager") {
+ facet(type: "android", name: "Android") {
+ configuration {
+ option(name: "UPDATE_PROPERTY_FILES", value:"true")
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/old/android/gen/zero1hd/rhythmbullet/BuildConfig.java b/old/android/gen/zero1hd/rhythmbullet/BuildConfig.java
new file mode 100644
index 0000000..c53e38b
--- /dev/null
+++ b/old/android/gen/zero1hd/rhythmbullet/BuildConfig.java
@@ -0,0 +1,6 @@
+/** Automatically generated file. DO NOT MODIFY */
+package zero1hd.rhythmbullet;
+
+public final class BuildConfig {
+ public final static boolean DEBUG = true;
+}
\ No newline at end of file
diff --git a/old/android/gen/zero1hd/rhythmbullet/R.java b/old/android/gen/zero1hd/rhythmbullet/R.java
new file mode 100644
index 0000000..37011d4
--- /dev/null
+++ b/old/android/gen/zero1hd/rhythmbullet/R.java
@@ -0,0 +1,22 @@
+/* AUTO-GENERATED FILE. DO NOT MODIFY.
+ *
+ * This class was automatically generated by the
+ * aapt tool from the resource data it found. It
+ * should not be modified by hand.
+ */
+
+package zero1hd.rhythmbullet;
+
+public final class R {
+ public static final class attr {
+ }
+ public static final class drawable {
+ public static final int ic_launcher=0x7f020000;
+ }
+ public static final class string {
+ public static final int app_name=0x7f030000;
+ }
+ public static final class style {
+ public static final int GdxTheme=0x7f040000;
+ }
+}
diff --git a/old/android/ic_launcher-web.png b/old/android/ic_launcher-web.png
new file mode 100644
index 0000000..8f0110d
Binary files /dev/null and b/old/android/ic_launcher-web.png differ
diff --git a/old/android/libs/arm64-v8a/libgdx-freetype.so b/old/android/libs/arm64-v8a/libgdx-freetype.so
new file mode 100644
index 0000000..2b7f8ca
Binary files /dev/null and b/old/android/libs/arm64-v8a/libgdx-freetype.so differ
diff --git a/old/android/libs/arm64-v8a/libgdx.so b/old/android/libs/arm64-v8a/libgdx.so
new file mode 100644
index 0000000..24f4c99
Binary files /dev/null and b/old/android/libs/arm64-v8a/libgdx.so differ
diff --git a/old/android/libs/armeabi-v7a/libgdx-freetype.so b/old/android/libs/armeabi-v7a/libgdx-freetype.so
new file mode 100644
index 0000000..1b4c5d1
Binary files /dev/null and b/old/android/libs/armeabi-v7a/libgdx-freetype.so differ
diff --git a/old/android/libs/armeabi-v7a/libgdx.so b/old/android/libs/armeabi-v7a/libgdx.so
new file mode 100644
index 0000000..32664c4
Binary files /dev/null and b/old/android/libs/armeabi-v7a/libgdx.so differ
diff --git a/old/android/libs/armeabi/libgdx-freetype.so b/old/android/libs/armeabi/libgdx-freetype.so
new file mode 100644
index 0000000..c10bf64
Binary files /dev/null and b/old/android/libs/armeabi/libgdx-freetype.so differ
diff --git a/old/android/libs/armeabi/libgdx.so b/old/android/libs/armeabi/libgdx.so
new file mode 100644
index 0000000..b7fcf3f
Binary files /dev/null and b/old/android/libs/armeabi/libgdx.so differ
diff --git a/old/android/libs/x86_64/libgdx-freetype.so b/old/android/libs/x86_64/libgdx-freetype.so
new file mode 100644
index 0000000..3b05cfc
Binary files /dev/null and b/old/android/libs/x86_64/libgdx-freetype.so differ
diff --git a/old/android/libs/x86_64/libgdx.so b/old/android/libs/x86_64/libgdx.so
new file mode 100644
index 0000000..358f77c
Binary files /dev/null and b/old/android/libs/x86_64/libgdx.so differ
diff --git a/old/android/proguard-rules.pro b/old/android/proguard-rules.pro
new file mode 100644
index 0000000..b166b1e
--- /dev/null
+++ b/old/android/proguard-rules.pro
@@ -0,0 +1,45 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+-verbose
+
+-dontwarn android.support.**
+-dontwarn com.badlogic.gdx.backends.android.AndroidFragmentApplication
+-dontwarn com.badlogic.gdx.utils.GdxBuild
+-dontwarn com.badlogic.gdx.physics.box2d.utils.Box2DBuild
+-dontwarn com.badlogic.gdx.jnigen.BuildTarget*
+-dontwarn com.badlogic.gdx.graphics.g2d.freetype.FreetypeBuild
+
+-keep class com.badlogic.gdx.controllers.android.AndroidControllers
+
+-keepclassmembers class com.badlogic.gdx.backends.android.AndroidInput* {
+ (com.badlogic.gdx.Application, android.content.Context, java.lang.Object, com.badlogic.gdx.backends.android.AndroidApplicationConfiguration);
+}
+
+-keepclassmembers class com.badlogic.gdx.physics.box2d.World {
+ boolean contactFilter(long, long);
+ void beginContact(long);
+ void endContact(long);
+ void preSolve(long, long);
+ void postSolve(long, long);
+ boolean reportFixture(long);
+ float reportRayFixture(long, float, float, float, float, float);
+}
diff --git a/old/android/project.properties b/old/android/project.properties
new file mode 100644
index 0000000..3fefa92
--- /dev/null
+++ b/old/android/project.properties
@@ -0,0 +1,9 @@
+# This file is used by the Eclipse ADT plugin. It is unnecessary for IDEA and Android Studio projects, which
+# configure Proguard and the Android target via the build.gradle file.
+
+# To enable ProGuard to work with Eclipse ADT, uncomment this (available properties: sdk.dir, user.home)
+# and ensure proguard.jar in the Android SDK is up to date (or alternately reduce the android target to 23 or lower):
+# proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-rules.pro
+
+# Project target.
+target=android-19
diff --git a/old/android/res/drawable-hdpi/ic_launcher.png b/old/android/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..91f696b
Binary files /dev/null and b/old/android/res/drawable-hdpi/ic_launcher.png differ
diff --git a/old/android/res/drawable-mdpi/ic_launcher.png b/old/android/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..c1ab239
Binary files /dev/null and b/old/android/res/drawable-mdpi/ic_launcher.png differ
diff --git a/old/android/res/drawable-xhdpi/ic_launcher.png b/old/android/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..2011cc0
Binary files /dev/null and b/old/android/res/drawable-xhdpi/ic_launcher.png differ
diff --git a/old/android/res/drawable-xxhdpi/ic_launcher.png b/old/android/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..25fcef0
Binary files /dev/null and b/old/android/res/drawable-xxhdpi/ic_launcher.png differ
diff --git a/old/android/res/drawable-xxxhdpi/ic_launcher.png b/old/android/res/drawable-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..d109946
Binary files /dev/null and b/old/android/res/drawable-xxxhdpi/ic_launcher.png differ
diff --git a/old/android/res/values/strings.xml b/old/android/res/values/strings.xml
new file mode 100644
index 0000000..148fdbc
--- /dev/null
+++ b/old/android/res/values/strings.xml
@@ -0,0 +1,6 @@
+
+
+
+ RhythmBullet
+
+
diff --git a/old/android/res/values/styles.xml b/old/android/res/values/styles.xml
new file mode 100644
index 0000000..3f00fc5
--- /dev/null
+++ b/old/android/res/values/styles.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/old/android/src/zero1hd/rhythmbullet/AndroidLauncher.java b/old/android/src/zero1hd/rhythmbullet/AndroidLauncher.java
new file mode 100644
index 0000000..8e9b6d9
--- /dev/null
+++ b/old/android/src/zero1hd/rhythmbullet/AndroidLauncher.java
@@ -0,0 +1,14 @@
+package zero1hd.rhythmbullet;
+
+import android.os.Bundle;
+
+import com.badlogic.gdx.backends.android.AndroidApplication;
+
+public class AndroidLauncher extends AndroidApplication {
+ @Override
+ protected void onCreate (Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+// AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
+// initialize(new RhythmBullet(), config);
+ }
+}
diff --git a/old/build.gradle b/old/build.gradle
new file mode 100644
index 0000000..bf528ec
--- /dev/null
+++ b/old/build.gradle
@@ -0,0 +1,91 @@
+buildscript {
+
+
+ repositories {
+ mavenLocal()
+ mavenCentral()
+ maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
+ maven { url "https://dl.bintray.com/ijabz/maven/" }
+ jcenter()
+ google()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:3.1.0'
+
+
+ }
+}
+
+allprojects {
+ apply plugin: "eclipse"
+ apply plugin: "idea"
+
+ version = '1.0'
+ ext {
+ appName = "RhythmBullet"
+ gdxVersion = '1.9.8'
+ roboVMVersion = '2.3.3'
+ box2DLightsVersion = '1.4'
+ ashleyVersion = '1.7.0'
+ aiVersion = '1.8.0'
+ }
+
+ repositories {
+ mavenLocal()
+ mavenCentral()
+ maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
+ maven { url "https://oss.sonatype.org/content/repositories/releases/" }
+ }
+}
+
+project(":desktop") {
+ apply plugin: "java"
+
+
+ dependencies {
+ compile project(":core")
+ compile "com.badlogicgames.gdx:gdx-backend-lwjgl:$gdxVersion"
+ compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop"
+ compile "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-desktop"
+ }
+}
+
+project(":android") {
+ apply plugin: "android"
+
+ configurations { natives }
+
+ dependencies {
+ compile project(":core")
+ compile "com.badlogicgames.gdx:gdx-backend-android:$gdxVersion"
+ natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi"
+ natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi-v7a"
+ natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-arm64-v8a"
+ natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86"
+ natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86_64"
+ compile "com.badlogicgames.ashley:ashley:$ashleyVersion"
+ compile "com.badlogicgames.gdx:gdx-freetype:$gdxVersion"
+ natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-armeabi"
+ natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-armeabi-v7a"
+ natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-arm64-v8a"
+ natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-x86"
+ natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-x86_64"
+ }
+}
+
+project(":core") {
+ apply plugin: "java"
+
+
+ dependencies {
+ compile "com.badlogicgames.gdx:gdx:$gdxVersion"
+ compile "com.badlogicgames.ashley:ashley:$ashleyVersion"
+ compile "com.badlogicgames.gdx:gdx-freetype:$gdxVersion"
+ compile "com.github.rwl:jtransforms:2.4.0"
+ compile "org.apache.commons:commons-math3:3.2"
+ }
+}
+
+tasks.eclipse.doLast {
+ delete ".project"
+}
\ No newline at end of file
diff --git a/old/core/.classpath b/old/core/.classpath
new file mode 100644
index 0000000..555bea3
--- /dev/null
+++ b/old/core/.classpath
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/old/core/.project b/old/core/.project
new file mode 100644
index 0000000..a67050c
--- /dev/null
+++ b/old/core/.project
@@ -0,0 +1,18 @@
+
+
+ RhythmBullet-core
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.springsource.ide.eclipse.gradle.core.nature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/old/core/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs b/old/core/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs
new file mode 100644
index 0000000..74a3dd7
--- /dev/null
+++ b/old/core/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs
@@ -0,0 +1,4 @@
+#org.springsource.ide.eclipse.gradle.core.preferences.GradleProjectPreferences
+#Mon Sep 10 00:40:41 CDT 2018
+org.springsource.ide.eclipse.gradle.linkedresources=
+org.springsource.ide.eclipse.gradle.rootprojectloc=..
diff --git a/old/core/.settings/gradle/org.springsource.ide.eclipse.gradle.refresh.prefs b/old/core/.settings/gradle/org.springsource.ide.eclipse.gradle.refresh.prefs
new file mode 100644
index 0000000..599cb88
--- /dev/null
+++ b/old/core/.settings/gradle/org.springsource.ide.eclipse.gradle.refresh.prefs
@@ -0,0 +1,8 @@
+#org.springsource.ide.eclipse.gradle.core.actions.GradleRefreshPreferences
+#Mon Sep 10 00:40:41 CDT 2018
+addResourceFilters=true
+afterTasks=afterEclipseImport;
+beforeTasks=cleanEclipse;eclipse;
+enableAfterTasks=true
+enableBeforeTasks=true
+useHierarchicalNames=false
diff --git a/old/core/.settings/org.eclipse.jdt.core.prefs b/old/core/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..3a21537
--- /dev/null
+++ b/old/core/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,11 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/old/core/build.gradle b/old/core/build.gradle
new file mode 100644
index 0000000..03cd1be
--- /dev/null
+++ b/old/core/build.gradle
@@ -0,0 +1,11 @@
+apply plugin: "java"
+
+sourceCompatibility = 1.6
+[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
+
+sourceSets.main.java.srcDirs = [ "src/" ]
+
+
+eclipse.project {
+ name = appName + "-core"
+}
diff --git a/old/core/lib/jaudiotagger-2.2.3-javadoc.jar b/old/core/lib/jaudiotagger-2.2.3-javadoc.jar
new file mode 100644
index 0000000..122f5ae
Binary files /dev/null and b/old/core/lib/jaudiotagger-2.2.3-javadoc.jar differ
diff --git a/old/core/lib/jaudiotagger-2.2.3-sources.jar b/old/core/lib/jaudiotagger-2.2.3-sources.jar
new file mode 100644
index 0000000..31d7173
Binary files /dev/null and b/old/core/lib/jaudiotagger-2.2.3-sources.jar differ
diff --git a/old/core/lib/jaudiotagger-2.2.3.jar b/old/core/lib/jaudiotagger-2.2.3.jar
new file mode 100644
index 0000000..7069a3b
Binary files /dev/null and b/old/core/lib/jaudiotagger-2.2.3.jar differ
diff --git a/old/core/src/zero1hd/rhythmbullet/RhythmBullet.java b/old/core/src/zero1hd/rhythmbullet/RhythmBullet.java
new file mode 100644
index 0000000..5afdb48
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/RhythmBullet.java
@@ -0,0 +1,231 @@
+package zero1hd.rhythmbullet;
+
+import com.badlogic.gdx.Application;
+import com.badlogic.gdx.Game;
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.Preferences;
+import com.badlogic.gdx.Screen;
+import com.badlogic.gdx.assets.AssetManager;
+import com.badlogic.gdx.assets.loaders.ParticleEffectLoader;
+import com.badlogic.gdx.assets.loaders.SoundLoader;
+import com.badlogic.gdx.assets.loaders.TextureAtlasLoader;
+import com.badlogic.gdx.assets.loaders.TextureLoader;
+import com.badlogic.gdx.assets.loaders.resolvers.InternalFileHandleResolver;
+import com.badlogic.gdx.assets.loaders.resolvers.ResolutionFileResolver.Resolution;
+import com.badlogic.gdx.audio.Sound;
+import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.graphics.g2d.ParticleEffect;
+import com.badlogic.gdx.graphics.g2d.TextureAtlas;
+import com.badlogic.gdx.scenes.scene2d.ui.Skin;
+
+import zero1hd.rhythmbullet.util.AssetPack;
+import zero1hd.rhythmbullet.util.GenericFileTypeHandler;
+import zero1hd.rhythmbullet.util.InitialScreen;
+import zero1hd.rhythmbullet.util.RoundingResolutionHandler;
+import zero1hd.rhythmbullet.util.ScreenConfiguration;
+import zero1hd.rhythmbullet.util.ResizeReadyScreen;
+
+
+public class RhythmBullet extends Game {
+ public static final int WORLD_WIDTH = 64;
+ public static final int WORLD_HEIGHT = 48;
+ public static final int SPAWN_CIRCLE_RADIUS = 6;
+ public static int pixels_per_unit;
+ private boolean initiated;
+ private boolean resizing, simpleResizeOnce;
+ private int screenWidth, screenHeight;
+ public static final String VERSION = "(1.0.0) R1-PreAlpha";
+
+ private AssetManager assetManager = new AssetManager();
+ private Skin skin;
+ private Preferences preferences;
+ private RoundingResolutionHandler rRHandler;
+ private InitialScreen initialScreen;
+ private AssetPack assetPack;
+ private ScreenConfiguration screenConfiguration;
+ /**
+ * This should be called before passed to LWJGL. Setup for system-dependent items such as UI and assets.
+ * @param initialScreen the first screen to go to.
+ * @param assetPack the asset package to be used.
+ */
+ public void setup(InitialScreen initialScreen, AssetPack assetPack, ScreenConfiguration screenConfiguration) {
+ this.initialScreen = initialScreen;
+ this.assetPack = assetPack;
+ this.screenConfiguration = screenConfiguration;
+ screenConfiguration.queueBorderless(true);
+ }
+
+ @Override
+ public void create() {
+ setScreen(initialScreen);
+ Gdx.app.setLogLevel(Application.LOG_DEBUG);
+ screenWidth = Gdx.graphics.getWidth();
+ screenHeight = Gdx.graphics.getHeight();
+ initialScreen.init();
+ initialLoad();
+ }
+
+ private void initialLoad() {
+ if (initiated) throw new IllegalStateException("Initiation cannot occur more than once.");
+
+ simpleResizeOnce = true;
+ skin = new Skin();
+ assetPack.initiate();
+
+ preferences = Gdx.app.getPreferences("RhythmBullet Preferences");
+
+ Resolution[] resolution = {
+ new Resolution(1280, 720, "1280x720"),
+ new Resolution(1366, 768, "1366x768"),
+ new Resolution(1280, 800, "1280x800"),
+ new Resolution(1920, 1080, "1920x1080"),
+ new Resolution(1920, 1200, "1920x1200"),
+ new Resolution(2560, 1440, "2560x1440"),
+ new Resolution(3840, 2160, "3840x2160")
+ };
+
+ InternalFileHandleResolver internalFileResolver = new InternalFileHandleResolver();
+ rRHandler = new RoundingResolutionHandler(internalFileResolver, resolution);
+ GenericFileTypeHandler genericFileFinder = new GenericFileTypeHandler(internalFileResolver);
+ assetManager.setLoader(TextureAtlas.class, new TextureAtlasLoader(rRHandler));
+ assetManager.setLoader(Texture.class, new TextureLoader(rRHandler));
+ assetManager.setLoader(ParticleEffect.class, new ParticleEffectLoader(genericFileFinder));
+ assetManager.setLoader(Sound.class, new SoundLoader(genericFileFinder));
+
+ rRHandler.setResolution(getPreferences().getInteger("screen-width"), getPreferences().getInteger("screen-height"));
+ queueAssets();
+ }
+
+ private void initialLoadComplete() {
+ screenConfiguration.queueBorderless(preferences.getBoolean("borderless", false));
+
+ skin.addRegions(assetManager.get("uiskin.atlas", TextureAtlas.class));
+ pixels_per_unit = (int) (Float.valueOf(screenHeight)/Float.valueOf(WORLD_HEIGHT));
+ if (getPreferences().getBoolean("fullscreen", true)) {
+ Gdx.graphics.setFullscreenMode(Gdx.graphics.getDisplayMode());
+ } else {
+ Gdx.graphics.setWindowedMode(getPreferences().getInteger("screen-width"), getPreferences().getInteger("screen-height"));
+ }
+ assetPack.generateFonts(skin);
+ assetPack.setupSkin(skin);
+ assetPack.complete(assetManager);
+
+ }
+
+ @Override
+ public void render() {
+ checkAssetQueue();
+ super.render();
+ }
+
+ public boolean checkAssetQueue() {
+ if (assetManager.update()) {
+ if (resizing) {
+ Gdx.app.debug("Resize", "Post resize is starting...");
+ if (skin != null) skin.dispose();
+ skin = new Skin();
+ skin.addRegions(assetManager.get("uiskin.atlas", TextureAtlas.class));
+
+ assetPack.generateFonts(skin);
+ assetPack.setupSkin(skin);
+ assetPack.complete(assetManager);
+ if (getScreen() instanceof ResizeReadyScreen) {
+ ((ResizeReadyScreen) getScreen()).postAssetLoad();
+ } else {
+ throw new IllegalStateException("Cannot perform window resize on a screen that isn't resize ready.");
+ }
+ Gdx.app.debug("Resize", "Post resize has ended.");
+ resizing = false;
+ } else if (!initiated) {
+ initiated = true;
+ initialLoadComplete();
+ setScreen(((InitialScreen) initialScreen).advance(this));
+ }
+ return true;
+ }
+ return false;
+ }
+
+
+ @Override
+ public void setScreen(Screen screen) {
+ if (screen instanceof ResizeReadyScreen) {
+ ResizeReadyScreen advancedResizeScreen = (ResizeReadyScreen) screen;
+ try {
+ advancedResizeScreen.preAssetLoad();
+ } catch (NullPointerException cleanScreen) {
+ Gdx.app.debug("Screen", "clean screen: " + advancedResizeScreen.getClass().getSimpleName());
+ //Tried to perform pre-asset reload, but had uninitialized objects, meaning this is a new screen, or "clean" screen.
+ } finally {
+ advancedResizeScreen.postAssetLoad();
+ }
+ }
+ super.setScreen(screen);
+ }
+
+ @Override
+ public void resize(int width, int height) {
+ if (screenWidth != width || screenHeight != height) {
+ Gdx.app.debug("resize", "Current size:" + screenWidth + "x" + screenHeight + " new size: " + width + "x" + height);
+ screenWidth = width;
+ screenHeight = height;
+ pixels_per_unit = (int) (Float.valueOf(screenHeight)/Float.valueOf(WORLD_HEIGHT));
+ rRHandler.setResolution(width, height);
+ preferences.putInteger("screen-width", width);
+ preferences.putInteger("screen-height", height);
+ preferences.flush();
+
+ if (!simpleResizeOnce) {
+ Gdx.app.debug("Resize", "complex pre-resize is happening. Resizing to " + width + "x" + height);
+ if (getScreen() instanceof ResizeReadyScreen) {
+ ((ResizeReadyScreen) getScreen()).preAssetLoad();
+ } else {
+ throw new IllegalStateException("Cannot perform window resize on a screen that isn't using a resize ready screen.");
+ }
+
+ resizing = true;
+ assetManager.clear();
+ queueAssets();
+ } else {
+ simpleResizeOnce = false;
+ }
+ super.resize(width, height);
+ }
+ }
+
+ public void queueAssets() {
+ assetPack.queueTextures(assetManager);
+ assetPack.queueSFX(assetManager);
+ assetPack.queueParticles(assetManager);
+ }
+
+ public AssetManager getAssetManager() {
+ return assetManager;
+ }
+
+ public Skin getSkin() {
+ return skin;
+ }
+
+ public Preferences getPreferences() {
+ return preferences;
+ }
+
+ @Override
+ public void dispose() {
+ Gdx.app.debug("Core", "disposing...");
+ try {
+ getScreen().dispose();
+ getSkin().dispose();
+ assetManager.dispose();
+ assetPack.dispose();
+ } catch (NullPointerException npe) {
+ Gdx.app.debug("Core", "Disposal error occurred, possibly caused by failing to complete initialization.", npe);
+ }
+ super.dispose();
+ }
+
+ public ScreenConfiguration getScreenConfiguration() {
+ return screenConfiguration;
+ }
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/audio/AudioMetadataController.java b/old/core/src/zero1hd/rhythmbullet/audio/AudioMetadataController.java
new file mode 100644
index 0000000..15bca8a
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/audio/AudioMetadataController.java
@@ -0,0 +1,166 @@
+package zero1hd.rhythmbullet.audio;
+
+import java.util.Comparator;
+import java.util.Observable;
+import java.util.Observer;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.files.FileHandle;
+import com.badlogic.gdx.utils.Array;
+import com.badlogic.gdx.utils.Disposable;
+import com.badlogic.gdx.utils.Sort;
+
+import zero1hd.rhythmbullet.audio.metadata.AudioMetadata;
+import zero1hd.rhythmbullet.audio.metadata.MP3Metadata;
+import zero1hd.rhythmbullet.audio.metadata.WAVMetadata;
+
+public class AudioMetadataController extends Observable implements Disposable, Observer {
+ private MusicList musicList;
+ private volatile Array metadataArray;
+ private MetadataLoadingThread loadingThread;
+ private volatile boolean searching;
+ private Comparator metadataComparer;
+
+ public AudioMetadataController(MusicList musicList) {
+ this.musicList = musicList;
+ metadataArray = new Array<>();
+ loadingThread = new MetadataLoadingThread();
+ musicList.addObserver(this);
+ metadataComparer = new Comparator() {
+ @Override
+ public int compare(AudioMetadata o1, AudioMetadata o2) {
+ return o1.getTitle().compareToIgnoreCase(o2.getTitle());
+ }
+ };
+ }
+
+ public MusicList getMusicList() {
+ return musicList;
+ }
+
+ /**
+ * Non-blocking, loads on separate thread.
+ */
+ public void loadAudioMetadata() {
+ if (!loadingThread.start()) {
+ loadingThread.stop();
+ loadingThread = new MetadataLoadingThread();
+ loadingThread.start();
+ }
+ }
+
+ /**
+ * if there is the same amount of metadata as there is music in the music list.
+ * @return whether or not both sizes are equal.
+ */
+ public boolean isSameSizeMusicList() {
+ return (metadataArray.size == musicList.getTotal());
+ }
+
+ @Override
+ public void dispose() {
+ for (int i = 0; i < metadataArray.size; i++) {
+ metadataArray.get(i).dispose();
+ }
+ }
+
+ public int size() {
+ return metadataArray.size;
+ }
+
+ public AudioMetadata getAudioMetadata(int index) {
+ return metadataArray.get(index);
+ }
+
+
+ public AudioMetadata getAudioMetadata(FileHandle filehandle) {
+ for (int i = 0; i < metadataArray.size; i++) {
+ if (metadataArray.get(i).getFileHandle() == filehandle) {
+ return metadataArray.get(i);
+ }
+ }
+ throw new IllegalArgumentException("Couldn't find file " + filehandle.name());
+ }
+
+ public boolean isSearching() {
+ return searching;
+ }
+
+ private class MetadataLoadingThread implements Runnable {
+ private Thread thread;
+ private String name = "AudioMetadata-Load";
+ private volatile boolean work = true;
+
+ @Override
+ public void run() {
+ Gdx.app.debug(name, "loading...");
+ clear();
+ synchronized (this) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ searching = true;
+ Array tempMetadataArray = new Array<>();
+ for (int i = 0; i < musicList.getTotal() && work; i++) {
+ FileHandle musicFile = musicList.getAudioFileHandle(i);
+ if (musicFile == null) return;
+ switch (SupportedFormats.valueOf(musicFile.extension().toUpperCase())) {
+ case MP3:
+ tempMetadataArray.add(new MP3Metadata(musicFile));
+ break;
+ case WAV:
+ tempMetadataArray.add(new WAVMetadata(musicFile));
+ break;
+ default:
+ break;
+ }
+ }
+
+ Sort.instance().sort(tempMetadataArray, metadataComparer);
+
+ if (work) {
+ metadataArray = tempMetadataArray;
+ searching = false;
+ Gdx.app.debug(name, "load complete.");
+ setChanged();
+ notifyObservers();
+ }
+ }
+
+ public boolean start() {
+ if (thread == null) {
+ thread = new Thread(this, name);
+ thread.start();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public void stop() {
+ work = false;
+ }
+ }
+
+ @Override
+ public void update(Observable o, Object arg) {
+ if (o == musicList && arg == musicList.states.COMPLETE) {
+ loadAudioMetadata();
+ }
+ }
+
+ public void clear() {
+ Gdx.app.postRunnable(() -> {
+ for (int i = 0; i < metadataArray.size; i++) {
+ metadataArray.get(i).dispose();
+ }
+ metadataArray.clear();
+ synchronized (loadingThread) {
+ loadingThread.notify();
+ }
+ });
+ }
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/audio/AudioProcessorFactory.java b/old/core/src/zero1hd/rhythmbullet/audio/AudioProcessorFactory.java
new file mode 100644
index 0000000..fdd39e2
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/audio/AudioProcessorFactory.java
@@ -0,0 +1,12 @@
+package zero1hd.rhythmbullet.audio;
+
+import com.badlogic.gdx.files.FileHandle;
+
+import zero1hd.rhythmbullet.audio.processor.AudioProcessor;
+
+public interface AudioProcessorFactory {
+ /**
+ * @return a new {@link #zero1hd.rhythmbullet.audio.processor.AudioProcessor()} from the appropriate platform.
+ */
+ public AudioProcessor newMP3AudioProcessor(FileHandle fileHandle);
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/audio/MinimalAudioHeader.java b/old/core/src/zero1hd/rhythmbullet/audio/MinimalAudioHeader.java
new file mode 100644
index 0000000..55a028e
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/audio/MinimalAudioHeader.java
@@ -0,0 +1,61 @@
+package zero1hd.rhythmbullet.audio;
+
+import java.io.IOException;
+
+import org.jaudiotagger.audio.AudioFile;
+import org.jaudiotagger.audio.AudioFileIO;
+import org.jaudiotagger.audio.AudioHeader;
+import org.jaudiotagger.audio.exceptions.CannotReadException;
+import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException;
+import org.jaudiotagger.audio.exceptions.ReadOnlyFileException;
+import org.jaudiotagger.audio.mp3.MP3AudioHeader;
+import org.jaudiotagger.audio.mp3.MP3File;
+import org.jaudiotagger.tag.TagException;
+
+import com.badlogic.gdx.files.FileHandle;
+
+public class MinimalAudioHeader {
+ private int sampleRate, channelCount;
+ private SupportedFormats format;
+ private FileHandle musicFile;
+ public MinimalAudioHeader(FileHandle musicFile) {
+ if (musicFile == null) throw new IllegalArgumentException("musicFile for minimal audio headers should not be null.");
+ this.musicFile = musicFile;
+ format = SupportedFormats.valueOf(musicFile.extension().toUpperCase());
+ try {
+ AudioFile file = AudioFileIO.read(musicFile.file());
+ AudioHeader header = file.getAudioHeader();
+ sampleRate = header.getSampleRateAsNumber();
+ channelCount = (header.getChannels().equals("Mono") ? 1 : 2);
+ } catch (CannotReadException | IOException | TagException | ReadOnlyFileException | InvalidAudioFrameException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+
+ public int getSampleRate() {
+ return sampleRate;
+ }
+
+ public int getChannelCount() {
+ return channelCount;
+ }
+
+
+ public long estimateSampleFrames() {
+ switch (format) {
+ case MP3:
+ try {
+ MP3File file = (MP3File) AudioFileIO.read(musicFile.file());
+ MP3AudioHeader header = file.getMP3AudioHeader();
+ return header.getNumberOfFrames();
+ } catch (CannotReadException | IOException | TagException | ReadOnlyFileException | InvalidAudioFrameException e) {
+ e.printStackTrace();
+ }
+ return -1;
+ default:
+ return -1;
+ }
+ }
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/audio/MusicController.java b/old/core/src/zero1hd/rhythmbullet/audio/MusicController.java
new file mode 100644
index 0000000..74ae39e
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/audio/MusicController.java
@@ -0,0 +1,262 @@
+package zero1hd.rhythmbullet.audio;
+
+import java.util.Observable;
+import java.util.Observer;
+import java.util.Random;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.Preferences;
+import com.badlogic.gdx.audio.Music;
+import com.badlogic.gdx.audio.Music.OnCompletionListener;
+import com.badlogic.gdx.files.FileHandle;
+
+/**
+ * Manages current games music playback and does this in tandem with the {@link MusicList} by asking to retrieve files and then feeding it to LibGDX.
+ * Notifies observers when a new song is loaded.
+ * The loading model is like taking a disk and loading it into a player. It doesn't necessarily mean it'll play right away, but its ready and the only track that has a stream opened.
+ * @author yunya
+ *
+ */
+public class MusicController extends Observable implements OnCompletionListener, Observer {
+ public final class States {
+ public final Integer LOADED = new Integer(0), PLAYING = new Integer(1), PAUSED = new Integer(2);
+ }
+
+ public final States states = new States();
+ private MusicList musicList;
+ private MinimalAudioHeader musicHeader;
+ private volatile Music music;
+ private int currentlyPlayingIndex;
+ private boolean autoPlay;
+ private boolean shuffle;
+ private Random rand;
+ private Preferences prefs;
+
+ public MusicController(MusicList musicList, Preferences prefs) {
+ if (prefs == null) throw new NullPointerException("preferences can't be null...");
+ if (musicList == null) throw new NullPointerException("music list can't be null...");
+ musicList.addObserver(this);
+ this.prefs = prefs;
+ this.musicList = musicList;
+ rand = new Random();
+ }
+
+ /**
+ * This play method automatically sets the volume.
+ */
+ public void play() {
+ if (music != null) {
+ Gdx.app.debug("MusicController", "Playing from controller.");
+ music.play();
+ music.setVolume(prefs.getFloat("music vol", 100f)/100f);
+ setChanged();
+ notifyObservers(states.PLAYING);
+ } else {
+ Gdx.app.debug("MusicController", "Music isn't loaded!");
+ Thread.dumpStack();
+ }
+ }
+
+ /**
+ * Called to pause current song. Does nothing if no song is playing or loaded.
+ */
+ public void pause() {
+ if (music != null) {
+ music.pause();
+ setChanged();
+ notifyObservers(states.PAUSED);
+ }
+ }
+
+ /**
+ * Loads music based on the index in the {@link MusicList}.
+ * @param index of music to play
+ */
+ public void setMusicByIndex(int index) {
+ this.currentlyPlayingIndex = index;
+ loadMusic();
+ }
+
+ /**
+ * Loads music using the given file. The given file must be found in the {@link MusicList}.
+ * This function gets the index of the given file within {@link MusicList} and passes that index to {@link #setMusicByIndex(index)}.
+ * @param fileHandle to use.
+ */
+ public void setMusicByFileHandle(FileHandle fileHandle) {
+ setMusicByIndex(musicList.getIndexOfFileHandle(fileHandle));
+ }
+
+ /**
+ * Goes to the next track
+ */
+ public void skip() {
+ currentlyPlayingIndex++;
+ if (shuffle) {
+ shuffle();
+ }
+ loadMusic();
+ }
+
+ /**
+ * Goes to the previous track
+ */
+ public void previous() {
+ currentlyPlayingIndex--;
+ if (shuffle) {
+ shuffle();
+ }
+ loadMusic();
+ }
+
+ @Override
+ public void onCompletion(Music music) {
+ if (autoPlay) {
+ if (shuffle) {
+ shuffle();
+ } else {
+ currentlyPlayingIndex++;
+ }
+ loadMusic();
+ play();
+ }
+ }
+
+ /**
+ * Shuffles the controller whether the shuffle boolean is true or false.
+ */
+ public void shuffle() {
+ Gdx.app.debug("MusicListController", "shuffled.");
+ if (musicList.getTotal() == 0) {
+ currentlyPlayingIndex = 0;
+ } else {
+ currentlyPlayingIndex = rand.nextInt(musicList.getTotal());
+ }
+ }
+
+ public void setAutoPlay(boolean autoPlay) {
+ this.autoPlay = autoPlay;
+ }
+
+ public void setShuffle(boolean shuffle) {
+ this.shuffle = shuffle;
+ }
+
+ public void setLoop(boolean loop) {
+ music.setLooping(loop);
+ }
+
+ public boolean isShuffle() {
+ return shuffle;
+ }
+
+ public boolean isAutoPlay() {
+ return autoPlay;
+ }
+
+ public boolean isLoop() {
+ return music.isLooping();
+ }
+
+ /**
+ * Loads the current selected song.
+ */
+ public void loadMusic() {
+ Gdx.app.debug("MusicListController", "music is being loaded from music list with " + musicList.getTotal() + " songs.");
+ boolean playing = isPlaying();
+ musicHeader = null;
+ if (music != null) {
+ music.dispose();
+ }
+ if (currentlyPlayingIndex < 0) {
+ currentlyPlayingIndex = musicList.getTotal()-1;
+ }
+ if (currentlyPlayingIndex >= musicList.getTotal()) {
+ currentlyPlayingIndex = 0;
+ }
+ if (musicList.getTotal() != 0) {
+ this.music = Gdx.audio.newMusic(musicList.getAudioFileHandle(currentlyPlayingIndex));
+ music.setOnCompletionListener(this);
+
+ setChanged();
+
+ notifyObservers(states.LOADED);
+ if (playing || autoPlay) {
+ play();
+ }
+ }
+ }
+
+ public MusicList getMusicList() {
+ return musicList;
+ }
+
+ public FileHandle getCurrentMusicFileHandle() {
+ return musicList.getSongFileHandleFromIndex(currentlyPlayingIndex);
+ }
+
+ public MinimalAudioHeader getCurrentMusicHeader() {
+ if (musicHeader != null) {
+ return musicHeader;
+ } else {
+ return musicHeader = musicList.newMinimalAudioHeader(getCurrentMusicFileHandle());
+ }
+ }
+
+ @Override
+ public void update(Observable o, Object arg) {
+ if (o == musicList) {
+ if (arg == musicList.states.LOADING) {
+ pause();
+ } else if (arg == musicList.states.COMPLETE) {
+ if (shuffle) {
+ shuffle();
+ }
+ loadMusic();
+ }
+ }
+ }
+
+ public String getCurrentSongName() {
+ return getCurrentMusicFileHandle().nameWithoutExtension();
+ }
+
+ public float getCurrentPosition() {
+ if (music != null) {
+ return music.getPosition();
+ }
+ return 0;
+ }
+
+ public void setMusicPosition(float position) {
+ if (music != null) {
+ music.setPosition(position);
+ }
+ }
+
+ public boolean isPlaying() {
+ if (music != null) {
+ return music.isPlaying();
+ }
+ return false;
+ }
+
+ /**
+ * Returns the current music. In no circumstances should this be used to begin playing or it would be playing independent of the controller.
+ * Doing otherwise would mean you are playing the music separately of the controller.
+ * @return the {@link Music} that is currently "loaded" and ready to play.
+ */
+ public Music getCurrentMusic() {
+ return music;
+ }
+
+ public int getCurrentlyPlayingIndex() {
+ return currentlyPlayingIndex;
+ }
+
+ public boolean hasSongLoaded() {
+ if (music != null) {
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/audio/MusicList.java b/old/core/src/zero1hd/rhythmbullet/audio/MusicList.java
new file mode 100644
index 0000000..1148d7b
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/audio/MusicList.java
@@ -0,0 +1,211 @@
+package zero1hd.rhythmbullet.audio;
+
+import java.util.Comparator;
+import java.util.Observable;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.files.FileHandle;
+import com.badlogic.gdx.utils.Array;
+import com.badlogic.gdx.utils.Sort;
+
+import zero1hd.rhythmbullet.audio.processor.AudioProcessor;
+import zero1hd.rhythmbullet.audio.processor.WAVAudioProcessor;
+
+/**
+ * A music list made to store paths to all the songs within a given directory. Can activate the music calling {@link #newAudioProcessor(FileHandle)} and its derivatives.
+ * Is observable, meaning, given there are observers, will notify when the list completes a refresh.
+ * @author yunya
+ */
+public class MusicList extends Observable {
+ public final class States {
+ public final Integer LOADING = new Integer(0), COMPLETE = new Integer(1), EMPTY = new Integer(2);
+ }
+ public States states = new States();
+ private Array musicList;
+ private RecursiveMusicSearchThread searchThread;
+ private AudioProcessorFactory audioProcFactory;
+ private volatile boolean searched;
+ private String searchPath;
+ private Comparator compare;
+
+ public MusicList(AudioProcessorFactory audioProcessorFactory, String searchPath) {
+ this.audioProcFactory = audioProcessorFactory;
+ musicList = new Array<>();
+ setSearchPath(searchPath);
+
+ compare = new Comparator() {
+
+ @Override
+ public int compare(FileHandle o1, FileHandle o2) {
+ return o1.nameWithoutExtension().compareTo(o2.nameWithoutExtension());
+ }
+ };
+ }
+
+ /**
+ * Asynchronous recursive search on music directory.
+ * Also notifies listeners that are on the main thread.
+ * @param refresh does a search whether or not path has changed and whether or not this list has searched before this.
+ */
+ public void attemptAsyncSearch(boolean refresh) {
+ if (refresh) {
+ notifyObservers(states.LOADING);
+ if (searchThread != null) {
+ if (!searchThread.start()) {
+ searchThread.stop();
+ searchThread = new RecursiveMusicSearchThread("Music Search Thread", Gdx.files.absolute(searchPath));
+ searchThread.start();
+ }
+ } else {
+ searchThread = new RecursiveMusicSearchThread("Music Search Thread", Gdx.files.absolute(searchPath));
+ searchThread.start();
+ }
+ } else {
+ if (!searched || hasChanged()) {
+ attemptAsyncSearch(true);
+ }
+ }
+ }
+
+ public void setSearchPath(String searchPath) {
+ if (this.searchPath != null && this.searchPath.equals(searchPath)) return;
+ this.searchPath = searchPath;
+ setChanged();
+ }
+
+ public String getSearchPath() {
+ return searchPath;
+ }
+
+ /**
+ * @param file
+ * @return a {@link AudioProcessor} of the given music file. Will return null if theres a format error.
+ */
+ public AudioProcessor newAudioProcessor(FileHandle file) {
+ switch (SupportedFormats.valueOf(file.extension().toUpperCase())) {
+ case MP3:
+ return audioProcFactory.newMP3AudioProcessor(file);
+ case WAV:
+ return new WAVAudioProcessor(file);
+ default:
+ break;
+ }
+ return null;
+ }
+
+ /**
+ *
+ * @param file the music file that you need the header for.
+ * @return the header containing minimal info of the song.
+ */
+ public MinimalAudioHeader newMinimalAudioHeader(FileHandle file) {
+ return new MinimalAudioHeader(file);
+ }
+
+ public AudioProcessor newAudioProcessorFromIndex(int index) {
+ if (!searched) {
+ Gdx.app.debug("MusicList", "Warning, this list has not completed it's search...");
+ Thread.dumpStack();
+ }
+ if (musicList.size == 0) {
+ return null;
+ }
+ return newAudioProcessor(musicList.get(index));
+ }
+
+
+ public FileHandle getSongFileHandleFromIndex(int index) {
+ if (!searched) {
+ Gdx.app.debug("MusicList", "Warning, this list has not completed it's search...");
+ Thread.dumpStack();
+ }
+ if (musicList.size == 0) {
+ return null;
+ }
+ return musicList.get(index);
+ }
+
+ public FileHandle getAudioFileHandle(int index) {
+ return musicList.get(index);
+ }
+
+ public int getIndexOfFileHandle(FileHandle file) {
+ return musicList.indexOf(file, true);
+ }
+
+ public boolean isSearched() {
+ return searched;
+ }
+
+ /**
+ *
+ * @return the amount of audio files discovered.
+ */
+ public int getTotal() {
+ return musicList.size;
+ }
+
+ private class RecursiveMusicSearchThread implements Runnable {
+ private Thread thread;
+ private String threadName;
+ private FileHandle directory;
+ private volatile boolean work;
+
+ public RecursiveMusicSearchThread(String name, FileHandle searchDirectory) {
+ this.threadName = name;
+ this.directory = searchDirectory;
+ }
+
+ @Override
+ public void run() {
+ Gdx.app.debug("MusicList", "recursive async search beginning.");
+ Array obtainedAudioFiles = recursiveMusicSearch(directory);
+ Sort.instance().sort(obtainedAudioFiles, compare);
+ if (work) {
+ musicList = obtainedAudioFiles;
+ searched = true;
+ Gdx.app.debug("MusicList", "recursive async search completed.");
+ setChanged();
+ if (musicList.size != 0) {
+ notifyObservers(states.COMPLETE);
+ } else {
+ notifyObservers(states.EMPTY);
+ }
+ }
+ }
+
+ public boolean start() {
+ if (thread == null) {
+ work = true;
+ thread = new Thread(this, threadName);
+ thread.setDaemon(true);
+ thread.start();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public void stop() {
+ work = false;
+ }
+
+ private Array recursiveMusicSearch(FileHandle fileHandle) {
+ Array musicFiles = new Array<>();
+ FileHandle[] files = fileHandle.list();
+ for (int i = 0; i < files.length && work; i++) {
+ if (files[i].isDirectory()) {
+ musicFiles.addAll(recursiveMusicSearch(files[i]));
+ } else {
+ try {
+ SupportedFormats.valueOf(files[i].extension().toUpperCase());
+ musicFiles.add(files[i]);
+ } catch (IllegalArgumentException e) {
+ Gdx.app.log("MusicList", "Unsupported file format: " + files[i].name());
+ }
+ }
+ }
+ return musicFiles;
+ }
+ }
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/audio/SupportedFormats.java b/old/core/src/zero1hd/rhythmbullet/audio/SupportedFormats.java
new file mode 100644
index 0000000..da39e60
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/audio/SupportedFormats.java
@@ -0,0 +1,5 @@
+package zero1hd.rhythmbullet.audio;
+
+public enum SupportedFormats {
+ WAV, MP3;
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/audio/analyzer/AudioAnalyzerSection.java b/old/core/src/zero1hd/rhythmbullet/audio/analyzer/AudioAnalyzerSection.java
new file mode 100644
index 0000000..b238aac
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/audio/analyzer/AudioAnalyzerSection.java
@@ -0,0 +1,49 @@
+package zero1hd.rhythmbullet.audio.analyzer;
+
+import com.badlogic.gdx.utils.FloatArray;
+
+public class AudioAnalyzerSection {
+ private int lower, upper, thresholdRange;
+ private float thresholdFactor;
+ private FloatArray peaks;
+ private int pUID;
+
+ public AudioAnalyzerSection(int lowerBin, int upperBin, float thresholdFactor, int thresholdRange) {
+ this.upper = upperBin;
+ this.lower = lowerBin;
+ this.thresholdRange = thresholdRange;
+ this.thresholdFactor = thresholdFactor;
+ }
+
+ public void setPUID(int pUID) {
+ this.pUID = pUID;
+ }
+
+ public void setPeaks(FloatArray peaks) {
+ this.peaks = peaks;
+ }
+
+ public int getLower() {
+ return lower;
+ }
+
+ public int getUpper() {
+ return upper;
+ }
+
+ public float getThresholdFactor() {
+ return thresholdFactor;
+ }
+
+ public int getThresholdRange() {
+ return thresholdRange;
+ }
+
+ public FloatArray getPeaks() {
+ return peaks;
+ }
+
+ public int getPUID() {
+ return pUID;
+ }
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/audio/analyzer/DynamicAudioAnalyzer.java b/old/core/src/zero1hd/rhythmbullet/audio/analyzer/DynamicAudioAnalyzer.java
new file mode 100644
index 0000000..b645d04
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/audio/analyzer/DynamicAudioAnalyzer.java
@@ -0,0 +1,148 @@
+package zero1hd.rhythmbullet.audio.analyzer;
+
+import java.util.Observable;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.utils.FloatArray;
+import com.badlogic.gdx.utils.TimeUtils;
+
+import edu.emory.mathcs.jtransforms.fft.FloatFFT_1D;
+import zero1hd.rhythmbullet.audio.processor.AudioProcessor;
+
+public class DynamicAudioAnalyzer extends Observable implements Runnable {
+ private volatile boolean work = true;
+ private Thread thread;
+ private String threadName = "analyzer";
+ private final int WINDOWLENGTH = 1024;
+ private AudioProcessor processor;
+ private AudioAnalyzerSection[] sections;
+ private FloatArray[] flux;
+ private FloatArray[] threshold;
+ private volatile int pUID = 0;
+ private long timer;
+
+ public DynamicAudioAnalyzer(AudioProcessor processor, AudioAnalyzerSection... sections) {
+ this.sections = sections;
+ this.processor = processor;
+ flux = new FloatArray[sections.length];
+ threshold = new FloatArray[sections.length];
+
+ for (int section = 0; section < sections.length; section++) {
+ flux[section] = new FloatArray();
+ threshold[section] = new FloatArray();
+ }
+ }
+
+ @Override
+ public void run() {
+ calculateSpectralFlux();
+ calculateThreshold();
+ calculatePeaks();
+ }
+
+ public void start() {
+ if (thread == null) {
+ thread = new Thread(this, threadName);
+ thread.setDaemon(true);
+ thread.start();
+ } else {
+ throw new IllegalStateException("Cannot have two analyzer threads.");
+ }
+ }
+
+ public void stop() {
+ work = false;
+ }
+
+ private void calculateSpectralFlux() {
+ Gdx.app.debug("Spectral Flux Calculation", "Beginning...");
+ timer = TimeUtils.millis();
+ float[] audioPCM = new float[WINDOWLENGTH];
+ float[] spectrum = new float[(WINDOWLENGTH/2)+1];
+ float[] lastSpectrum = new float[spectrum.length];
+ FloatFFT_1D fft = new FloatFFT_1D(WINDOWLENGTH);
+ int windowsComplete = 0;
+ int seedCurrentDigit = 0;
+
+ int totalWindows = (int) processor.getSampleFrames()/WINDOWLENGTH;
+ while (processor.readFrames(audioPCM) > 0 && work) {
+ fft.realForward(audioPCM);
+
+ //Building a PUID (Pseudo unique ID)
+ if (windowsComplete == (seedCurrentDigit*totalWindows/9)) {
+ float avg = 0;
+ for (int frame = 0; frame < spectrum.length; frame++) {
+ avg += spectrum[frame];
+ }
+ avg /= spectrum.length;
+ if (avg < 0) {
+ avg *= -1f;
+ }
+ pUID +=(int) Math.pow(10, 9-seedCurrentDigit) * ((int)(avg*1000f)-(int)(avg*100f)*10);
+ seedCurrentDigit ++;
+ }
+
+ System.arraycopy(spectrum, 0, lastSpectrum, 0, spectrum.length);
+ System.arraycopy(audioPCM, 0, spectrum, 0, spectrum.length);
+
+ for (int section = 0; section < sections.length; section++) {
+ float currentFlux = 0;
+ for (int bin = sections[section].getLower(); bin < sections[section].getUpper(); bin++) {
+ currentFlux += Math.max(0f, spectrum[bin] - lastSpectrum[bin]);
+ }
+ flux[section].add(currentFlux);
+ }
+
+ windowsComplete++;
+ }
+
+ for (int section = 0; section < sections.length; section++) {
+ sections[section].setPUID(pUID);
+ }
+
+ Gdx.app.debug("Spectral Flux Calculation", "Finished. Took " + (TimeUtils.timeSinceMillis(timer)) + "ms");
+ }
+
+ private void calculateThreshold() {
+ long subTimer = TimeUtils.millis();
+ Gdx.app.debug("Threshold Calculation", "Beginning...");
+ for (int section = 0; section < sections.length && work; section++) {
+ FloatArray fluxArray = flux[section];
+ for (int bin = 0; bin < fluxArray.size; bin++) {
+ int range = sections[section].getThresholdRange();
+ int start = Math.max(0, bin - range);
+ int end = Math.min(fluxArray.size, bin + range);
+
+ float average = 0;
+ for (int pos = start; pos < end; pos++) {
+ average += fluxArray.get(pos);
+ }
+ average /= (end - start);
+ threshold[section].add(average);
+ }
+ }
+
+ Gdx.app.debug("Spectral Flux Calculation", "Finished. Took " + (TimeUtils.timeSinceMillis(subTimer)) + "ms");
+ }
+
+ private void calculatePeaks() {
+ long subTimer = TimeUtils.millis();
+ Gdx.app.debug("Peak Calculation", "Beginning...");
+ for (int section = 0; section < sections.length && work; section++) {
+ FloatArray peaks = new FloatArray();
+
+ for (int bin = 0; bin < threshold[section].size -1; bin++) {
+ float prunedFlux = flux[section].get(bin) - threshold[section].get(bin);
+ float prunedNextFlux = flux[section].get(bin + 1) - threshold[section].get(bin + 1);
+
+ peaks.add((prunedFlux > prunedNextFlux) ? prunedFlux : 0);
+ }
+
+ sections[section].setPeaks(peaks);
+ }
+ Gdx.app.debug("Spectral Flux Calculation", "Finished. Took " + (TimeUtils.timeSinceMillis(subTimer)) + "ms. Total time was " + (TimeUtils.timeSinceMillis(timer)));
+
+ setChanged();
+ notifyObservers();
+ }
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/audio/metadata/AudioMetadata.java b/old/core/src/zero1hd/rhythmbullet/audio/metadata/AudioMetadata.java
new file mode 100644
index 0000000..10157bb
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/audio/metadata/AudioMetadata.java
@@ -0,0 +1,70 @@
+/**
+ * Metadata for audio. Not thread-safe.
+ * @author yunya
+ *
+ */
+
+package zero1hd.rhythmbullet.audio.metadata;
+
+import com.badlogic.gdx.files.FileHandle;
+import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.utils.Disposable;
+
+public interface AudioMetadata extends Disposable {
+ /**
+ * Load the album art data in to memory.
+ * Will not load if already loaded.
+ */
+ public void loadAlbumCover();
+
+ /**
+ * Unloads album art from memory.
+ * Requires OpenGL context.
+ */
+ public void unloadAlbumCover();
+
+ /**
+ *
+ * @return the author for the song in the metadata.
+ */
+ public String getAuthor();
+
+ /**
+ *
+ * @return the title of the song in the metadata, or if it doesn't exist, the filename without extension and _ is given.
+ */
+ public String getTitle();
+
+ /**
+ *
+ * @return the length of the song with proper fomatting.
+ */
+ public String getDuration();
+
+ /**
+ *
+ * @return the length of the song in seconds.
+ */
+ public int getLength();
+
+ /**
+ * Requires a OpenGL context.
+ * @return the texture. Needs to be loaded before hand or else will return null.
+ */
+ public Texture getAlbumCover();
+
+ /**
+ *
+ * @return returns the genre of the song stored in metadata.
+ */
+ public String getGenre();
+
+ /**
+ *
+ * @return the filehandle.
+ */
+ public FileHandle getFileHandle();
+
+ @Override
+ public void dispose();
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/audio/metadata/MP3Metadata.java b/old/core/src/zero1hd/rhythmbullet/audio/metadata/MP3Metadata.java
new file mode 100644
index 0000000..8ac7145
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/audio/metadata/MP3Metadata.java
@@ -0,0 +1,124 @@
+package zero1hd.rhythmbullet.audio.metadata;
+
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.jaudiotagger.audio.AudioFileIO;
+import org.jaudiotagger.audio.exceptions.CannotReadException;
+import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException;
+import org.jaudiotagger.audio.exceptions.ReadOnlyFileException;
+import org.jaudiotagger.audio.mp3.MP3File;
+import org.jaudiotagger.tag.TagException;
+import org.jaudiotagger.tag.id3.ID3v23FieldKey;
+import org.jaudiotagger.tag.id3.ID3v23Tag;
+import org.jaudiotagger.tag.images.Artwork;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.files.FileHandle;
+import com.badlogic.gdx.graphics.Pixmap;
+import com.badlogic.gdx.graphics.Texture;
+
+public class MP3Metadata implements AudioMetadata {
+ private String title, author, duration, genre;
+ private int length;
+ private Texture albumCover;
+ private FileHandle fileHandle;
+ private Pixmap pixmap;
+
+ public MP3Metadata(FileHandle fileHandle) {
+ this.fileHandle = fileHandle;
+
+ try {
+ MP3File mp3file = (MP3File) AudioFileIO.read(fileHandle.file());
+ ID3v23Tag tag;
+ tag = (ID3v23Tag) mp3file.getTagAndConvertOrCreateAndSetDefault();
+
+ length = mp3file.getAudioHeader().getTrackLength();
+ SimpleDateFormat f = new SimpleDateFormat("m:ss");
+ duration = f.format(new Date(length*1000));
+
+ author = tag.getFirst(ID3v23FieldKey.ARTIST);
+ genre = tag.getFirst(ID3v23FieldKey.GENRE);
+ title = tag.getFirst(ID3v23FieldKey.TITLE);
+ if (title.isEmpty()) {
+ title = fileHandle.nameWithoutExtension().replace('_', ' ');
+ }
+ } catch (IOException | CannotReadException | TagException | ReadOnlyFileException | InvalidAudioFrameException e) {
+ Gdx.app.error("MP3Metadata", "Failed to read metadata of file: " + fileHandle.name());
+ }
+ }
+
+ @Override
+ public void loadAlbumCover() {
+ if (pixmap == null) {
+ try {
+ MP3File mp3file;
+ mp3file = (MP3File) AudioFileIO.read(fileHandle.file());
+ Artwork art = mp3file.getTag().getFirstArtwork();
+ if (art != null) {
+ byte[] imageData = art.getBinaryData();
+ pixmap = new Pixmap(imageData, 0, imageData.length);
+ }
+
+ } catch (CannotReadException | IOException | TagException | ReadOnlyFileException | InvalidAudioFrameException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ @Override
+ public String getAuthor() {
+ return author;
+ }
+
+ @Override
+ public String getTitle() {
+ return title;
+ }
+
+ @Override
+ public String getDuration() {
+ return duration;
+ }
+
+ @Override
+ public int getLength() {
+ return length;
+ }
+
+ @Override
+ public String getGenre() {
+ return genre;
+ }
+
+ @Override
+ public void unloadAlbumCover() {
+ if (albumCover != null) {
+ albumCover.dispose();
+ albumCover = null;
+ }
+ }
+
+ @Override
+ public Texture getAlbumCover() {
+ if (pixmap != null && albumCover == null) {
+ albumCover = new Texture(pixmap);
+ pixmap.dispose();
+ pixmap = null;
+ }
+ return albumCover;
+ }
+
+ @Override
+ public FileHandle getFileHandle() {
+ return fileHandle;
+ }
+
+ @Override
+ public void dispose() {
+ unloadAlbumCover();
+ }
+
+
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/audio/metadata/WAVMetadata.java b/old/core/src/zero1hd/rhythmbullet/audio/metadata/WAVMetadata.java
new file mode 100644
index 0000000..ce6afb0
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/audio/metadata/WAVMetadata.java
@@ -0,0 +1,114 @@
+package zero1hd.rhythmbullet.audio.metadata;
+
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.jaudiotagger.audio.AudioFile;
+import org.jaudiotagger.audio.AudioFileIO;
+import org.jaudiotagger.audio.exceptions.CannotReadException;
+import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException;
+import org.jaudiotagger.audio.exceptions.ReadOnlyFileException;
+import org.jaudiotagger.tag.FieldKey;
+import org.jaudiotagger.tag.Tag;
+import org.jaudiotagger.tag.TagException;
+import org.jaudiotagger.tag.images.Artwork;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.files.FileHandle;
+import com.badlogic.gdx.graphics.Pixmap;
+import com.badlogic.gdx.graphics.Texture;
+
+public class WAVMetadata implements AudioMetadata {
+ private String title, author, duration, genre;
+ private int length;
+ private Texture albumCover;
+ private FileHandle fileHandle;
+ private Pixmap pixmap;
+
+ public WAVMetadata(FileHandle fileHandle) {
+ this.fileHandle = fileHandle;
+
+ try {
+ AudioFile wav = AudioFileIO.read(fileHandle.file());
+ length = wav.getAudioHeader().getTrackLength();
+ SimpleDateFormat f = new SimpleDateFormat("m:ss");
+ duration = f.format(new Date(length*1000));
+
+ Tag tag = wav.getTag();
+ title = tag.getFirst(FieldKey.TITLE);
+ author = tag.getFirst(FieldKey.ARTIST);
+ genre = tag.getFirst(FieldKey.GENRE);
+ if (title.isEmpty()) {
+ title = fileHandle.nameWithoutExtension().replace('_', ' ');
+ }
+ } catch (CannotReadException | IOException | TagException | ReadOnlyFileException | InvalidAudioFrameException e) {
+ Gdx.app.error("WAVMetadata", "Failed to read metadata of file: " + fileHandle.name());
+ }
+ }
+
+ @Override
+ public void loadAlbumCover() {
+ if (pixmap == null) {
+ try {
+ AudioFile wav = AudioFileIO.read(fileHandle.file());
+ Artwork art = wav.getTag().getFirstArtwork();
+
+ if (art != null) {
+ byte[] imageData = art.getBinaryData();
+ pixmap = new Pixmap(imageData, 0, imageData.length);
+ }
+ } catch (CannotReadException | IOException | TagException | ReadOnlyFileException | InvalidAudioFrameException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ @Override
+ public void unloadAlbumCover() {
+ if (albumCover != null) {
+ albumCover.dispose();
+ albumCover = null;
+ }
+ }
+ @Override
+ public String getAuthor() {
+ return author;
+ }
+ @Override
+ public String getTitle() {
+ return title;
+ }
+ @Override
+ public String getDuration() {
+ return duration;
+ }
+
+ @Override
+ public int getLength() {
+ return length;
+ }
+
+ @Override
+ public Texture getAlbumCover() {
+ if (pixmap != null && albumCover == null) {
+ albumCover = new Texture(pixmap);
+ pixmap.dispose();
+ pixmap = null;
+ }
+ return albumCover;
+ }
+ @Override
+ public String getGenre() {
+ return genre;
+ }
+ @Override
+ public FileHandle getFileHandle() {
+ return fileHandle;
+ }
+ @Override
+ public void dispose() {
+ unloadAlbumCover();
+ }
+
+
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/audio/processor/AudioProcessor.java b/old/core/src/zero1hd/rhythmbullet/audio/processor/AudioProcessor.java
new file mode 100644
index 0000000..6496443
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/audio/processor/AudioProcessor.java
@@ -0,0 +1,44 @@
+package zero1hd.rhythmbullet.audio.processor;
+
+import com.badlogic.gdx.files.FileHandle;
+import com.badlogic.gdx.utils.Disposable;
+
+public interface AudioProcessor extends Disposable {
+ /**
+ * @return number of channels
+ */
+ public boolean isStereo();
+
+ /**
+ * @return sample rate
+ */
+ public int getSampleRate();
+
+ /**
+ * Reads samples with interwoven data for stereo.
+ * stored in 16 bit format (first 8 are the first byte of data while the second 8 are the second byte of data that composes a short value)
+ * @param pcm the array the samples should fill
+ * @return the amount of samples read.
+ */
+ public int readSamples(short[] pcm);
+
+ /**
+ * Reads frames with interwoven data for stereo.
+ * stored in 16 bit format (first 8 are the first byte of data while the second 8 are the second byte of data that composes a short value)
+ * @param pcm the array the samples should fill
+ * @return the amount of samples read.
+ */
+ public int readFrames(float[] pcm);
+
+ /**
+ *
+ * @return The music file's {@link FileHandle}
+ */
+ public FileHandle getMusicFileHandle();
+
+ /**
+ *
+ * @return the number of sample frames in the song.
+ */
+ public long getSampleFrames();
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/audio/processor/WAVAudioProcessor.java b/old/core/src/zero1hd/rhythmbullet/audio/processor/WAVAudioProcessor.java
new file mode 100644
index 0000000..8f175ef
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/audio/processor/WAVAudioProcessor.java
@@ -0,0 +1,108 @@
+package zero1hd.rhythmbullet.audio.processor;
+
+import java.io.IOException;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.UnsupportedAudioFileException;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.files.FileHandle;
+
+public class WAVAudioProcessor implements AudioProcessor {
+ private boolean stereo;
+ private int sampleRate;
+ private byte[] buffer;
+ private FileHandle fileHandle;
+ private AudioInputStream audioInputStream;
+ private long sampleFrames;
+
+ public WAVAudioProcessor(FileHandle fileHandle) {
+ this.fileHandle = fileHandle;
+ AudioFormat format;
+ try {
+ audioInputStream = AudioSystem.getAudioInputStream(fileHandle.file());
+ format = audioInputStream.getFormat();
+ stereo = format.getChannels() > 1 ? true : false;
+ sampleRate = (int) format.getSampleRate();
+ sampleFrames = audioInputStream.getFrameLength();
+ } catch (UnsupportedAudioFileException | IOException e) {
+ Gdx.app.debug("WAVAudioProcessor", "Couldn't instantiate WAVAUdioProcessor due to error.");
+ e.printStackTrace();
+ }
+ buffer = new byte[audioInputStream.getFormat().getFrameSize()];
+
+ }
+
+ public boolean isStereo() {
+ return stereo;
+ }
+
+ public int getSampleRate() {
+ return sampleRate;
+ }
+
+ @Override
+ public int readSamples(short[] pcm) {
+ int framesRead = 0;
+ for (int sampleID = 0; sampleID < pcm.length; sampleID++) {
+ try {
+ if (audioInputStream.read(buffer) > 0) {
+ pcm[sampleID] = (short) ((buffer[1] << 8) + (buffer[0] & 0x00ff));
+ if (stereo) {
+ short secondChan = (short) ((buffer[3] << 8) + (buffer[2] & 0x00ff));
+ sampleID++;
+ pcm[sampleID] = secondChan;
+ }
+ framesRead++;
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ }
+ return framesRead;
+ }
+
+ @Override
+ public int readFrames(float[] pcm) {
+ int framesRead = 0;
+ for (int sampleID = 0; sampleID < pcm.length; sampleID++) {
+ try {
+ if (audioInputStream.read(buffer) > 0) {
+ pcm[sampleID] = (short) ((buffer[1] << 8) + (buffer[0] & 0x00ff));
+ if (stereo) {
+ short secondChan = (short) ((buffer[3] << 8) + (buffer[2] & 0x00ff));
+ pcm[sampleID] = secondChan > pcm[sampleID] ? secondChan : pcm[sampleID];
+ }
+ framesRead++;
+ pcm[sampleID] /= Short.MAX_VALUE+1;
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ }
+ return framesRead;
+ }
+
+ @Override
+ public FileHandle getMusicFileHandle() {
+ return fileHandle;
+ }
+
+ @Override
+ public long getSampleFrames() {
+ return sampleFrames;
+ }
+
+ @Override
+ public void dispose() {
+ try {
+ audioInputStream.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
\ No newline at end of file
diff --git a/old/core/src/zero1hd/rhythmbullet/audio/visualizer/CircularVisualizer.java b/old/core/src/zero1hd/rhythmbullet/audio/visualizer/CircularVisualizer.java
new file mode 100644
index 0000000..38f9bcb
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/audio/visualizer/CircularVisualizer.java
@@ -0,0 +1,235 @@
+package zero1hd.rhythmbullet.audio.visualizer;
+
+import java.util.Comparator;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.graphics.Camera;
+import com.badlogic.gdx.graphics.GL20;
+import com.badlogic.gdx.graphics.Mesh;
+import com.badlogic.gdx.graphics.OrthographicCamera;
+import com.badlogic.gdx.graphics.VertexAttribute;
+import com.badlogic.gdx.graphics.VertexAttributes.Usage;
+import com.badlogic.gdx.graphics.glutils.ShaderProgram;
+import com.badlogic.gdx.math.Vector2;
+import com.badlogic.gdx.utils.Array;
+import com.badlogic.gdx.utils.Disposable;
+
+import zero1hd.rhythmbullet.RhythmBullet;
+
+public class CircularVisualizer implements Disposable {
+ private PCMSystem pcm;
+ private int centerX, centerY;
+ private int r;
+ private int componentCount = 2 + 1;
+ private Array circlePoints;
+ private float[] vertComponents;
+ private float color;
+ private Mesh mesh;
+ private ShaderProgram shader;
+ private int barCount = 180;
+ private float barHeightMultiplier = 1.5f;
+ private float[] audioSpectrum;
+ private Camera camera;
+
+ public CircularVisualizer(PCMSystem PCMSystem) {
+ this.pcm = PCMSystem;
+ shader = new ShaderProgram(Gdx.files.internal("shaders/mesh.vsh"), Gdx.files.internal("shaders/mesh.fsh"));
+ if (!shader.isCompiled() || shader.getLog().length() != 0) {
+ Gdx.app.debug("Circular visualizer shader", shader.getLog());
+ Gdx.app.exit();
+ }
+ r = RhythmBullet.pixels_per_unit*RhythmBullet.SPAWN_CIRCLE_RADIUS;
+ }
+
+ /**
+ * Only should be called when all changes have been done.
+ */
+ public void applyPositionChanges() {
+ circlePoints = new Array<>();
+ createCircleVertices(r);
+ vertComponents = new float[circlePoints.size * componentCount];
+
+ if (mesh != null) {
+ mesh.dispose();
+ }
+ mesh = new Mesh(true, circlePoints.size, 0, new VertexAttribute(Usage.Position, 2, "a_position"), new VertexAttribute(Usage.ColorPacked, 4, "a_color"));
+ }
+
+ public void setCenter(int x, int y) {
+ this.centerX = x;
+ this.centerY = y;
+ }
+
+ public void drawVisualizer() {
+ for (int circlePointIndex = 0; circlePointIndex < circlePoints.size; circlePointIndex++) {
+ for (int comp = 0; comp < componentCount; comp++) {
+ if (comp != 2) {
+ vertComponents[circlePointIndex*componentCount + comp] = circlePoints.get(circlePointIndex).x + centerX;
+ comp++;
+ vertComponents[circlePointIndex*componentCount + comp] = circlePoints.get(circlePointIndex).y + centerY;
+ } else {
+ vertComponents[circlePointIndex*componentCount + comp] = color;
+ }
+ }
+ }
+
+ flush();
+ }
+
+ private void flush() {
+ mesh.setVertices(vertComponents);
+ Gdx.gl.glDepthMask(false);
+ Gdx.gl.glEnable(GL20.GL_BLEND);
+ Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
+
+ int vertexCount = circlePoints.size;
+ ((OrthographicCamera) camera).setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
+
+ shader.begin();
+ mesh.render(shader, GL20.GL_LINE_STRIP, 0, vertexCount);
+ shader.end();
+
+ Gdx.gl.glDepthMask(true);
+ }
+
+ private void createCircleVertices(int radius) {
+ int x = radius - 1;
+ int y = 0;
+ int dx = 1;
+ int dy = 1;
+ int err = dx - (radius << 1);
+ circlePoints.clear();
+
+ while (x >= y) {
+ circlePoints.add(new Vector2(+ x, + y));
+ circlePoints.add(new Vector2(+ y, + x));
+ circlePoints.add(new Vector2(- y, + x));
+ circlePoints.add(new Vector2(- x, + y));
+ circlePoints.add(new Vector2(- x, - y));
+ circlePoints.add(new Vector2(- y, - x));
+ circlePoints.add(new Vector2(+ y, - x));
+ circlePoints.add(new Vector2(+ x, - y));
+
+ if (err <= 0) {
+ y++;
+ err += dy;
+ dy += 2;
+ } else {
+ x--;
+ dx += 2;
+ err += dx - (radius << 1);
+ }
+ }
+
+ circlePoints.sort(new Comparator() {
+ @Override
+ public int compare(Vector2 o1, Vector2 o2) {
+ double deg1;
+ if (o1.x != 0 || o1.y != 0) {
+ deg1 = Math.atan(Math.abs(o1.y)/Math.abs(o1.x));
+ if (o1.x < 0) {
+ if (o1.y < 0) {
+ deg1 += 180;
+ } else {
+ deg1 = 180 - deg1;
+ }
+ } else {
+ if (o1.y < 0) {
+ deg1 = 360 - deg1;
+ }
+ }
+
+ } else {
+ if (o1.x != 0) {
+ if (o1.x > 0) {
+ deg1 = 0;
+ } else {
+ deg1 = 180;
+ }
+ deg1 = 0;
+ } else {
+ if (o1.y > 0) {
+ deg1 = 90;
+ } else {
+ deg1 = 270;
+ }
+ }
+ }
+
+ double deg2;
+ if (o2.x != 0 || o2.y != 0) {
+ deg2 = Math.atan(Math.abs(o2.y)/Math.abs(o2.x));
+ if (o2.x < 0) {
+ if (o2.y < 0) {
+ deg2 += 180;
+ } else {
+ deg2 = 180 - deg2;
+ }
+ } else {
+ if (o2.y < 0) {
+ deg2 = 360 - deg2;
+ }
+ }
+ } else {
+ if (o2.x != 0) {
+ if (o2.x > 0) {
+ deg2 = 0;
+ } else {
+ deg2 = 180;
+ }
+ deg2 = 0;
+ } else {
+ if (o2.y > 0) {
+ deg2 = 90;
+ } else {
+ deg2 = 270;
+ }
+ }
+ }
+
+ if ((deg1 - deg2) > 0) {
+ return 1;
+ } else if (deg1 - deg2 == 0) {
+ return 0;
+ } else {
+ return -1;
+ }
+
+ }
+ });
+ }
+
+ public void setColor(float color) {
+ this.color = color;
+ }
+
+ @Override
+ public void dispose() {
+ mesh.dispose();
+ shader.dispose();
+ }
+
+ /**
+ * set the maximum radius
+ * @param r
+ */
+ public void setR(int r) {
+ this.r = r;
+ }
+
+ /**
+ * get the maximum radius
+ * @return
+ */
+ public int getR() {
+ return r;
+ }
+
+ public void setCamera(Camera camera) {
+ this.camera = camera;
+ }
+
+ public Camera getCamera() {
+ return camera;
+ }
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/audio/visualizer/DoubleHorizontalVisualizer.java b/old/core/src/zero1hd/rhythmbullet/audio/visualizer/DoubleHorizontalVisualizer.java
new file mode 100644
index 0000000..cd02d9d
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/audio/visualizer/DoubleHorizontalVisualizer.java
@@ -0,0 +1,212 @@
+package zero1hd.rhythmbullet.audio.visualizer;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.graphics.Color;
+import com.badlogic.gdx.graphics.GL20;
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
+import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;
+import com.badlogic.gdx.math.MathUtils;
+import com.badlogic.gdx.utils.Disposable;
+
+import zero1hd.rhythmbullet.audio.MusicController;
+
+public class DoubleHorizontalVisualizer implements Disposable {
+ private int width, height, barWidth, spaceBetweenBars;
+ private int x, y;
+ private ShapeRenderer shapeRenderer;
+ private PCMSystem pcm;
+ private float[] amplitudes;
+ private int[] barHeights;
+ private int binsPerBar;
+ private float offset;
+ private int boundaryThickness;
+ private boolean debug = false;
+ private boolean significantBeat;
+ private float maxAverageAmplitude;
+ private byte significantFrames;
+ private byte requiredSignificantFrames;
+ private float targetDelta;
+ private float significantThreshold = 0.5f;
+ private float spacePercentage = 0.7f;
+ private float baseSensitivity = 0.009f;
+ private int barCount = 120;
+ private float barChangeRate = 6.5f;
+ private int smoothRange = 2;
+ private int binsToInclude = 120;
+ private Color color = new Color(0.5f, 0.6f, 0.8f, 0.46f);
+ private int averageAmplitude;
+
+ /**
+ *
+ * @param barCount amount of bars this visualizer should have.
+ * @param width the width of the visualizer.
+ * @param spacePercentage the percentage of a bar that should be space.
+ */
+ public DoubleHorizontalVisualizer(int width, int height, float heightSensitivity, int boundaryThickness, int targetFPS, MusicController musicController, PCMSystem PCMSystem) {
+ this.barWidth = width/barCount;
+ this.spaceBetweenBars = MathUtils.round(barWidth * spacePercentage);
+ this.barWidth -= spaceBetweenBars;
+ this.baseSensitivity *= heightSensitivity;
+ pcm = PCMSystem;
+ binsPerBar = (binsToInclude/barCount);
+ this.width = width;
+ this.height = height;
+ amplitudes = new float[barCount];
+ barHeights = new int[barCount];
+ shapeRenderer = new ShapeRenderer();
+ boundaryThickness = barWidth;
+ offset = (width - (barCount*(barWidth+spaceBetweenBars)-spaceBetweenBars))/2f + x;
+ this.targetDelta = 1f/targetFPS;
+ }
+
+ public void act(float delta) {
+ if (pcm.hasAudioChanged()) {
+ maxAverageAmplitude = 0;
+ averageAmplitude = 0;
+ significantBeat = false;
+ }
+ float[] freqBins = pcm.getFrequencyBins();
+ averageAmplitude = 0;
+ for (int bar = 0; bar < amplitudes.length; bar++) {
+ amplitudes[bar] = 0;
+ for (int freq = bar*binsPerBar; freq < (bar*binsPerBar) + binsPerBar; freq++) {
+ amplitudes[bar] += Math.abs(freqBins[freq]) * baseSensitivity;
+ }
+ amplitudes[bar] /= binsPerBar;
+
+ averageAmplitude += amplitudes[bar];
+ }
+
+ averageAmplitude /= amplitudes.length;
+ if (averageAmplitude > maxAverageAmplitude) {
+ maxAverageAmplitude = averageAmplitude;
+ }
+ if (averageAmplitude > maxAverageAmplitude*significantThreshold && !significantBeat) {
+ if (maxAverageAmplitude > 0) {
+ significantFrames++;
+ if (significantFrames >= requiredSignificantFrames) {
+ significantFrames = 0;
+ significantBeat = true;
+ }
+ }
+ } else {
+ if (significantBeat) {
+ significantBeat = false;
+ requiredSignificantFrames = 16;
+ } else {
+ requiredSignificantFrames = 4;
+ }
+ significantFrames = 0;
+ }
+
+ for (int bar = 0; bar < barHeights.length; bar++) {
+ int smoothCount = 1;
+ for (int range = 0; range < smoothRange; range++) {
+ if (bar+range < amplitudes.length) {
+ amplitudes[bar] += amplitudes[bar+range];
+ smoothCount++;
+ }
+ if (bar-range > 0) {
+ amplitudes[bar] += amplitudes[bar-range];
+ smoothCount++;
+ }
+ }
+ amplitudes[bar] /= smoothCount;
+
+
+ int pixelsMoved = 0;
+ int difference = MathUtils.round(amplitudes[bar] - barHeights[bar]);
+ pixelsMoved = MathUtils.floor(difference*targetDelta*barChangeRate);
+ if (pixelsMoved >= 0) {
+ if (barHeights[bar] + pixelsMoved > amplitudes[bar]) {
+ barHeights[bar] += MathUtils.round(difference*targetDelta);
+ } else {
+ barHeights[bar] += pixelsMoved;
+ }
+ } else {
+ if (barHeights[bar] + pixelsMoved < amplitudes[bar]) {
+ barHeights[bar] += MathUtils.round(difference*targetDelta);
+ } else {
+ barHeights[bar] += pixelsMoved;
+ }
+ }
+
+ }
+ }
+
+ public void draw(Batch batch, float parentAlpha) {
+ batch.end();
+ Gdx.gl.glEnable(GL20.GL_BLEND);
+ shapeRenderer.begin(ShapeType.Filled);
+ shapeRenderer.setProjectionMatrix(batch.getProjectionMatrix());
+ shapeRenderer.setTransformMatrix(batch.getTransformMatrix());
+ if (boundaryThickness > 0) {
+ shapeRenderer.rect(x, y, width, boundaryThickness);
+ shapeRenderer.rect(x, y+height, width, -boundaryThickness);
+ }
+
+ for (int bar = 0; bar < barCount; bar++) {
+ shapeRenderer.setColor(color);
+ shapeRenderer.rect(offset + (spaceBetweenBars+barWidth)*bar, y+height, barWidth, barHeights[bar]);
+ shapeRenderer.rect(offset + (spaceBetweenBars+barWidth)*bar, y, barWidth, -barHeights[barHeights.length - 1 - bar]);
+ }
+ if (debug) {
+ shapeRenderer.setColor(Color.RED);
+ shapeRenderer.rect(0, maxAverageAmplitude+y, width, 1);
+ if (significantBeat) {
+ shapeRenderer.setColor(Color.GREEN);
+ } else {
+ shapeRenderer.setColor(Color.WHITE);
+ }
+ shapeRenderer.rect(0, averageAmplitude+y, width, 1);
+ shapeRenderer.setColor(Color.YELLOW);
+ shapeRenderer.rect(0, maxAverageAmplitude*significantThreshold + y, width, 1);
+ }
+ shapeRenderer.end();
+ Gdx.gl.glDisable(GL20.GL_BLEND);
+ batch.begin();
+ }
+
+ public int getWidth() {
+ return width;
+ }
+
+ public int getHeight() {
+ return height;
+ }
+
+ public void setX(int x) {
+ this.x = x;
+ }
+
+ public void setY(int y) {
+ this.y = y;
+ }
+
+ public void setPosition(int x, int y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ public int getX() {
+ return x;
+ }
+
+ public int getY() {
+ return y;
+ }
+
+ public boolean isSignificantBeat() {
+ return significantBeat;
+ }
+
+ public void updateMusic() {
+ pcm.loadMusic();
+ }
+
+ @Override
+ public void dispose() {
+ pcm.dispose();
+ }
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/audio/visualizer/PCMSystem.java b/old/core/src/zero1hd/rhythmbullet/audio/visualizer/PCMSystem.java
new file mode 100644
index 0000000..8a2e092
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/audio/visualizer/PCMSystem.java
@@ -0,0 +1,14 @@
+package zero1hd.rhythmbullet.audio.visualizer;
+
+import com.badlogic.gdx.utils.Disposable;
+
+public interface PCMSystem extends Disposable {
+
+ float[] getFrequencyBins();
+
+ int getWindowSize();
+
+ void loadMusic();
+
+ boolean hasAudioChanged();
+}
\ No newline at end of file
diff --git a/old/core/src/zero1hd/rhythmbullet/audio/wavedecoder/WAVSampleReader.java b/old/core/src/zero1hd/rhythmbullet/audio/wavedecoder/WAVSampleReader.java
new file mode 100644
index 0000000..708d738
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/audio/wavedecoder/WAVSampleReader.java
@@ -0,0 +1,68 @@
+package zero1hd.rhythmbullet.audio.wavedecoder;
+
+import java.io.IOException;
+
+import javax.sound.sampled.AudioInputStream;
+
+public class WAVSampleReader {
+ private int channels;
+ private double sampleRate;
+ private byte[] buffer;
+ private AudioInputStream audioInputStream;
+ private boolean mergeChannels;
+
+ public WAVSampleReader(AudioInputStream ais) throws IOException {
+ audioInputStream = ais;
+ buffer = new byte[audioInputStream.getFormat().getFrameSize()];
+
+ channels = audioInputStream.getFormat().getChannels();
+ sampleRate = audioInputStream.getFormat().getSampleRate();
+ }
+
+ public int getChannels() {
+ return channels;
+ }
+
+ public double getSampleRate() {
+ return sampleRate;
+ }
+
+ public long getFrameLength() {
+ return audioInputStream.getFrameLength();
+ }
+
+ public int readSamplesAsFrames(float[] samples) throws IOException {
+ int framesRead = 0;
+ for (int sampleID = 0; sampleID < samples.length; sampleID++) {
+ if (audioInputStream.read(buffer) > 0) {
+ samples[sampleID] += (buffer[1] << 8) + (buffer[0] & 0x00ff);
+ if (audioInputStream.getFormat().getChannels() > 1) {
+ short altChan = (short) ((buffer[3] << 8) + (buffer[2] & 0x00ff));
+ if (mergeChannels) {
+ samples[sampleID] = altChan > samples[sampleID] ? altChan : samples[sampleID];
+ } else {
+ sampleID++;
+ samples[sampleID] = altChan;
+ }
+ }
+ framesRead ++;
+ samples[sampleID] /= Short.MAX_VALUE+1;
+ }
+
+ }
+ return framesRead;
+ }
+
+ public AudioInputStream getAudioInputStream() {
+ return audioInputStream;
+ }
+
+
+ public void setMergeChannels(boolean mergeChannels) {
+ this.mergeChannels = mergeChannels;
+ }
+ public boolean isMergeChannels() {
+ return mergeChannels;
+ }
+
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/entity/CollisionDetector.java b/old/core/src/zero1hd/rhythmbullet/entity/CollisionDetector.java
new file mode 100644
index 0000000..8c13551
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/entity/CollisionDetector.java
@@ -0,0 +1,56 @@
+package zero1hd.rhythmbullet.entity;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.Preferences;
+import com.badlogic.gdx.assets.AssetManager;
+import com.badlogic.gdx.audio.Sound;
+import com.badlogic.gdx.utils.Array;
+
+public class CollisionDetector {
+ Array enemies;
+ Array allies;
+
+ AssetManager assets;
+ Preferences prefs;
+
+ private int amassedPoints;
+ Sound explosionSFX;
+ public CollisionDetector(Array enemies, Array allies, AssetManager assetManager, Preferences prefs) {
+ this.enemies = enemies;
+ this.allies = allies;
+ assets = assetManager;
+ this.prefs = prefs;
+
+ }
+
+ public void collisionCheck() {
+ if ((enemies.size != 0) && (allies.size != 0)) {
+ for (int f = 0; f < enemies.size; f++) {
+ Entity enemy = enemies.get(f);
+ if (enemy.getHitZone() != null) {
+ for (int s = 0; s < allies.size; s++) {
+ Entity ally = allies.get(s);
+ if (ally.getHitZone() != null) {
+ if (enemy.getHitZone().overlaps(ally.getHitZone())) {
+ Gdx.app.debug("Collision Detector", "Collision between entities: " + enemy.getClass().getSimpleName() + " and " + ally.getClass().getSimpleName());
+
+ enemy.collided(ally);
+ ally.collided(enemy);
+
+ amassedPoints += enemy.getPoints();
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ public int getAmassedPoints() {
+ int amassedPoints = this.amassedPoints;
+ this.amassedPoints = 0;
+ return amassedPoints;
+ }
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/entity/Entity.java b/old/core/src/zero1hd/rhythmbullet/entity/Entity.java
new file mode 100644
index 0000000..28d8785
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/entity/Entity.java
@@ -0,0 +1,201 @@
+package zero1hd.rhythmbullet.entity;
+
+import java.security.InvalidParameterException;
+
+import com.badlogic.gdx.Preferences;
+import com.badlogic.gdx.assets.AssetManager;
+import com.badlogic.gdx.graphics.Color;
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.g2d.Sprite;
+import com.badlogic.gdx.math.MathUtils;
+import com.badlogic.gdx.math.Rectangle;
+import com.badlogic.gdx.math.Vector2;
+import com.badlogic.gdx.utils.Pool.Poolable;
+
+import zero1hd.rhythmbullet.RhythmBullet;
+import zero1hd.rhythmbullet.entity.coordinator.Coordinator;
+
+public class Entity implements Poolable {
+ private Coordinator coordinator;
+ private EntityFrame> ef;
+
+ protected AssetManager assets;
+ protected Preferences prefs;
+ protected EntityManager ec;
+
+ protected boolean enemy;
+ protected boolean move = true;
+
+ protected boolean dead;
+ protected Rectangle hitbox;
+ protected Sprite sprite;
+ protected Vector2 rotRatios;
+ public float angle;
+ public float speed;
+ protected float hitBoxScale;
+
+ protected int points;
+
+ /**
+ * called by the entity frame and only once (when this object is created).
+ * Used by the frame to setup variables for simple calling later.
+ * Anything that needs to be setup for the entity on first call should not override this.
+ * (Unless you call the super of this and then the rest which is fine too).
+ * This will then call preInit() which is the method you should override.
+ */
+ protected void setup(EntityManager ec, EntityFrame> ef) {
+ this.ec = ec;
+ this.ef = ef;
+ assets = ec.getAssets();
+ prefs = ec.getPrefs();
+ rotRatios = new Vector2();
+ hitbox = new Rectangle();
+
+ preInit();
+ }
+
+ /**
+ * Method to override should any setup need to be done once (on entity first creation).
+ */
+ public void preInit() {
+ if (sprite.getTexture() == null) throw new NullPointerException("what, your not going to have a texture for your entity?");
+ sprite.setOriginCenter();
+ }
+
+ public void init(float deg, float speed, int hp) {
+ rotRatios.set(MathUtils.cosDeg(angle), MathUtils.sinDeg(angle));
+ sprite.setSize(sprite.getTexture().getWidth()/RhythmBullet.pixels_per_unit, sprite.getTexture().getHeight()/RhythmBullet.pixels_per_unit);
+ float r = RhythmBullet.SPAWN_CIRCLE_RADIUS - sprite.getWidth();
+ if (r < RhythmBullet.SPAWN_CIRCLE_RADIUS -1) {
+ throw new InvalidParameterException("Entity is too big! Calculated final distance from center: " + r);
+ }
+ sprite.setPosition(r*rotRatios.x, r*rotRatios.y);
+ updatePosition();
+ }
+
+ /**
+ * Called whenever a collision is detected
+ * @param entity is the entity that hit this one.
+ */
+ public void collided(Entity entity) {
+ }
+
+ /**
+ * gets the box that represents the hit box to calculate whether there is a collision or not
+ * @return the object that represents the hit box
+ */
+ public Rectangle getHitZone() {
+ return hitbox;
+ }
+
+ public boolean isDead() {
+ return dead;
+ }
+
+ public void calculate(float delta) {
+ if (coordinator != null) {
+ coordinator.coordinate(delta);
+ }
+
+ if (dead) {
+ ef.recycleEntity(this);
+ }
+
+ if (angle >= 360f) {
+ angle -= 360f;
+ }
+
+ if (sprite.getX() > RhythmBullet.WORLD_WIDTH || sprite.getY() > RhythmBullet.WORLD_HEIGHT || sprite.getX() < 0-sprite.getWidth() || sprite.getX() < 0-sprite.getWidth()) {
+ dead = true;
+ }
+
+ updatePosition();
+ }
+
+ public void draw(Batch batch) {
+ sprite.draw(batch);
+ batch.setColor(Color.WHITE);
+ }
+
+ public void moveBy(float x, float y) {
+ sprite.setCenter(sprite.getX() + x, sprite.getY() + y);
+ }
+
+ public void updatePosition() {
+ rotRatios.set(MathUtils.cosDeg(angle), MathUtils.sinDeg(angle));
+ sprite.setOriginCenter();
+ sprite.setRotation(angle);
+ hitbox.setCenter(sprite.getOriginX(), sprite.getOriginY());
+ }
+
+ @Override
+ public void reset() {
+ if (coordinator != null) {
+ coordinator.clean();
+ coordinator = null;
+ }
+ rotRatios.set(0, 0);
+ sprite.setPosition(0, 0);
+ hitbox.set(0, 0, 0, 0);
+ sprite.setRotation(0);
+ sprite.setColor(Color.WHITE);
+ angle = 0;
+ speed = 0;
+ points = 0;
+ dead = false;
+ }
+
+ public float getAngle() {
+ return angle;
+ }
+
+ public void setSpeed(float speed) {
+ this.speed = speed;
+ }
+
+ public float getSpeed() {
+ return speed;
+ }
+
+ public void setCoordinator(Coordinator coordinator) {
+ this.coordinator = coordinator;
+ coordinator.setEntity(this);
+ }
+
+ public void kill() {
+ dead = true;
+ }
+
+ public int getPoints() {
+ return points + (coordinator != null ? coordinator.getScoreBonus() : 0);
+ }
+
+ public float getX() {
+ return sprite.getX();
+ }
+
+ public float getY() {
+ return sprite.getY();
+ }
+
+ public void setPosition(float x, float y) {
+ sprite.setPosition(x, y);
+ updatePosition();
+ }
+
+ public float getWidth() {
+ return sprite.getWidth();
+ }
+
+ public float getHeight() {
+ return sprite.getHeight();
+ }
+
+ public void setSize(float width, float height) {
+ sprite.setSize(width, height);
+ }
+
+ public void setHitboxScale(float scale) {
+ hitbox.setSize(sprite.getWidth()*scale, sprite.getHeight()*scale);
+ }
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/entity/EntityFrame.java b/old/core/src/zero1hd/rhythmbullet/entity/EntityFrame.java
new file mode 100644
index 0000000..91bfc3a
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/entity/EntityFrame.java
@@ -0,0 +1,66 @@
+package zero1hd.rhythmbullet.entity;
+
+import com.badlogic.gdx.utils.Pool;
+
+public class EntityFrame {
+ private Pool pool;
+ private EntityManager ec;
+ Class ct;
+ EntityFrame ef;
+
+ /**
+ * Manages the entities pooling.
+ * @param entityController
+ * @param classType
+ */
+ public EntityFrame(EntityManager entityController, Class classType) {
+ this.ct = classType;
+ ef = this;
+ ec = entityController;
+ pool = new Pool() {
+ @Override
+ protected T newObject() {
+ try {
+ T entity = ct.newInstance();
+ entity.setup(ec, ef);
+
+ return entity;
+ } catch (InstantiationException | IllegalAccessException e) {
+ e.printStackTrace();
+ return null;
+
+ }
+ }
+ };
+ }
+
+ public T buildEntity() {
+ T entity = pool.obtain();
+
+ if (entity.enemy) {
+ ec.activeEnemies.add(entity);
+ } else {
+ ec.activeAllies.add(entity);
+ }
+ return entity;
+ }
+
+
+ /**
+ * Free the entity if no longer used.
+ * @param entity to be freed.
+ */
+ protected void recycleEntity(Entity entity) {
+ if (entity.enemy) {
+ ec.activeEnemies.removeValue(entity, true);
+ } else {
+ ec.activeAllies.removeValue(entity, true);
+ }
+ pool.free(ct.cast(entity));
+ }
+
+ @Override
+ public String toString() {
+ return ct.getSimpleName();
+ }
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/entity/EntityManager.java b/old/core/src/zero1hd/rhythmbullet/entity/EntityManager.java
new file mode 100644
index 0000000..fc82563
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/entity/EntityManager.java
@@ -0,0 +1,46 @@
+package zero1hd.rhythmbullet.entity;
+
+import com.badlogic.gdx.Preferences;
+import com.badlogic.gdx.assets.AssetManager;
+import com.badlogic.gdx.utils.Array;
+
+import zero1hd.rhythmbullet.entity.ally.Laser;
+import zero1hd.rhythmbullet.entity.enemies.Pellet;
+import zero1hd.rhythmbullet.entity.enemies.Shard;
+
+public class EntityManager {
+ private AssetManager assets;
+ private Preferences prefs;
+
+ public Array activeAllies;
+ public Array activeEnemies;
+
+ public EntityFrame pellet;
+ public EntityFrame shard;
+
+ public EntityFrame laser;
+
+ public EntityManager(AssetManager assetManager, Preferences preferences) {
+ activeAllies = new Array();
+ activeEnemies = new Array();
+ this.assets = assetManager;
+ this.prefs = preferences;
+
+ setup();
+ }
+
+ private void setup() {
+ pellet = new EntityFrame<>(this, Pellet.class);
+ shard = new EntityFrame<>(this, Shard.class);
+ laser = new EntityFrame<>(this, Laser.class);
+
+ }
+
+ public AssetManager getAssets() {
+ return assets;
+ }
+
+ public Preferences getPrefs() {
+ return prefs;
+ }
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/entity/ally/Laser.java b/old/core/src/zero1hd/rhythmbullet/entity/ally/Laser.java
new file mode 100644
index 0000000..3982954
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/entity/ally/Laser.java
@@ -0,0 +1,52 @@
+package zero1hd.rhythmbullet.entity.ally;
+
+import com.badlogic.gdx.audio.Sound;
+import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.g2d.Sprite;
+
+import zero1hd.rhythmbullet.RhythmBullet;
+import zero1hd.rhythmbullet.entity.Entity;
+
+public class Laser extends Entity {
+ Sound sfx;
+
+ @Override
+ public void preInit() {
+ sprite = new Sprite(assets.get("laser.png", Texture.class));
+ sfx = assets.get("laser.ogg", Sound.class);
+ setSize(0.25f, 2f);
+ super.preInit();
+ }
+
+ public void init(float x, float y, float rate) {
+ setPosition(x-getWidth()/2f, y-getHeight()/2f);
+ speed = rate;
+ sfx.play(prefs.getFloat("fx vol")/100f);
+ angle = 90f;
+ }
+
+ @Override
+ public void calculate(float delta) {
+ if (getY() > RhythmBullet.WORLD_HEIGHT) {
+ dead = true;
+ }
+ super.calculate(delta);
+ }
+
+ @Override
+ public void draw(Batch batch) {
+ super.draw(batch);
+ }
+
+ @Override
+ public void reset() {
+ super.reset();
+ }
+
+ @Override
+ public void collided(Entity entity) {
+ dead = true;
+ }
+
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/entity/ally/PolyjetEntity.java b/old/core/src/zero1hd/rhythmbullet/entity/ally/PolyjetEntity.java
new file mode 100644
index 0000000..4e80252
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/entity/ally/PolyjetEntity.java
@@ -0,0 +1,95 @@
+package zero1hd.rhythmbullet.entity.ally;
+
+import com.badlogic.gdx.assets.AssetManager;
+import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.g2d.ParticleEffect;
+import com.badlogic.gdx.math.Rectangle;
+
+import zero1hd.rhythmbullet.RhythmBullet;
+import zero1hd.rhythmbullet.entity.Entity;
+
+public class PolyjetEntity extends Entity {
+ public float health;
+ private ParticleEffect thrust;
+ private Texture polyjet;
+ private ParticleEffect teleportCloak;
+ public boolean moveLeft, moveRight, moveUp, moveDown, teleporting, accelerate;
+ private float speed, accel;
+ private float rate;
+ private int maxH;
+ public PolyjetEntity(AssetManager assets, float speed, float accel,int maxHealth, String jet) {
+ health = 100;
+ this.speed = speed;
+ this.accel = accel;
+ setSize(1.5f, 1.5f);
+ setPosition(RhythmBullet.WORLD_WIDTH/2 - getWidth()/2, -4f);
+ maxH = maxHealth;
+ hitbox = new Rectangle(getX(), getY(), getWidth(), getHeight());
+ polyjet = assets.get("polyjet-" + jet + ".png", Texture.class);
+ thrust = assets.get("standard_thrust.p", ParticleEffect.class);
+ thrust.start();
+
+ teleportCloak = assets.get("teleport-cloak.p", ParticleEffect.class);
+
+ }
+
+ @Override
+ public void calculate(float delta) {
+ hitbox.setPosition(getX(), getY());
+
+ thrust.setPosition(getX()+(getWidth())/2 - 1f/16f, getY()-0.2f);
+ thrust.update(delta);
+ teleportCloak.setPosition(getX() +(getWidth()-1)/2, getY() + (getHeight()-1)/2);
+
+ hitbox.setPosition(getX(), getY());
+
+ //Movement!
+ if (accelerate) {
+ rate = speed + accel;
+ } else {
+ rate = speed;
+ }
+
+ if (moveLeft && !moveRight) {
+ moveBy(-(rate*delta), 0);
+ }
+ if (moveRight && !moveLeft) {
+ moveBy(rate*delta, 0);
+ }
+ if (moveUp && !moveDown) {
+ moveBy(0, rate*delta);
+ }
+
+ if (moveDown && !moveUp) {
+ moveBy(0, -rate*delta);
+ }
+
+ if (health <= 0) {
+ dead = true;
+ } else if (health > maxH) {
+ health = maxH;
+ }
+
+ super.calculate(delta);
+ }
+
+ @Override
+ public void draw(Batch batch) {
+ thrust.draw(batch);
+ batch.draw(polyjet, getX(), getY(), getWidth(), getHeight());
+ super.draw(batch);
+ }
+
+ @Override
+ public void collided(Entity entity) {
+ }
+
+ public Rectangle getHitbox() {
+ return hitbox;
+ }
+
+ public void setHealth(float health) {
+ this.health = health;
+ }
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/entity/coordinator/Coordinator.java b/old/core/src/zero1hd/rhythmbullet/entity/coordinator/Coordinator.java
new file mode 100644
index 0000000..f6cbae6
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/entity/coordinator/Coordinator.java
@@ -0,0 +1,47 @@
+package zero1hd.rhythmbullet.entity.coordinator;
+
+import com.badlogic.gdx.utils.Pool.Poolable;
+
+import zero1hd.rhythmbullet.entity.Entity;
+import zero1hd.rhythmbullet.entity.EntityManager;
+
+/**
+ * Coordinator coordinates movement of an entity. Movement can range from basic pre-determined to more advanced (with condition based behavior).
+ * @author Yunyang
+ *
+ */
+public class Coordinator implements Poolable {
+ private CoordinatorFrame extends Coordinator> cf;
+ protected EntityManager em;
+ protected Entity entity;
+ protected int scoreBonus;
+
+ public void setup(EntityManager em, CoordinatorFrame extends Coordinator> cf) {
+ this.em = em;
+ this.cf = cf;
+ }
+
+ public void init(Entity entity) {
+ this.entity = entity;
+ }
+
+ public void coordinate(float delta) {
+ }
+
+ public void clean() {
+ cf.recycleCoordinator(this);
+ }
+
+ public void setEntity(Entity entity) {
+ this.entity = entity;
+ }
+
+ @Override
+ public void reset() {
+ entity = null;
+ }
+
+ public int getScoreBonus() {
+ return scoreBonus;
+ }
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/entity/coordinator/CoordinatorFrame.java b/old/core/src/zero1hd/rhythmbullet/entity/coordinator/CoordinatorFrame.java
new file mode 100644
index 0000000..b968e13
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/entity/coordinator/CoordinatorFrame.java
@@ -0,0 +1,50 @@
+package zero1hd.rhythmbullet.entity.coordinator;
+
+import com.badlogic.gdx.utils.Pool;
+
+import zero1hd.rhythmbullet.entity.EntityManager;
+
+public class CoordinatorFrame {
+ private Pool pool;
+ private EntityManager em;
+ CoordinatorFrame cf;
+ Class coordinatorType;
+
+ /**
+ * Similar to an entityFrame, however this time, for a coordinator.
+ * @param entityManager
+ * @param classtype
+ */
+ public CoordinatorFrame(EntityManager entityManager, Class classtype) {
+ this.em = entityManager;
+ coordinatorType = classtype;
+ cf = this;
+ pool = new Pool() {
+ @Override
+ protected T newObject() {
+ try {
+ T coordinator = coordinatorType.newInstance();
+ coordinator.setup(em, cf);
+ return coordinator;
+ } catch (InstantiationException | IllegalAccessException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+ };
+ }
+
+ public T buildCoordinator() {
+ T coordinator = pool.obtain();
+ return coordinator;
+ }
+
+ protected void recycleCoordinator(Coordinator coordinator) {
+ pool.free(coordinatorType.cast(coordinator));
+ }
+
+ @Override
+ public String toString() {
+ return coordinatorType.getSimpleName();
+ }
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/entity/coordinator/CoordinatorManager.java b/old/core/src/zero1hd/rhythmbullet/entity/coordinator/CoordinatorManager.java
new file mode 100644
index 0000000..a4ab439
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/entity/coordinator/CoordinatorManager.java
@@ -0,0 +1,20 @@
+package zero1hd.rhythmbullet.entity.coordinator;
+
+import zero1hd.rhythmbullet.entity.EntityManager;
+
+public class CoordinatorManager {
+ private EntityManager em;
+
+ public CoordinatorFrame slowLeft;
+ public CoordinatorFrame slowRight;
+
+ public CoordinatorManager(EntityManager em) {
+ this.em = em;
+ setup();
+ }
+
+ private void setup() {
+ slowLeft = new CoordinatorFrame<>(em, SlowLeftCoordinator.class);
+ slowRight = new CoordinatorFrame<>(em, SlowRightCoordinator.class);
+ }
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/entity/coordinator/SlowLeftCoordinator.java b/old/core/src/zero1hd/rhythmbullet/entity/coordinator/SlowLeftCoordinator.java
new file mode 100644
index 0000000..1942e6c
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/entity/coordinator/SlowLeftCoordinator.java
@@ -0,0 +1,9 @@
+package zero1hd.rhythmbullet.entity.coordinator;
+
+public class SlowLeftCoordinator extends Coordinator {
+ @Override
+ public void coordinate(float delta) {
+ entity.angle -= 32*delta;
+ super.coordinate(delta);
+ }
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/entity/coordinator/SlowRightCoordinator.java b/old/core/src/zero1hd/rhythmbullet/entity/coordinator/SlowRightCoordinator.java
new file mode 100644
index 0000000..9fae5dd
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/entity/coordinator/SlowRightCoordinator.java
@@ -0,0 +1,9 @@
+package zero1hd.rhythmbullet.entity.coordinator;
+
+public class SlowRightCoordinator extends Coordinator {
+ @Override
+ public void coordinate(float delta) {
+ entity.angle += 32*delta;
+ super.coordinate(delta);
+ }
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/entity/enemies/Pellet.java b/old/core/src/zero1hd/rhythmbullet/entity/enemies/Pellet.java
new file mode 100644
index 0000000..6e5023e
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/entity/enemies/Pellet.java
@@ -0,0 +1,40 @@
+package zero1hd.rhythmbullet.entity.enemies;
+
+import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.graphics.g2d.Sprite;
+import com.badlogic.gdx.utils.Pool.Poolable;
+
+import zero1hd.rhythmbullet.entity.Entity;
+
+public class Pellet extends Entity implements Poolable {
+
+ @Override
+ public void preInit() {
+ sprite = new Sprite(assets.get("pellet.png", Texture.class));
+ enemy = true;
+ setSize(0.5f, 0.5f);
+ sprite.setColor(0.5f, 1f, 1f, 0.5f);
+ super.preInit();
+ }
+
+ @Override
+ public void init(float deg, float speed, int hp) {
+ this.speed = speed;
+ this.angle = deg;
+ super.init(deg, speed, hp);
+ }
+
+
+ @Override
+ public void collided(Entity entity) {
+ dead = true;
+ super.collided(entity);
+ }
+
+ @Override
+ public void reset() {
+ dead = false;
+ super.reset();
+ }
+
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/entity/enemies/Shard.java b/old/core/src/zero1hd/rhythmbullet/entity/enemies/Shard.java
new file mode 100644
index 0000000..76e4444
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/entity/enemies/Shard.java
@@ -0,0 +1,68 @@
+package zero1hd.rhythmbullet.entity.enemies;
+
+import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.g2d.Sprite;
+import com.badlogic.gdx.math.Rectangle;
+
+import zero1hd.rhythmbullet.entity.Entity;
+import zero1hd.rhythmbullet.entity.ally.Laser;
+
+public class Shard extends Entity {
+ private int hp;
+ private int maxHp;
+
+ @Override
+ public void preInit() {
+ sprite = new Sprite(assets.get("shard.png", Texture.class));
+ setSize(2f, 2f);
+ sprite.setSize(3f, 2f);
+ enemy = true;
+ super.preInit();
+ }
+
+ @Override
+ public void init(float deg, float speed, int hp) {
+ this.speed = speed;
+ this.hp = hp;
+ maxHp = hp;
+ this.angle = deg;
+ super.init(deg, speed, hp);
+ }
+
+ @Override
+ public void reset() {
+ hp = 0;
+ maxHp = 0;
+ super.reset();
+ }
+
+ @Override
+ public void calculate(float delta) {
+ if (hp <= 0) {
+ dead = true;
+ }
+ super.calculate(delta);
+ }
+
+ @Override
+ public void draw(Batch batch) {
+ sprite.setColor(((float)hp/(float)maxHp), ((float)hp/(float)maxHp), ((float)hp/(float)maxHp), 0.5f);
+ super.draw(batch);
+ }
+
+ @Override
+ public void collided(Entity entity) {
+ if (entity.getClass() == Laser.class) {
+ hp --;
+ } else {
+ dead = true;
+ }
+ }
+
+ @Override
+ public Rectangle getHitZone() {
+ return hitbox;
+ }
+
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/game/EntitySpawnInfo.java b/old/core/src/zero1hd/rhythmbullet/game/EntitySpawnInfo.java
new file mode 100644
index 0000000..23a1a5e
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/game/EntitySpawnInfo.java
@@ -0,0 +1,28 @@
+package zero1hd.rhythmbullet.game;
+
+import java.util.HashMap;
+
+import zero1hd.rhythmbullet.entity.Entity;
+import zero1hd.rhythmbullet.entity.EntityFrame;
+import zero1hd.rhythmbullet.entity.coordinator.Coordinator;
+import zero1hd.rhythmbullet.entity.coordinator.CoordinatorFrame;
+
+public class EntitySpawnInfo {
+ private EntityFrame extends Entity> entityToSpawn;
+ private CoordinatorFrame extends Coordinator> entityCoordinator;
+ public HashMap parameters;
+
+
+ public EntitySpawnInfo(EntityFrame extends Entity> entityToSpawn, CoordinatorFrame extends Coordinator> coordinator) {
+ this.entityToSpawn = entityToSpawn;
+ parameters = new HashMap<>();
+ }
+
+ public EntityFrame extends Entity> getEntityToSpawn() {
+ return entityToSpawn;
+ }
+
+ public CoordinatorFrame extends Coordinator> getEntityCoordinator() {
+ return entityCoordinator;
+ }
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/game/MapWindowData.java b/old/core/src/zero1hd/rhythmbullet/game/MapWindowData.java
new file mode 100644
index 0000000..9a77b8a
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/game/MapWindowData.java
@@ -0,0 +1,18 @@
+package zero1hd.rhythmbullet.game;
+
+import com.badlogic.gdx.utils.Array;
+
+public class MapWindowData {
+ Array entityDatas;
+ public MapWindowData() {
+ entityDatas = new Array<>(EntitySpawnInfo.class);
+ }
+
+ public void addEntity(EntitySpawnInfo entity) {
+ entityDatas.add(entity);
+ }
+
+ public EntitySpawnInfo[] getArray() {
+ return entityDatas.toArray();
+ }
+}
\ No newline at end of file
diff --git a/old/core/src/zero1hd/rhythmbullet/game/ScoreManager.java b/old/core/src/zero1hd/rhythmbullet/game/ScoreManager.java
new file mode 100644
index 0000000..abbdd97
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/game/ScoreManager.java
@@ -0,0 +1,26 @@
+package zero1hd.rhythmbullet.game;
+
+public class ScoreManager {
+ private int score;
+ private boolean different;
+
+ public void setScore(int score) {
+ this.score = score;
+ different = true;
+ }
+
+ public int getScore() {
+ return score;
+ }
+
+ public void addScore(int addedScore) {
+ score += addedScore;
+ different = true;
+ }
+
+ public boolean checkDifferent() {
+ boolean current = different;
+ different = false;
+ return current;
+ }
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/graphics/shaders/BloomShader.java b/old/core/src/zero1hd/rhythmbullet/graphics/shaders/BloomShader.java
new file mode 100644
index 0000000..5cf49ea
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/graphics/shaders/BloomShader.java
@@ -0,0 +1,153 @@
+package zero1hd.rhythmbullet.graphics.shaders;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.graphics.GL20;
+import com.badlogic.gdx.graphics.OrthographicCamera;
+import com.badlogic.gdx.graphics.Pixmap.Format;
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.g2d.TextureRegion;
+import com.badlogic.gdx.graphics.glutils.FrameBuffer;
+import com.badlogic.gdx.graphics.glutils.ShaderProgram;
+import com.badlogic.gdx.utils.Disposable;
+import com.badlogic.gdx.utils.viewport.ScreenViewport;
+
+public class BloomShader implements Disposable {
+ private ShaderProgram gaussianBlurShader;
+ private ShaderProgram brightFilterShader;
+ private ShaderProgram combineShader;
+ private FrameBuffer lightFilterBuffer;
+ private FrameBuffer normalBuffer;
+ private FrameBuffer hBlur, vBlur;
+ private TextureRegion fboRegion;
+ private Batch screenBatch;
+ private ScreenViewport screenViewport;
+
+ public BloomShader(Batch batch) {
+ this.screenBatch = batch;
+
+ Gdx.app.debug("Shader", "Loading glow shaders.");
+ screenViewport = new ScreenViewport();
+ screenViewport.update(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
+ ((OrthographicCamera) screenViewport.getCamera()).setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
+
+ Gdx.app.debug("Shader", "using glow shader");
+ brightFilterShader = new ShaderProgram(Gdx.files.internal("shaders/basic.vsh"), Gdx.files.internal("shaders/bright_filter.fsh"));
+ if (!brightFilterShader.isCompiled()) {
+ Gdx.app.error("Shader failed to compile bright filter shader", brightFilterShader.getLog());
+ System.exit(1);
+ }
+ if (brightFilterShader.getLog().length() != 0) {
+ Gdx.app.error("Shader", brightFilterShader.getLog());
+ }
+
+ gaussianBlurShader = new ShaderProgram(Gdx.files.internal("shaders/basic.vsh"), Gdx.files.internal("shaders/gaussian_blur.fsh"));
+ if (!gaussianBlurShader.isCompiled()) {
+ Gdx.app.error("Shader failed to compile gaussian blur shader", gaussianBlurShader.getLog());
+ System.exit(1);
+ }
+ if (gaussianBlurShader.getLog().length() != 0) {
+ Gdx.app.error("Shader", gaussianBlurShader.getLog());
+ }
+
+ combineShader = new ShaderProgram(Gdx.files.internal("shaders/basic.vsh"), Gdx.files.internal("shaders/combine.fsh"));
+ if (!combineShader.isCompiled()) {
+ Gdx.app.error("Shader failed to compile combination shader", combineShader.getLog());
+ System.exit(1);
+ }
+ if (combineShader.getLog().length() != 0) {
+ Gdx.app.error("Shader", combineShader.getLog());
+ }
+
+ lightFilterBuffer = new FrameBuffer(Format.RGBA8888, Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), false);
+ normalBuffer = new FrameBuffer(Format.RGBA8888, Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), false);
+ hBlur = new FrameBuffer(Format.RGBA8888, Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), false);
+ vBlur = new FrameBuffer(Format.RGBA8888, Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), false);
+
+ fboRegion = new TextureRegion(normalBuffer.getColorBufferTexture());
+ fboRegion.flip(false, true);
+
+ combineShader.begin();
+ combineShader.setUniformi("u_texture1", 1);
+ combineShader.end();
+
+ gaussianBlurShader.begin();
+ gaussianBlurShader.setUniformf("radius", 1.5f);
+ gaussianBlurShader.setUniformf("resolution", hBlur.getWidth(), vBlur.getHeight());
+ gaussianBlurShader.end();
+
+ vBlur.getColorBufferTexture().bind(1);
+ lightFilterBuffer.getColorBufferTexture().bind(2);
+ Gdx.gl.glActiveTexture(GL20.GL_TEXTURE0);
+ }
+
+ public void begin() {
+// Begin drawing a normal version of screen
+ normalBuffer.begin();
+ Gdx.gl.glClearColor(0f, 0f, 0f, 1f);
+ Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
+ }
+
+ public void end(float width, float height) {
+ normalBuffer.end();
+
+// BEGINNING NORMAL SCREEN RENDER
+ screenViewport.apply();
+
+// Begin light filtering
+ lightFilterBuffer.begin();
+ Gdx.gl.glClearColor(0f, 0f, 0f, 1f);
+ Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
+ fboRegion.setTexture(normalBuffer.getColorBufferTexture());
+ screenBatch.setShader(brightFilterShader);
+ screenBatch.setProjectionMatrix(screenViewport.getCamera().combined);
+ screenBatch.begin(); //SCREEN BATCH STARTS HERE
+ screenBatch.draw(fboRegion, 0, 0, width, height);
+ screenBatch.flush();
+ lightFilterBuffer.end();
+
+// Horizontal gaussian blur
+ fboRegion.setTexture(lightFilterBuffer.getColorBufferTexture());
+ hBlur.begin();
+ screenBatch.setShader(gaussianBlurShader);
+ gaussianBlurShader.setUniformi("pass", 0);
+ screenBatch.draw(fboRegion, 0f, 0f, width, height);
+ screenBatch.flush();
+ hBlur.end();
+
+
+// //Vertical gaussian blur
+ fboRegion.setTexture(hBlur.getColorBufferTexture());
+ vBlur.begin();
+ gaussianBlurShader.setUniformi("pass", 1);
+ screenBatch.draw(fboRegion, 0f, 0f, width, height);
+ screenBatch.flush();
+ vBlur.end();
+
+ Gdx.gl.glClearColor(0f, 0f, 0f, 1f);
+ Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
+ screenBatch.setShader(combineShader);
+ fboRegion.setTexture(normalBuffer.getColorBufferTexture());
+ screenBatch.draw(fboRegion, 0f, 0f, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
+ screenBatch.setShader(null);
+ screenBatch.end(); //STAGE BATCH ENDS HERE
+ }
+
+ @Override
+ public void dispose() {
+ brightFilterShader.dispose();
+ combineShader.dispose();
+ gaussianBlurShader.dispose();
+ normalBuffer.dispose();
+ lightFilterBuffer.dispose();
+ vBlur.dispose();
+ hBlur.dispose();
+
+ brightFilterShader = null;
+ combineShader = null;
+ gaussianBlurShader = null;
+ normalBuffer = null;
+ lightFilterBuffer = null;
+ vBlur = null;
+ hBlur = null;
+ }
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/graphics/ui/Page.java b/old/core/src/zero1hd/rhythmbullet/graphics/ui/Page.java
new file mode 100644
index 0000000..9f3d13f
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/graphics/ui/Page.java
@@ -0,0 +1,74 @@
+package zero1hd.rhythmbullet.graphics.ui;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.math.Vector3;
+import com.badlogic.gdx.scenes.scene2d.Group;
+import com.badlogic.gdx.scenes.scene2d.Stage;
+import com.badlogic.gdx.scenes.scene2d.Touchable;
+import com.badlogic.gdx.scenes.scene2d.ui.Label;
+import com.badlogic.gdx.scenes.scene2d.ui.Skin;
+import com.badlogic.gdx.utils.Disposable;
+import com.badlogic.gdx.utils.viewport.ScreenViewport;
+
+public class Page extends Group implements Disposable {
+ private Label pageTitle;
+ private int baseXPos, baseYPos;
+
+ public Page(int baseXPos, int baseYPos) {
+ this.baseXPos = baseXPos;
+ this.baseYPos = baseYPos;
+ setSize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
+ setTouchable(Touchable.childrenOnly);
+ setToBasePosition();
+ setName(getClass().getSimpleName());
+ }
+
+ public Page(int baseXPos, int baseYPos, String titleText, Skin skin) {
+ this(baseXPos, baseYPos);
+ pageTitle = new Label(titleText, skin, "large-font", skin.getColor("default"));
+ pageTitle.setPosition(18f, getHeight()-pageTitle.getHeight()-15f);
+ addActor(pageTitle);
+ }
+
+ public float getHeightBelowTitle() {
+ return pageTitle.getY();
+ }
+
+ @Override
+ public void setStage(Stage stage) {
+ if (stage == null) {
+ if (!hasParent()) {
+ dispose();
+ }
+ } else if (!(stage.getViewport() instanceof ScreenViewport)) {
+ throw new IllegalArgumentException("Pages are explicitly for GUIs, and thus should have a 1:1 ratio between pixel and texture size for maximum clarity. This means that the stage should be using a ScreenViewport.");
+ }
+ super.setStage(stage);
+ }
+
+ public void setCameraPositionToPage(Vector3 cameraPosition) {
+ cameraPosition.x = (baseXPos+0.5f) * getWidth();
+ cameraPosition.y = (baseYPos+0.5f) * getHeight();
+ }
+
+ public void setToBasePosition() {
+ setPosition(baseXPos*getWidth(), baseYPos*getHeight());
+ }
+
+ @Override
+ public void setParent(Group parent) {
+ if (parent == null && getStage() == null) {
+ dispose();
+ }
+ super.setParent(parent);
+ }
+
+ @Override
+ public void dispose() {
+ Gdx.app.debug(getClass().getSimpleName(), "Disposing...");
+ }
+
+ public void simpleDebug(String message) {
+ Gdx.app.debug(getClass().getSimpleName(), message);
+ }
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/graphics/ui/components/HealthBar.java b/old/core/src/zero1hd/rhythmbullet/graphics/ui/components/HealthBar.java
new file mode 100644
index 0000000..b68adba
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/graphics/ui/components/HealthBar.java
@@ -0,0 +1,71 @@
+package zero1hd.rhythmbullet.graphics.ui.components;
+
+import com.badlogic.gdx.math.MathUtils;
+import com.badlogic.gdx.scenes.scene2d.actions.Actions;
+import com.badlogic.gdx.scenes.scene2d.ui.Image;
+import com.badlogic.gdx.scenes.scene2d.ui.Skin;
+import com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup;
+
+import zero1hd.rhythmbullet.entity.ally.PolyjetEntity;
+
+public class HealthBar extends WidgetGroup {
+ Image empty;
+ Image filler;
+ float health;
+ float maxHealth;
+
+ PolyjetEntity pje;
+ public HealthBar(Skin skin, float maxHealth) {
+ super();
+ filler = new Image(skin.getPatch("bar-fill"));
+ addActor(filler);
+
+ empty = new Image(skin.getPatch("bar-empty"));
+ addActor(empty);
+
+ this.maxHealth = maxHealth;
+
+ }
+
+ public void setPolyjetEntity(PolyjetEntity pje) {
+ this.pje = pje;
+ }
+
+ public void setHealth(float health) {
+ this.health = health;
+
+ filler.addAction(Actions.sizeTo(getWidth(), MathUtils.round((health/maxHealth)*getHeight()), 0.1f));;
+ }
+
+ @Override
+ public void act(float delta) {
+ if (pje != null) {
+ health = pje.health;
+ }
+ super.act(delta);
+ }
+
+ @Override
+ public void setSize(float width, float height) {
+ empty.setSize(width, height);
+ filler.setSize(width, height);
+ super.setSize(width, height);
+ }
+
+ @Override
+ public void setWidth(float width) {
+ empty.setWidth(width);
+ filler.setWidth(width);
+ super.setWidth(width);
+ }
+
+ @Override
+ public void setHeight(float height) {
+ empty.setHeight(height);
+ super.setHeight(height);
+ }
+
+ public float getMaxHealth() {
+ return maxHealth;
+ }
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/graphics/ui/components/MusicControls.java b/old/core/src/zero1hd/rhythmbullet/graphics/ui/components/MusicControls.java
new file mode 100644
index 0000000..2e7287c
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/graphics/ui/components/MusicControls.java
@@ -0,0 +1,81 @@
+package zero1hd.rhythmbullet.graphics.ui.components;
+
+import com.badlogic.gdx.scenes.scene2d.Actor;
+import com.badlogic.gdx.scenes.scene2d.InputEvent;
+import com.badlogic.gdx.scenes.scene2d.ui.CheckBox;
+import com.badlogic.gdx.scenes.scene2d.ui.HorizontalGroup;
+import com.badlogic.gdx.scenes.scene2d.ui.ImageButton;
+import com.badlogic.gdx.scenes.scene2d.ui.Skin;
+import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
+import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
+
+import zero1hd.rhythmbullet.audio.MusicController;
+
+public class MusicControls extends HorizontalGroup {
+ private ImageButton reverse, forward;
+ private CheckBox shuffle, play;
+ public MusicControls(Skin skin, final MusicController sc) {
+ reverse = new ImageButton(skin, "rewind-button");
+ reverse.addListener(new ChangeListener() {
+ @Override
+ public void changed(ChangeEvent event, Actor actor) {
+ sc.previous();
+ }
+ });
+ addActor(reverse);
+
+ play = new CheckBox(null, skin, "play-button") {
+ @Override
+ public void act(float delta) {
+ if (sc.hasSongLoaded()) {
+ play.setChecked(sc.isPlaying());
+ } else {
+ play.setChecked(false);
+ }
+ super.act(delta);
+ }
+ };
+ play.addListener(new ClickListener() {
+ @Override
+ public void clicked(InputEvent event, float x, float y) {
+ if (play.isChecked()) {
+ sc.play();
+ } else {
+ sc.pause();
+ }
+ super.clicked(event, x, y);
+ }
+ });
+ addActor(play);
+
+ forward = new ImageButton(skin, "fast-forward-button");
+ forward.addListener(new ChangeListener() {
+ @Override
+ public void changed(ChangeEvent event, Actor actor) {
+ sc.skip();
+ }
+ });
+ addActor(forward);
+ shuffle = new CheckBox(null, skin, "shuffle-button") {
+ @Override
+ public void act(float delta) {
+ shuffle.setChecked(sc.isShuffle());
+ super.act(delta);
+ }
+ };
+ shuffle.addListener(new ChangeListener() {
+ @Override
+ public void changed(ChangeEvent event, Actor actor) {
+ if (shuffle.isChecked()) {
+ sc.setShuffle(true);
+ } else {
+ sc.setShuffle(false);
+ }
+ }
+ });
+ addActor(shuffle);
+ space(15);
+
+ setSize(getMinWidth(), getMinHeight());
+ }
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/graphics/ui/components/ScrollingText.java b/old/core/src/zero1hd/rhythmbullet/graphics/ui/components/ScrollingText.java
new file mode 100644
index 0000000..9111e44
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/graphics/ui/components/ScrollingText.java
@@ -0,0 +1,205 @@
+package zero1hd.rhythmbullet.graphics.ui.components;
+
+import com.badlogic.gdx.graphics.Color;
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.g2d.BitmapFont;
+import com.badlogic.gdx.graphics.g2d.GlyphLayout;
+import com.badlogic.gdx.graphics.g2d.NinePatch;
+import com.badlogic.gdx.math.Rectangle;
+import com.badlogic.gdx.math.Vector2;
+import com.badlogic.gdx.scenes.scene2d.Actor;
+import com.badlogic.gdx.scenes.scene2d.InputEvent;
+import com.badlogic.gdx.scenes.scene2d.ui.Skin;
+import com.badlogic.gdx.scenes.scene2d.ui.Widget;
+import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
+import com.badlogic.gdx.scenes.scene2d.utils.ScissorStack;
+
+public class ScrollingText extends Widget {
+ Rectangle scissors = new Rectangle();
+ Rectangle clipBounds = new Rectangle();
+
+ GlyphLayout gLayout;
+ String text1;
+ String text2;
+ BitmapFont font;
+ private float textHeight;
+ private float text1Width;
+ private float text2Width;
+
+ private boolean dupFirstText;
+ private boolean scrollOnHover;
+ private boolean scroll;
+
+ private float text1Offset, text2Offset;
+
+ private NinePatch background;
+
+ private Vector2 coords;
+
+ private float targetDelta;
+
+ public ScrollingText(String text, String text2, Skin skin, boolean scrollOnHover, boolean useBackground, float targetDelta) {
+ super();
+ font = skin.getFont("default-font");
+ init(text, text2, skin, scrollOnHover, useBackground);
+ this.targetDelta = targetDelta;
+ }
+
+ public ScrollingText(String text, String text2, Skin skin, String fontName, Color color, boolean scrollOnHover, boolean useBackground) {
+ super();
+ font = skin.getFont(fontName);
+ font.setColor(color);
+ init(text, text2, skin, scrollOnHover, useBackground);
+ }
+
+ private void init(String text1, String text2, Skin skin, boolean scrollOnHover, boolean useBackground) {
+ setName(text1);
+ if (useBackground) {
+ this.background = skin.getPatch("side-bars");
+ }
+
+ this.scrollOnHover = scrollOnHover;
+
+ coords = new Vector2();
+ addListener(new ClickListener() {
+ @Override
+ public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor) {
+ scroll = true;
+ super.enter(event, x, y, pointer, fromActor);
+ }
+
+ @Override
+ public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) {
+ scroll = false;
+ super.exit(event, x, y, pointer, toActor);
+ }
+
+ @Override
+ public void clicked(InputEvent event, float x, float y) {
+ }
+ });
+
+ setText(text1, text2);
+ layout();
+ }
+
+ public float getFontHeight() {
+ return textHeight;
+ }
+
+ public float getFontWidth() {
+ return text1Width;
+ }
+
+ @Override
+ public void layout() {
+ super.layout();
+
+ if (getHeight() < (textHeight+4)) {
+ setHeight(textHeight + 4);
+ }
+ clipBounds.setSize(getWidth()-2, getHeight()*1.5f);
+
+ text2Offset = clipBounds.getWidth();
+ if (text1Width < clipBounds.getWidth()) {
+ text1Offset = (clipBounds.getWidth()-text1Width)/2f;
+ }
+ }
+
+ public void scroll(float delta) {
+ if (text1Offset >= -text1Width) {
+ text1Offset -= 60*targetDelta;
+ if ((text1Offset < - Math.abs((text1Width - clipBounds.getWidth())) - 50) || text2Offset != clipBounds.getWidth()) {
+ text2Offset -= 60*targetDelta;
+ if (text2Offset <= -text2Width) {
+ text2Offset = clipBounds.getWidth();
+ }
+ }
+
+ } else {
+ text2Offset -= 60*targetDelta;
+ if (text2Offset < - Math.abs((text2Width - clipBounds.getWidth())) - 50) {
+ text1Offset = clipBounds.getWidth();
+ }
+ }
+ }
+
+ @Override
+ public void act(float delta) {
+ clipBounds.setSize(getWidth()-2, getHeight()*1.5f);
+ if (dupFirstText) {
+ if (text1Width > clipBounds.getWidth()) {
+ if (scrollOnHover) {
+ if (scroll || text1Offset < 0 || text1Offset > 2) {
+ scroll(delta);
+ }
+ } else {
+ scroll(delta);
+ }
+ }
+ } else {
+ if (text1Width + text2Width > clipBounds.getWidth()) {
+ if (scrollOnHover) {
+ if (scroll || text1Offset < 0 || text1Offset > 2) {
+ scroll(delta);
+ }
+ } else {
+ scroll(delta);
+ }
+ }
+ }
+ super.act(delta);
+ }
+
+ @Override
+ public void draw(Batch batch, float parentAlpha) {
+ if (background != null) {
+ background.draw(batch, getX(), getY(), getWidth(), getHeight());
+ }
+ coords.x = getX();
+ coords.y = getY();
+
+ clipBounds.setX(coords.x+1);
+ clipBounds.setY(coords.y - 0.5f*getHeight());
+
+ getStage().calculateScissors(clipBounds, scissors);
+ batch.flush();
+ if (ScissorStack.pushScissors(scissors)) {
+ font.draw(batch, text1, coords.x + text1Offset, coords.y + getFontHeight() + 4);
+ font.draw(batch, text2, coords.x + text2Offset, coords.y + getFontHeight() + 4);
+ batch.flush();
+ ScissorStack.popScissors();
+ }
+
+ super.draw(batch, parentAlpha);
+ }
+
+ @Override
+ public float getMinHeight() {
+ return textHeight;
+ }
+
+ /**
+ * Sets the two strings that will be scrolling.
+ * @param text1 cannot be null.
+ * @param text2 can be null.
+ */
+ public void setText(String text1, String text2) {
+ this.text1 = text1;
+ gLayout = new GlyphLayout(font, text1);
+ text1Width = gLayout.width;
+ textHeight = gLayout.height;
+
+ if (text2 != null) {
+ this.text2 = text2;
+ gLayout = new GlyphLayout(font, text2);
+ text2Width = gLayout.width;
+ } else {
+ dupFirstText = true;
+ this.text2 = text1;
+ this.text2Width = text1Width;
+ }
+
+ layout();
+ }
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/util/AssetPack.java b/old/core/src/zero1hd/rhythmbullet/util/AssetPack.java
new file mode 100644
index 0000000..815e422
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/util/AssetPack.java
@@ -0,0 +1,45 @@
+package zero1hd.rhythmbullet.util;
+
+import com.badlogic.gdx.assets.AssetManager;
+import com.badlogic.gdx.scenes.scene2d.ui.Skin;
+import com.badlogic.gdx.utils.Disposable;
+
+public interface AssetPack extends Disposable {
+
+ /**
+ * Called right after the game instance is created and passed to LWJGL. This method is called once for you to instantiate things for later use but require Libgdx functions.
+ */
+ public void initiate();
+
+ /**
+ * Game manager calls this when it needs to load textures.
+ */
+ public void queueTextures(AssetManager assetManager);
+
+ /**
+ * Game manager calls this when it needs to load sound effects.
+ */
+ public void queueSFX(AssetManager assetManager);
+
+ /**
+ * Game manager calls this when it needs to load particles.
+ */
+ public void queueParticles(AssetManager assetManager);
+
+ /**
+ * Game manager calls when it needs to load particles. Usually called after textures are loaded since the skin requires the other assets.
+ * @param skin the skin object to set up.
+ */
+ public void setupSkin(Skin skin);
+
+ /**
+ * Game manager calls when it needs the fonts to be generated. Usually called right before setting up the skin itself since items in the skin need fonts.
+ */
+ public void generateFonts(Skin skin);
+
+ /**
+ * Game manager calls this once all assets are loaded. This function should be used to make some in-code adjustments to assets that will be consistent throughout the game for that run.
+ * @param assetManager gives you access to the assets to modify.
+ */
+ public void complete(AssetManager assetManager);
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/util/GenericFileTypeHandler.java b/old/core/src/zero1hd/rhythmbullet/util/GenericFileTypeHandler.java
new file mode 100644
index 0000000..0a6ddee
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/util/GenericFileTypeHandler.java
@@ -0,0 +1,25 @@
+package zero1hd.rhythmbullet.util;
+
+import com.badlogic.gdx.assets.loaders.FileHandleResolver;
+import com.badlogic.gdx.files.FileHandle;
+
+public class GenericFileTypeHandler implements FileHandleResolver {
+ private final FileHandleResolver resolver;
+
+ public GenericFileTypeHandler(FileHandleResolver fileResolver) {
+ resolver = fileResolver;
+ }
+
+ @Override
+ public FileHandle resolve(String fileName) {
+
+ if (fileName.endsWith(".p")) {
+ return resolver.resolve("particles/" +fileName);
+ } else if (fileName.endsWith(".ogg")) {
+ return resolver.resolve("sounds/" + fileName);
+ } else {
+ return null;
+ }
+ }
+
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/util/InitialScreen.java b/old/core/src/zero1hd/rhythmbullet/util/InitialScreen.java
new file mode 100644
index 0000000..9cf038c
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/util/InitialScreen.java
@@ -0,0 +1,20 @@
+package zero1hd.rhythmbullet.util;
+
+import com.badlogic.gdx.Screen;
+
+import zero1hd.rhythmbullet.RhythmBullet;
+
+public interface InitialScreen extends ResizeReadyScreen {
+ /**
+ * Called when everythings loaded and ready to advance.
+ * Screen should be created on platform.
+ * @param gameManager the game manager.
+ * @return the screen that is created.
+ */
+ public Screen advance(RhythmBullet gameManager);
+
+ /**
+ * Immediately called after the LibGDX instance has been instantiated.
+ */
+ public void init();
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/util/ResizeReadyScreen.java b/old/core/src/zero1hd/rhythmbullet/util/ResizeReadyScreen.java
new file mode 100644
index 0000000..b4e99a2
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/util/ResizeReadyScreen.java
@@ -0,0 +1,15 @@
+package zero1hd.rhythmbullet.util;
+
+import com.badlogic.gdx.Screen;
+
+public interface ResizeReadyScreen extends Screen {
+ /**
+ * called before assets are cleared from memory.
+ */
+ public void preAssetLoad();
+
+ /**
+ * called after transition completes and assets reloaded.
+ */
+ public void postAssetLoad();
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/util/RoundingResolutionHandler.java b/old/core/src/zero1hd/rhythmbullet/util/RoundingResolutionHandler.java
new file mode 100644
index 0000000..cdd39c5
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/util/RoundingResolutionHandler.java
@@ -0,0 +1,77 @@
+package zero1hd.rhythmbullet.util;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.assets.loaders.FileHandleResolver;
+import com.badlogic.gdx.assets.loaders.resolvers.ResolutionFileResolver.Resolution;
+import com.badlogic.gdx.files.FileHandle;
+
+public class RoundingResolutionHandler implements FileHandleResolver {
+ private final Resolution[] descriptors;
+ private final FileHandleResolver resolver;
+ private boolean silent = true;
+ private int width, height;
+ public RoundingResolutionHandler(FileHandleResolver fileResolver, Resolution... descriptors) {
+ if (descriptors.length == 0) throw new IllegalArgumentException("At least one Resolution needs to be supplied.");
+ this.descriptors = descriptors;
+ this.resolver = fileResolver;
+ }
+
+ public void setResolution(int width, int height) {
+ this.width = width;
+ this.height = height;
+ }
+
+ public void resetResolution() {
+ width = Gdx.graphics.getWidth();
+ height = Gdx.graphics.getHeight();
+ }
+
+ public Resolution chooseRounded(Resolution... descriptors) {
+ Resolution best = descriptors[0];
+
+ int leastDifference = -1;
+
+ int w = width, h = height;
+
+ if (w > h) {
+ for (int i = 0; i < descriptors.length; i++) {
+ int currentDiff = h - descriptors[i].portraitHeight;
+
+ if (currentDiff < 0) {
+ currentDiff = currentDiff*-1;
+ }
+
+ if ((currentDiff < leastDifference) || leastDifference == -1) {
+ best = descriptors[i];
+ leastDifference = currentDiff;
+ }
+ }
+ } else {
+ for (int i = 0; i < descriptors.length; i++) {
+ int currentDiff = w - descriptors[i].portraitWidth;
+
+ if (currentDiff < 0) {
+ currentDiff = currentDiff*-1;
+ }
+
+ if (currentDiff < leastDifference || leastDifference == -1) {
+ best = descriptors[i];
+ leastDifference = currentDiff;
+ }
+ }
+ }
+ return best;
+ }
+
+ @Override
+ public FileHandle resolve(String fileName) {
+ Resolution bestRes = chooseRounded(descriptors);
+ if (!silent) {
+ Gdx.app.debug("RResolution Handler", "Finding best match for resolution: " + width + "x" + height + " for file: " + fileName);
+ Gdx.app.debug("RResolution Handler", "Selected folder: " + bestRes.folder);
+ }
+ FileHandle resSpecificFile = resolver.resolve(bestRes.folder + "/" + fileName);
+ if (!resSpecificFile.exists()) resSpecificFile = resolver.resolve(fileName);
+ return resSpecificFile;
+ }
+}
diff --git a/old/core/src/zero1hd/rhythmbullet/util/ScreenConfiguration.java b/old/core/src/zero1hd/rhythmbullet/util/ScreenConfiguration.java
new file mode 100644
index 0000000..122dcd2
--- /dev/null
+++ b/old/core/src/zero1hd/rhythmbullet/util/ScreenConfiguration.java
@@ -0,0 +1,30 @@
+package zero1hd.rhythmbullet.util;
+
+public interface ScreenConfiguration {
+ public void setFramesPerSecond(int fps);
+
+ public int getTargetFramesPerSecond();
+
+ /**
+ * @param useVsync whether or not to use vSync.
+ */
+ public void setVsync(boolean useVsync);
+
+ public boolean getVsync();
+
+ public int getScreenWidth();
+
+ public int getScreenHeight();
+
+ public int getWindowPosX();
+
+ public int getWindowPosY();
+
+ public void setWindowLocationX(int x);
+
+ public void setWindowLocationY(int y);
+
+ public void setWindowLocation(int x, int y);
+
+ public void queueBorderless(boolean borderless);
+}
diff --git a/old/desktop/.classpath b/old/desktop/.classpath
new file mode 100644
index 0000000..a382805
--- /dev/null
+++ b/old/desktop/.classpath
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/old/desktop/.project b/old/desktop/.project
new file mode 100644
index 0000000..6478e3d
--- /dev/null
+++ b/old/desktop/.project
@@ -0,0 +1,25 @@
+
+
+ RhythmBullet-desktop
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.springsource.ide.eclipse.gradle.core.nature
+ org.eclipse.jdt.core.javanature
+
+
+
+ assets
+ 2
+ PARENT-1-PROJECT_LOC/android/assets
+
+
+
diff --git a/old/desktop/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs b/old/desktop/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs
new file mode 100644
index 0000000..b6b91f6
--- /dev/null
+++ b/old/desktop/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs
@@ -0,0 +1,4 @@
+#org.springsource.ide.eclipse.gradle.core.preferences.GradleProjectPreferences
+#Mon Sep 10 00:40:48 CDT 2018
+org.springsource.ide.eclipse.gradle.linkedresources=assets/;
+org.springsource.ide.eclipse.gradle.rootprojectloc=..
diff --git a/old/desktop/.settings/gradle/org.springsource.ide.eclipse.gradle.refresh.prefs b/old/desktop/.settings/gradle/org.springsource.ide.eclipse.gradle.refresh.prefs
new file mode 100644
index 0000000..539dcf9
--- /dev/null
+++ b/old/desktop/.settings/gradle/org.springsource.ide.eclipse.gradle.refresh.prefs
@@ -0,0 +1,8 @@
+#org.springsource.ide.eclipse.gradle.core.actions.GradleRefreshPreferences
+#Mon Sep 10 00:40:48 CDT 2018
+addResourceFilters=true
+afterTasks=afterEclipseImport;
+beforeTasks=cleanEclipse;eclipse;
+enableAfterTasks=true
+enableBeforeTasks=true
+useHierarchicalNames=false
diff --git a/old/desktop/.settings/org.eclipse.jdt.core.prefs b/old/desktop/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..3a21537
--- /dev/null
+++ b/old/desktop/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,11 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/old/desktop/build.gradle b/old/desktop/build.gradle
new file mode 100644
index 0000000..9d9b713
--- /dev/null
+++ b/old/desktop/build.gradle
@@ -0,0 +1,55 @@
+apply plugin: "java"
+
+sourceCompatibility = 1.6
+sourceSets.main.java.srcDirs = [ "src/" ]
+
+project.ext.mainClassName = "zero1hd.rhythmbullet.desktop.DesktopLauncher"
+project.ext.assetsDir = new File("../android/assets");
+
+task run(dependsOn: classes, type: JavaExec) {
+ main = project.mainClassName
+ classpath = sourceSets.main.runtimeClasspath
+ standardInput = System.in
+ workingDir = project.assetsDir
+ ignoreExitValue = true
+}
+
+task debug(dependsOn: classes, type: JavaExec) {
+ main = project.mainClassName
+ classpath = sourceSets.main.runtimeClasspath
+ standardInput = System.in
+ workingDir = project.assetsDir
+ ignoreExitValue = true
+ debug = true
+}
+
+task dist(type: Jar) {
+ from files(sourceSets.main.output.classesDir)
+ from files(sourceSets.main.output.resourcesDir)
+ from {configurations.compile.collect {zipTree(it)}}
+ from files(project.assetsDir);
+
+ manifest {
+ attributes 'Main-Class': project.mainClassName
+ }
+}
+
+dist.dependsOn classes
+
+eclipse {
+ project {
+ name = appName + "-desktop"
+ linkedResource name: 'assets', type: '2', location: 'PARENT-1-PROJECT_LOC/android/assets'
+ }
+}
+
+task afterEclipseImport(description: "Post processing after project generation", group: "IDE") {
+ doLast {
+ def classpath = new XmlParser().parse(file(".classpath"))
+ new Node(classpath, "classpathentry", [ kind: 'src', path: 'assets' ]);
+ def writer = new FileWriter(file(".classpath"))
+ def printer = new XmlNodePrinter(new PrintWriter(writer))
+ printer.setPreserveWhitespace(true)
+ printer.print(classpath)
+ }
+}
diff --git a/old/desktop/src/zero1hd/rhythmbullet/desktop/Controls.java b/old/desktop/src/zero1hd/rhythmbullet/desktop/Controls.java
new file mode 100644
index 0000000..1cccc7e
--- /dev/null
+++ b/old/desktop/src/zero1hd/rhythmbullet/desktop/Controls.java
@@ -0,0 +1,45 @@
+package zero1hd.rhythmbullet.desktop;
+
+import com.badlogic.gdx.Preferences;
+import com.badlogic.gdx.Input.Keys;
+
+public enum Controls {
+ UP("Forward", Keys.UP), DOWN("Backwards", Keys.DOWN), LEFT("Left", Keys.LEFT), RIGHT("Right", Keys.RIGHT), SHOOT("Shoot", Keys.SPACE), ACCELERATE("Boost", Keys.SHIFT_LEFT);
+ private int keycode;
+ private final String friendly;
+ private final int defectKey;
+
+ private Controls(String friendly, int defectKey) {
+ this.friendly = friendly;
+ this.defectKey = defectKey;
+ this.keycode = defectKey;
+ }
+
+ public Controls setKeycode(int keycode) {
+ Controls[] controls = Controls.values();
+ for (int i = 0; i < controls.length; i++) {
+ if (controls[i] != this && controls[i].getKeycode() == keycode) {
+ return controls[i];
+ }
+ }
+ this.keycode = keycode;
+ return null;
+ }
+
+ public int getKeycode() {
+ return keycode;
+ }
+
+ public void loadKeyFromPreferences(Preferences preferences) {
+ setKeycode(preferences.getInteger(name(), defectKey));
+ }
+
+ public void saveKeyToPreferences(Preferences preferences) {
+ preferences.putInteger(name(), keycode);
+ }
+
+ @Override
+ public String toString() {
+ return friendly;
+ }
+}
diff --git a/old/desktop/src/zero1hd/rhythmbullet/desktop/DesktopAssetPack.java b/old/desktop/src/zero1hd/rhythmbullet/desktop/DesktopAssetPack.java
new file mode 100644
index 0000000..cdf7eff
--- /dev/null
+++ b/old/desktop/src/zero1hd/rhythmbullet/desktop/DesktopAssetPack.java
@@ -0,0 +1,238 @@
+package zero1hd.rhythmbullet.desktop;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.Preferences;
+import com.badlogic.gdx.assets.AssetManager;
+import com.badlogic.gdx.audio.Sound;
+import com.badlogic.gdx.graphics.Color;
+import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.graphics.g2d.ParticleEffect;
+import com.badlogic.gdx.graphics.g2d.TextureAtlas;
+import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
+import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator.FreeTypeFontParameter;
+import com.badlogic.gdx.math.MathUtils;
+import com.badlogic.gdx.scenes.scene2d.ui.Skin;
+import com.badlogic.gdx.scenes.scene2d.ui.Button.ButtonStyle;
+import com.badlogic.gdx.scenes.scene2d.ui.CheckBox.CheckBoxStyle;
+import com.badlogic.gdx.scenes.scene2d.ui.ImageButton.ImageButtonStyle;
+import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle;
+import com.badlogic.gdx.scenes.scene2d.ui.List.ListStyle;
+import com.badlogic.gdx.scenes.scene2d.ui.ProgressBar.ProgressBarStyle;
+import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane.ScrollPaneStyle;
+import com.badlogic.gdx.scenes.scene2d.ui.SelectBox.SelectBoxStyle;
+import com.badlogic.gdx.scenes.scene2d.ui.Slider.SliderStyle;
+import com.badlogic.gdx.scenes.scene2d.ui.TextButton.TextButtonStyle;
+import com.badlogic.gdx.scenes.scene2d.ui.TextField.TextFieldStyle;
+import com.badlogic.gdx.scenes.scene2d.ui.Window.WindowStyle;
+
+import zero1hd.rhythmbullet.util.AssetPack;
+
+public class DesktopAssetPack implements AssetPack {
+ private FreeTypeFontGenerator default_fontGenerator;
+ private FreeTypeFontGenerator darktech_ldr_fontGenerator;
+
+ @Override
+ public void initiate() {
+ default_fontGenerator = new FreeTypeFontGenerator(Gdx.files.internal("fonts/Gasalt-Regular.ttf"));
+ darktech_ldr_fontGenerator = new FreeTypeFontGenerator(Gdx.files.internal("fonts/darktech_ldr.ttf"));
+ }
+
+ @Override
+ public void queueTextures(AssetManager assetManager) {
+ assetManager.load("uiskin.atlas", TextureAtlas.class);
+ assetManager.load("Tech-Circle1.png", Texture.class);
+ assetManager.load("polyjet-standard.png", Texture.class);
+ assetManager.load("keyboard.atlas", TextureAtlas.class);
+ assetManager.load("cybercircle3B.png", Texture.class);
+ assetManager.load("title.png", Texture.class);
+ assetManager.load("cybercircle1.png", Texture.class);
+ assetManager.load("defaultCover.png", Texture.class);
+ assetManager.load("laser.png", Texture.class);
+ assetManager.load("pellet.png", Texture.class);
+ assetManager.load("shard.png", Texture.class);
+ assetManager.load("bar.png", Texture.class);
+ assetManager.load("flake.png", Texture.class);
+ assetManager.load("void_circle.png", Texture.class);
+ assetManager.load("tpSelector.png", Texture.class);
+ assetManager.load("backgrounds/mainBG.png", Texture.class);
+ assetManager.load("magic1.png", Texture.class);
+ }
+
+ @Override
+ public void queueSFX(AssetManager assetManager) {
+ assetManager.load("pop_open.ogg", Sound.class);
+ assetManager.load("pop_close.ogg", Sound.class);
+ assetManager.load("laser.ogg", Sound.class);
+ assetManager.load("explosion.ogg", Sound.class);
+ assetManager.load("disintegrate.ogg", Sound.class);
+ }
+
+ @Override
+ public void queueParticles(AssetManager assetManager) {
+ assetManager.load("standard_thrust.p", ParticleEffect.class);
+ assetManager.load("teleport-cloak.p", ParticleEffect.class);
+ assetManager.load("explosion-s.p", ParticleEffect.class);
+ assetManager.load("beateffect.p", ParticleEffect.class);
+ }
+
+ @Override
+ public void setupSkin(Skin skin) {
+ skin.add("default", Color.WHITE);
+ skin.add("inverse", Color.BLACK);
+
+ TextButtonStyle defaultTextButton = new TextButtonStyle();
+ defaultTextButton.up = skin.getDrawable("rect");
+ defaultTextButton.down = skin.getDrawable("rect-down");
+ defaultTextButton.font = skin.getFont("default-font");
+ defaultTextButton.fontColor = skin.getColor("default");
+ defaultTextButton.disabled = skin.getDrawable("rect-disabled");
+ skin.add("default", defaultTextButton);
+
+ TextButtonStyle subTextbutton = new TextButtonStyle(defaultTextButton);
+ subTextbutton.font = skin.getFont("sub-font");
+ skin.add("sub", subTextbutton);
+
+ TextButtonStyle windowTextButton = new TextButtonStyle(defaultTextButton);
+ windowTextButton.font = skin.getFont("window-font");
+ skin.add("window", windowTextButton);
+
+ SliderStyle defaultSlider = new SliderStyle(skin.getDrawable("default-slider"), skin.getDrawable("default-slider-knob"));
+ skin.add("default-horizontal", defaultSlider);
+
+ SliderStyle vertSlider = new SliderStyle(defaultSlider);
+ vertSlider.knob = skin.getDrawable("vertical-slider-knob");
+ skin.add("default-vertical", vertSlider);
+
+ ProgressBarStyle defaultProgressBar = new ProgressBarStyle(skin.getDrawable("default-slider"), skin.getDrawable("progress-slider-knob"));
+
+ LabelStyle defaultLabel = new LabelStyle();
+ defaultLabel.font = skin.getFont("default-font");
+ defaultLabel.fontColor = skin.getColor("default");
+ skin.add("default", defaultLabel);
+
+ TextFieldStyle defaultTextField = new TextFieldStyle(skin.getFont("sub-font"), skin.getColor("default"), skin.getDrawable("cursor"), skin.getDrawable("selection"), skin.getDrawable("textfield"));
+ skin.add("default", defaultTextField);
+
+ TextFieldStyle uiTextField = new TextFieldStyle(defaultTextField);
+ uiTextField.font = skin.getFont("window-font");
+ skin.add("ui", uiTextField);
+
+ WindowStyle defaultWindow = new WindowStyle(skin.getFont("window-font"), skin.getColor("default"), skin.getDrawable("default-window"));
+ skin.add("default", defaultWindow);
+
+ WindowStyle tintedWindow = new WindowStyle(defaultWindow);
+ tintedWindow.titleFontColor = skin.getColor("inverse");
+ tintedWindow.background = skin.getDrawable("tinted-window");
+ skin.add("tinted", tintedWindow);
+
+ ListStyle defaultList = new ListStyle(skin.getFont("window-font"), skin.getColor("inverse"), skin.getColor("default"), skin.getDrawable("selection"));
+ skin.add("default", defaultList);
+
+ ScrollPaneStyle defaultScrollPane = new ScrollPaneStyle();
+ defaultScrollPane.vScroll = skin.getDrawable("default-scroll");
+ defaultScrollPane.hScrollKnob = skin.getDrawable("default-round-large");
+ defaultScrollPane.hScroll = skin.getDrawable("default-scroll");
+ defaultScrollPane.vScrollKnob = skin.getDrawable("default-round-large");
+ skin.add("default", defaultScrollPane);
+
+ CheckBoxStyle defaultCheckBox = new CheckBoxStyle(skin.getDrawable("check-off"), skin.getDrawable("check-on"), skin.getFont("window-font"), skin.getColor("default"));
+ defaultCheckBox.checkboxOffDisabled = skin.getDrawable("check-disabled");
+ skin.add("default", defaultCheckBox);
+
+ SelectBoxStyle defaultSelectBox = new SelectBoxStyle(skin.getFont("default-font"), skin.getColor("default"), skin.getDrawable("default-select"), defaultScrollPane, defaultList);
+ skin.add("default", defaultSelectBox);
+
+ Gdx.app.debug("Prelaunch Debug Info", "UI Skin has been defined.");
+
+ CheckBoxStyle playButtonStyle = new CheckBoxStyle(defaultCheckBox);
+ playButtonStyle.checkboxOn = skin.getDrawable("play-down");
+ playButtonStyle.checkboxOff = skin.getDrawable("play");
+ skin.add("play-button", playButtonStyle);
+
+ ImageButtonStyle pauseButtonStyle = new ImageButtonStyle();
+ pauseButtonStyle.down = skin.getDrawable("pause-down");
+ pauseButtonStyle.up = skin.getDrawable("pause");
+ skin.add("pause-button", pauseButtonStyle);
+
+ ImageButtonStyle fastForwardButtonStyle = new ImageButtonStyle();
+ fastForwardButtonStyle.down = skin.getDrawable("fast-forward-down");
+ fastForwardButtonStyle.up = skin.getDrawable("fast-forward");
+ skin.add("fast-forward-button", fastForwardButtonStyle);
+
+ ImageButtonStyle reverseButtonStyle = new ImageButtonStyle();
+ reverseButtonStyle.down = skin.getDrawable("rewind-down");
+ reverseButtonStyle.up = skin.getDrawable("rewind");
+ skin.add("rewind-button", reverseButtonStyle);
+
+ CheckBoxStyle shuffleButtonStyle = new CheckBoxStyle(defaultCheckBox);
+ shuffleButtonStyle.checkboxOff = skin.getDrawable("shuffle");
+ shuffleButtonStyle.checkboxOn = skin.getDrawable("shuffle-down");
+ skin.add("shuffle-button", shuffleButtonStyle);
+
+ ButtonStyle selectableButton = new ButtonStyle();
+ selectableButton.checked = skin.getDrawable("holo-pane-down");
+ selectableButton.up = skin.getDrawable("holo-pane");
+ skin.add("selectable-button", selectableButton);
+
+ ButtonStyle selectableCleanButton = new ButtonStyle();
+ skin.add("selectable-clean-button", selectableCleanButton);
+ }
+
+ @Override
+ public void generateFonts(Skin skin) {
+ int height = Gdx.graphics.getHeight();
+
+ skin.add("window-font", default_fontGenerator.generateFont(new FreeTypeFontParameter() {
+ {
+ size = 18;
+ }
+ }));
+ skin.add("sub-font", default_fontGenerator.generateFont(new FreeTypeFontParameter() {
+ {
+ size = fontScale(0.05f, height);
+ }
+ }));
+ skin.add("default-font", default_fontGenerator.generateFont(new FreeTypeFontParameter() {
+ {
+ size = fontScale(0.07f, height);
+ }
+ }));
+ skin.add("large-font", default_fontGenerator.generateFont(new FreeTypeFontParameter() {
+ {
+ size = fontScale(0.085f, height);
+ }
+ }));
+ skin.add("special-font", darktech_ldr_fontGenerator.generateFont(new FreeTypeFontParameter() {
+ {
+ size = fontScale(0.075f, height);
+ }
+ }));
+ }
+
+ public int fontScale(float fontSize, int height) {
+ int size = MathUtils.round(Gdx.graphics.getDensity()*(fontSize*height));
+ if (size >= 200) {
+ size = 200;
+ }
+ return size;
+ }
+
+ @Override
+ public void complete(AssetManager assetManager) {
+ assetManager.get("standard_thrust.p", ParticleEffect.class).flipY();
+
+ Preferences controlsPrefs = Gdx.app.getPreferences("RhythmBullet_Controls");
+ Controls.UP.loadKeyFromPreferences(controlsPrefs);
+ Controls.DOWN.loadKeyFromPreferences(controlsPrefs);
+ Controls.LEFT.loadKeyFromPreferences(controlsPrefs);
+ Controls.RIGHT.loadKeyFromPreferences(controlsPrefs);
+ Controls.SHOOT.loadKeyFromPreferences(controlsPrefs);
+ Controls.ACCELERATE.loadKeyFromPreferences(controlsPrefs);
+ }
+
+ @Override
+ public void dispose() {
+ darktech_ldr_fontGenerator.dispose();
+ default_fontGenerator.dispose();
+ }
+}
diff --git a/old/desktop/src/zero1hd/rhythmbullet/desktop/DesktopLauncher.java b/old/desktop/src/zero1hd/rhythmbullet/desktop/DesktopLauncher.java
new file mode 100644
index 0000000..eadd3e8
--- /dev/null
+++ b/old/desktop/src/zero1hd/rhythmbullet/desktop/DesktopLauncher.java
@@ -0,0 +1,28 @@
+package zero1hd.rhythmbullet.desktop;
+
+import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
+import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
+
+import zero1hd.rhythmbullet.RhythmBullet;
+import zero1hd.rhythmbullet.desktop.screens.SplashScreen;
+
+public class DesktopLauncher {
+
+ public static void main (String[] arg) {
+ RhythmBullet core;
+ LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
+ DesktopScreenConfiguration screenConfig = new DesktopScreenConfiguration(config);
+
+ config.title = "Rhythm Bullet";
+ config.resizable = false;
+ config.useHDPI = true;
+ config.samples = 2;
+ config.width = 320;
+ config.height = 320;
+ config.allowSoftwareMode = true;
+ core = new RhythmBullet();
+ core.setup(new SplashScreen(), new DesktopAssetPack(), screenConfig);
+
+ LwjglApplication app = new LwjglApplication(core, config);
+ }
+}
diff --git a/old/desktop/src/zero1hd/rhythmbullet/desktop/DesktopScreenConfiguration.java b/old/desktop/src/zero1hd/rhythmbullet/desktop/DesktopScreenConfiguration.java
new file mode 100644
index 0000000..4f86650
--- /dev/null
+++ b/old/desktop/src/zero1hd/rhythmbullet/desktop/DesktopScreenConfiguration.java
@@ -0,0 +1,79 @@
+package zero1hd.rhythmbullet.desktop;
+
+import org.lwjgl.opengl.Display;
+
+import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
+
+import zero1hd.rhythmbullet.util.ScreenConfiguration;
+
+public class DesktopScreenConfiguration implements ScreenConfiguration {
+ private LwjglApplicationConfiguration configuration;
+ private boolean vSync;
+
+ public DesktopScreenConfiguration(LwjglApplicationConfiguration configuration) {
+ this.configuration = configuration;
+ vSync = configuration.vSyncEnabled;
+ }
+
+ @Override
+ public void setFramesPerSecond(int fps) {
+ configuration.foregroundFPS = fps;
+ }
+
+
+ @Override
+ public int getTargetFramesPerSecond() {
+ return configuration.foregroundFPS;
+ }
+
+ @Override
+ public void setVsync(boolean useVsync) {
+ configuration.vSyncEnabled = useVsync;
+ Display.setVSyncEnabled(useVsync);
+ }
+
+ @Override
+ public boolean getVsync() {
+ return vSync;
+ }
+
+ @Override
+ public int getScreenWidth() {
+ return Display.getDesktopDisplayMode().getWidth();
+ }
+
+ @Override
+ public int getScreenHeight() {
+ return Display.getDesktopDisplayMode().getHeight();
+ }
+
+ @Override
+ public int getWindowPosX() {
+ return Display.getX();
+ }
+
+ @Override
+ public int getWindowPosY() {
+ return Display.getY();
+ }
+
+ @Override
+ public void setWindowLocationX(int x) {
+ Display.setLocation(x, getWindowPosY());
+ }
+
+ @Override
+ public void setWindowLocationY(int y) {
+ Display.setLocation(getWindowPosX(), y);
+ }
+
+ @Override
+ public void setWindowLocation(int x, int y) {
+ Display.setLocation(x, y);
+ }
+
+ @Override
+ public void queueBorderless(boolean borderless) {
+ System.setProperty("org.lwjgl.opengl.Window.undecorated", String.valueOf(borderless));
+ }
+}
diff --git a/old/desktop/src/zero1hd/rhythmbullet/desktop/audio/PCMObtainer.java b/old/desktop/src/zero1hd/rhythmbullet/desktop/audio/PCMObtainer.java
new file mode 100644
index 0000000..a451ade
--- /dev/null
+++ b/old/desktop/src/zero1hd/rhythmbullet/desktop/audio/PCMObtainer.java
@@ -0,0 +1,269 @@
+package zero1hd.rhythmbullet.desktop.audio;
+
+import static org.lwjgl.openal.AL10.alGetSourcef;
+
+import java.math.RoundingMode;
+import java.nio.ByteBuffer;
+import java.nio.ShortBuffer;
+import java.text.DecimalFormat;
+import java.util.Observable;
+import java.util.Observer;
+
+import org.lwjgl.openal.AL;
+import org.lwjgl.openal.AL11;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.backends.lwjgl.audio.OpenALMusic;
+import com.badlogic.gdx.math.MathUtils;
+import com.badlogic.gdx.utils.TimeUtils;
+import com.badlogic.gdx.utils.reflect.ClassReflection;
+import com.badlogic.gdx.utils.reflect.Field;
+import com.badlogic.gdx.utils.reflect.ReflectionException;
+
+import edu.emory.mathcs.jtransforms.fft.FloatFFT_1D;
+import zero1hd.rhythmbullet.audio.MusicController;
+import zero1hd.rhythmbullet.audio.visualizer.PCMSystem;
+
+public class PCMObtainer implements Observer, PCMSystem {
+ private int windowSize = 1024;
+ private int sampleRate;
+ private long millisPerWindow;
+ private boolean songChanged;
+ private DecimalFormat df;
+ private float[] PCM = new float[windowSize];
+ private float[] frequencyBins = new float[windowSize / 2];
+ private FloatFFT_1D fft = new FloatFFT_1D(windowSize);
+ private ShortBuffer playingBuffer;
+ private ShortBuffer intermediateBuffer;
+ private ShortBuffer buffer;
+ private volatile int sourceID;
+ private int channelCount;
+ private MusicController mc;
+ private BufferStreamReadThread streamReadThread;
+ private int windowsRead;
+ private int currentPlaybackWindow;
+ private volatile boolean updated;
+
+ public PCMObtainer(MusicController musicController) {
+ this.mc = musicController;
+ mc.addObserver(this);
+ try {
+ Field bufferField = ClassReflection.getDeclaredField(OpenALMusic.class, "tempBuffer");
+ bufferField.setAccessible(true);
+ buffer = ((ByteBuffer) bufferField.get(null)).asShortBuffer().asReadOnlyBuffer();
+ playingBuffer = ShortBuffer.allocate(buffer.capacity());
+ intermediateBuffer = ShortBuffer.allocate(buffer.capacity());
+ } catch (IllegalArgumentException | SecurityException | ReflectionException e) {
+ Gdx.app.debug("Visualizer reflection", "Failed attempt at retrieving tempBuffer field.", e);
+ Gdx.app.exit();
+ }
+
+ streamReadThread = new BufferStreamReadThread();
+
+ df = new DecimalFormat("#.###");
+ df.setRoundingMode(RoundingMode.HALF_EVEN);
+ }
+
+ private boolean calcPCMData() {
+ synchronized (PCM) {
+ boolean empty = true;
+ short chanVal;
+ for (int sid = 0; sid < PCM.length && sid < playingBuffer.remaining(); sid++) {
+ PCM[sid] = 0;
+ for (int channel = 0; channel < channelCount; channel++) {
+ if (PCM[sid] < (chanVal = playingBuffer.get())) {
+ PCM[sid] = chanVal;
+ }
+ }
+ PCM[sid] /= Short.MAX_VALUE + 1f;
+
+ if (PCM[sid] != 0) {
+ empty = false;
+ }
+
+ }
+ return empty;
+ }
+ }
+
+ private void checkValidityOfPlaybackBuffer() {
+ // Begin comparison
+ buffer.rewind();
+ if (intermediateBuffer.compareTo(buffer) != 0) {
+ bufferChanged();
+
+ // Begin copying current buffer to the comparison buffer
+ intermediateBuffer.clear();
+ intermediateBuffer.put(buffer);
+ intermediateBuffer.flip();
+ }
+ }
+
+ private void bufferChanged() {
+ playingBuffer.rewind();
+ playingBuffer.put(intermediateBuffer);
+ playingBuffer.rewind();
+ synchronizeBufferWithPlayback();
+ }
+
+ private int calculateBufferPosition() {
+ int offset = (int) alGetSourcef(sourceID, AL11.AL_SAMPLE_OFFSET);
+ offset = (offset / windowSize) * windowSize;
+ return offset;
+ }
+
+ private boolean synchronizeBufferWithPlayback() {
+ int bufferPos = calculateBufferPosition();
+ synchronized (this) {
+ if (bufferPos <= playingBuffer.limit() && bufferPos >= 0) {
+ playingBuffer.position(bufferPos);
+ windowsRead = (int) ((mc.getCurrentPosition() * sampleRate) / windowSize);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void loadMusic() {
+ Gdx.app.debug("PCMObtainer", "music loaded.");
+ sourceID = -1;
+
+ channelCount = mc.getCurrentMusicHeader().getChannelCount();
+ sampleRate = mc.getCurrentMusicHeader().getSampleRate();
+ String millisPerWindowF = df.format(windowSize/(float) sampleRate);
+ millisPerWindow = (long) (Float.valueOf(millisPerWindowF)*1000);
+ songChanged = true;
+
+ intermediateBuffer.clear();
+ playingBuffer.clear();
+ begin();
+ }
+
+ @Override
+ public float[] getFrequencyBins() {
+ if (mc.isPlaying()) {
+ if (updated) {
+ synchronized (PCM) {
+ fft.realForward(PCM);
+ System.arraycopy(PCM, 1, frequencyBins, 0, frequencyBins.length);
+ }
+ updated = false;
+ }
+ } else {
+ for (int freqID = 0; freqID < frequencyBins.length; freqID++) {
+ frequencyBins[freqID] = 0;
+ }
+ }
+ return frequencyBins;
+ }
+
+ @Override
+ public int getWindowSize() {
+ return windowSize;
+ }
+
+
+
+ private class BufferStreamReadThread implements Runnable {
+ private String name = "PCM-Audio-Processing";
+ private Thread thread;
+ private volatile boolean run = true;
+ private long timeOfLastRead;
+ private long waitTime;
+ @Override
+ public void run() {
+ while (run) {
+ if (mc.isPlaying()) {
+ //record time of read
+ timeOfLastRead = TimeUtils.millis();
+
+ //calculate current pcm data and notify that there is new data
+ checkValidityOfPlaybackBuffer();
+ updated = !calcPCMData();
+ windowsRead++;
+
+ //contemplate synchronization
+ currentPlaybackWindow = MathUtils.round((mc.getCurrentPosition() * sampleRate) / windowSize);
+ if (windowsRead != currentPlaybackWindow) {
+ synchronizeBufferWithPlayback();
+ }
+ //wait for a bit before reading again depending on the speed at which the system does playback.
+ waitTime = Math.max(0, millisPerWindow - TimeUtils.timeSinceMillis(timeOfLastRead));
+ try {
+ Thread.sleep(waitTime);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ } else {
+
+ synchronized (this) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ Gdx.app.debug(thread.getName(), "stopped");
+ }
+
+ public void start() {
+ if (thread == null) {
+ thread = new Thread(this, name);
+ thread.setDaemon(true);
+ thread.start();
+ } else {
+ synchronized (this) {
+ notify();
+ }
+ }
+ }
+
+ public void stop() {
+ run = false;
+ }
+ }
+
+ @Override
+ public void update(Observable o, Object arg) {
+ if (o == mc) {
+ if (arg == mc.states.LOADED) {
+ loadMusic();
+ } else if (arg == mc.states.PLAYING) {
+ begin();
+ }
+ }
+ }
+
+ private void begin() {
+ if (mc.isPlaying()) {
+ if (sourceID == -1) {
+ try {
+ Field sourceIDField = ClassReflection.getDeclaredField(OpenALMusic.class, "sourceID");
+ sourceIDField.setAccessible(true);
+ sourceID = (int) sourceIDField.get(mc.getCurrentMusic());
+ } catch (ReflectionException e) {
+ e.printStackTrace();
+ }
+ }
+ streamReadThread.start();
+ }
+ }
+
+ @Override
+ public void dispose() {
+ streamReadThread.stop();
+ }
+
+ @Override
+ public boolean hasAudioChanged() {
+ if (songChanged) {
+ songChanged = false;
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/old/desktop/src/zero1hd/rhythmbullet/desktop/audio/processor/DesktopAudioProcessorFactory.java b/old/desktop/src/zero1hd/rhythmbullet/desktop/audio/processor/DesktopAudioProcessorFactory.java
new file mode 100644
index 0000000..d17f35f
--- /dev/null
+++ b/old/desktop/src/zero1hd/rhythmbullet/desktop/audio/processor/DesktopAudioProcessorFactory.java
@@ -0,0 +1,14 @@
+package zero1hd.rhythmbullet.desktop.audio.processor;
+
+import com.badlogic.gdx.files.FileHandle;
+
+import zero1hd.rhythmbullet.audio.AudioProcessorFactory;
+import zero1hd.rhythmbullet.audio.MinimalAudioHeader;
+import zero1hd.rhythmbullet.audio.processor.AudioProcessor;
+
+public class DesktopAudioProcessorFactory implements AudioProcessorFactory {
+ @Override
+ public AudioProcessor newMP3AudioProcessor(FileHandle fileHandle) {
+ return new MP3AudioProcessor(fileHandle, new MinimalAudioHeader(fileHandle));
+ }
+}
diff --git a/old/desktop/src/zero1hd/rhythmbullet/desktop/audio/processor/MP3AudioProcessor.java b/old/desktop/src/zero1hd/rhythmbullet/desktop/audio/processor/MP3AudioProcessor.java
new file mode 100644
index 0000000..d19387c
--- /dev/null
+++ b/old/desktop/src/zero1hd/rhythmbullet/desktop/audio/processor/MP3AudioProcessor.java
@@ -0,0 +1,158 @@
+package zero1hd.rhythmbullet.desktop.audio.processor;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.files.FileHandle;
+
+import javazoom.jl.decoder.Bitstream;
+import javazoom.jl.decoder.BitstreamException;
+import javazoom.jl.decoder.DecoderException;
+import javazoom.jl.decoder.Header;
+import javazoom.jl.decoder.MP3Decoder;
+import javazoom.jl.decoder.OutputBuffer;
+import zero1hd.rhythmbullet.audio.MinimalAudioHeader;
+import zero1hd.rhythmbullet.audio.processor.AudioProcessor;
+
+
+public class MP3AudioProcessor implements AudioProcessor {
+ private boolean stereo;
+ private int sampleRate;
+ private long sampleFrames;
+ private FileHandle fileHandle;
+ private byte[] currentByteSet;
+ private byte[] workset;
+ Bitstream bitstream;
+ MP3Decoder decoder;
+ OutputBuffer sampleBuffer;
+ private int indexHead = -1;
+
+
+ public MP3AudioProcessor(FileHandle fileHandle, MinimalAudioHeader minimalAudioHeader) {
+ this.fileHandle = fileHandle;
+
+ bitstream = new Bitstream(fileHandle.read());
+
+
+ stereo = minimalAudioHeader.getChannelCount() == 1 ? false : true;
+ sampleRate = minimalAudioHeader.getSampleRate();
+ sampleFrames = minimalAudioHeader.estimateSampleFrames();
+
+ decoder = new MP3Decoder();
+ sampleBuffer = new OutputBuffer(stereo ? 2 : 1, false);
+ decoder.setOutputBuffer(sampleBuffer);
+ workset = new byte[(stereo ? 2 : 1)*2];
+ }
+
+ @Override
+ public boolean isStereo() {
+ return stereo;
+ }
+
+
+ @Override
+ public int getSampleRate() {
+ return sampleRate;
+ }
+
+ @Override
+ public int readSamples(short[] pcm) {
+ int samplesRead = 0;
+ for (int sid = 0; sid < pcm.length; sid++) {
+ for (int wsid = 0; wsid < workset.length; wsid++) {
+ workset[wsid] = nextByte();
+ }
+ if (currentByteSet != null) {
+ pcm[sid] += (workset[1] << 8) + (workset[0] & 0x00ff);
+ if (stereo) {
+ short altChan = (short) ((workset[3] << 8) + (workset[2] & 0x00ff));
+ sid++;
+ pcm[sid] = altChan;
+ }
+ samplesRead ++;
+ }
+ }
+ return samplesRead;
+ }
+
+ @Override
+ public int readFrames(float[] pcm) {
+ int framesRead = 0;
+ for (int sid = 0; sid < pcm.length; sid++) {
+ for (int wsid = 0; wsid < workset.length; wsid++) {
+ workset[wsid] = nextByte();
+ }
+ if (currentByteSet != null) {
+ pcm[sid] += (workset[1] << 8) + (workset[0] & 0x00ff);
+ if (stereo) {
+ short altChan = (short) ((workset[3] << 8) + (workset[2] & 0x00ff));
+ pcm[sid] = altChan > pcm[sid] ? altChan : pcm[sid];
+ }
+ framesRead++;
+ pcm[sid] /= Short.MAX_VALUE+1;
+ }
+ }
+ return framesRead;
+ }
+
+ public byte nextByte() {
+ indexHead++;
+ if (currentByteSet == null || indexHead >= currentByteSet.length) {
+ loadNextBuffer();
+ if (currentByteSet == null) {
+ return 0;
+ }
+ indexHead = 0;
+ }
+
+ return currentByteSet[indexHead];
+ }
+
+ public int loadNextBuffer() {
+ if (bitstream != null) {
+ int bytesRead = 0;
+ try {
+ Header header = bitstream.readFrame();
+ if (header != null) {
+
+ try {
+ decoder.decodeFrame(header, bitstream);
+ } catch (ArrayIndexOutOfBoundsException ae) {
+ Gdx.app.debug("Mp3Manager", "Last buffer reached since array was out of bounds.");
+ } catch (DecoderException de) {
+ Gdx.app.error("MP3 Decoder Error", de.toString());
+ }
+ bitstream.closeFrame();
+ bytesRead = sampleBuffer.reset();
+ currentByteSet = sampleBuffer.getBuffer();
+ } else {
+ currentByteSet = null;
+ }
+ } catch (BitstreamException be) {
+ be.printStackTrace();
+ }
+ return bytesRead;
+ } else {
+ return 0;
+ }
+ }
+
+ @Override
+ public FileHandle getMusicFileHandle() {
+ return fileHandle;
+ }
+
+ @Override
+ public long getSampleFrames() {
+ return sampleFrames;
+ }
+
+ @Override
+ public void dispose() {
+ Gdx.app.debug("MP3Manager", "Disposing...");
+ try {
+ bitstream.close();
+ bitstream = null;
+ } catch (BitstreamException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/old/desktop/src/zero1hd/rhythmbullet/desktop/graphics/ui/components/GraphicsOptions.java b/old/desktop/src/zero1hd/rhythmbullet/desktop/graphics/ui/components/GraphicsOptions.java
new file mode 100644
index 0000000..8815847
--- /dev/null
+++ b/old/desktop/src/zero1hd/rhythmbullet/desktop/graphics/ui/components/GraphicsOptions.java
@@ -0,0 +1,78 @@
+package zero1hd.rhythmbullet.desktop.graphics.ui.components;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.Preferences;
+import com.badlogic.gdx.scenes.scene2d.Actor;
+import com.badlogic.gdx.scenes.scene2d.ui.Label;
+import com.badlogic.gdx.scenes.scene2d.ui.Skin;
+import com.badlogic.gdx.scenes.scene2d.ui.Table;
+import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
+import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
+import com.badlogic.gdx.utils.Align;
+
+public class GraphicsOptions extends Table {
+ private Label resolutions;
+
+ private ResolutionButton
+ _3840x2160,
+ _2560x1440,
+ _1920x1200,
+ _1920x1080,
+ _1280x800,
+ _1280x720,
+ _1366x768;
+
+
+ public GraphicsOptions(Skin skin, final Preferences prefs) {
+ align(Align.center);
+ defaults().space(10f);
+ resolutions = new Label("Resolutions: ", skin);
+ add(resolutions).left();
+ row();
+
+
+ TextButton fullscreen = new TextButton("Fullscreen", skin);
+ fullscreen.addListener(new ChangeListener() {
+
+ @Override
+ public void changed(ChangeEvent event, Actor actor) {
+ if (!Gdx.graphics.isFullscreen()) {
+ Gdx.graphics.setFullscreenMode(Gdx.graphics.getDisplayMode());
+ prefs.putBoolean("fullscreen", true);
+ prefs.flush();
+ }
+ }
+ });
+ add(fullscreen).fillX();
+ row();
+
+ _3840x2160 = new ResolutionButton(3840, 2160, skin, prefs);
+ add(_3840x2160).fillX();
+ row();
+
+ _2560x1440 = new ResolutionButton(2560, 1440, skin, prefs);
+ add(_2560x1440).fillX();
+ row();
+
+ _1920x1200 = new ResolutionButton(1920, 1200, skin, prefs);
+ add(_1920x1200).fillX();
+ row();
+
+ _1920x1080 = new ResolutionButton(1920, 1080, skin, prefs);
+ add(_1920x1080).fillX();
+ row();
+
+ _1280x800 = new ResolutionButton(1280, 800, skin, prefs);
+ add(_1280x800).fillX();
+ row();
+
+ _1366x768 = new ResolutionButton(1366, 768, skin, prefs);
+ add(_1366x768).fillX();
+ row();
+
+ _1280x720 = new ResolutionButton(1280, 720, skin, prefs);
+ add(_1280x720).fillX();
+ row();
+ pack();
+ }
+}
diff --git a/old/desktop/src/zero1hd/rhythmbullet/desktop/graphics/ui/components/ResolutionButton.java b/old/desktop/src/zero1hd/rhythmbullet/desktop/graphics/ui/components/ResolutionButton.java
new file mode 100644
index 0000000..2eb5ecb
--- /dev/null
+++ b/old/desktop/src/zero1hd/rhythmbullet/desktop/graphics/ui/components/ResolutionButton.java
@@ -0,0 +1,36 @@
+package zero1hd.rhythmbullet.desktop.graphics.ui.components;
+
+import java.awt.Dimension;
+import java.awt.Toolkit;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.Preferences;
+import com.badlogic.gdx.scenes.scene2d.Actor;
+import com.badlogic.gdx.scenes.scene2d.ui.Skin;
+import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
+import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
+
+public class ResolutionButton extends TextButton {
+
+ public ResolutionButton(int width, int height, Skin skin, Preferences prefs) {
+ super(width + "x" + height, skin);
+
+ Dimension screenDim = Toolkit.getDefaultToolkit().getScreenSize();
+
+ if (screenDim.getWidth() < width || screenDim.getHeight() < height) {
+ setDisabled(true);
+ }
+
+ addListener(new ChangeListener() {
+
+ @Override
+ public void changed(ChangeEvent event, Actor actor) {
+ Gdx.graphics.setWindowedMode(width, height);
+ prefs.putInteger("screen-width", width);
+ prefs.putInteger("screen-height", height);
+ prefs.putBoolean("fullscreen", false);
+ prefs.flush();
+ }
+ });
+ }
+}
diff --git a/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/EndScreen.java b/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/EndScreen.java
new file mode 100644
index 0000000..8153fac
--- /dev/null
+++ b/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/EndScreen.java
@@ -0,0 +1,8 @@
+package zero1hd.rhythmbullet.desktop.screens;
+
+import com.badlogic.gdx.ScreenAdapter;
+
+public class EndScreen extends ScreenAdapter {
+ public EndScreen() {
+ }
+}
diff --git a/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/GameScreen.java b/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/GameScreen.java
new file mode 100644
index 0000000..c8e0cf4
--- /dev/null
+++ b/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/GameScreen.java
@@ -0,0 +1,42 @@
+package zero1hd.rhythmbullet.desktop.screens;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.Preferences;
+import com.badlogic.gdx.ScreenAdapter;
+import com.badlogic.gdx.assets.AssetManager;
+import com.badlogic.gdx.graphics.Color;
+import com.badlogic.gdx.graphics.GL20;
+import com.badlogic.gdx.graphics.g2d.SpriteBatch;
+import com.badlogic.gdx.utils.viewport.ExtendViewport;
+
+import zero1hd.rhythmbullet.RhythmBullet;
+import zero1hd.rhythmbullet.audio.MusicController;
+import zero1hd.rhythmbullet.audio.visualizer.CircularVisualizer;
+import zero1hd.rhythmbullet.desktop.audio.PCMObtainer;
+
+public class GameScreen extends ScreenAdapter {
+ private AssetManager assets;
+ private SpriteBatch batch;
+ private ExtendViewport viewport;
+ private CircularVisualizer circleVisualizer;
+
+ public GameScreen(AssetManager assets, Preferences prefs, MusicController musicController) {
+ this.assets = assets;
+ batch = new SpriteBatch();
+ viewport = new ExtendViewport(RhythmBullet.WORLD_WIDTH, RhythmBullet.WORLD_HEIGHT);
+ circleVisualizer = new CircularVisualizer(new PCMObtainer(musicController));
+ circleVisualizer.setCenter(Gdx.graphics.getWidth()/2, Gdx.graphics.getHeight()/2);
+ circleVisualizer.setCamera(viewport.getCamera());
+ circleVisualizer.setColor(Color.CYAN.toFloatBits());
+ circleVisualizer.applyPositionChanges();
+ }
+
+
+ @Override
+ public void render(float delta) {
+ Gdx.gl.glClearColor(0.22f, 0.22f, 0.22f, 1f);
+ Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
+ circleVisualizer.drawVisualizer();
+ super.render(delta);
+ }
+}
diff --git a/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/SplashScreen.java b/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/SplashScreen.java
new file mode 100644
index 0000000..4a71d94
--- /dev/null
+++ b/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/SplashScreen.java
@@ -0,0 +1,58 @@
+package zero1hd.rhythmbullet.desktop.screens;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.Screen;
+import com.badlogic.gdx.ScreenAdapter;
+import com.badlogic.gdx.graphics.GL20;
+import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.graphics.g2d.SpriteBatch;
+
+import zero1hd.rhythmbullet.RhythmBullet;
+import zero1hd.rhythmbullet.desktop.screens.main.MainScreen;
+import zero1hd.rhythmbullet.util.InitialScreen;
+
+public class SplashScreen extends ScreenAdapter implements InitialScreen {
+ private Texture splashTexture;
+ private SpriteBatch batch;
+
+ @Override
+ public void init() {
+ batch = new SpriteBatch();
+ splashTexture = new Texture(Gdx.files.internal("splash_texture.png"));
+ }
+
+ @Override
+ public void render(float delta) {
+ Gdx.gl.glClearColor(1f, 1f, 1f, 1f);
+ Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
+ batch.begin();
+ batch.draw(splashTexture, 0, 0);
+ batch.end();
+
+ super.render(delta);
+ }
+
+ @Override
+ public void hide() {
+ splashTexture.dispose();
+ super.hide();
+ }
+
+ @Override
+ public void preAssetLoad() {
+ }
+
+ @Override
+ public void postAssetLoad() {
+ }
+
+ @Override
+ public void resize(int width, int height) {
+ super.resize(width, height);
+ }
+
+ @Override
+ public Screen advance(RhythmBullet game) {
+ return new MainScreen(game);
+ }
+}
diff --git a/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/AnalysisPage.java b/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/AnalysisPage.java
new file mode 100644
index 0000000..0ee4e9b
--- /dev/null
+++ b/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/AnalysisPage.java
@@ -0,0 +1,157 @@
+package zero1hd.rhythmbullet.desktop.screens.main;
+
+import com.badlogic.gdx.math.Vector3;
+import com.badlogic.gdx.scenes.scene2d.Actor;
+import com.badlogic.gdx.scenes.scene2d.ui.Image;
+import com.badlogic.gdx.scenes.scene2d.ui.Label;
+import com.badlogic.gdx.scenes.scene2d.ui.Skin;
+import com.badlogic.gdx.scenes.scene2d.ui.Slider;
+import com.badlogic.gdx.scenes.scene2d.ui.Table;
+import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
+import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
+
+import zero1hd.rhythmbullet.audio.AudioMetadataController;
+import zero1hd.rhythmbullet.audio.MusicController;
+import zero1hd.rhythmbullet.audio.analyzer.AudioAnalyzerSection;
+import zero1hd.rhythmbullet.audio.analyzer.DynamicAudioAnalyzer;
+import zero1hd.rhythmbullet.audio.metadata.AudioMetadata;
+import zero1hd.rhythmbullet.graphics.ui.Page;
+
+public class AnalysisPage extends Page {
+ private TextButton backButton;
+ private DynamicAudioAnalyzer audioAnalyzer;
+ private Table table;
+ private Table adjustment;
+ private Label difficultyModLabel, healthModLabel, speedModLabel;
+ private Slider difficultyModifierSlider, healthModifierSlider, speedModifierSlider;
+ private Label diffModPercentLabel, heltModPercentLabel, speeModPercentLabel;
+ private Label progressLabel;
+ private TextButton confirmButton;
+ private Image albumImage;
+ private AudioMetadataController amc;
+ private MusicController mc;
+
+ public AnalysisPage(MusicController mc, AudioMetadataController amc, Skin skin, ChangeListener backButtonListener, ChangeListener confirmedButtonListener) {
+ super(2, 0);
+ table = new Table();
+ table.setFillParent(true);
+ table.defaults().space(10f);
+ addActor(table);
+ adjustment = new Table();
+ this.mc = mc;
+ this.amc = amc;
+
+ difficultyModLabel = new Label("Difficulty Modifier: ", skin, "sub-font", skin.getColor("default"));
+ difficultyModifierSlider = new Slider(1, 3, 0.5f, false, skin);
+ diffModPercentLabel = new Label(String.valueOf(difficultyModifierSlider.getValue()) + "x", skin);
+ difficultyModifierSlider.addListener(new ChangeListener() {
+ @Override
+ public void changed(ChangeEvent event, Actor actor) {
+ diffModPercentLabel.setText(String.valueOf(difficultyModifierSlider.getValue()) + "x");
+ }
+ });
+
+ adjustment.add(difficultyModLabel);
+ adjustment.add(difficultyModifierSlider).minWidth(0.5f*getWidth());
+ adjustment.add(diffModPercentLabel).spaceLeft(10f).center().expandX().fill();
+ adjustment.row();
+ healthModLabel = new Label("Health Modifier: ", skin, "sub-font", skin.getColor("default"));
+ healthModifierSlider = new Slider(1f, 3f, 0.5f, false, skin);
+ heltModPercentLabel = new Label(String.valueOf(healthModifierSlider.getValue()) + "x", skin);
+ healthModifierSlider.addListener(new ChangeListener() {
+ @Override
+ public void changed(ChangeEvent event, Actor actor) {
+ heltModPercentLabel.setText(String.valueOf(healthModifierSlider.getValue()) + "x");
+ }
+ });
+ adjustment.add(healthModLabel);
+ adjustment.add(healthModifierSlider).fillX();
+ adjustment.add(heltModPercentLabel).spaceLeft(10f);
+ adjustment.row();
+ speedModLabel = new Label("Speed Modifier: ", skin, "sub-font", skin.getColor("default"));
+ speedModifierSlider = new Slider(1, 3, 0.5f, false, skin);
+ speeModPercentLabel = new Label(String.valueOf(speedModifierSlider.getValue()) + "x", skin);
+ speedModifierSlider.addListener(new ChangeListener() {
+ @Override
+ public void changed(ChangeEvent event, Actor actor) {
+ speeModPercentLabel.setText(String.valueOf(speedModifierSlider.getValue()) + "x");
+ }
+ });
+ adjustment.add(speedModLabel);
+ adjustment.add(speedModifierSlider).fillX();
+ adjustment.add(speeModPercentLabel).spaceLeft(10f);
+ adjustment.row();
+
+ confirmButton = new TextButton("Confirm", skin);
+ confirmButton.addListener(new ChangeListener() {
+ @Override
+ public void changed(ChangeEvent event, Actor actor) {
+ confirmButton.setDisabled(true);
+ speedModifierSlider.setDisabled(true);
+ healthModifierSlider.setDisabled(true);
+ difficultyModifierSlider.setDisabled(true);
+
+ progressLabel.setText("Loading...");
+ }
+ });
+ confirmButton.addListener(confirmedButtonListener);
+
+ adjustment.add(confirmButton).colspan(3).fillX();
+ adjustment.row();
+ progressLabel = new Label("Please confirm... ", skin);
+ adjustment.add(progressLabel).colspan(2).left().spaceTop(20f);
+
+ backButton = new TextButton("Cancel", skin);
+ backButton.setWidth(backButton.getWidth() + 20);
+ backButton.addListener(backButtonListener);
+ backButton.addListener(new ChangeListener() {
+ @Override
+ public void changed(ChangeEvent event, Actor actor) {
+ if (audioAnalyzer != null) {
+ audioAnalyzer.stop();
+ audioAnalyzer = null;
+ albumImage.setDrawable(null);
+ mc.setLoop(false);
+
+ }
+ }
+ });
+ backButton.setPosition(15, getHeight()-backButton.getHeight()-25);
+ addActor(backButton);
+
+ }
+
+ public void processSong() {
+ mc.setLoop(true);
+ AudioMetadata metadata = amc.getAudioMetadata(mc.getCurrentMusicFileHandle());
+ metadata.loadAlbumCover();
+ albumImage = new Image(metadata.getAlbumCover());
+ table.clear();
+ table.add(albumImage).size(adjustment.getMinHeight());
+ table.row();
+ table.add(adjustment);
+
+ AudioAnalyzerSection bass = new AudioAnalyzerSection(1, 5, 1.7f, 3);
+ AudioAnalyzerSection midSection = new AudioAnalyzerSection(7, 25, 1.5f, 3);
+
+ audioAnalyzer = new DynamicAudioAnalyzer(mc.getMusicList().newAudioProcessor(mc.getCurrentMusicFileHandle()), bass, midSection);
+ audioAnalyzer.start();
+ }
+
+ @Override
+ public void dispose() {
+ super.dispose();
+ }
+
+ @Override
+ public void setCameraPositionToPage(Vector3 cameraPosition) {
+ confirmButton.setDisabled(false);
+ speedModifierSlider.setDisabled(false);
+ healthModifierSlider.setDisabled(false);
+ difficultyModifierSlider.setDisabled(false);
+
+ processSong();
+
+ super.setCameraPositionToPage(cameraPosition);
+ }
+}
diff --git a/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/CreditsPage.java b/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/CreditsPage.java
new file mode 100644
index 0000000..9ed51d3
--- /dev/null
+++ b/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/CreditsPage.java
@@ -0,0 +1,30 @@
+package zero1hd.rhythmbullet.desktop.screens.main;
+
+import com.badlogic.gdx.scenes.scene2d.ui.Label;
+import com.badlogic.gdx.scenes.scene2d.ui.Skin;
+
+import zero1hd.rhythmbullet.graphics.ui.Page;
+
+public class CreditsPage extends Page {
+
+ public CreditsPage(Skin skin) {
+ super(0, 1);
+
+ Label title = new Label("Credits", skin, "large-font", skin.getColor("default"));
+ title.setPosition(15, getHeight()-title.getHeight()-15);
+ addActor(title);
+
+ Label subtitle = new Label("This game wouldn't be possible without these people.", skin, "sub-font", skin.getColor("default"));
+ subtitle.setPosition(title.getX(), title.getY()-subtitle.getHeight());
+ addActor(subtitle);
+
+ Label listOfNames = new Label(
+ "TheClimbingHippo (texture)\n"
+ + "Crepitus (sound effects)\n"
+ + "Neoqueto - Darktech LDR (font)\n"
+ + "Rémi Lagast - Gasalt (font)\n"
+ + "Timour Jgenti - Iron Maiden (font)", skin, "sub-font", skin.getColor("default"));
+ listOfNames.setPosition(subtitle.getX()+16, subtitle.getY()-listOfNames.getHeight()-10);
+ addActor(listOfNames);
+ }
+}
diff --git a/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/GraphicsPage.java b/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/GraphicsPage.java
new file mode 100644
index 0000000..349f280
--- /dev/null
+++ b/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/GraphicsPage.java
@@ -0,0 +1,43 @@
+package zero1hd.rhythmbullet.desktop.screens.main;
+
+import com.badlogic.gdx.Preferences;
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
+import com.badlogic.gdx.scenes.scene2d.ui.Skin;
+import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
+import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
+
+import zero1hd.rhythmbullet.desktop.graphics.ui.components.GraphicsOptions;
+import zero1hd.rhythmbullet.graphics.ui.Page;
+
+public class GraphicsPage extends Page {
+ private ScrollPane scrollPane;
+ private GraphicsOptions graphicsTable;
+ private TextButton backButton;
+
+ public GraphicsPage(Skin skin, Preferences preferences, ChangeListener backButtonListener) {
+ super(-1, 1);
+ graphicsTable = new GraphicsOptions(skin, preferences);
+ scrollPane = new ScrollPane(graphicsTable, skin);
+ scrollPane.setFadeScrollBars(false);
+ scrollPane.setFillParent(true);
+ addActor(scrollPane);
+
+ backButton = new TextButton("Back", skin);
+ backButton.setPosition(10, getHeight() - 10 - backButton.getHeight());
+ backButton.setWidth(backButton.getWidth() + 20);
+ backButton.addListener(backButtonListener);
+
+ addActor(backButton);
+ }
+
+ @Override
+ public void draw(Batch batch, float parentAlpha) {
+ super.draw(batch, parentAlpha);
+ }
+
+ @Override
+ public void act(float delta) {
+ super.act(delta);
+ }
+}
diff --git a/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/KeybindPage.java b/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/KeybindPage.java
new file mode 100644
index 0000000..daf3e3e
--- /dev/null
+++ b/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/KeybindPage.java
@@ -0,0 +1,224 @@
+package zero1hd.rhythmbullet.desktop.screens.main;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.Preferences;
+import com.badlogic.gdx.Input.Keys;
+import com.badlogic.gdx.assets.AssetManager;
+import com.badlogic.gdx.graphics.Color;
+import com.badlogic.gdx.graphics.g2d.TextureAtlas;
+import com.badlogic.gdx.graphics.g2d.TextureRegion;
+import com.badlogic.gdx.math.Vector3;
+import com.badlogic.gdx.scenes.scene2d.Actor;
+import com.badlogic.gdx.scenes.scene2d.InputEvent;
+import com.badlogic.gdx.scenes.scene2d.InputListener;
+import com.badlogic.gdx.scenes.scene2d.Touchable;
+import com.badlogic.gdx.scenes.scene2d.actions.Actions;
+import com.badlogic.gdx.scenes.scene2d.ui.Button;
+import com.badlogic.gdx.scenes.scene2d.ui.ButtonGroup;
+import com.badlogic.gdx.scenes.scene2d.ui.Image;
+import com.badlogic.gdx.scenes.scene2d.ui.Label;
+import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
+import com.badlogic.gdx.scenes.scene2d.ui.Skin;
+import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
+import com.badlogic.gdx.scenes.scene2d.ui.VerticalGroup;
+import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
+import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
+import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
+import com.badlogic.gdx.utils.Array;
+
+import zero1hd.rhythmbullet.desktop.Controls;
+import zero1hd.rhythmbullet.graphics.ui.Page;
+
+public class KeybindPage extends Page {
+ private ButtonGroup buttonOptions;
+ private VerticalGroup group;
+ private ScrollPane scrollPane;
+ private Skin skin;
+ TextureAtlas keyTextures;
+ private Preferences keyBindPrefs;
+ private InputListener inputListener;
+ private ChangeListener checkedListener;
+
+ public KeybindPage(AssetManager assetManager, Skin skin, ChangeListener backButtonListener) {
+ super(-1, -1);
+ setTouchable(Touchable.enabled);
+ this.skin = skin;
+ keyTextures = assetManager.get("keyboard.atlas", TextureAtlas.class);
+ this.keyBindPrefs = Gdx.app.getPreferences("PolyJet_Controls");
+ TextButton backButton = new TextButton("Back", skin);
+ backButton.setWidth(backButton.getWidth()+20f);
+ backButton.setPosition(getWidth()-backButton.getWidth()-15f, getHeight() - backButton.getHeight() - 15f);
+ backButton.addListener(backButtonListener);
+ addActor(backButton);
+
+ inputListener = new InputListener() {
+ @Override
+ public boolean keyUp(InputEvent event, int keycode) {
+ KeyChangeButton button = buttonOptions.getChecked();
+ if (button != null) {
+ if (keycode != Keys.ESCAPE) {
+ button.attemptSetKeycode(keycode);
+ }
+ getStage().setKeyboardFocus(null);
+ }
+ return super.keyUp(event, keycode);
+ }
+ };
+
+ checkedListener = new ChangeListener() {
+ @Override
+ public void changed(ChangeEvent event, Actor actor) {
+ KeyChangeButton button = (KeyChangeButton) actor;
+ if (button.isChecked()) {
+ button.ready();
+ } else {
+ button.done();
+ }
+ }
+ };
+
+ buttonOptions = new ButtonGroup<>();
+ buttonOptions.setMinCheckCount(0);
+ buttonOptions.setMaxCheckCount(1);
+ group = new VerticalGroup();
+ group.setTouchable(Touchable.childrenOnly);
+ group.space(15f);
+ Controls[] controls = Controls.values();
+ for (int i = 0; i < controls.length; i++) {
+ KeyChangeButton button = new KeyChangeButton(controls[i]);
+ buttonOptions.add(button);
+ group.addActor(button);
+ }
+ scrollPane = new ScrollPane(group);
+ scrollPane.setHeight(Math.min(getHeight(), group.getPrefHeight()));
+ scrollPane.setWidth(group.getPrefWidth());
+ scrollPane.setPosition((getWidth()-scrollPane.getWidth())/2f, (getHeight()-scrollPane.getHeight())/2f);
+ scrollPane.setTouchable(Touchable.childrenOnly);
+ addActor(scrollPane);
+ addListener(new ClickListener() {
+ @Override
+ public void clicked(InputEvent event, float x, float y) {
+ if (hit(x, y, true) == event.getListenerActor()) {
+ simpleDebug("unchecking selected key change buttons.");
+ buttonOptions.uncheckAll();
+ }
+ super.clicked(event, x, y);
+ }
+ });
+ }
+
+ @Override
+ public void setCameraPositionToPage(Vector3 cameraPosition) {
+ getStage().setScrollFocus(scrollPane);
+ super.setCameraPositionToPage(cameraPosition);
+ }
+
+ @Override
+ public void dispose() {
+ save();
+ super.dispose();
+ }
+ public void save() {
+ keyBindPrefs.flush();
+ }
+
+ public class KeyChangeButton extends Button {
+ private Image keyImage;
+ private Label nameLabel;
+ private Controls control;
+ private boolean error;
+
+ public KeyChangeButton(Controls control) {
+ super(skin, "selectable-clean-button");
+ this.control = control;
+ nameLabel = new Label(control.toString(), skin);
+ keyImage = new Image(getIcon(control.getKeycode()));
+
+ add(nameLabel).expandX().left().spaceRight(20f);
+ add(keyImage).expandX().right();
+
+ addListener(inputListener);
+ addListener(checkedListener);
+ }
+
+ public void attemptSetKeycode(int keycode) {
+ simpleDebug("Attempting to set keycode to " + keycode);
+ TextureRegion textureRegion = getIcon(keycode);
+ if (textureRegion != null) {
+ setKeycode(keycode, textureRegion);
+ error = false;
+ } else {
+ error = true;
+ }
+ setChecked(false);
+ }
+
+ public void setKeycode(int keycode, TextureRegion texture) {
+
+ Controls conflict = control.setKeycode(keycode);
+ if (conflict != null) {
+ Array buttons = buttonOptions.getButtons();
+ for (int i = 0; i < buttons.size; i++) {
+ System.out.println(buttons.get(i).getControl());
+ if (buttons.get(i).getControl() == conflict) {
+ KeyChangeButton b = buttons.get(i);
+ scrollPane.scrollTo(b.getX(), b.getY(), b.getWidth(), b.getHeight());
+ b.done(true);
+ return;
+ }
+ }
+ }
+ TextureRegion textureRegion = getIcon(keycode);
+ if (textureRegion != null) {
+ keyImage.setDrawable(new TextureRegionDrawable(texture));
+ control.saveKeyToPreferences(keyBindPrefs);
+ }
+ }
+
+ public void ready() {
+ getStage().setKeyboardFocus(this);
+ keyImage.setColor(Color.ORANGE);
+ }
+
+ public void done() {
+ done(error);
+ }
+
+ public void done(boolean error) {
+ if (error) {
+ keyImage.addAction(Actions.repeat(3, Actions.sequence(Actions.color(Color.RED, 0.2f), Actions.color(Color.WHITE, 0.1f))));
+ } else {
+ keyImage.addAction(Actions.color(Color.WHITE, 0.2f));
+ }
+ }
+
+ public Controls getControl() {
+ return control;
+ }
+ }
+
+ public TextureRegion getIcon(int keycode) {
+ switch (keycode) {
+ case Keys.ALT_LEFT:
+ case Keys.ALT_RIGHT:
+ return keyTextures.findRegion("Keyboard_Black_Alt");
+ case Keys.SHIFT_LEFT:
+ case Keys.SHIFT_RIGHT:
+ return keyTextures.findRegion("Keyboard_Black_Shift");
+ case Keys.LEFT_BRACKET:
+ return keyTextures.findRegion("Keyboard_Black_Bracket_Left");
+ case Keys.RIGHT_BRACKET:
+ return keyTextures.findRegion("Keyboard_Black_Bracket_Right");
+ case Keys.SEMICOLON:
+ return keyTextures.findRegion("Keyboard_Black_Semicolon");
+ case Keys.SLASH:
+ return keyTextures.findRegion("Keyboard_Black_Slash");
+ case Keys.NUM:
+ return keyTextures.findRegion("Keyboard_Black_Num_Lock");
+ case Keys.ESCAPE:
+ return null;
+ default:
+ return keyTextures.findRegion("Keyboard_Black_" + Keys.toString(keycode).replace(' ', '_'));
+ }
+ }
+}
diff --git a/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/MainPage.java b/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/MainPage.java
new file mode 100644
index 0000000..bafdb8f
--- /dev/null
+++ b/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/MainPage.java
@@ -0,0 +1,209 @@
+package zero1hd.rhythmbullet.desktop.screens.main;
+
+import java.util.Observable;
+import java.util.Observer;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.assets.AssetManager;
+import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.g2d.ParticleEffect;
+import com.badlogic.gdx.graphics.g2d.ParticleEffectPool;
+import com.badlogic.gdx.graphics.g2d.ParticleEffectPool.PooledEffect;
+import com.badlogic.gdx.math.Vector3;
+import com.badlogic.gdx.scenes.scene2d.Actor;
+import com.badlogic.gdx.scenes.scene2d.ui.Image;
+import com.badlogic.gdx.scenes.scene2d.ui.Label;
+import com.badlogic.gdx.scenes.scene2d.ui.Skin;
+import com.badlogic.gdx.scenes.scene2d.ui.Table;
+import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
+import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
+import com.badlogic.gdx.utils.Align;
+import com.badlogic.gdx.utils.Array;
+
+import zero1hd.rhythmbullet.RhythmBullet;
+import zero1hd.rhythmbullet.audio.MusicController;
+import zero1hd.rhythmbullet.audio.AudioMetadataController;
+import zero1hd.rhythmbullet.audio.visualizer.DoubleHorizontalVisualizer;
+import zero1hd.rhythmbullet.desktop.audio.PCMObtainer;
+import zero1hd.rhythmbullet.graphics.ui.Page;
+import zero1hd.rhythmbullet.graphics.ui.components.MusicControls;
+import zero1hd.rhythmbullet.graphics.ui.components.ScrollingText;
+import zero1hd.rhythmbullet.util.ScreenConfiguration;
+
+public class MainPage extends Page implements Observer {
+ private MusicController mc;
+ private AudioMetadataController amc;
+
+ private Label versionLabel;
+ private Image title;
+
+ private Table menuTable;
+ private TextButton playButton;
+ private TextButton optionsButton;
+ private TextButton quitButton;
+
+ private MusicControls musicControls;
+ private ScrollingText scrollText;
+
+ private DoubleHorizontalVisualizer dhv;
+
+ private boolean playParticles = true;
+ private ParticleEffectPool particlePool;
+ private Array particles;
+ private float particleScale;
+
+ public MainPage(MusicController musicController, AudioMetadataController mmc, AssetManager assetManager, Skin skin, ScreenConfiguration screenConfiguration, ChangeListener playButtonListener, ChangeListener optionsButtonListener) {
+ super(0, 0);
+ this.mc = musicController;
+ this.mc.addObserver(this);
+ mc.getMusicList().addObserver(this);
+ this.amc = mmc;
+ this.amc.addObserver(this);
+
+ dhv = new DoubleHorizontalVisualizer((int) getWidth(), (int) 0, getHeight(), 0, screenConfiguration.getTargetFramesPerSecond(), mc, new PCMObtainer(mc));
+ dhv.setPosition(0, (int) ((getHeight() - dhv.getHeight())/2f));
+
+ title = new Image(assetManager.get("title.png", Texture.class));
+ title.setScale((getHeight()/3f)/title.getHeight());
+ if (title.getWidth()*title.getScaleX() > getWidth() - getWidth()*0.075f) {
+ title.setScale((getWidth()*(1f-0.075f))/title.getWidth()*getScaleX());
+ }
+ title.setPosition((getWidth()-title.getWidth()*title.getScaleX())/2f, (getHeight()-title.getHeight()*title.getScaleY())/2f);
+ addActor(title);
+
+ versionLabel = new Label("Version: " + RhythmBullet.VERSION, skin, "sub-font", skin.getColor("default"));
+ versionLabel.setPosition(3, 3);
+ addActor(versionLabel);
+
+ menuTable = new Table();
+ menuTable.setSize(getWidth(), title.getY());
+ menuTable.align(Align.center);
+ menuTable.defaults().space(10f);
+ addActor(menuTable);
+ playButton = new TextButton("Start!", skin);
+ playButton.addListener(playButtonListener);
+ menuTable.add(playButton).width(Gdx.graphics.getWidth()*0.2f);
+
+ menuTable.row();
+
+ optionsButton = new TextButton("Options", skin, "sub");
+ optionsButton.addListener(optionsButtonListener);
+ menuTable.add(optionsButton).fillX();
+
+ menuTable.row();
+
+ quitButton = new TextButton("Quit", skin, "sub");
+ quitButton.addListener(new ChangeListener() {
+ @Override
+ public void changed(ChangeEvent event, Actor actor) {
+ Gdx.app.exit();
+ }
+ });
+ menuTable.add(quitButton).fillX();
+
+ musicControls = new MusicControls(skin, mc);
+ musicControls.setPosition((getWidth()-musicControls.getWidth() - 15f), 15f);
+ addActor(musicControls);
+
+ scrollText = new ScrollingText("...", "...", skin, false, true, 1f/screenConfiguration.getTargetFramesPerSecond());
+ scrollText.setWidth(0.5f*getWidth());
+ scrollText.setPosition(15, getHeight() - scrollText.getHeight()-30f);
+ addActor(scrollText);
+
+ if (mc.getMusicList().isSearched() && amc.isSameSizeMusicList()) {
+ scrollText.setText("Currently playing: " + amc.getAudioMetadata(mc.getCurrentMusicFileHandle()).getTitle(), null);
+ dhv.updateMusic();
+ }
+
+ particles = new Array<>();
+ ParticleEffect particle = assetManager.get("beateffect.p", ParticleEffect.class);
+ particleScale = getWidth()/particle.findEmitter("main").getSpawnWidth().getHighMax();
+ particlePool = new ParticleEffectPool(assetManager.get("beateffect.p", ParticleEffect.class), 0, 16);
+
+ }
+
+ @Override
+ public void act(float delta) {
+ dhv.act(delta);
+ super.act(delta);
+ }
+
+ @Override
+ public void draw(Batch batch, float parentAlpha) {
+ dhv.draw(batch, parentAlpha);
+ updateParticles(batch);
+ super.draw(batch, parentAlpha);
+ }
+
+ private void updateParticles(Batch batch) {
+ if (playParticles) {
+ if (particles.size < 16 && dhv.isSignificantBeat()) {
+ PooledEffect particle = particlePool.obtain();
+ particle.scaleEffect(particleScale);
+ particles.add(particle);
+ }
+ if (particles.size > 0) {
+ for (int i = particles.size - 1; i >= 0 && particles.size > 0; i--) {
+ PooledEffect particle = particles.get(i);
+ particle.draw(batch, Gdx.graphics.getDeltaTime());
+ if (particle.isComplete()) {
+ particles.removeIndex(i);
+ particle.free();
+ }
+ }
+ }
+ }
+ }
+
+ public void stopParticles() {
+ playParticles = false;
+ }
+
+ @Override
+ public void dispose() {
+ dhv.dispose();
+ mc.getMusicList().deleteObserver(this);
+ for (int i = particles.size - 1; i >= 0 && particles.size > 0; i--) {
+ particles.get(i).free();
+ particles.clear();
+ }
+ super.dispose();
+ }
+
+ @Override
+ public void setCameraPositionToPage(Vector3 cameraPosition) {
+ getStage().setScrollFocus(null);
+ playParticles = true;
+ super.setCameraPositionToPage(cameraPosition);
+ }
+
+ @Override
+ public void update(Observable o, Object arg) {
+ if (o == mc) {
+ if (arg == mc.states.LOADED) {
+ if (amc.isSameSizeMusicList()) {
+ scrollText.setText("Currently playing: " + amc.getAudioMetadata(mc.getCurrentMusicFileHandle()).getTitle(), null);
+ } else {
+ scrollText.setText("Currently playing: " + mc.getCurrentMusicFileHandle().nameWithoutExtension().replace('_', ' '), null);
+ }
+ } else if (arg == mc.states.PAUSED) {
+ if (amc.isSameSizeMusicList()) {
+ scrollText.setText("Currently paused: " + amc.getAudioMetadata(mc.getCurrentMusicFileHandle()).getTitle(), null);
+ } else {
+ scrollText.setText("Currently paused: " + mc.getCurrentMusicFileHandle().nameWithoutExtension().replace('_', ' '), null);
+ }
+ }
+ } else if (o == amc) {
+ if (amc.isSameSizeMusicList()) {
+ scrollText.setText("Currently playing: " + amc.getAudioMetadata(mc.getCurrentMusicFileHandle()).getTitle(), null);
+ }
+ } else if (o == mc.getMusicList()) {
+ if (arg == mc.getMusicList().states.EMPTY) {
+ scrollText.setText("Couldn't find MP3/WAV files", null);
+ } else if (arg == mc.getMusicList().states.LOADING) {
+ scrollText.setText("Loading...", null);
+ }
+ }
+ }
+}
diff --git a/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/MainScreen.java b/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/MainScreen.java
new file mode 100644
index 0000000..bc8270e
--- /dev/null
+++ b/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/MainScreen.java
@@ -0,0 +1,248 @@
+package zero1hd.rhythmbullet.desktop.screens.main;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.ScreenAdapter;
+import com.badlogic.gdx.graphics.GL20;
+import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.g2d.SpriteBatch;
+import com.badlogic.gdx.math.Vector3;
+import com.badlogic.gdx.scenes.scene2d.Actor;
+import com.badlogic.gdx.scenes.scene2d.Stage;
+import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
+import com.badlogic.gdx.utils.viewport.ScreenViewport;
+
+import zero1hd.rhythmbullet.RhythmBullet;
+import zero1hd.rhythmbullet.audio.AudioMetadataController;
+import zero1hd.rhythmbullet.audio.MusicList;
+import zero1hd.rhythmbullet.audio.MusicController;
+import zero1hd.rhythmbullet.desktop.audio.processor.DesktopAudioProcessorFactory;
+import zero1hd.rhythmbullet.graphics.shaders.BloomShader;
+import zero1hd.rhythmbullet.graphics.ui.Page;
+import zero1hd.rhythmbullet.util.ResizeReadyScreen;
+
+public class MainScreen extends ScreenAdapter implements ResizeReadyScreen {
+ private Stage stage;
+ private Vector3 cameraPosition;
+ private PageChangeListeners listeners;
+ private String selectedPage;
+ private MainPage mainPage;
+ private OptionsPage optionsPage;
+ private KeybindPage keybindPage;
+ private GraphicsPage graphicsPage;
+ private CreditsPage creditsPage;
+ private MusicSelectionPage musicSelectionPage;
+ private AnalysisPage analysisPage;
+
+ private MusicController musicController;
+ private AudioMetadataController musicMetadataController;
+
+ private RhythmBullet rhythmBullet;
+
+ private BloomShader bloomShader;
+
+ private Texture background;
+
+ private Batch screenBatch;
+ private boolean resizing;
+
+ public MainScreen(RhythmBullet core) {
+ this.rhythmBullet = core;
+ stage = new Stage(new ScreenViewport());
+ cameraPosition = new Vector3(stage.getCamera().position);
+
+ MusicList musicList = new MusicList(new DesktopAudioProcessorFactory(), core.getPreferences().getString("music dir"));
+ musicController = new MusicController(musicList, core.getPreferences());
+ musicController.setAutoPlay(true);
+ musicController.setShuffle(true);
+ musicMetadataController = new AudioMetadataController(musicList);
+
+ listeners = new PageChangeListeners();
+ screenBatch = new SpriteBatch();
+ }
+
+ @Override
+ public void render(float delta) {
+ Gdx.gl.glClearColor(0f, 0f, 0f, 1f);
+ Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
+
+ if (!resizing) {
+ stage.act(delta);
+ if (bloomShader != null) {
+ bloomShader.begin();
+ draw();
+ bloomShader.end(stage.getWidth(), stage.getHeight());
+ } else {
+ draw();
+ }
+ }
+ if (stage.getCamera().position.x != cameraPosition.x || stage.getCamera().position.y != cameraPosition.y) {
+ stage.getCamera().position.lerp(cameraPosition, 0.15f);
+ stage.getViewport().apply();
+ }
+ super.render(delta);
+ }
+
+ private void draw() {
+ stage.getViewport().apply();
+ screenBatch.begin();
+ screenBatch.draw(background, 0, 0, stage.getViewport().getScreenWidth(), stage.getViewport().getScreenHeight());
+ screenBatch.end();
+ stage.draw();
+ }
+
+ @Override
+ public void preAssetLoad() {
+ resizing = true;
+ stage.clear();
+ if (bloomShader != null) {
+ bloomShader.dispose();
+ bloomShader = null;
+ }
+ background = null;
+ musicController.deleteObservers();
+ musicMetadataController.deleteObservers();
+ }
+
+ @Override
+ public void postAssetLoad() {
+ resizing = false;
+ bloomShader = new BloomShader(screenBatch);
+
+ background = rhythmBullet.getAssetManager().get("backgrounds/mainBG.png", Texture.class);
+
+ mainPage = new MainPage(musicController, musicMetadataController, rhythmBullet.getAssetManager(), rhythmBullet.getSkin(), rhythmBullet.getScreenConfiguration(), listeners.musicSelectionPageButtonListener, listeners.optionsPageButtonListener);
+ stage.addActor(mainPage);
+ //End main menu
+
+ optionsPage = new OptionsPage(musicController, rhythmBullet.getSkin(), rhythmBullet.getPreferences(), listeners.returnToMainPageListener, listeners.graphicsPageButtonListener, listeners.keybindPageButtonListener);
+ stage.addActor(optionsPage);
+
+ keybindPage = new KeybindPage(rhythmBullet.getAssetManager(), rhythmBullet.getSkin(), listeners.optionsPageButtonListener);
+ stage.addActor(keybindPage);
+
+ graphicsPage = new GraphicsPage(rhythmBullet.getSkin(), rhythmBullet.getPreferences(), listeners.optionsPageButtonListener);
+ stage.addActor(graphicsPage);
+
+ creditsPage = new CreditsPage(rhythmBullet.getSkin());
+ stage.addActor(creditsPage);
+
+ musicSelectionPage = new MusicSelectionPage(rhythmBullet.getAssetManager(), rhythmBullet.getSkin(), musicController, musicMetadataController, rhythmBullet.getScreenConfiguration(), listeners.returnToMainPageListener, listeners.analysisPageButtonListener);
+ stage.addActor(musicSelectionPage);
+
+ analysisPage = new AnalysisPage(musicController, musicMetadataController, rhythmBullet.getSkin(), listeners.musicSelectionPageButtonListener, listeners.confirmedSongListener);
+ stage.addActor(analysisPage);
+
+ musicController.getMusicList().attemptAsyncSearch(false);
+
+ if (selectedPage != null) {
+ for (Actor actor : stage.getActors().items) {
+ if (actor.getName().equals(selectedPage)) {
+ setDisplayedPage((Page) actor);
+ break;
+ }
+ }
+ }
+ }
+
+ @Override
+ public void show() {
+ Gdx.input.setInputProcessor(stage);
+ super.show();
+ }
+
+ @Override
+ public void hide() {
+ saveAll();
+ super.hide();
+ }
+
+ public void saveAll() {
+ if (optionsPage != null) {
+ optionsPage.saveOptions();
+ rhythmBullet.getPreferences().flush();
+ }
+ }
+
+ @Override
+ public void resize(int width, int height) {
+ stage.getViewport().update(width, height, false);
+ super.resize(width, height);
+ }
+
+ @Override
+ public void dispose() {
+ Gdx.app.debug("Mainscreen", "disposing...");
+ stage.dispose();
+ musicMetadataController.dispose();
+ screenBatch.dispose();
+ super.dispose();
+ }
+
+ public void setDisplayedPage(Page page) {
+ Gdx.app.debug("Mainscreen", "Switching to " + page.getName());
+ page.setCameraPositionToPage(cameraPosition);
+ this.selectedPage = page.getName();
+ }
+
+ private class PageChangeListeners {
+ ChangeListener musicSelectionPageButtonListener = new ChangeListener() {
+ @Override
+ public void changed(ChangeEvent event, Actor actor) {
+ setDisplayedPage(musicSelectionPage);
+ mainPage.stopParticles();
+ }
+ };
+
+ ChangeListener analysisPageButtonListener = new ChangeListener() {
+ @Override
+ public void changed(ChangeEvent event, Actor actor) {
+ setDisplayedPage(analysisPage);
+ }
+ };
+
+ ChangeListener returnToMainPageListener = new ChangeListener() {
+ @Override
+ public void changed(ChangeEvent event, Actor actor) {
+ setDisplayedPage(mainPage);
+ }
+ };
+
+ ChangeListener optionsPageButtonListener = new ChangeListener() {
+ @Override
+ public void changed(ChangeEvent event, Actor actor) {
+ setDisplayedPage(optionsPage);
+ mainPage.stopParticles();
+ }
+ };
+
+ ChangeListener graphicsPageButtonListener = new ChangeListener() {
+ @Override
+ public void changed(ChangeEvent event, Actor actor) {
+ setDisplayedPage(graphicsPage);
+ }
+ };
+
+ ChangeListener keybindPageButtonListener = new ChangeListener() {
+ @Override
+ public void changed(ChangeEvent event, Actor actor) {
+ setDisplayedPage(keybindPage);
+ }
+ };
+
+ ChangeListener creditPageButtonListener = new ChangeListener() {
+ @Override
+ public void changed(ChangeEvent event, Actor actor) {
+ setDisplayedPage(creditsPage);
+ mainPage.stopParticles();
+ }
+ };
+
+ ChangeListener confirmedSongListener = new ChangeListener() {
+ @Override
+ public void changed(ChangeEvent event, Actor actor) {
+
+ }
+ };
+ }
+}
diff --git a/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/MusicSelectionPage.java b/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/MusicSelectionPage.java
new file mode 100644
index 0000000..198bd8b
--- /dev/null
+++ b/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/MusicSelectionPage.java
@@ -0,0 +1,585 @@
+package zero1hd.rhythmbullet.desktop.screens.main;
+
+import java.util.Observable;
+import java.util.Observer;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.Input.Keys;
+import com.badlogic.gdx.Preferences;
+import com.badlogic.gdx.assets.AssetManager;
+import com.badlogic.gdx.files.FileHandle;
+import com.badlogic.gdx.graphics.Color;
+import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.g2d.TextureRegion;
+import com.badlogic.gdx.math.Vector2;
+import com.badlogic.gdx.math.Vector3;
+import com.badlogic.gdx.scenes.scene2d.Actor;
+import com.badlogic.gdx.scenes.scene2d.InputEvent;
+import com.badlogic.gdx.scenes.scene2d.InputListener;
+import com.badlogic.gdx.scenes.scene2d.ui.Button;
+import com.badlogic.gdx.scenes.scene2d.ui.ButtonGroup;
+import com.badlogic.gdx.scenes.scene2d.ui.Image;
+import com.badlogic.gdx.scenes.scene2d.ui.Label;
+import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
+import com.badlogic.gdx.scenes.scene2d.ui.Skin;
+import com.badlogic.gdx.scenes.scene2d.ui.Table;
+import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
+import com.badlogic.gdx.scenes.scene2d.ui.VerticalGroup;
+import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
+import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
+import com.badlogic.gdx.utils.Align;
+import com.badlogic.gdx.utils.Array;
+
+import zero1hd.rhythmbullet.audio.AudioMetadataController;
+import zero1hd.rhythmbullet.audio.metadata.AudioMetadata;
+import zero1hd.rhythmbullet.audio.MusicController;
+import zero1hd.rhythmbullet.graphics.ui.Page;
+import zero1hd.rhythmbullet.graphics.ui.components.ScrollingText;
+import zero1hd.rhythmbullet.util.ScreenConfiguration;
+
+public class MusicSelectionPage extends Page implements Observer {
+ Preferences musicFileAnnotation;
+
+ private MusicController mc;
+ private AudioMetadataController mmc;
+ private MusicSelectableButtonGroup selectables;
+ private VerticalGroup vGroup;
+ private TextButton back;
+ private ScrollPane scrollPane;
+ private ScreenConfiguration screenConfig;
+
+ private musicSelectionLoaderThread selectionLoaderThread;
+
+ private InformationTable musicInfoTable;
+
+ private AssetManager assets;
+ private Skin skin;
+
+ private boolean down, up;
+
+ private boolean frameUsed;
+
+ private TextButton beginButton;
+
+ private float scrollTimer, scrollDelay = 0.2f, scrollDelMod, songSelectionTimer;
+ private float musicSelectDelay;
+
+ public MusicSelectionPage(AssetManager assetManager, Skin skin, MusicController musicController, AudioMetadataController musicMetadataController, ScreenConfiguration screenConfiguration, ChangeListener backButtonListener, ChangeListener beginButtonListener) {
+ super(1, 0);
+ this.assets = assetManager;
+ this.mc = musicController;
+ this.mmc = musicMetadataController;
+ this.skin = skin;
+ vGroup = new VerticalGroup();
+ vGroup.space(10f);
+ selectables = new MusicSelectableButtonGroup();
+ selectables.setMinCheckCount(0);
+ musicFileAnnotation = Gdx.app.getPreferences("music_file_annotation");
+ this.screenConfig = screenConfiguration;
+ scrollPane = new ScrollPane(vGroup, skin);
+ scrollPane.setSize(0.45f*getWidth(), getHeight());
+ scrollPane.setOverscroll(false, false);
+ scrollPane.setColor(Color.BLUE);
+ addActor(scrollPane);
+ back = new TextButton("Back", skin);
+ back.setWidth(back.getWidth()+20f);
+ back.setPosition(getWidth()-back.getWidth()-15f, getHeight() - back.getHeight() - 15f);
+ back.addListener(backButtonListener);
+ addActor(back);
+ back.toFront();
+
+ addListener(new InputListener() {
+ @Override
+ public boolean keyDown(InputEvent event, int keycode) {
+ scrollTimer = 0;
+ scrollDelMod = 1f;
+ if (keycode == Keys.DOWN) {
+ down = true;
+ }
+ if (keycode == Keys.UP) {
+ up = true;
+ }
+ return super.keyDown(event, keycode);
+ }
+
+ @Override
+ public boolean keyUp(InputEvent event, int keycode) {
+ if (keycode == Keys.DOWN) {
+ down = false;
+ }
+
+ if (keycode == Keys.UP) {
+ up = false;
+ }
+ return super.keyUp(event, keycode);
+ }
+ });
+
+ musicInfoTable = new InformationTable(getWidth()-scrollPane.getWidth(), getHeight());
+ addActor(musicInfoTable);
+
+ beginButton = new TextButton("Begin", skin);
+ beginButton.addListener(new ChangeListener() {
+ @Override
+ public void changed(ChangeEvent event, Actor actor) {
+ if (musicSelectDelay != 0) {
+ mc.setMusicByFileHandle(getSelectedMusic());
+ musicSelectDelay = 0f;
+ }
+ }
+ });
+ beginButton.addListener(beginButtonListener);
+ mmc.addObserver(this);
+ mc.addObserver(this);
+ mc.getMusicList().addObserver(this);
+ selectionLoaderThread = new musicSelectionLoaderThread();
+
+ musicInfoTable.setToDefault();
+ }
+
+ @Override
+ public void act(float delta) {
+
+ if (frameUsed) {
+ frameUsed = false;
+ }
+
+ if (down) {
+ if (scrollDelMod > 0.25f) {
+ scrollDelMod -= delta/0.5f;
+ }
+ if (scrollTimer <= 0) {
+ scrollTimer = scrollDelay*scrollDelMod;
+ scrollDown();
+
+ } else {
+ scrollTimer -= delta;
+ }
+ }
+
+ if (up) {
+ if (scrollDelMod > 0.25f) {
+ scrollDelMod -= delta/0.5f;
+ }
+ if (scrollTimer <= 0) {
+ scrollTimer = scrollDelay*scrollDelMod;
+ scrollUp();
+ } else {
+ scrollTimer -= delta;
+ }
+ }
+
+ if (songSelectionTimer > 0f) {
+ songSelectionTimer -= delta;
+ if (songSelectionTimer <= 0f) {
+ }
+ }
+ if (mc.getMusicList().isSearched()) {
+ if (mc.getMusicList().getTotal() != 0) {
+
+ }
+ }
+
+ updateList(delta);
+
+ super.act(delta);
+ }
+
+ private synchronized void updateList(float delta) {
+ if (mc.getMusicList().isSearched()) {
+ if (mc.getMusicList().getTotal() != 0) {
+ if (mmc.isSameSizeMusicList() && !mmc.isSearching()) {
+ if (selectables.size() != mmc.size()) {
+ MusicSelectable selectable = new MusicSelectable(mmc.getAudioMetadata(selectables.size()));
+ selectables.add(selectable);
+ } else if (selectables.size() != vGroup.getChildren().size) {
+ vGroup.addActor(selectables.getButtons().get(vGroup.getChildren().size));
+ } else {
+ if (selectables.getChecked() == null) {
+ selectables.setMinCheckCount(1);
+ selectables.setChecked(mc.getCurrentMusicFileHandle());
+ scrollPane.scrollTo(selectables.getChecked().getX(), selectables.getChecked().getY(), selectables.getChecked().getWidth(), selectables.getChecked().getHeight());
+ } else if (selectables.getChecked().getMetadata().getFileHandle() != mc.getCurrentMusicFileHandle()) {
+ musicSelectDelay += delta;
+ if (musicSelectDelay >= 1f) {
+ mc.setMusicByFileHandle(selectables.getChecked().getMetadata().getFileHandle());
+ musicSelectDelay = 0;
+ }
+ }
+ }
+ }
+
+ } else {
+ //TODO: Error message reporting empty music list or something
+ }
+ }
+ }
+
+ private void scrollDown() {
+ if (selectables.selectNext()) {
+ scrollPane.scrollTo(selectables.getChecked().getX(), selectables.getChecked().getY(), selectables.getChecked().getWidth(), selectables.getChecked().getHeight());
+ }
+ }
+
+ private void scrollUp() {
+ if (selectables.selectPrevious()) {
+ scrollPane.scrollTo(selectables.getChecked().getX(), selectables.getChecked().getY(), selectables.getChecked().getWidth(), selectables.getChecked().getHeight());
+ }
+ }
+
+ public FileHandle getSelectedMusic() {
+ return selectables.getChecked().getMetadata().getFileHandle();
+ }
+
+ @Override
+ public void dispose() {
+ mc.getMusicList().deleteObserver(this);
+ selectionLoaderThread.stop();
+ super.dispose();
+ }
+
+ @Override
+ public void update(Observable o, Object arg) {
+ if (o == mmc) {
+ selectionLoaderThread.start();
+ } else if (o == mc) {
+ if (selectables.getChecked() != null && mc.getMusicList().getTotal() == selectables.size() && mc.getCurrentMusicFileHandle() != selectables.getChecked().getMetadata().getFileHandle()) {
+ selectables.setChecked(mc.getCurrentMusicFileHandle());
+ }
+ } else if (o == mc.getMusicList()) {
+ if (arg == mc.getMusicList().states.LOADING) {
+ synchronized (this) {
+ vGroup.clear();
+ selectables.clear();
+ musicInfoTable.setToDefault();
+ selectionLoaderThread.clear();
+ }
+ }
+
+ }
+ }
+
+ @Override
+ public void setCameraPositionToPage(Vector3 cameraPosition) {
+ getStage().setKeyboardFocus(this);
+ getStage().setScrollFocus(scrollPane);
+ super.setCameraPositionToPage(cameraPosition);
+ }
+
+ private class musicSelectionLoaderThread implements Runnable {
+ private Thread thread;
+ private String name = "Music-Selection-Loader-Thread";
+ private volatile boolean work = true;
+ private LinkedBlockingQueue queue;
+ public musicSelectionLoaderThread() {
+ queue = new LinkedBlockingQueue<>();
+ }
+
+ @Override
+ public void run() {
+ while (work) {
+ try {
+ MusicSelectable selectable = queue.take();
+ if (!selectable.isOffScreen()) {
+ selectable.getMetadata().loadAlbumCover();
+ selectable.loadAttempted();
+ simpleDebug("Loaded album cover of " + selectable.getMetadata().getTitle());
+ } else {
+ simpleDebug("Skipping " + selectable.getMetadata().getTitle());
+ }
+ } catch (InterruptedException e) {
+ simpleDebug("Thread was interupted.");
+ }
+ }
+ }
+
+ public boolean start() {
+ if (thread == null) {
+ thread = new Thread(this, name);
+ thread.setDaemon(true);
+ thread.start();
+ return true;
+ }
+ return false;
+ }
+
+ public void stop() {
+ clear();
+ if (thread != null) {
+ thread.interrupt();
+ }
+ work = false;
+ }
+
+ public void clear() {
+ queue.clear();
+ }
+
+ public void queue(MusicSelectable selectable) {
+ queue.add(selectable);
+ }
+
+ }
+
+ private class MusicSelectable extends Button {
+ private Vector2 actualCoords;
+ private Image albumCoverImage;
+ private Table informationTable;
+ private Label name, artist;
+ private Label time;
+ private float timeSinceChanged;
+ private AudioMetadata metadata;
+ private Texture defaultAlbumArt;
+ private TextureRegion albumArtTexture;
+ private volatile boolean offScreen, albumArtDisplayed, albumArtQueued, noReset;
+
+ public MusicSelectable(AudioMetadata metadata) {
+ super(skin, "selectable-button");
+
+ this.metadata = metadata;
+ this.defaultAlbumArt = assets.get("defaultCover.png");
+ albumArtTexture = new TextureRegion(defaultAlbumArt);
+
+ albumCoverImage = new Image();
+ updateAlbumArtImage(defaultAlbumArt);
+
+ informationTable = new Table();
+ informationTable.row().width(0.75f*getWidth());
+ name = new Label(metadata.getTitle(), skin, "default-font", skin.getColor("default"));
+ name.setEllipsis(true);
+ informationTable.add(name).colspan(2).left().expand();
+ informationTable.row();
+ artist = new Label(metadata.getAuthor(), skin, "sub-font", skin.getColor("default"));
+ artist.setEllipsis(true);
+ informationTable.add(artist).left().width(getWidth()*0.375f);
+ time = new Label(metadata.getDuration(), skin, "sub-font", skin.getColor("default"));
+ informationTable.add(time).right();
+ add(informationTable).spaceRight(15f).padLeft(15f);
+
+ add(albumCoverImage).right().expandX().size(informationTable.getMinHeight());
+
+ albumCoverImage.setSize(100, 100);
+ actualCoords = new Vector2();
+ }
+
+ @Override
+ public void act(float delta) {
+ actualCoords.x = getX() + getParent().getX();
+ actualCoords.y = getY() + getParent().getY();
+
+ if ((actualCoords.y < 0 - getHeight() - getStage().getHeight()*0.5f || actualCoords.y > getStage().getHeight()*1.5f) && selectables.getChecked() != this) {
+ offScreenAct(delta);
+ } else {
+ onScreenAct(delta);
+ }
+ super.act(delta);
+ }
+
+ @Override
+ public void draw(Batch batch, float parentAlpha) {
+ super.draw(batch, parentAlpha);
+ }
+
+ public void onScreenAct(float delta) {
+ if (offScreen) {
+ offScreen = false;
+ timeSinceChanged = 0;
+ } else if (timeSinceChanged < 0.05f) {
+ timeSinceChanged += delta;
+ } else {
+ if (!frameUsed && metadata.getAlbumCover() != null && !albumArtDisplayed) {
+ updateAlbumArtImage(metadata.getAlbumCover());
+ albumArtDisplayed = true;
+ frameUsed = true;
+ } else if (!albumArtQueued) {
+ selectionLoaderThread.queue(this);
+ albumArtQueued = true;
+ }
+ }
+ }
+
+ private void updateAlbumArtImage(Texture texture) {
+ if (texture == null) throw new IllegalArgumentException("Texture can't be null!");
+ albumArtTexture.setRegion(texture);
+ albumCoverImage.setDrawable(new TextureRegionDrawable(albumArtTexture));
+ }
+
+ public void offScreenAct(float delta) {
+ if (!offScreen) {
+ offScreen = true;
+ timeSinceChanged = 0;
+ }
+ if (metadata.getAlbumCover() != null) {
+ timeSinceChanged += delta;
+ if (timeSinceChanged >= 2) {
+ updateAlbumArtImage(defaultAlbumArt);
+ metadata.unloadAlbumCover();
+ albumArtDisplayed = false;
+ albumArtQueued = false;
+ noReset = false;
+ }
+ }
+ }
+
+ public AudioMetadata getMetadata() {
+ return metadata;
+ }
+
+ public FileHandle getFileHandle() {
+ return metadata.getFileHandle();
+ }
+
+ @Override
+ public float getPrefWidth() {
+ return scrollPane.getScrollWidth();
+ }
+
+ @Override
+ public float getPrefHeight() {
+ return super.getPrefHeight();
+ }
+
+ public TextureRegion getAlbumArtTexture() {
+ return albumArtTexture;
+ }
+
+ public boolean isOffScreen() {
+ if (offScreen && !noReset) {
+ albumArtDisplayed = false;
+ albumArtQueued = false;
+ }
+ return offScreen;
+ }
+
+ public void loadAttempted() {
+ noReset = true;
+ }
+ }
+
+ private class MusicSelectableButtonGroup extends ButtonGroup {
+ private Array buttons;
+
+ public MusicSelectableButtonGroup() {
+ buttons = getButtons();
+ }
+
+ public void setChecked(FileHandle fileHandle) {
+ if (fileHandle == null) throw new IllegalArgumentException("fileHandle can't be null.");
+ MusicSelectable button;
+ for (int i = 0; i < buttons.size; i++) {
+ button = buttons.get(i);
+ if (button.getFileHandle() == fileHandle) {
+ button.setChecked(true);
+ return;
+ }
+ }
+
+ }
+
+ public boolean selectNext() {
+ int index = getCheckedIndex() + 1;
+ if (index == buttons.size) {
+ return false;
+ }
+ buttons.get(index).setChecked(true);
+ return true;
+ }
+
+ public boolean selectPrevious() {
+ int index = getCheckedIndex() - 1;
+ if (index == -1) {
+ return false;
+ }
+ buttons.get(index).setChecked(true);
+ return true;
+ }
+
+ @Override
+ protected boolean canCheck(MusicSelectable button, boolean newState) {
+ if (newState) {
+ musicInfoTable.setDisplayedSelectable(button);
+ musicSelectDelay = 0f;
+ }
+ return super.canCheck(button, newState);
+ }
+
+ public int size() {
+ return buttons.size;
+ }
+ }
+
+ private class InformationTable extends Table {
+ private ScrollingText songTitle;
+ private Label author;
+ private Label musicDuration;
+ private Label previousTop;
+ private Label ratedDifficulty;
+ private Image albumCover;
+
+ private Table subInformation;
+
+ public InformationTable(float width, float height) {
+ defaults().center();
+ setPosition(scrollPane.getWidth() + scrollPane.getX(), 0);
+ setSize(width, height);
+ subInformation = new Table(skin);
+ albumCover = new Image(assets.get("defaultCover.png", Texture.class));
+ songTitle = new ScrollingText("", null, skin, true, true, 1f/screenConfig.getTargetFramesPerSecond());
+ author = new Label(null, skin, "sub-font", skin.getColor("default"));
+ musicDuration = new Label(null, skin, "sub-font", skin.getColor("default"));
+ previousTop = new Label(null, skin, "sub-font", skin.getColor("default"));
+ ratedDifficulty = new Label(null, skin, "sub-font", skin.getColor("default"));
+ }
+
+ public void setDisplayedSelectable(MusicSelectable displayedSelectable) {
+ if (displayedSelectable != null) {
+ AudioMetadata metadata = displayedSelectable.getMetadata();
+ albumCover.setDrawable(new TextureRegionDrawable(displayedSelectable.getAlbumArtTexture()));
+ songTitle.setText(metadata.getTitle(), null);
+ author.setText(metadata.getAuthor());
+ musicDuration.setText(metadata.getDuration());
+ //TODO previous top
+ //TODO rated difficulty
+ beginButton.setDisabled(false);
+ } else {
+ albumCover.setDrawable(new TextureRegionDrawable(new TextureRegion(assets.get("defaultCover.png", Texture.class))));
+ songTitle.setText("loading...", null);
+ author.setText("...");
+ musicDuration.setText("...");
+ previousTop.setText("...");
+ ratedDifficulty.setText("...");
+ }
+ }
+
+ public void setToDefault() {
+ clear();
+ subInformation.clear();
+
+ albumCover.setDrawable(new TextureRegionDrawable(new TextureRegion(assets.get("defaultCover.png", Texture.class))));
+ add(albumCover).size(getWidth()/2f).spaceBottom(25f);
+ row();
+ songTitle.setText("...", null);
+ add(songTitle).width(getWidth()*0.6f).spaceBottom(30f);
+ row();
+ author.setText("...");
+ author.setEllipsis(true);
+ author.setAlignment(Align.center);
+ subInformation.add(author).expand();
+ subInformation.row();
+ musicDuration.setText("...");
+ subInformation.add(musicDuration);
+ subInformation.row();
+ previousTop.setText("...");
+ subInformation.add(previousTop);
+ subInformation.row();
+ ratedDifficulty.setText("...");
+ subInformation.add(ratedDifficulty);
+ add(subInformation).width(0.4f*getWidth());
+ row();
+ add(beginButton).spaceTop(20f).fillX();
+ beginButton.setDisabled(true);
+ }
+ }
+}
diff --git a/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/OptionsPage.java b/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/OptionsPage.java
new file mode 100644
index 0000000..9fdf0dc
--- /dev/null
+++ b/old/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/OptionsPage.java
@@ -0,0 +1,163 @@
+package zero1hd.rhythmbullet.desktop.screens.main;
+
+import java.text.NumberFormat;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.Preferences;
+import com.badlogic.gdx.scenes.scene2d.Actor;
+import com.badlogic.gdx.scenes.scene2d.ui.Label;
+import com.badlogic.gdx.scenes.scene2d.ui.ProgressBar;
+import com.badlogic.gdx.scenes.scene2d.ui.Skin;
+import com.badlogic.gdx.scenes.scene2d.ui.Slider;
+import com.badlogic.gdx.scenes.scene2d.ui.Table;
+import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
+import com.badlogic.gdx.scenes.scene2d.ui.TextField;
+import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
+
+import zero1hd.rhythmbullet.audio.MusicController;
+import zero1hd.rhythmbullet.graphics.ui.Page;
+
+public class OptionsPage extends Page {
+ Table optionsTable;
+ private ProgressBar musicVolSlider;
+ private ProgressBar fxVolSlider;
+ private TextField directoryField;
+ private float musicSearchTimer;
+ private Preferences prefs;
+ private NumberFormat percentFormat;
+
+ public OptionsPage(MusicController musicController, Skin skin, Preferences preferences, ChangeListener backButtonListener, ChangeListener graphicsButtonListener, ChangeListener controlsButtonListener) {
+ super(-1, 0, "General", skin);
+ this.prefs = preferences;
+ percentFormat = NumberFormat.getPercentInstance();
+ percentFormat.setMaximumFractionDigits(1);
+
+ //Back button
+ TextButton backButton = new TextButton("Back", skin);
+ backButton.addListener(backButtonListener);
+ backButton.setWidth(backButton.getWidth() + 20);
+ backButton.setPosition(getWidth() - backButton.getWidth() - 10, getHeightBelowTitle() + 5);
+ addActor(backButton);
+
+ optionsTable = new Table();
+ optionsTable.defaults().space(10f);
+
+ addActor(optionsTable);
+
+ Label musicVolSliderLabel = new Label("Music Volume: ", skin);
+ optionsTable.add(musicVolSliderLabel);
+ musicVolSlider = new Slider(0, 100, 1f, false, skin);
+ musicVolSlider.setValue(preferences.getFloat("music vol", 100f));
+ optionsTable.add(musicVolSlider).minWidth(0.3f*getWidth());
+ final Label musicVolPercentage = new Label(percentFormat.format(musicVolSlider.getPercent()), skin);
+ musicVolSlider.addListener(new ChangeListener() {
+ @Override
+ public void changed(ChangeEvent event, Actor actor) {
+ musicVolPercentage.setText(percentFormat.format(musicVolSlider.getPercent()));
+ musicController.getCurrentMusic().setVolume(musicVolSlider.getPercent());
+ preferences.putFloat("music vol", musicVolSlider.getValue());
+ }
+ });
+ optionsTable.add(musicVolPercentage).expandX().left();
+
+ optionsTable.row();
+
+ Label fxVolSliderLabel = new Label("FX Volume: ", skin);
+ optionsTable.add(fxVolSliderLabel);
+ fxVolSlider = new Slider(0, 100, 1f, false, skin);
+ fxVolSlider.setValue(preferences.getFloat("fx vol", 100f));
+ optionsTable.add(fxVolSlider).fillX();
+ final Label fxVolPercentage = new Label(percentFormat.format(fxVolSlider.getPercent()), skin);
+ fxVolSlider.addListener(new ChangeListener() {
+ @Override
+ public void changed(ChangeEvent event, Actor actor) {
+ fxVolPercentage.setText(percentFormat.format(fxVolSlider.getPercent()));
+ preferences.putFloat("fx vol", fxVolSlider.getValue());
+ }
+ });
+
+ optionsTable.add(fxVolPercentage).left();
+
+ optionsTable.row();
+
+ Label musicDirectoryLabel = new Label("Music Directory: ", skin);
+ optionsTable.add(musicDirectoryLabel);
+ directoryField = new TextField(null, skin ) {
+ @Override
+ public void act(float delta) {
+ if (musicSearchTimer > 0) {
+ musicSearchTimer -= delta;
+ if (musicSearchTimer <= 0) {
+ musicController.getMusicList().setSearchPath(directoryField.getText());
+ musicController.getMusicList().attemptAsyncSearch(false);
+ }
+ }
+ super.act(delta);
+ }
+ };
+ directoryField.setText(preferences.getString("music dir", System.getProperty("user.home")+System.getProperty("file.separator")+"Music"));
+ directoryField.addListener(new ChangeListener() {
+ @Override
+ public void changed(ChangeEvent event, Actor actor) {
+ musicSearchTimer = 2;
+ }
+ });
+ optionsTable.add(directoryField).fillX();
+
+ optionsTable.row();
+
+ TextButton keybindSettings = new TextButton("Set Controls", skin);
+ keybindSettings.addListener(controlsButtonListener);
+ optionsTable.add(keybindSettings).colspan(2).fillX();
+
+ optionsTable.row();
+
+ TextButton graphicsSettings = new TextButton("Graphics", skin);
+ graphicsSettings.addListener(graphicsButtonListener);
+ optionsTable.add(graphicsSettings).colspan(2).fillX();
+
+ optionsTable.row();
+
+ Label fpsLabel = new Label("", skin) {
+ @Override
+ public void act(float delta) {
+ setText("Current FPS: " + Gdx.graphics.getFramesPerSecond());
+ super.act(delta);
+ }
+ };
+ optionsTable.add(fpsLabel).colspan(2);
+
+ optionsTable.row();
+
+ Label usageLabel = new Label("Current Usage (JVM): ", skin) {
+ float refreshTime = 20;
+ @Override
+ public void act(float delta) {
+ refreshTime -= delta;
+ if (refreshTime <= 0) {
+ refreshTime = 4;
+ String formatted = percentFormat.format(((float)(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())/(float)Runtime.getRuntime().totalMemory()));
+ setText("Current usage (JVM): " + formatted);
+ }
+ super.act(delta);
+ }
+ };
+
+ optionsTable.add(usageLabel).colspan(2);
+
+ optionsTable.pack();
+ optionsTable.setX((getWidth()-optionsTable.getWidth())/2f);
+ optionsTable.setSize(getWidth() - optionsTable.getX(), backButton.getY());
+ }
+
+ public void saveOptions() {
+ prefs.putString("music dir", directoryField.getText());
+ Gdx.app.debug("Preferences", "Saved all basic options page values.");
+ }
+
+ @Override
+ public void dispose() {
+ saveOptions();
+ super.dispose();
+ }
+}
diff --git a/old/gradle.properties b/old/gradle.properties
new file mode 100644
index 0000000..ff329ac
--- /dev/null
+++ b/old/gradle.properties
@@ -0,0 +1,3 @@
+org.gradle.daemon=true
+org.gradle.jvmargs=-Xms128m -Xmx1500m
+org.gradle.configureondemand=false
diff --git a/old/gradle/wrapper/gradle-wrapper.jar b/old/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..bafc550
Binary files /dev/null and b/old/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/old/gradle/wrapper/gradle-wrapper.properties b/old/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..9f7b58b
--- /dev/null
+++ b/old/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Fri Jun 09 23:06:52 EDT 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-bin.zip
diff --git a/old/gradlew b/old/gradlew
new file mode 100644
index 0000000..4453cce
--- /dev/null
+++ b/old/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save ( ) {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/old/gradlew.bat b/old/gradlew.bat
new file mode 100644
index 0000000..f955316
--- /dev/null
+++ b/old/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/old/settings.gradle b/old/settings.gradle
new file mode 100644
index 0000000..77ae463
--- /dev/null
+++ b/old/settings.gradle
@@ -0,0 +1 @@
+include 'desktop', 'android', 'core'
\ No newline at end of file