diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..a8ef0bd
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,9 @@
+{
+ "tabWidth": 2,
+ "useTabs": false,
+ "arrowParens": "always",
+ "singleQuote": true,
+ "semi": true,
+ "trailingComma": "all",
+ "bracketSpacing": true
+}
diff --git a/.todo b/.todo
index 8e9ab6e..675c30f 100644
--- a/.todo
+++ b/.todo
@@ -1,39 +1,43 @@
Setup:
✔ make game canvas @done(22-01-28 20:23)
✔ add a block to canvas movable with keyboard @done(22-01-28 20:53)
- ☐ create basic socket.io server
- ☐ connect players to the server
- ☐ draw other players on canvas
- ☐ update player position on canvas
+ ✔ create basic socket.io server @done(22-01-28 22:43)
+ ✔ connect players to the server @done(22-01-29 00:51)
+ ✔ draw other players on canvas @done(22-01-29 00:51)
+ ✔ update player position on canvas @done(22-01-29 00:51)
Game:
- ☐ add physics for player to fall down
- ☐ add interaction with blocks (and ground)
- ☐ implement jump
- ☐ add plyer collision?
+ ✔ add physics for player to fall down @done(22-01-29 02:02)
+ ✔ add interaction with blocks (and ground) @done(22-01-29 11:17)
+ ✔ implement jump @done(22-01-29 02:02)
+ ✘ add plyer collision? @cancelled(22-01-29 11:18)
☐ allow player to enter a name before starting the game
☐ show players names above their heads
- ☐ restrict some words and name length
+ ☐ add name length limit
Server:
- ☐ do the same calculations for game logic (maybe use the same code base)
+ ✘ do the same calculations for game logic (maybe use the same code base) @cancelled(22-01-29 11:18)
☐ set player name
- ☐ IMPLEMENT BANNING PEOPLE
+ ✘ IMPLEMENT BANNING PEOPLE @cancelled(22-01-29 11:18)
Win condition?:
☐ reach some specific height? (premade map)
☐ when time runs out player at the highest point wins? (randomy generated map)
last one standing:
- ☐ player that is too far back from leading one looses?
+ ✘ player that is too far back from leading one looses? @cancelled(22-01-29 11:19)
☐ last player after specific time is eliminated?
Game art:
- ☐ randomly generated from assets?
- ☐ choosing one of preset characters?
- ☐ character builder?
+ ✘ randomly generated from assets? @cancelled(22-01-29 11:19)
+ ✘ choosing one of preset characters? @cancelled(22-01-29 11:19)
+ ✘ character builder? @cancelled(22-01-29 11:19)
misc:
- ☐ user accounts to track their score and save their chacaters?
- ☐ game ratio 9x16?
- ☐ game ratio 16x9?
\ No newline at end of file
+ ✘ user accounts to track their score and save their chacaters? @cancelled(22-01-29 11:18)
+ ✔ game ratio 9x16? @done(22-01-29 11:17)
+ ✘ game ratio 16x9? @cancelled(22-01-29 11:17)
+
+
+ideas:
+ ✘ block fall off platform if they are 1/3 off it @cancelled(22-01-29 11:18)
diff --git a/android/.gitignore b/android/.gitignore
new file mode 100644
index 0000000..63c86fe
--- /dev/null
+++ b/android/.gitignore
@@ -0,0 +1,96 @@
+# Using Android gitignore template: https://github.com/github/gitignore/blob/HEAD/Android.gitignore
+
+# Built application files
+*.apk
+*.aar
+*.ap_
+*.aab
+
+# Files for the ART/Dalvik VM
+*.dex
+
+# Java class files
+*.class
+
+# Generated files
+bin/
+gen/
+out/
+# Uncomment the following line in case you need and you don't have the release build type files in your app
+# release/
+
+# Gradle files
+.gradle/
+build/
+
+# Local configuration file (sdk path, etc)
+local.properties
+
+# Proguard folder generated by Eclipse
+proguard/
+
+# Log Files
+*.log
+
+# Android Studio Navigation editor temp files
+.navigation/
+
+# Android Studio captures folder
+captures/
+
+# IntelliJ
+*.iml
+.idea/workspace.xml
+.idea/tasks.xml
+.idea/gradle.xml
+.idea/assetWizardSettings.xml
+.idea/dictionaries
+.idea/libraries
+# Android Studio 3 in .gitignore file.
+.idea/caches
+.idea/modules.xml
+# Comment next line if keeping position of elements in Navigation Editor is relevant for you
+.idea/navEditor.xml
+
+# Keystore files
+# Uncomment the following lines if you do not want to check your keystore files in.
+#*.jks
+#*.keystore
+
+# External native build folder generated in Android Studio 2.2 and later
+.externalNativeBuild
+.cxx/
+
+# Google Services (e.g. APIs or Firebase)
+# google-services.json
+
+# Freeline
+freeline.py
+freeline/
+freeline_project_description.json
+
+# fastlane
+fastlane/report.xml
+fastlane/Preview.html
+fastlane/screenshots
+fastlane/test_output
+fastlane/readme.md
+
+# Version control
+vcs.xml
+
+# lint
+lint/intermediates/
+lint/generated/
+lint/outputs/
+lint/tmp/
+# lint/reports/
+
+# Android Profiling
+*.hprof
+
+# Cordova plugins for Capacitor
+capacitor-cordova-android-plugins
+
+# Copied web assets
+app/src/main/assets/public
diff --git a/android/.idea/.gitignore b/android/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/android/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/android/.idea/compiler.xml b/android/.idea/compiler.xml
new file mode 100644
index 0000000..fb7f4a8
--- /dev/null
+++ b/android/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/.idea/jarRepositories.xml b/android/.idea/jarRepositories.xml
new file mode 100644
index 0000000..e34606c
--- /dev/null
+++ b/android/.idea/jarRepositories.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/.idea/misc.xml b/android/.idea/misc.xml
new file mode 100644
index 0000000..2a4d5b5
--- /dev/null
+++ b/android/.idea/misc.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/app/.gitignore b/android/app/.gitignore
new file mode 100644
index 0000000..043df80
--- /dev/null
+++ b/android/app/.gitignore
@@ -0,0 +1,2 @@
+/build/*
+!/build/.npmkeep
diff --git a/android/app/build.gradle b/android/app/build.gradle
new file mode 100644
index 0000000..ced7d59
--- /dev/null
+++ b/android/app/build.gradle
@@ -0,0 +1,51 @@
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion rootProject.ext.compileSdkVersion
+ defaultConfig {
+ applicationId "lt.rdarius.kawaiijumper"
+ minSdkVersion rootProject.ext.minSdkVersion
+ targetSdkVersion rootProject.ext.targetSdkVersion
+ versionCode 1
+ versionName "1.0"
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ aaptOptions {
+ // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
+ // Default: https://android.googlesource.com/platform/frameworks/base/+/282e181b58cf72b6ca770dc7ca5f91f135444502/tools/aapt/AaptAssets.cpp#61
+ ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~'
+ }
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+repositories {
+ flatDir{
+ dirs '../capacitor-cordova-android-plugins/src/main/libs', 'libs'
+ }
+}
+
+dependencies {
+ implementation fileTree(include: ['*.jar'], dir: 'libs')
+ implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
+ implementation project(':capacitor-android')
+ testImplementation "junit:junit:$junitVersion"
+ androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
+ androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
+ implementation project(':capacitor-cordova-android-plugins')
+}
+
+apply from: 'capacitor.build.gradle'
+
+try {
+ def servicesJSON = file('google-services.json')
+ if (servicesJSON.text) {
+ apply plugin: 'com.google.gms.google-services'
+ }
+} catch(Exception e) {
+ logger.info("google-services.json not found, google-services plugin not applied. Push Notifications won't work")
+}
diff --git a/android/app/capacitor.build.gradle b/android/app/capacitor.build.gradle
new file mode 100644
index 0000000..8c6c4e9
--- /dev/null
+++ b/android/app/capacitor.build.gradle
@@ -0,0 +1,22 @@
+// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN
+
+android {
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+}
+
+apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
+dependencies {
+ implementation project(':capacitor-app')
+ implementation project(':capacitor-haptics')
+ implementation project(':capacitor-keyboard')
+ implementation project(':capacitor-status-bar')
+
+}
+
+
+if (hasProperty('postBuildExtras')) {
+ postBuildExtras()
+}
diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro
new file mode 100644
index 0000000..f1b4245
--- /dev/null
+++ b/android/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# 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 *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java b/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java
new file mode 100644
index 0000000..f2c2217
--- /dev/null
+++ b/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java
@@ -0,0 +1,26 @@
+package com.getcapacitor.myapp;
+
+import static org.junit.Assert.*;
+
+import android.content.Context;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see Testing documentation
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+
+ @Test
+ public void useAppContext() throws Exception {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+
+ assertEquals("com.getcapacitor.app", appContext.getPackageName());
+ }
+}
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..e6b2c70
--- /dev/null
+++ b/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/app/src/main/assets/capacitor.config.json b/android/app/src/main/assets/capacitor.config.json
new file mode 100644
index 0000000..a2f50fa
--- /dev/null
+++ b/android/app/src/main/assets/capacitor.config.json
@@ -0,0 +1,6 @@
+{
+ "appId": "io.ionic.starter",
+ "appName": "Kawaii-Jumper",
+ "webDir": "www",
+ "bundledWebRuntime": false
+}
diff --git a/android/app/src/main/assets/capacitor.plugins.json b/android/app/src/main/assets/capacitor.plugins.json
new file mode 100644
index 0000000..101dda7
--- /dev/null
+++ b/android/app/src/main/assets/capacitor.plugins.json
@@ -0,0 +1,18 @@
+[
+ {
+ "pkg": "@capacitor/app",
+ "classpath": "com.capacitorjs.plugins.app.AppPlugin"
+ },
+ {
+ "pkg": "@capacitor/haptics",
+ "classpath": "com.capacitorjs.plugins.haptics.HapticsPlugin"
+ },
+ {
+ "pkg": "@capacitor/keyboard",
+ "classpath": "com.capacitorjs.plugins.keyboard.KeyboardPlugin"
+ },
+ {
+ "pkg": "@capacitor/status-bar",
+ "classpath": "com.capacitorjs.plugins.statusbar.StatusBarPlugin"
+ }
+]
diff --git a/android/app/src/main/java/lt/rdarius/kawaiijumper/MainActivity.java b/android/app/src/main/java/lt/rdarius/kawaiijumper/MainActivity.java
new file mode 100644
index 0000000..e813f5a
--- /dev/null
+++ b/android/app/src/main/java/lt/rdarius/kawaiijumper/MainActivity.java
@@ -0,0 +1,5 @@
+package lt.rdarius.kawaiijumper;
+
+import com.getcapacitor.BridgeActivity;
+
+public class MainActivity extends BridgeActivity {}
diff --git a/android/app/src/main/res/drawable-land-hdpi/splash.png b/android/app/src/main/res/drawable-land-hdpi/splash.png
new file mode 100644
index 0000000..e31573b
Binary files /dev/null and b/android/app/src/main/res/drawable-land-hdpi/splash.png differ
diff --git a/android/app/src/main/res/drawable-land-mdpi/splash.png b/android/app/src/main/res/drawable-land-mdpi/splash.png
new file mode 100644
index 0000000..f7a6492
Binary files /dev/null and b/android/app/src/main/res/drawable-land-mdpi/splash.png differ
diff --git a/android/app/src/main/res/drawable-land-xhdpi/splash.png b/android/app/src/main/res/drawable-land-xhdpi/splash.png
new file mode 100644
index 0000000..8077255
Binary files /dev/null and b/android/app/src/main/res/drawable-land-xhdpi/splash.png differ
diff --git a/android/app/src/main/res/drawable-land-xxhdpi/splash.png b/android/app/src/main/res/drawable-land-xxhdpi/splash.png
new file mode 100644
index 0000000..14c6c8f
Binary files /dev/null and b/android/app/src/main/res/drawable-land-xxhdpi/splash.png differ
diff --git a/android/app/src/main/res/drawable-land-xxxhdpi/splash.png b/android/app/src/main/res/drawable-land-xxxhdpi/splash.png
new file mode 100644
index 0000000..244ca25
Binary files /dev/null and b/android/app/src/main/res/drawable-land-xxxhdpi/splash.png differ
diff --git a/android/app/src/main/res/drawable-port-hdpi/splash.png b/android/app/src/main/res/drawable-port-hdpi/splash.png
new file mode 100644
index 0000000..74faaa5
Binary files /dev/null and b/android/app/src/main/res/drawable-port-hdpi/splash.png differ
diff --git a/android/app/src/main/res/drawable-port-mdpi/splash.png b/android/app/src/main/res/drawable-port-mdpi/splash.png
new file mode 100644
index 0000000..e944f4a
Binary files /dev/null and b/android/app/src/main/res/drawable-port-mdpi/splash.png differ
diff --git a/android/app/src/main/res/drawable-port-xhdpi/splash.png b/android/app/src/main/res/drawable-port-xhdpi/splash.png
new file mode 100644
index 0000000..564a82f
Binary files /dev/null and b/android/app/src/main/res/drawable-port-xhdpi/splash.png differ
diff --git a/android/app/src/main/res/drawable-port-xxhdpi/splash.png b/android/app/src/main/res/drawable-port-xxhdpi/splash.png
new file mode 100644
index 0000000..bfabe68
Binary files /dev/null and b/android/app/src/main/res/drawable-port-xxhdpi/splash.png differ
diff --git a/android/app/src/main/res/drawable-port-xxxhdpi/splash.png b/android/app/src/main/res/drawable-port-xxxhdpi/splash.png
new file mode 100644
index 0000000..6929071
Binary files /dev/null and b/android/app/src/main/res/drawable-port-xxxhdpi/splash.png differ
diff --git a/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 0000000..c7bd21d
--- /dev/null
+++ b/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/app/src/main/res/drawable/ic_launcher_background.xml b/android/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..d5fccc5
--- /dev/null
+++ b/android/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/app/src/main/res/drawable/splash.png b/android/app/src/main/res/drawable/splash.png
new file mode 100644
index 0000000..f7a6492
Binary files /dev/null and b/android/app/src/main/res/drawable/splash.png differ
diff --git a/android/app/src/main/res/layout/activity_main.xml b/android/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..b5ad138
--- /dev/null
+++ b/android/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..036d09b
--- /dev/null
+++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..036d09b
--- /dev/null
+++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..c023e50
Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..2127973
Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ
diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..b441f37
Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..72905b8
Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..8ed0605
Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ
diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..9502e47
Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..4d1e077
Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..df0f158
Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ
diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..853db04
Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..6cdf97c
Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..2960cbb
Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ
diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..8e3093a
Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..46de6e2
Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..d2ea9ab
Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ
diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..a40d73e
Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/android/app/src/main/res/values/ic_launcher_background.xml b/android/app/src/main/res/values/ic_launcher_background.xml
new file mode 100644
index 0000000..c5d5899
--- /dev/null
+++ b/android/app/src/main/res/values/ic_launcher_background.xml
@@ -0,0 +1,4 @@
+
+
+ #FFFFFF
+
\ No newline at end of file
diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..423bd0b
--- /dev/null
+++ b/android/app/src/main/res/values/strings.xml
@@ -0,0 +1,7 @@
+
+
+ Kawaii-Jumper
+ Kawaii-Jumper
+ io.ionic.starter
+ io.ionic.starter
+
diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..bb45498
--- /dev/null
+++ b/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/app/src/main/res/xml/config.xml b/android/app/src/main/res/xml/config.xml
new file mode 100644
index 0000000..1b1b0e0
--- /dev/null
+++ b/android/app/src/main/res/xml/config.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/app/src/main/res/xml/file_paths.xml b/android/app/src/main/res/xml/file_paths.xml
new file mode 100644
index 0000000..bd0c4d8
--- /dev/null
+++ b/android/app/src/main/res/xml/file_paths.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java b/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java
new file mode 100644
index 0000000..0297327
--- /dev/null
+++ b/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java
@@ -0,0 +1,18 @@
+package com.getcapacitor.myapp;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+
+ @Test
+ public void addition_isCorrect() throws Exception {
+ assertEquals(4, 2 + 2);
+ }
+}
diff --git a/android/build.gradle b/android/build.gradle
new file mode 100644
index 0000000..ad085c3
--- /dev/null
+++ b/android/build.gradle
@@ -0,0 +1,29 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+
+ repositories {
+ google()
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:4.2.1'
+ classpath 'com.google.gms:google-services:4.3.5'
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+apply from: "variables.gradle"
+
+allprojects {
+ repositories {
+ google()
+ jcenter()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/android/capacitor.settings.gradle b/android/capacitor.settings.gradle
new file mode 100644
index 0000000..bd35873
--- /dev/null
+++ b/android/capacitor.settings.gradle
@@ -0,0 +1,15 @@
+// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN
+include ':capacitor-android'
+project(':capacitor-android').projectDir = new File('../node_modules/@capacitor/android/capacitor')
+
+include ':capacitor-app'
+project(':capacitor-app').projectDir = new File('../node_modules/@capacitor/app/android')
+
+include ':capacitor-haptics'
+project(':capacitor-haptics').projectDir = new File('../node_modules/@capacitor/haptics/android')
+
+include ':capacitor-keyboard'
+project(':capacitor-keyboard').projectDir = new File('../node_modules/@capacitor/keyboard/android')
+
+include ':capacitor-status-bar'
+project(':capacitor-status-bar').projectDir = new File('../node_modules/@capacitor/status-bar/android')
diff --git a/android/gradle.properties b/android/gradle.properties
new file mode 100644
index 0000000..0566c22
--- /dev/null
+++ b/android/gradle.properties
@@ -0,0 +1,24 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx1536m
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app's APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Automatically convert third-party libraries to use AndroidX
+android.enableJetifier=true
diff --git a/android/gradle/wrapper/gradle-wrapper.jar b/android/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..e708b1c
Binary files /dev/null and b/android/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..3c4101c
--- /dev/null
+++ b/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-all.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/android/gradlew b/android/gradlew
new file mode 100644
index 0000000..4f906e0
--- /dev/null
+++ b/android/gradlew
@@ -0,0 +1,185 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+## 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='"-Xmx64m" "-Xms64m"'
+
+# 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 or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; 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=`expr $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"
+
+exec "$JAVACMD" "$@"
diff --git a/android/gradlew.bat b/android/gradlew.bat
new file mode 100644
index 0000000..107acd3
--- /dev/null
+++ b/android/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@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 Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@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="-Xmx64m" "-Xms64m"
+
+@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 execute
+
+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 execute
+
+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
+
+: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 %*
+
+: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/android/settings.gradle b/android/settings.gradle
new file mode 100644
index 0000000..3b4431d
--- /dev/null
+++ b/android/settings.gradle
@@ -0,0 +1,5 @@
+include ':app'
+include ':capacitor-cordova-android-plugins'
+project(':capacitor-cordova-android-plugins').projectDir = new File('./capacitor-cordova-android-plugins/')
+
+apply from: 'capacitor.settings.gradle'
\ No newline at end of file
diff --git a/android/variables.gradle b/android/variables.gradle
new file mode 100644
index 0000000..967549c
--- /dev/null
+++ b/android/variables.gradle
@@ -0,0 +1,14 @@
+ext {
+ minSdkVersion = 21
+ compileSdkVersion = 30
+ targetSdkVersion = 30
+ androidxActivityVersion = '1.2.0'
+ androidxAppCompatVersion = '1.2.0'
+ androidxCoordinatorLayoutVersion = '1.1.0'
+ androidxCoreVersion = '1.3.2'
+ androidxFragmentVersion = '1.3.0'
+ junitVersion = '4.13.1'
+ androidxJunitVersion = '1.1.2'
+ androidxEspressoCoreVersion = '3.3.0'
+ cordovaAndroidVersion = '7.0.0'
+}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 19a11ce..c53b559 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2426,6 +2426,11 @@
"to-fast-properties": "^2.0.0"
}
},
+ "@capacitor/android": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/@capacitor/android/-/android-3.4.0.tgz",
+ "integrity": "sha512-O2hHGVzdTH2Lsmz58EI8zHY5byEFIWl9KrW60WSrO/tV6u9DpfaUq56FaejvfU27GFXDZkmoQNa33EvDYWp4wA=="
+ },
"@capacitor/app": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@capacitor/app/-/app-1.1.0.tgz",
@@ -5112,6 +5117,11 @@
"resolved": "https://registry.npmjs.org/@socket.io/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
"integrity": "sha512-dOlCBKnDw4iShaIsH/bxujKTM18+2TOAsYz+KSc11Am38H4q5Xw8Bbz97ZYdrVNM+um3p7w86Bvvmcn9q+5+eQ=="
},
+ "@socket.io/component-emitter": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.0.0.tgz",
+ "integrity": "sha512-2pTGuibAXJswAPJjaKisthqS/NOK5ypG4LYT6tEAV0S/mxW0zOIvYvGK0V8w8+SHxAm6vRMSjqSalFXeBAqs+Q=="
+ },
"@stencil/core": {
"version": "2.12.1",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.12.1.tgz",
@@ -6186,6 +6196,11 @@
"@babel/helper-define-polyfill-provider": "^0.2.4"
}
},
+ "backo2": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
+ "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc="
+ },
"balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -7090,8 +7105,7 @@
"core-js": {
"version": "3.20.3",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.20.3.tgz",
- "integrity": "sha512-vVl8j8ph6tRS3B8qir40H7yw7voy17xL0piAjlbBUsH7WIfzoedL/ZOr1OV9FyZQLWXsayOJyV4tnRyXR85/ag==",
- "dev": true
+ "integrity": "sha512-vVl8j8ph6tRS3B8qir40H7yw7voy17xL0piAjlbBUsH7WIfzoedL/ZOr1OV9FyZQLWXsayOJyV4tnRyXR85/ag=="
},
"core-js-compat": {
"version": "3.20.3",
@@ -7998,6 +8012,29 @@
}
}
},
+ "engine.io-client": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.1.1.tgz",
+ "integrity": "sha512-V05mmDo4gjimYW+FGujoGmmmxRaDsrVr7AXA3ZIfa04MWM1jOfZfUwou0oNqhNwy/votUDvGDt4JA4QF4e0b4g==",
+ "requires": {
+ "@socket.io/component-emitter": "~3.0.0",
+ "debug": "~4.3.1",
+ "engine.io-parser": "~5.0.0",
+ "has-cors": "1.1.0",
+ "parseqs": "0.0.6",
+ "parseuri": "0.0.6",
+ "ws": "~8.2.3",
+ "xmlhttprequest-ssl": "~2.0.0",
+ "yeast": "0.1.2"
+ },
+ "dependencies": {
+ "ws": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz",
+ "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA=="
+ }
+ }
+ },
"engine.io-parser": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.3.tgz",
@@ -9478,6 +9515,11 @@
"integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==",
"dev": true
},
+ "has-cors": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz",
+ "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk="
+ },
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
@@ -11894,6 +11936,31 @@
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
"dev": true
},
+ "ngrx": {
+ "version": "0.0.1-security",
+ "resolved": "https://registry.npmjs.org/ngrx/-/ngrx-0.0.1-security.tgz",
+ "integrity": "sha512-3hYh1th9Arjoh7mA3KvOt7NB/ZGynOwibYUYftovFRAojsqtI+WZpa51JZ0u+INv3Lcvbi5qkJYupar17aLGdg=="
+ },
+ "ngx-socket-io": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ngx-socket-io/-/ngx-socket-io-4.1.0.tgz",
+ "integrity": "sha512-p/IxD/hdpF/3+Xu6FFoo1OMIi9+rbqN55smJKE1RSFHAhS0UmRno2soHd1RTG3QXm6hCntp2vvfPE4tn60P5mw==",
+ "requires": {
+ "core-js": "^3.0.0",
+ "reflect-metadata": "^0.1.10",
+ "socket.io": "^4.0.0",
+ "socket.io-client": "^4.0.0",
+ "tslib": "^2.0.0",
+ "zone.js": "^0.10.1"
+ },
+ "dependencies": {
+ "zone.js": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.10.3.tgz",
+ "integrity": "sha512-LXVLVEq0NNOqK/fLJo3d0kfzd4sxwn2/h67/02pjCjfKDxgx1i9QqpvtHD8CrBnSSwMw5+dy11O7FRX5mkO7Cg=="
+ }
+ }
+ },
"nice-napi": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz",
@@ -12637,6 +12704,16 @@
"parse5": "^6.0.1"
}
},
+ "parseqs": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz",
+ "integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w=="
+ },
+ "parseuri": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz",
+ "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow=="
+ },
"parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
@@ -14851,8 +14928,7 @@
"reflect-metadata": {
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
- "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==",
- "dev": true
+ "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg=="
},
"regenerate": {
"version": "1.4.2",
@@ -15811,6 +15887,30 @@
"resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz",
"integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ=="
},
+ "socket.io-client": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.4.1.tgz",
+ "integrity": "sha512-N5C/L5fLNha5Ojd7Yeb/puKcPWWcoB/A09fEjjNsg91EDVr5twk/OEyO6VT9dlLSUNY85NpW6KBhVMvaLKQ3vQ==",
+ "requires": {
+ "@socket.io/component-emitter": "~3.0.0",
+ "backo2": "~1.0.2",
+ "debug": "~4.3.2",
+ "engine.io-client": "~6.1.1",
+ "parseuri": "0.0.6",
+ "socket.io-parser": "~4.1.1"
+ },
+ "dependencies": {
+ "socket.io-parser": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.1.1.tgz",
+ "integrity": "sha512-USQVLSkDWE5nbcY760ExdKaJxCE65kcsG/8k5FDGZVVxpD1pA7hABYXYkCUvxUuYYh/+uQw0N/fvBzfT8o07KA==",
+ "requires": {
+ "@socket.io/component-emitter": "~3.0.0",
+ "debug": "~4.3.1"
+ }
+ }
+ }
+ },
"socket.io-parser": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz",
@@ -17389,6 +17489,11 @@
"integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=",
"dev": true
},
+ "xmlhttprequest-ssl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz",
+ "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A=="
+ },
"xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
@@ -17452,6 +17557,11 @@
"fd-slicer": "~1.1.0"
}
},
+ "yeast": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
+ "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk="
+ },
"yn": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
diff --git a/package.json b/package.json
index a08d6f6..7b5d826 100644
--- a/package.json
+++ b/package.json
@@ -19,13 +19,16 @@
"@angular/platform-browser": "~13.0.0",
"@angular/platform-browser-dynamic": "~13.0.0",
"@angular/router": "~13.0.0",
+ "@capacitor/android": "^3.4.0",
"@capacitor/app": "1.1.0",
"@capacitor/core": "3.4.0",
"@capacitor/haptics": "1.1.4",
"@capacitor/keyboard": "1.2.1",
"@capacitor/status-bar": "1.0.7",
"@ionic/angular": "^6.0.0",
- "rxjs": "~6.6.0",
+ "ngrx": "0.0.1-security",
+ "ngx-socket-io": "^4.1.0",
+ "rxjs": "^6.6.7",
"socket.io": "^4.4.1",
"tslib": "^2.2.0",
"zone.js": "~0.11.4"
diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts
index e7b0d5a..5712c96 100644
--- a/src/app/app-routing.module.ts
+++ b/src/app/app-routing.module.ts
@@ -2,15 +2,10 @@ import { NgModule } from '@angular/core';
import { PreloadAllModules, RouterModule, Routes } from '@angular/router';
const routes: Routes = [
- {
- path: 'home',
- loadChildren: () => import('./home/home.module').then( m => m.HomePageModule)
- },
{
path: '',
- redirectTo: 'home',
- pathMatch: 'full'
- },
+ loadChildren: () => import('./home/home.module').then( m => m.HomePageModule)
+ }
];
@NgModule({
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index f8b75ac..323dff4 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -1,16 +1,20 @@
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';
-
+
import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
+import { SocketIoConfig, SocketIoModule } from 'ngx-socket-io';
+
+const config: SocketIoConfig = { url: 'http://localhost:3000', options: {} };
+// const config: SocketIoConfig = { url: 'https://ggj2022.rapalis.lt', options: {} };
@NgModule({
declarations: [AppComponent],
entryComponents: [],
- imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule],
+ imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule, SocketIoModule.forRoot(config)],
providers: [{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }],
bootstrap: [AppComponent],
})
diff --git a/src/app/home/applyGravity.ts b/src/app/home/applyGravity.ts
new file mode 100644
index 0000000..739cd86
--- /dev/null
+++ b/src/app/home/applyGravity.ts
@@ -0,0 +1,10 @@
+import { Vector } from './types.dto';
+
+export const applyGravity = (
+ currentVelocity: Vector,
+ deltaTime: number,
+): Vector => {
+ currentVelocity.y += 0.003 * deltaTime;
+ currentVelocity.y = currentVelocity.y > 0.9 ? 0.9 : currentVelocity.y;
+ return { ...currentVelocity };
+};
diff --git a/src/app/home/deltaTime.ts b/src/app/home/deltaTime.ts
new file mode 100644
index 0000000..ae427ee
--- /dev/null
+++ b/src/app/home/deltaTime.ts
@@ -0,0 +1,27 @@
+export class DeltaTime {
+ private lastTick: number;
+ private static instance: DeltaTime;
+ private deltaTime: number;
+
+ private constructor() {
+ this.lastTick = Date.now();
+ }
+
+ public static getInstance() {
+ if (!this.instance) {
+ this.instance = new DeltaTime();
+ }
+ return this.instance;
+ }
+
+ public updateDeltaTime() {
+ const time = Date.now();
+ this.deltaTime = time - this.lastTick;
+ this.lastTick = time;
+ }
+
+ public getDeltaTime(): number {
+ return this.deltaTime;
+ }
+
+}
\ No newline at end of file
diff --git a/src/app/home/drawMap.ts b/src/app/home/drawMap.ts
new file mode 100644
index 0000000..13aa863
--- /dev/null
+++ b/src/app/home/drawMap.ts
@@ -0,0 +1,11 @@
+import { MapTile } from '../../../../Kawaii-Jumper-server/src/mapTile';
+
+export const drawMap = (
+ mapTiles: MapTile[],
+ context: CanvasRenderingContext2D,
+ images: HTMLImageElement[],
+) => {
+ for (let tile of mapTiles) {
+ context.drawImage(images[tile.color], tile.x, tile.y, tile.w, tile.h);
+ }
+};
diff --git a/src/app/home/getAngleBetweenTwoPoints.ts b/src/app/home/getAngleBetweenTwoPoints.ts
new file mode 100644
index 0000000..85304d7
--- /dev/null
+++ b/src/app/home/getAngleBetweenTwoPoints.ts
@@ -0,0 +1,5 @@
+import { Vector } from './types.dto';
+
+export const getAngleBetweenTwoPoints = (p1: Vector, p2: Vector): number => {
+ return Math.atan2(p2.y - p1.y, p2.x - p1.x);
+};
diff --git a/src/app/home/getXFromAngle.ts b/src/app/home/getXFromAngle.ts
new file mode 100644
index 0000000..fe1eb24
--- /dev/null
+++ b/src/app/home/getXFromAngle.ts
@@ -0,0 +1,3 @@
+export const getXFromAngle = (angle: number) => {
+ return Math.cos(angle);
+};
diff --git a/src/app/home/getYFromAngle.ts b/src/app/home/getYFromAngle.ts
new file mode 100644
index 0000000..d2e3ea1
--- /dev/null
+++ b/src/app/home/getYFromAngle.ts
@@ -0,0 +1,3 @@
+export const getYFromAngle = (angle: number) => {
+ return Math.sin(angle);
+};
diff --git a/src/app/home/globals.ts b/src/app/home/globals.ts
new file mode 100644
index 0000000..027a819
--- /dev/null
+++ b/src/app/home/globals.ts
@@ -0,0 +1,68 @@
+import { Socket } from 'ngx-socket-io';
+import { MapTile } from '../../../../Kawaii-Jumper-server/src/mapTile';
+import { makeHTMLAudioElements } from './makeHTMLAudioElements';
+import { makeHTMLImageElements } from './makeHTMLImageObjects';
+import { scaleScreen } from './scaleScreen';
+import { Vector } from './types.dto';
+
+export class Globals {
+ public width: number = 0;
+ public height: number = 0;
+ public canvasScale: number = 0;
+ public pageWidth: number = 0;
+ public pageHeight: number = 0;
+ public canvas: HTMLCanvasElement;
+ public context: CanvasRenderingContext2D;
+ public playerImages: HTMLImageElement[] = [];
+ public platformImages: HTMLImageElement[] = [];
+ public socket: Socket;
+ public socketId: string;
+ public colors: string[] = ['#FF63C8', '#79e7ff'];
+ public sounds: HTMLAudioElement[] = [];
+ public playerSize: Vector = { x: 50, y: 34 };
+ public map: MapTile[] = [];
+ public backgroudnImage: HTMLImageElement;
+
+ private readonly playerImageFiles: string[] = [
+ '/assets/slime-1-left.png',
+ '/assets/slime-1-right.png',
+ '/assets/slime-2-left.png',
+ '/assets/slime-2-right.png',
+ ];
+ private readonly platformImageFiles: string[] = [
+ '/assets/platform-1.png',
+ '/assets/platform-2.png',
+ ];
+ private readonly soundFiles: string[] = [
+ '/assets/jump.wav',
+ '/assets/land.wav',
+ ];
+ private static instance: Globals;
+
+ private constructor() {
+ this.setupImages();
+ this.setupSounds();
+ }
+
+ private setupImages(): void {
+ this.playerImages = makeHTMLImageElements(this.playerImageFiles);
+ this.platformImages = makeHTMLImageElements(this.platformImageFiles);
+ this.backgroudnImage = makeHTMLImageElements(['/assets/bg.png'])[0];
+ }
+ private setupSounds(): void {
+ this.sounds = makeHTMLAudioElements(this.soundFiles);
+ }
+
+ public static getInstance(): Globals {
+ if (!this.instance) {
+ this.instance = new Globals();
+ }
+ return this.instance;
+ }
+
+ public setupCanvas() {
+ this.canvas = document.getElementById('game') as HTMLCanvasElement;
+ this.context = this.canvas.getContext('2d');
+ scaleScreen();
+ }
+}
diff --git a/src/app/home/home.page.html b/src/app/home/home.page.html
index 3e47db2..93ea3ac 100644
--- a/src/app/home/home.page.html
+++ b/src/app/home/home.page.html
@@ -1 +1,4 @@
-
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/src/app/home/home.page.ts b/src/app/home/home.page.ts
index 45a0b27..66fcd3c 100644
--- a/src/app/home/home.page.ts
+++ b/src/app/home/home.page.ts
@@ -1,4 +1,28 @@
-import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
+import { Component, OnInit } from '@angular/core';
+import { Socket } from 'ngx-socket-io';
+
+import { Position } from '../../../../Kawaii-Jumper-server/src/position';
+import {
+ PlayerDTO,
+ PlayerDTOList,
+ PlayerList,
+ StringNumber,
+ StringVector,
+ Vector,
+} from './types.dto';
+
+import { MapTile } from '../../../../Kawaii-Jumper-server/src/mapTile';
+import { getXFromAngle } from './getXFromAngle';
+import { getAngleBetweenTwoPoints } from './getAngleBetweenTwoPoints';
+import { getYFromAngle } from './getYFromAngle';
+import { applyGravity } from './applyGravity';
+import { IsIntersecting } from './isIntersecting';
+import { drawMap } from './drawMap';
+
+import { Globals } from './globals';
+import { Players } from './players';
+import { MySocket } from './mySocket';
+import { DeltaTime } from './deltaTime';
@Component({
selector: 'app-home',
@@ -6,50 +30,505 @@ import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
styleUrls: ['home.page.scss'],
})
export class HomePage implements OnInit {
+ globals: Globals;
+ players: Players;
+ mySocket: MySocket;
+ deltaTime: DeltaTime;
- canvas: HTMLCanvasElement;
- context: CanvasRenderingContext2D;
+ myLastPosition: Position = { x: 0, y: 0 };
- pageHeight = window.innerHeight;
- pageWidth = window.innerWidth;
+ jumpPower = Date.now();
- constructor() {
+ lastPointerPosition: Position = { x: 0, y: 0 };
+
+ keysDown: { [key: number]: boolean } = {};
+
+ mapBuilder = false;
+
+ builtMap: MapTile[] = [];
+
+ constructor(private socket: Socket) {
+ this.globals = Globals.getInstance();
+ this.players = Players.getInstance();
+ this.deltaTime = DeltaTime.getInstance();
+ this.globals.socket = socket;
+ this.mySocket = MySocket.getInstance();
+ this.globals.pageHeight = window.innerHeight;
+ this.globals.pageWidth = window.innerWidth;
+
+ this.setupSocketListeners();
}
ngOnInit(): void {
- this.canvas = document.getElementById('game') as HTMLCanvasElement;
- this.context = this.canvas.getContext('2d');
- this.scaleScreen();
+ this.globals.setupCanvas();
+ this.setListeners();
this.gameLoop();
}
- gameLoop() {
-
- this.drawPlayer();
-
- requestAnimationFrame(() => {this.gameLoop();});
+ setupSocketListeners() {
+ this.mySocket.onId((id: string) => (this.globals.socketId = id));
+ this.mySocket.onMap((map: MapTile[]) => (this.globals.map = map));
+ this.mySocket.onPlayerConnected((players: PlayerDTOList) =>
+ this.players.addMultiplaPlayers(players),
+ );
+ this.mySocket.onNewPlayerConnected((player: PlayerDTO) =>
+ this.players.addPlayer(player),
+ );
+ this.mySocket.onPlayerDisconnected((id: string) =>
+ this.players.removePlayer(id),
+ );
+ this.mySocket.onUpdatedPlayerColor((playersColor: StringNumber) =>
+ this.players.updatePlayerColor(playersColor),
+ );
+ this.mySocket.onUpdatedPlayerPosition((playersPosition: StringVector) =>
+ this.players.updatePlayerPosition(playersPosition),
+ );
+ this.mySocket.onUpdatedPlayerDirection((playersDirection: StringNumber) =>
+ this.players.updatePlayerDirection(playersDirection),
+ );
}
- drawPlayer() {
- this.context.fillStyle = 'white';
- this.context.fillRect(50, 50, 50, 50);
+ getJumpPower(): number {
+ let power = Date.now() - this.jumpPower;
+ return Math.abs(getXFromAngle(power / 1000) * 1.4);
}
-
- setCanvasSize(w: number, h: number) {
- this.canvas.style.height = h + 'px';
- this.canvas.style.width = w + 'px';
- this.canvas.height = h;
- this.canvas.width = w;
+ getJumpDirection(x: number, y: number) {
+ return getAngleBetweenTwoPoints(
+ {
+ x:
+ this.players.getMyself().getPosition().x +
+ this.globals.playerSize.x / 2,
+ y:
+ this.players.getMyself().getPosition().y +
+ this.globals.playerSize.y / 2,
+ },
+ {
+ x: x * this.globals.canvasScale,
+ y: y * this.globals.canvasScale,
+ },
+ );
}
- scaleScreen() {
- const scaleX = this.pageWidth / 9;
- const scaleY = this.pageHeight / 16;
- if (scaleX > scaleY) { // width is longer, calculate based on height
- return this.setCanvasSize(this.pageHeight / 16 * 9, this.pageHeight);
+ clickEndListener($event): Position {
+ console.log('click');
+ if (!this.players.getMyself()) return;
+ console.log('I found myself');
+ if (!this.players.getMyself().isGrounded()) return;
+ console.log('I am grounded');
+
+ this.players.getMyself().swapColor();
+ this.socket.emit('updatedColor', this.players.getMyself().getColor());
+ this.players.getMyself().setGrounded(false);
+ const angle = this.getJumpDirection($event.offsetX, $event.offsetY);
+ this.players.getMyself().jump(angle, this.getJumpPower());
+
+ this.socket.emit(
+ 'updatedDirection',
+ this.players.getMyself().getDirection(),
+ );
+ this.globals.sounds[0].play();
+ return this.players.getMyself().getMovingVelocity();
+ }
+
+ mapClickListenerEnd($event) {
+ this.builtMap.push({
+ color: 0,
+ x: $event.offsetX * this.globals.canvasScale,
+ y: $event.offsetY * this.globals.canvasScale,
+ w: 130,
+ h: 30,
+ });
+ console.log(this.builtMap);
+ }
+
+ moveListener($event): void {
+ if (!this.globals.socketId) return;
+ this.lastPointerPosition = {
+ x: $event.offsetX * this.globals.canvasScale,
+ y: $event.offsetY * this.globals.canvasScale,
+ };
+ }
+
+ setListeners() {
+ window.addEventListener('keydown', (e) => this.keyListener(e, true));
+ window.addEventListener('keyup', (e) => this.keyListener(e, false));
+ window.addEventListener('mouseup', (e) => this.mapBuilder ? this.mapClickListenerEnd(e) : this.clickEndListener(e));
+ window.addEventListener('touchend', (e) => this.clickEndListener(e));
+ window.addEventListener('mousemove', (e) => this.moveListener(e));
+ }
+
+ keyListener($event, state) {
+ this.keysDown[$event.keyCode] = state;
+ }
+
+ detectCollisions() {
+ const player = this.players.getMyself();
+ for (let block of this.globals.map) {
+ if (block.color !== this.players.getMyself().getColor()) continue;
+
+ const playerWidth = this.globals.playerSize.x;
+ const playerHeight = this.globals.playerSize.y;
+ const myPosition = player.getPosition();
+
+ const playerTopLeft: Position = myPosition;
+ const playerTopRight: Position = {
+ x: myPosition.x + playerWidth,
+ y: myPosition.y,
+ };
+ const playerBottomLeft: Position = {
+ x: myPosition.x,
+ y: myPosition.y + playerHeight,
+ };
+ const playerBottomRight: Position = {
+ x: myPosition.x + playerWidth,
+ y: myPosition.y + playerHeight,
+ };
+
+ const blockTopLeft: Position = { x: block.x, y: block.y };
+ const blockTopRight: Position = { x: block.x + block.w, y: block.y };
+ const blockBottomLeft: Position = { x: block.x, y: block.y + block.h };
+ const blockBottomRight: Position = {
+ x: block.x + block.w,
+ y: block.y + block.h,
+ };
+
+ if (
+ IsIntersecting(
+ playerTopRight,
+ playerBottomRight,
+ blockTopLeft,
+ blockTopRight,
+ ) &&
+ IsIntersecting(
+ playerBottomLeft,
+ playerBottomRight,
+ blockTopLeft,
+ blockBottomLeft,
+ )
+ ) {
+ const dx = this.getDistanceX(playerBottomRight, blockTopLeft);
+ const dy = this.getDistanceY(playerBottomRight, blockTopLeft);
+ console.log('collision on top left corner of platform');
+
+ return dx < dy
+ ? this.players.getMyself().touchRight(blockTopLeft.x)
+ : this.players.getMyself().touchBottom(blockTopLeft.y);
+ }
+
+ if (
+ IsIntersecting(
+ playerTopRight,
+ playerBottomRight,
+ blockBottomLeft,
+ blockBottomRight,
+ ) &&
+ IsIntersecting(
+ playerTopLeft,
+ playerTopRight,
+ blockTopLeft,
+ blockBottomLeft,
+ )
+ ) {
+ const dx = this.getDistanceX(playerTopRight, blockBottomLeft);
+ const dy = this.getDistanceY(playerTopRight, blockBottomLeft);
+ console.log('collision on bottom left corner of platform');
+
+ return dx < dy
+ ? this.players.getMyself().touchRight(blockBottomLeft.x)
+ : this.players.getMyself().touchTop(blockBottomLeft.y);
+ }
+
+ if (
+ IsIntersecting(
+ playerTopLeft,
+ playerBottomLeft,
+ blockTopLeft,
+ blockTopRight,
+ ) &&
+ IsIntersecting(
+ playerBottomLeft,
+ playerBottomRight,
+ blockTopRight,
+ blockBottomRight,
+ )
+ ) {
+ const dx = this.getDistanceX(playerBottomLeft, blockTopRight);
+ const dy = this.getDistanceY(playerBottomLeft, blockTopRight);
+ console.log('collision on top right corner of platform');
+
+ return dx < dy
+ ? this.players.getMyself().touchLeft(blockTopRight.x)
+ : this.players.getMyself().touchBottom(blockTopRight.y);
+ }
+
+ if (
+ IsIntersecting(
+ playerTopLeft,
+ playerBottomLeft,
+ blockBottomLeft,
+ blockBottomRight,
+ ) &&
+ IsIntersecting(
+ playerTopLeft,
+ playerTopRight,
+ blockTopRight,
+ blockBottomRight,
+ )
+ ) {
+ const dx = this.getDistanceX(playerTopLeft, blockBottomRight);
+ const dy = this.getDistanceY(playerTopLeft, blockBottomRight);
+ console.log('collision on bottom right corner of platform');
+
+ return dx < dy
+ ? this.players.getMyself().touchLeft(blockBottomRight.x)
+ : this.players.getMyself().touchTop(blockBottomRight.y);
+ }
+
+ if (
+ IsIntersecting(
+ playerTopLeft,
+ playerTopRight,
+ blockTopLeft,
+ blockBottomLeft,
+ ) &&
+ IsIntersecting(
+ playerBottomLeft,
+ playerBottomRight,
+ blockTopLeft,
+ blockBottomLeft,
+ )
+ ) {
+ console.log(
+ 'collision on left side of platform (platform bigger than player)',
+ );
+ return this.players.getMyself().touchRight(blockBottomLeft.x);
+ }
+
+ if (
+ IsIntersecting(
+ playerTopLeft,
+ playerTopRight,
+ blockTopRight,
+ blockBottomRight,
+ ) &&
+ IsIntersecting(
+ playerBottomLeft,
+ playerBottomRight,
+ blockTopRight,
+ blockBottomRight,
+ )
+ ) {
+ console.log(
+ 'collision on right side of platform (platform bigger than player)',
+ );
+ return this.players.getMyself().touchLeft(blockBottomRight.x);
+ }
+
+ if (
+ IsIntersecting(
+ playerTopLeft,
+ playerBottomLeft,
+ blockBottomLeft,
+ blockBottomRight,
+ ) &&
+ IsIntersecting(
+ playerTopRight,
+ playerBottomRight,
+ blockBottomLeft,
+ blockBottomRight,
+ )
+ ) {
+ console.log(
+ 'collision on bottom side of platform (platform bigger than player)',
+ );
+ return this.players.getMyself().touchTop(blockBottomLeft.y);
+ }
+
+ if (
+ IsIntersecting(
+ playerTopLeft,
+ playerBottomLeft,
+ blockTopLeft,
+ blockTopRight,
+ ) &&
+ IsIntersecting(
+ playerTopRight,
+ playerBottomRight,
+ blockTopLeft,
+ blockTopRight,
+ )
+ ) {
+ console.log(
+ 'collision on top side of platform (platform bigger than player)',
+ );
+ return this.players.getMyself().touchBottom(blockTopLeft.y);
+ }
+
+ if (
+ IsIntersecting(
+ playerTopLeft,
+ playerBottomLeft,
+ blockTopLeft,
+ blockTopRight,
+ )
+ ) {
+ console.log(
+ 'collision on right side of platform (platform smaller than player)',
+ );
+ return this.players.getMyself().touchLeft(blockTopRight.x);
+ }
+
+ if (
+ IsIntersecting(
+ playerTopRight,
+ playerBottomRight,
+ blockTopLeft,
+ blockTopRight,
+ )
+ ) {
+ console.log(
+ 'collision on left side of platform (platform smaller than player)',
+ );
+ return this.players.getMyself().touchRight(blockTopLeft.x);
+ }
+
+ if (
+ IsIntersecting(
+ playerTopLeft,
+ playerTopRight,
+ blockTopLeft,
+ blockBottomLeft,
+ )
+ ) {
+ console.log(
+ 'collision on bottom side of platform (platform smaller than player)',
+ );
+ return this.players.getMyself().touchTop(blockBottomLeft.y);
+ }
+
+ if (
+ IsIntersecting(
+ playerBottomLeft,
+ playerBottomRight,
+ blockTopLeft,
+ blockBottomLeft,
+ )
+ ) {
+ console.log(
+ 'collision on top side of platform (platform smaller than player)',
+ );
+ return this.players.getMyself().touchBottom(blockTopLeft.y);
+ }
+ }
+
+ /* MAP BOUNDS */
+ if (
+ this.players.getMyself().getPosition().y >
+ this.globals.height - this.globals.playerSize.y
+ ) {
+ this.players.getMyself().touchBottom(this.globals.height);
+ }
+
+ if (this.players.getMyself().getPosition().x < 0) {
+ this.players.getMyself().touchLeft(0);
+ }
+
+ if (
+ this.players.getMyself().getPosition().x >
+ this.globals.width - this.globals.playerSize.x
+ ) {
+ this.players.getMyself().touchRight(this.globals.width);
}
- this.setCanvasSize(this.pageWidth, this.pageWidth / 9 * 16) // height is longer, calculate based on width
}
+ updatePlayerPosition() {
+ if (!this.players.getMyself()) return;
+ this.detectCollisions();
+ if (
+ this.players.getMyself().getPosition().x !== this.myLastPosition.x ||
+ this.players.getMyself().getPosition().y !== this.myLastPosition.y
+ ) {
+ this.socket.emit(
+ 'updatedPosition',
+ this.players.getMyself().getPosition(),
+ );
+ this.myLastPosition = { ...this.players.getMyself().getPosition() };
+ }
+ }
+
+ getDistanceX(p1: Position, p2: Position): number {
+ return Math.abs(p1.x - p2.x);
+ }
+
+ getDistanceY(p1: Position, p2: Position): number {
+ return Math.abs(p1.y - p2.y);
+ }
+
+ drawPointer() {
+ if (!this.globals.socketId) return;
+ this.globals.context.strokeStyle = '#00ff0066';
+ this.globals.context.lineWidth = 5;
+ const angle = getAngleBetweenTwoPoints(
+ {
+ x:
+ this.players.getMyself().getPosition().x +
+ this.globals.playerSize.x / 2,
+ y:
+ this.players.getMyself().getPosition().y +
+ this.globals.playerSize.y / 2,
+ },
+ this.lastPointerPosition,
+ );
+ this.globals.context.beginPath();
+ this.globals.context.moveTo(
+ this.players.getMyself().getPosition().x + this.globals.playerSize.x / 2,
+ this.players.getMyself().getPosition().y + this.globals.playerSize.y / 2,
+ );
+ this.globals.context.lineTo(
+ this.players.getMyself().getPosition().x +
+ this.globals.playerSize.x / 2 +
+ getXFromAngle(angle) * this.getJumpPower() * 50,
+ this.players.getMyself().getPosition().y +
+ this.globals.playerSize.y / 2 +
+ getYFromAngle(angle) * this.getJumpPower() * 50,
+ );
+ this.globals.context.stroke();
+ }
+
+ gameLoop() {
+ this.globals.context.fillStyle = 'gray';
+ this.globals.context.drawImage(
+ this.globals.backgroudnImage,
+ 0,
+ 0,
+ this.globals.width,
+ this.globals.height,
+ );
+
+ drawMap(
+ this.globals.map,
+ this.globals.context,
+ this.globals.platformImages,
+ );
+ if (this.mapBuilder) {
+ drawMap(
+ this.builtMap,
+ this.globals.context,
+ this.globals.platformImages,
+ );
+ }
+
+ this.deltaTime.updateDeltaTime();
+
+ this.players.tick();
+ this.players.draw();
+
+ this.updatePlayerPosition();
+ this.drawPointer();
+
+ requestAnimationFrame(() => {
+ this.gameLoop();
+ });
+ }
}
diff --git a/src/app/home/isIntersecting.ts b/src/app/home/isIntersecting.ts
new file mode 100644
index 0000000..9ab14df
--- /dev/null
+++ b/src/app/home/isIntersecting.ts
@@ -0,0 +1,25 @@
+import { Vector } from './types.dto';
+
+export const IsIntersecting = (
+ l1p1: Vector, // line 1 point 1
+ l1p2: Vector, // line 1 point 2
+ l2p1: Vector, // line 2 point 1
+ l2p2: Vector, // line 2 point 2
+): boolean => {
+ const denominator =
+ (l1p2.x - l1p1.x) * (l2p2.y - l2p1.y) -
+ (l1p2.y - l1p1.y) * (l2p2.x - l2p1.x);
+ const numerator1 =
+ (l1p1.y - l2p1.y) * (l2p2.x - l2p1.x) -
+ (l1p1.x - l2p1.x) * (l2p2.y - l2p1.y);
+ const numerator2 =
+ (l1p1.y - l2p1.y) * (l1p2.x - l1p1.x) -
+ (l1p1.x - l2p1.x) * (l1p2.y - l1p1.y);
+
+ if (denominator == 0) return numerator1 == 0 && numerator2 == 0;
+
+ const r = numerator1 / denominator;
+ const s = numerator2 / denominator;
+
+ return r >= 0 && r <= 1 && s >= 0 && s <= 1;
+};
diff --git a/src/app/home/makeHTMLAudioElements.ts b/src/app/home/makeHTMLAudioElements.ts
new file mode 100644
index 0000000..779bd74
--- /dev/null
+++ b/src/app/home/makeHTMLAudioElements.ts
@@ -0,0 +1,11 @@
+export const makeHTMLAudioElements = (
+ fileList: string[],
+): HTMLAudioElement[] => {
+ const sounds: HTMLAudioElement[] = [];
+
+ for (let file of fileList) {
+ sounds.push(new Audio(file));
+ }
+
+ return sounds;
+};
diff --git a/src/app/home/makeHTMLImageObjects.ts b/src/app/home/makeHTMLImageObjects.ts
new file mode 100644
index 0000000..35471c8
--- /dev/null
+++ b/src/app/home/makeHTMLImageObjects.ts
@@ -0,0 +1,13 @@
+export const makeHTMLImageElements = (
+ fileList: string[],
+): HTMLImageElement[] => {
+ const images: HTMLImageElement[] = [];
+
+ for (let file of fileList) {
+ const image = new Image();
+ image.src = file;
+ images.push(image);
+ }
+
+ return images;
+};
diff --git a/src/app/home/mySocket.ts b/src/app/home/mySocket.ts
new file mode 100644
index 0000000..7dd1dad
--- /dev/null
+++ b/src/app/home/mySocket.ts
@@ -0,0 +1,49 @@
+import { Globals } from './globals';
+
+export class MySocket {
+ private static instance: MySocket;
+ private globals: Globals;
+
+ private constructor() {
+ this.globals = Globals.getInstance();
+ }
+
+ public static getInstance(): MySocket {
+ if (!this.instance) {
+ this.instance = new MySocket();
+ }
+ return this.instance;
+ }
+
+ public onId(callback: CallableFunction): void {
+ this.globals.socket.on('takeYourIdAndLeaveMeAlone', callback);
+ }
+
+ public onPlayerConnected(callback: CallableFunction): void {
+ this.globals.socket.on('connectedPlayers', callback);
+ }
+
+ public onNewPlayerConnected(callback: CallableFunction): void {
+ this.globals.socket.on('newPlayer', callback);
+ }
+
+ public onPlayerDisconnected(callback: CallableFunction): void {
+ this.globals.socket.on('playerDisconnected', callback);
+ }
+
+ public onUpdatedPlayerPosition(callback: CallableFunction): void {
+ this.globals.socket.on('updatedPlayerPositions', callback);
+ }
+
+ public onUpdatedPlayerColor(callback: CallableFunction): void {
+ this.globals.socket.on('updatedPlayerColor', callback);
+ }
+
+ public onUpdatedPlayerDirection(callback: CallableFunction): void {
+ this.globals.socket.on('updatedPlayerDirection', callback);
+ }
+
+ public onMap(callback: CallableFunction): void {
+ this.globals.socket.on('takeTheMapAndBeQuiet', callback);
+ }
+}
diff --git a/src/app/home/player.ts b/src/app/home/player.ts
new file mode 100644
index 0000000..2f72fd3
--- /dev/null
+++ b/src/app/home/player.ts
@@ -0,0 +1,146 @@
+import { Position } from '../../../../Kawaii-Jumper-server/src/position';
+import { applyGravity } from './applyGravity';
+import { DeltaTime } from './deltaTime';
+import { getXFromAngle } from './getXFromAngle';
+import { getYFromAngle } from './getYFromAngle';
+import { Globals } from './globals';
+import { PlayerDTO, Vector } from './types.dto';
+
+export class Player {
+ private readonly globals: Globals;
+ private readonly deltaTime: DeltaTime;
+ private id: string;
+ private position: Vector;
+ private name: string;
+ private movingVelocity: Vector;
+ private color: number;
+ private direction: number;
+ private grounded: boolean;
+
+ public constructor(id: string, data: PlayerDTO) {
+ this.globals = Globals.getInstance();
+ this.deltaTime = DeltaTime.getInstance();
+ this.id = id;
+ this.position = data.position;
+ this.name = data.name;
+ this.movingVelocity = data.movingVelocity;
+ this.color = data.color;
+ this.direction = data.direction;
+ this.grounded = true;
+ }
+
+ public applyGravity() {
+ this.movingVelocity = {
+ ...applyGravity(this.movingVelocity, this.deltaTime.getDeltaTime()),
+ };
+ }
+
+ public resetVelocity() {
+ this.movingVelocity = { x: 0, y: 0 };
+ }
+
+ public updatePosition(position: Vector): void {
+ this.position = { ...position };
+ }
+
+ public updateDirection(direction: number): void {
+ this.direction = direction;
+ }
+
+ public updateColor(color: number): void {
+ this.color = color;
+ }
+
+ public getId(): string {
+ return this.id;
+ }
+
+ public getPosition(): Vector {
+ return { ...this.position };
+ }
+
+ public getName(): string {
+ return this.name;
+ }
+
+ public getColor(): number {
+ return this.color;
+ }
+
+ public getDirection(): number {
+ return this.direction;
+ }
+
+ public isGrounded(): boolean {
+ return this.grounded;
+ }
+
+ public setGrounded(grounded: boolean): void {
+ this.grounded = grounded;
+ }
+
+ public getMovingVelocity(): Vector {
+ return { ...this.movingVelocity };
+ }
+
+ public swapColor(): void {
+ this.color = this.color === 0 ? 1 : 0;
+ }
+
+ public jump(angle: number, jumpPower: number): void {
+ this.movingVelocity.x = getXFromAngle(angle) * jumpPower;
+ this.movingVelocity.y = getYFromAngle(angle) * jumpPower;
+ this.direction = this.movingVelocity.x > 0 ? 1 : 0;
+ }
+
+ public move(): void {
+ this.position.x += this.movingVelocity.x * this.deltaTime.getDeltaTime();
+ this.position.y += this.movingVelocity.y * this.deltaTime.getDeltaTime();
+ }
+
+ public touchBottom(resetPoint: number) {
+ this.position.y = resetPoint - this.globals.playerSize.y - 1;
+ this.grounded = true;
+ if (this.id === this.globals.socketId) {
+ this.globals.sounds[1].play();
+ }
+ this.resetVelocity();
+ }
+
+ public touchTop(resetPoint: number) {
+ this.position.y = resetPoint + 1;
+ this.resetVelocity();
+ }
+
+ public touchLeft(resetPoint: number) {
+ this.position.x = resetPoint + 1;
+ this.resetVelocity();
+ }
+
+ public touchRight(resetPoint: number) {
+ this.position.x = resetPoint - this.globals.playerSize.x - 1;
+ this.resetVelocity();
+ }
+
+ public isMyself(): boolean {
+ return this.id === this.globals.socketId;
+ }
+
+ public draw() {
+ this.globals.context.drawImage(
+ this.globals.playerImages[this.color * 2 + this.direction],
+ this.position.x,
+ this.position.y,
+ this.globals.playerSize.x,
+ this.globals.playerSize.y,
+ );
+ this.globals.context.fillStyle = 'black';
+ this.globals.context.textAlign = 'center';
+ this.globals.context.font = '25px Arial';
+ this.globals.context.fillText(
+ this.name,
+ this.position.x + this.globals.playerSize.x / 2,
+ this.position.y - 30,
+ );
+ }
+}
diff --git a/src/app/home/players.ts b/src/app/home/players.ts
new file mode 100644
index 0000000..dc0101c
--- /dev/null
+++ b/src/app/home/players.ts
@@ -0,0 +1,98 @@
+import { applyGravity } from './applyGravity';
+import { Globals } from './globals';
+import { Player } from './player';
+import {
+ PlayerDTO,
+ PlayerDTOList,
+ PlayerList,
+ StringNumber,
+ StringVector,
+ Vector,
+} from './types.dto';
+
+export class Players {
+ private globals: Globals;
+ private players: PlayerList = {};
+ private static instance: Players;
+
+ private constructor() {
+ this.globals = Globals.getInstance();
+ }
+
+ public static getInstance(): Players {
+ if (!this.instance) {
+ this.instance = new Players();
+ }
+ return this.instance;
+ }
+
+ public tick(): void {
+ for (let id of this.getPlayerIds()) {
+ if (this.getPlayer(id).isGrounded()) {
+ continue;
+ }
+ this.getPlayer(id).applyGravity();
+ this.getPlayer(id).move();
+ }
+ }
+
+ public resetVelocity(id: string): void {
+ this.getPlayer(id).resetVelocity();
+ }
+
+ public resetMyVelocity(): void {
+ this.resetVelocity(this.globals.socketId);
+ }
+
+ public getPlayerIds(): string[] {
+ return Object.keys(this.players);
+ }
+
+ public getPlayer(id: string): Player {
+ return this.players[id];
+ }
+
+ public addMultiplaPlayers(players: PlayerDTOList): void {
+ for (let player of Object.keys(players)) {
+ this.addPlayer(players[player]);
+ }
+ }
+
+ public addPlayer(player: PlayerDTO): Players {
+ this.players[player.id] = new Player(player.id, player);
+ return this;
+ }
+
+ public removePlayer(id: string): Players {
+ delete this.players[id];
+ return this;
+ }
+
+ public updatePlayerPosition(playersPosition: StringVector): void {
+ for (let id of Object.keys(playersPosition)) {
+ this.getPlayer(id).updatePosition(playersPosition[id]);
+ }
+ }
+
+ public updatePlayerDirection(playersDirection: StringNumber): void {
+ for (let id of Object.keys(playersDirection)) {
+ this.getPlayer(id).updateDirection(playersDirection[id]);
+ }
+ }
+
+ public updatePlayerColor(playersColor: { [key: string]: number }): void {
+ for (let id of Object.keys(playersColor)) {
+ this.getPlayer(id).updateColor(playersColor[id]);
+ }
+ }
+
+ public getMyself(): Player {
+ return this.getPlayer(Globals.getInstance().socketId);
+ }
+
+ public draw(): void {
+ for (let id of this.getPlayerIds()) {
+ this.players[id].draw();
+ }
+ }
+}
diff --git a/src/app/home/scaleScreen.ts b/src/app/home/scaleScreen.ts
new file mode 100644
index 0000000..2bfcc6f
--- /dev/null
+++ b/src/app/home/scaleScreen.ts
@@ -0,0 +1,11 @@
+import { Globals } from "./globals";
+import { setCanvasSize } from "./setCanvasSize";
+
+export const scaleScreen = () => {
+ const scaleX = Globals.getInstance().pageWidth / 9;
+ const scaleY = Globals.getInstance().pageHeight / 16;
+ if (scaleX > scaleY) { // width is longer, calculate based on height
+ return setCanvasSize((Globals.getInstance().pageHeight / 16) * 9, Globals.getInstance().pageHeight);
+ }
+ setCanvasSize(Globals.getInstance().pageWidth, (Globals.getInstance().pageWidth / 9) * 16); // height is longer, calculate based on width
+ }
\ No newline at end of file
diff --git a/src/app/home/setCanvasSize.ts b/src/app/home/setCanvasSize.ts
new file mode 100644
index 0000000..38b67c6
--- /dev/null
+++ b/src/app/home/setCanvasSize.ts
@@ -0,0 +1,11 @@
+import { Globals } from "./globals";
+
+export const setCanvasSize = (w: number, h: number) => {
+ Globals.getInstance().canvasScale = 1920 / h;
+ Globals.getInstance().width = w * Globals.getInstance().canvasScale;
+ Globals.getInstance().height = h * Globals.getInstance().canvasScale;
+ Globals.getInstance().canvas.style.height = h + 'px';
+ Globals.getInstance().canvas.style.width = w + 'px';
+ Globals.getInstance().canvas.height = Globals.getInstance().height;
+ Globals.getInstance().canvas.width = Globals.getInstance().width;
+ }
\ No newline at end of file
diff --git a/src/app/home/types.dto.ts b/src/app/home/types.dto.ts
new file mode 100644
index 0000000..3820482
--- /dev/null
+++ b/src/app/home/types.dto.ts
@@ -0,0 +1,21 @@
+import { Position } from '../../../../Kawaii-Jumper-server/src/position';
+import { Player } from './player';
+
+export type PlayerDTO = {
+ id: string;
+ position: Position;
+ name: string;
+ movingVelocity: Position;
+ color: number;
+ direction: number;
+};
+
+export type PlayerList = { [key: string]: Player };
+export type PlayerDTOList = { [key: string]: PlayerDTO };
+
+export type Vector = { x: number; y: number };
+
+export type StringString = { [key: string]: string };
+export type StringNumber = { [key: string]: number };
+export type StringVector = { [key: string]: Vector };
+export type StringBoolean = { [key: string]: boolean };
diff --git a/src/assets/bg.png b/src/assets/bg.png
new file mode 100644
index 0000000..c025ccb
Binary files /dev/null and b/src/assets/bg.png differ
diff --git a/src/assets/jump.wav b/src/assets/jump.wav
new file mode 100644
index 0000000..90312f8
Binary files /dev/null and b/src/assets/jump.wav differ
diff --git a/src/assets/land.wav b/src/assets/land.wav
new file mode 100644
index 0000000..67022dc
Binary files /dev/null and b/src/assets/land.wav differ
diff --git a/src/assets/platform-1.png b/src/assets/platform-1.png
new file mode 100644
index 0000000..8ec790e
Binary files /dev/null and b/src/assets/platform-1.png differ
diff --git a/src/assets/platform-2.png b/src/assets/platform-2.png
new file mode 100644
index 0000000..841b529
Binary files /dev/null and b/src/assets/platform-2.png differ
diff --git a/src/assets/slime-1-left.png b/src/assets/slime-1-left.png
new file mode 100644
index 0000000..d762ba7
Binary files /dev/null and b/src/assets/slime-1-left.png differ
diff --git a/src/assets/slime-1-right.png b/src/assets/slime-1-right.png
new file mode 100644
index 0000000..13cd8f7
Binary files /dev/null and b/src/assets/slime-1-right.png differ
diff --git a/src/assets/slime-2-left.png b/src/assets/slime-2-left.png
new file mode 100644
index 0000000..0b25bf2
Binary files /dev/null and b/src/assets/slime-2-left.png differ
diff --git a/src/assets/slime-2-right.png b/src/assets/slime-2-right.png
new file mode 100644
index 0000000..bc096e3
Binary files /dev/null and b/src/assets/slime-2-right.png differ
diff --git a/src/index.html b/src/index.html
index 3b0aae1..897f0dd 100644
--- a/src/index.html
+++ b/src/index.html
@@ -11,6 +11,9 @@
+
+
+