diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 520a863..0000000 --- a/.gitignore +++ /dev/null @@ -1,55 +0,0 @@ -# Built application files -*.apk -*.ap_ - -# Files for the ART/Dalvik VM -*.dex - -# Java class files -*.class - -# Generated files -bin/ -gen/ -out/ - -# 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/dictionaries -.idea/libraries - -# Keystore files -*.jks - -# External native build folder generated in Android Studio 2.2 and later -.externalNativeBuild - -# Google Services (e.g. APIs or Firebase) -google-services.json - -# Freeline -freeline.py -freeline/ -freeline_project_description.json diff --git a/CODESTYLE.md b/CODESTYLE.md new file mode 100644 index 0000000..9a7348e --- /dev/null +++ b/CODESTYLE.md @@ -0,0 +1,62 @@ +# Code Style + +## Naming conventions + +* File names: PascalCase +* Folder names: PascalCase +* Class names: PascalCase +* Functions: camelCase +* Local variables: underscore_case +* Constants: SCREAMING_SNAKE_CASE + +## Class Style + +```Java +class Image { + + // Class vars + int example_int, example_int2; + boolean example_bool; + + public Image() {} + + /* DRAW */ + public void draw() {} + + /* SCALING */ + public void scale() {} + public void scale(double factor) {} + + /* EXAMPLE GROUP */ + public void exampleFunc() {} + public void exampleFunc2() { + + // Calculate something + calculate(); + calculateAgain(); + + // next group + doSomething(); + again(); + + } + + ... + +} +``` + +* Public functions and members at top, protected in middle, private at bottom +* Class variables at top, then constructor then special functions, divided into groups. +* Often, code is divided by comments. + +## Functions + +* Function names should be descriptive of what they do and should be a verb ("doing word") +* Functions which return "bool" should be a question eg + +```Java +boolean isXGreaterThan5 (int x) { + return x > 5; +} +``` diff --git a/License.txt b/License.txt new file mode 100644 index 0000000..9f3dec6 --- /dev/null +++ b/License.txt @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2018 Tim Ofenbach + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, +and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +Selling copies of the Software is forbidden! + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE diff --git a/README.md b/README.md index 5759a81..68ef5ec 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,43 @@ -# catengine -Easy to use 2D Framework for Android. - -# use cases -- creating simple 2D games - - animations/movements - - particle - - different screens (intro, menu, game, options etc) -- creating simple apps with animations, movements etc. - -# contact -Questions? Email me: tim@ofenba.ch +# catengine developer edition 😼 +Welcome to the developer-branch! +From here you can check out some of the new features that aren't available yet. + +See full changelog: engine/main/MainActivity.java + +# new features 💪 +The update is done! Release coming soon. ++ ✅ gravity support ++ ✅ save support ++ ✅ sprite support ++ ✅ automatic positions ++ ✅ better touch functions ++ ✅ improved codestyle + +# guide 📖 +1. Download the engine folder. +2. Import the folder into your app project (@src). +3. Fix the imports depending on your app/package name. +4. Create GameStart.java to load your screens. +6. Your app now runs catengine developer edition! + +# example 👀 +The example contains all new features that are available! + +# planned features 🤔 +Here's a list of features that will be implemented one day: ++ GUI version 😍 + + simple drag&drop to create apps 🖱️ + + simple kid-friendly coding 👶 ++ new effects (e.g. particles, explosions, fire) + +# donations 💸 +If you feel like supporting my work, feel free to donate: + +![alt text](https://steemit-production-imageproxy-upload.s3.amazonaws.com/DQmc8NTQJp8vubgKHs2DgFiRx9ie2BZRrpzfj99Nh6PnUn9) 31hwi7KqnCo2L4mmtm7FeQuarggVxMiRy8 +![alt text](https://steemit-production-imageproxy-upload.s3.amazonaws.com/DQmUJCKengMc25qYjBUKWodBUkXHb6m9VU47WnSTtwk46Qs) LVtnsswBGixXtBRm6a3nJths3QfABmSDZZ +![alt text](https://steemit-production-imageproxy-upload.s3.amazonaws.com/DQmdnnCcukhq9CAri1LaY9NGERrCNdexdwahAnLo8YFZ52K) 0xE6af1aaB8b26c88b36Af9bd0Fc16ced85EdB13d7 + +Thank you! ❤️ + +# contact ✉️ +Questions? Email me: tim@ofenba.ch diff --git a/engine/README.md b/engine/README.md new file mode 100644 index 0000000..f663571 --- /dev/null +++ b/engine/README.md @@ -0,0 +1,44 @@ +# Installation +1) Download main and framework folder. +2) Import them to your src folder in your android studio project. +3) Fix the imports depending on your package names (android studio will help you). +4) Create GameStart.java and your own screens. +5) Your app runs catengine. + +# Documentation + +## Image.java +Useful functions: + draw() + scale() + scale(double) + scaleFullscreen() + setAngle(int) + setAlpha(int) + getAngleTo(image): int + collidesWith(image): boolean + +## Button.java +Same as Image.java but can register touch. + isPressed(): boolean + +## Music.java +Basic functions: + play() + pause() + stop() + delete() + +## Sound.java +Basic functions: + play() + stop() + delete() + +## Device.java ++ get_screen_width(): int ++ get_screen_height(): int ++ setSavingInt(String, int) <- for saving numbers onto the device ++ setSavingBool(bool) <- for saving bool values onto the device ++ getSavingInt(String): int <- get int value of file (filename: parameter string) ++ getSavingBool(String): bool <-same with bool diff --git a/engine/framework/Button.java b/engine/framework/Button.java new file mode 100644 index 0000000..2b70889 --- /dev/null +++ b/engine/framework/Button.java @@ -0,0 +1,27 @@ +package ofenbach.exampleapp.framework; // change this to your package name + +import ofenbach.exampleapp.main.TouchEvent; // change this to your package name + +/* Same as Image.java but can register touch */ +/* @creation: March 2014 */ +/* @update: 25.4.2018 */ +/* @author: Tim B. Ofenbach */ + +public class Button extends Image { + + public Button(int path) { + super(path); + } + + public boolean isPressed() { + + // Touch coords + int touchX = TouchEvent.getX(); + int touchY = TouchEvent.getY(); + + // Hitbox check + return (touchX > super.getX() && touchX < super.getX() + super.getWidth() && touchY > super.getY() && touchY < super.getY() + super.getHeight()); + + } + +} \ No newline at end of file diff --git a/engine/framework/CollisionDetection.java b/engine/framework/CollisionDetection.java new file mode 100644 index 0000000..59157b0 --- /dev/null +++ b/engine/framework/CollisionDetection.java @@ -0,0 +1,64 @@ +package ofenbach.exampleapp.framework; // change this to your package name + +import android.graphics.Bitmap; +import android.graphics.Color; +import android.graphics.Rect; + +/* used by Image.java to detect collision between two images. */ + +public class CollisionDetection { + + /** + * @param bitmap1 First bitmap + * @param x1 x-position of bitmap1 on screen. + * @param y1 y-position of bitmap1 on screen. + * @param bitmap2 second bitmap + * @param x2 x-position of bitmap2 on screen. + * @param y2 y-position of bitmap2 on screen. + */ + + public static boolean isCollisionDetected(Bitmap bitmap1, int x1, int y1, Bitmap bitmap2, int x2, int y2) { + + Rect bounds1 = new Rect(x1, y1, x1+bitmap1.getWidth(), y1+bitmap1.getHeight()); + Rect bounds2 = new Rect(x2, y2, x2+bitmap2.getWidth(), y2+bitmap2.getHeight()); + + if (Rect.intersects(bounds1, bounds2)) { + Rect collisionBounds = getCollisionBounds(bounds1, bounds2); + + for (int i = collisionBounds.left; i < collisionBounds.right; i++) { + + for (int j = collisionBounds.top; j < collisionBounds.bottom; j++) { + + int bitmap1Pixel = bitmap1.getPixel(i-x1, j-y1); + int bitmap2Pixel = bitmap2.getPixel(i-x2, j-y2); + + if (isFilled(bitmap1Pixel) && isFilled(bitmap2Pixel)) { + return true; + } + + } + + } + + } + + return false; + + } + + private static Rect getCollisionBounds(Rect rect1, Rect rect2) { + + int left = (int) Math.max(rect1.left, rect2.left); + int top = (int) Math.max(rect1.top, rect2.top); + int right = (int) Math.min(rect1.right, rect2.right); + int bottom = (int) Math.min(rect1.bottom, rect2.bottom); + + return new Rect(left, top, right, bottom); + + } + + private static boolean isFilled(int pixel) { + return pixel != Color.TRANSPARENT; + } + +} \ No newline at end of file diff --git a/engine/framework/Image.java b/engine/framework/Image.java new file mode 100644 index 0000000..6bf1b11 --- /dev/null +++ b/engine/framework/Image.java @@ -0,0 +1,236 @@ +package ofenbach.exampleapp.framework; // change this to your package name + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Matrix; +import android.graphics.Paint; + +import ofenbach.exampleapp.main.Device; // change this to your package name +import ofenbach.exampleapp.main.MainActivity; // change this to your package name +import ofenbach.exampleapp.main.MainView; // change this to your package name + +/* able to display .png pictures*/ +/* @creation: February 2014 */ +/* @update: 28.4.2018 */ +/* @author: Tim B. Ofenbach */ + +/* update news 28.4.2018: + + added auomatic positions + + added gravity support + + improved comments + */ + +public class Image { + + // file + Bitmap bitmap; + int path; + + // position & angle + public double x, y; + int angle; + + // rotation & transparency + Matrix m; + Paint p; + + // gravity + public double gravity_factor, gravity_timer; + + /* CONSTRUCTOR */ + public Image(int path) { + + this.path = path; // save path + + m = new Matrix(); // initialize everything + p = new Paint(); + + // bitmap creation + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inScaled = false; + bitmap = BitmapFactory.decodeResource(MainActivity.context.getResources(), path, options); + + } + + /* DRAW */ + public void draw() { + + // angle & position settings + m.reset(); + m.postRotate(angle, bitmap.getWidth() / 2, bitmap.getHeight() / 2); + m.postTranslate((float) (x/1920)*Device.get_screen_width(), (float) (y/1080)*Device.get_screen_height()); + + // apply gravity + if (gravity_factor != 0) { + this.applyGravity(); + } + + // draw + MainView.global_canvas.drawBitmap(bitmap, m, p); + + } + + /* SCALING */ + public void scale() { + + // calculation + double ratio = (double) bitmap.getHeight() / (double) bitmap.getWidth(); + double real_width = Device.get_screen_width() * ((double) bitmap.getWidth() / 480); + double real_height = real_width * ratio;; + + // scaling + bitmap = Bitmap.createScaledBitmap(bitmap, (int) real_width, (int) real_height, false); + + } + public void scale(double factor) { + + // calculation + double relative_width = 1080 / (factor * bitmap.getWidth()); + double ratio = (double) bitmap.getHeight() / (double) bitmap.getWidth(); + double width = Device.get_screen_width() / relative_width; + double height = ratio * width; + + // scaling + bitmap = Bitmap.createScaledBitmap(bitmap, (int) width, (int) height, false); + + } + public void scaleFullscreen() { + bitmap = Bitmap.createScaledBitmap(bitmap, Device.get_screen_width(), Device.get_screen_height(), false); + } + + /* SET FUNCTIONS */ + public void setAlpha(int alpha) { + p.setAlpha(alpha); + } + public void setTransparency(double percent) { + int real_value = (int) percent * 255; // conversion from percent to 0-255 + p.setAlpha(real_value); + } + public void move(double distance) { + + // calculation + double distanceX = distance * Math.sin(angle); + double distanceY = distance * Math.cos(angle); + + // update x y + x += distanceX; + y += distanceY; + + } + public void goTo(int xPos, int yPos) { + x = xPos; + y = yPos; + } + public void setX(double xPos) { + this.x = xPos; + } + public void setXtoMiddle() { + // old way: this.x = Device.get_screen_width() / 2 - this.getWidth() / 2; + x = 1920 / 2 - getWidth() / 2; + } + public void setY(double yPos) { + this.y = yPos; + } + public void setYtoMiddle() { + //old way: this.y = Device.get_screen_height() / 2 - this.getHeight() / 2; + y = 1080 / 2 - getHeight() / 2; // new way: relative/automatic + } + public void setAngle(double angle) { + this.angle = (int) angle; + m.reset(); + m.postRotate((int) angle, bitmap.getWidth() / 2, bitmap.getHeight() / 2); + m.postTranslate((int) x, (int) y); + } + + /* GET FUNCTIONS */ + public double getX() { + return x; + } + public double getY() { + return y; + } + public int getWidth() { + return bitmap.getWidth(); + } + public int getHeight() { + return bitmap.getHeight(); + } + public int getAngle() { + return angle; + } + public double getAngleTo(Image image) { + + /* outdated, works but not recommended to use. */ + + // Vars + double delta_x; + double delta_y; + double hypo; // Pythagoras + double angle = 0; + + // ∆-X + if (image.x > this.x) { + delta_x = image.x - this.x; + } else { + delta_x = this.x - image.x; + } + + // ∆Y + // Wenn Image unter diesem Image + if (image.y > this.y) { + delta_y = image.y - this.y; + } else { // Wenn Image ueber diesem Image + delta_y = this.y - image.y; + } + + // Satz des Pythagoras a^2 + b^2 = c^2 + // <=> sin(alpha) = Gegenkathete (∆x) / Hypothenuse (Wurzel aus (∆x^2 + ∆y^2)) + // <=> alpha = arcsin(∆x / (sqrt(∆x^2+∆y^2) + hypo = Math.sqrt(delta_x*delta_x + delta_y*delta_y); + angle = Math.asin( delta_y / hypo ); // alpha = arcsin(gegenkathete / hypo) + angle = Math.toDegrees(angle); + + // Umkehrung des Winkels wenn Image "tiefer" als dieses Image ist + if (image.y > this.y) { + angle = -angle; + } + + return angle; + } + public int getAlpha() { + return p.getAlpha(); + } + public Bitmap getBitmap() { + return bitmap; + } + public boolean isInScreen() { + return (this.x > -this.getWidth() && this.x < Device.get_screen_width() && this.y > -this.getHeight() && this.y < Device.get_screen_height()); + } + + /* COLLISION */ + public boolean collidesWith(Image image) { + // See CollisionDetection.java + return CollisionDetection.isCollisionDetected(bitmap, (int) x, (int) y, image.bitmap, (int) image.x, (int) image.y); + } + + /* GRAVITY */ + public void setGravity(double factor) { // e.g. factor=9.81, factor = 0 -> false, factor != 0 -> true + this.gravity_factor = factor; + } + public void applyGravity() { // updates gravity movement (put this in your repeat()) + this.y += gravity_timer* gravity_factor; + this.gravity_timer += 0.016*4; + } + public void increaseGravity(int increase) { + this.gravity_timer += increase; + } + public void setGravityTimer(int value) { + this.gravity_timer = value; + } + + /* DELETE */ + public void delete() { + bitmap.recycle(); + } + +} diff --git a/engine/framework/Music.java b/engine/framework/Music.java new file mode 100644 index 0000000..ed78179 --- /dev/null +++ b/engine/framework/Music.java @@ -0,0 +1,68 @@ +package ofenbach.exampleapp.framework; // change this to your package name + +import android.media.MediaPlayer; + +import ofenbach.exampleapp.main.MainActivity; +import ofenbach.exampleapp.main.Settings; // change this to your package name + +/* Music.java to play simple background music in your app */ +/* @creation: May 2014 */ +/* @update: 28.4.2018 */ +/* @author: Tim B. Ofenbach */ + +/* update news 28.4.2018: + + turns off when Settings.sound_on is false + - removed unnecessary comments + */ + +public class Music { + + MediaPlayer mediaplayer; + int path; + + boolean isPrepared; + + public Music(int path) { + + this.path = path; + + mediaplayer = new MediaPlayer(); + mediaplayer = MediaPlayer.create(MainActivity.context, path); // load music + + } + + public void play() { + if (Settings.sound_enabled()) { + mediaplayer.start(); + } + } + + public void stop() { + mediaplayer.stop(); + synchronized (this) { + isPrepared = false; + } + } + + public void pause() { + if (mediaplayer.isPlaying()) { + mediaplayer.pause(); + } + } + + public void setVolume(float volume) { + mediaplayer.setVolume(volume, volume); + } + + public void setLooping(boolean looping) { + mediaplayer.setLooping(looping); + } + + public void delete() { + if (mediaplayer.isPlaying()) { + mediaplayer.stop(); + } + mediaplayer.release(); + } + +} diff --git a/engine/framework/Sound.java b/engine/framework/Sound.java new file mode 100644 index 0000000..ee0d929 --- /dev/null +++ b/engine/framework/Sound.java @@ -0,0 +1,44 @@ +package ofenbach.exampleapp.framework; // change this to your package name + +import android.media.AudioManager; +import android.media.SoundPool; + +import ofenbach.exampleapp.main.MainActivity; // change this to your package name +import ofenbach.exampleapp.main.Settings; // change this to your package name + +/* to create simple sounds in your app (e.g. explosions, gunshots). */ +/* @creation: May 2014 */ +/* @update: 25.4.2018 */ +/* @author: Tim B. Ofenbach */ + +/* update news 28.4.2018: + + turns off when Settings.sound_on is false + - removed unnecessary comments + */ + + +public class Sound { + + SoundPool soundPool; + int path; + + public Sound(int sound_direction) { + soundPool = new SoundPool(5, AudioManager.STREAM_MUSIC, 0); + this.path = soundPool.load(MainActivity.context, sound_direction, 1); + } + + public void play() { + if (Settings.sound_enabled()) { + soundPool.play(path, 1, 1, 0, 0, 1); + } + } + + public void setVolume(double procent) { + soundPool.setVolume(path, (float) procent, (float) procent); + } + + public void delete() { + soundPool.unload(path); + } + +} diff --git a/engine/framework/Sprite.java b/engine/framework/Sprite.java new file mode 100644 index 0000000..e697f5a --- /dev/null +++ b/engine/framework/Sprite.java @@ -0,0 +1,94 @@ +package ofenbach.exampleapp.framework; // change this to your package name + +import java.util.ArrayList; +import java.util.List; + +/* @creation: 28.4.2018 */ +/* @update: - */ +/* @author: Tim B. Ofenbach */ + +public class Sprite { + + public List images = new ArrayList<>(); // list with pictures + + int current_pic; // current pic to display + double duration; // how long each pic will display / change between the pics (in sec) + double complete_duration; // #pictures*duration + boolean animation; // to start the animation + double timer; // animationtimer + + public Sprite(int[] pictures, double duration) { + + // parameter update + this.duration = duration; + this.timer = duration; + this.complete_duration = pictures.length * duration; + + // load + for (int i = 0; i screens = new ArrayList<>(); // child list (used by MainView to display the right screen) + + public Screen() { + screens.add(this); // save child + } + + /* @override */ + public void repeat() {} // loop 60FPS + public void load() {} // when the screen starts + public void touchHold() {} // triggered by touch + public void touchDown() {} + public void touchUp() { } + +} diff --git a/engine/main/Settings.java b/engine/main/Settings.java new file mode 100644 index 0000000..c25b911 --- /dev/null +++ b/engine/main/Settings.java @@ -0,0 +1,23 @@ +package ofenbach.exampleapp.main; // change this to your package name + +/* class with mostly statics, to save your app settings */ +/* @creation: September 2016 */ +/* @update: 28.4.2018 */ +/* @author: Tim B. Ofenbach */ + +/* Explanation: */ +/* You should also save your app settings (e.g. sound on) here. */ + +public class Settings { + + public static boolean sound_on = Device.getSavingBool("sound_on"); + + public static void set_sound_enabled(boolean sound_on) { + this.sound_on = sound_on; + Device.setSavingBool("sound_on", sound_on); + } + public static boolean sound_enabled() { + return sound_on; + } + +} diff --git a/engine/main/TouchEvent.java b/engine/main/TouchEvent.java new file mode 100644 index 0000000..19e758c --- /dev/null +++ b/engine/main/TouchEvent.java @@ -0,0 +1,24 @@ +package ofenbach.exampleapp.main; // change this to your package name + +import android.view.MotionEvent; + +/* @creation: March 2018 */ +/* @update: 25.4.2018 */ +/* @author: Tim B. Ofenbach */ + +/* Explanation: */ +/* touch-events can be accessed now from everywhere thanks to this class */ + +public class TouchEvent { + + public static MotionEvent touch_event; // to access coordinations, action-event etc. + + public static int getX() { + return (int) touch_event.getX(); + } + + public static int getY() { + return (int) touch_event.getY(); + } + +} diff --git a/example/ExampleApp/.gitignore b/example/ExampleApp/.gitignore new file mode 100644 index 0000000..5edb4ee --- /dev/null +++ b/example/ExampleApp/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +.DS_Store +/build +/captures +.externalNativeBuild diff --git a/example/ExampleApp/.idea/caches/build_file_checksums.ser b/example/ExampleApp/.idea/caches/build_file_checksums.ser new file mode 100644 index 0000000..c8c4610 Binary files /dev/null and b/example/ExampleApp/.idea/caches/build_file_checksums.ser differ diff --git a/example/ExampleApp/.idea/codeStyles/Project.xml b/example/ExampleApp/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..30aa626 --- /dev/null +++ b/example/ExampleApp/.idea/codeStyles/Project.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/example/ExampleApp/.idea/gradle.xml b/example/ExampleApp/.idea/gradle.xml new file mode 100644 index 0000000..7ac24c7 --- /dev/null +++ b/example/ExampleApp/.idea/gradle.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/example/ExampleApp/.idea/misc.xml b/example/ExampleApp/.idea/misc.xml new file mode 100644 index 0000000..99202cc --- /dev/null +++ b/example/ExampleApp/.idea/misc.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/example/ExampleApp/.idea/runConfigurations.xml b/example/ExampleApp/.idea/runConfigurations.xml new file mode 100644 index 0000000..7f68460 --- /dev/null +++ b/example/ExampleApp/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/example/ExampleApp/app/.gitignore b/example/ExampleApp/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/example/ExampleApp/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/example/ExampleApp/app/build.gradle b/example/ExampleApp/app/build.gradle new file mode 100644 index 0000000..6305b95 --- /dev/null +++ b/example/ExampleApp/app/build.gradle @@ -0,0 +1,26 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 27 + defaultConfig { + applicationId "ofenbach.exampleapp.main" + minSdkVersion 15 + targetSdkVersion 27 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.1' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' +} diff --git a/example/ExampleApp/app/proguard-rules.pro b/example/ExampleApp/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/example/ExampleApp/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/example/ExampleApp/app/src/androidTest/java/ofenbach/exampleapp/main/ExampleInstrumentedTest.java b/example/ExampleApp/app/src/androidTest/java/ofenbach/exampleapp/main/ExampleInstrumentedTest.java new file mode 100644 index 0000000..a7f3ebb --- /dev/null +++ b/example/ExampleApp/app/src/androidTest/java/ofenbach/exampleapp/main/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package ofenbach.exampleapp.main; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("ofenbach.exampleapp.main", appContext.getPackageName()); + } +} diff --git a/example/ExampleApp/app/src/main/AndroidManifest.xml b/example/ExampleApp/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..6c9d143 --- /dev/null +++ b/example/ExampleApp/app/src/main/AndroidManifest.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/example/ExampleApp/app/src/main/java/ofenbach/exampleapp/framework/Button.java b/example/ExampleApp/app/src/main/java/ofenbach/exampleapp/framework/Button.java new file mode 100644 index 0000000..2b70889 --- /dev/null +++ b/example/ExampleApp/app/src/main/java/ofenbach/exampleapp/framework/Button.java @@ -0,0 +1,27 @@ +package ofenbach.exampleapp.framework; // change this to your package name + +import ofenbach.exampleapp.main.TouchEvent; // change this to your package name + +/* Same as Image.java but can register touch */ +/* @creation: March 2014 */ +/* @update: 25.4.2018 */ +/* @author: Tim B. Ofenbach */ + +public class Button extends Image { + + public Button(int path) { + super(path); + } + + public boolean isPressed() { + + // Touch coords + int touchX = TouchEvent.getX(); + int touchY = TouchEvent.getY(); + + // Hitbox check + return (touchX > super.getX() && touchX < super.getX() + super.getWidth() && touchY > super.getY() && touchY < super.getY() + super.getHeight()); + + } + +} \ No newline at end of file diff --git a/example/ExampleApp/app/src/main/java/ofenbach/exampleapp/framework/CollisionDetection.java b/example/ExampleApp/app/src/main/java/ofenbach/exampleapp/framework/CollisionDetection.java new file mode 100644 index 0000000..59157b0 --- /dev/null +++ b/example/ExampleApp/app/src/main/java/ofenbach/exampleapp/framework/CollisionDetection.java @@ -0,0 +1,64 @@ +package ofenbach.exampleapp.framework; // change this to your package name + +import android.graphics.Bitmap; +import android.graphics.Color; +import android.graphics.Rect; + +/* used by Image.java to detect collision between two images. */ + +public class CollisionDetection { + + /** + * @param bitmap1 First bitmap + * @param x1 x-position of bitmap1 on screen. + * @param y1 y-position of bitmap1 on screen. + * @param bitmap2 second bitmap + * @param x2 x-position of bitmap2 on screen. + * @param y2 y-position of bitmap2 on screen. + */ + + public static boolean isCollisionDetected(Bitmap bitmap1, int x1, int y1, Bitmap bitmap2, int x2, int y2) { + + Rect bounds1 = new Rect(x1, y1, x1+bitmap1.getWidth(), y1+bitmap1.getHeight()); + Rect bounds2 = new Rect(x2, y2, x2+bitmap2.getWidth(), y2+bitmap2.getHeight()); + + if (Rect.intersects(bounds1, bounds2)) { + Rect collisionBounds = getCollisionBounds(bounds1, bounds2); + + for (int i = collisionBounds.left; i < collisionBounds.right; i++) { + + for (int j = collisionBounds.top; j < collisionBounds.bottom; j++) { + + int bitmap1Pixel = bitmap1.getPixel(i-x1, j-y1); + int bitmap2Pixel = bitmap2.getPixel(i-x2, j-y2); + + if (isFilled(bitmap1Pixel) && isFilled(bitmap2Pixel)) { + return true; + } + + } + + } + + } + + return false; + + } + + private static Rect getCollisionBounds(Rect rect1, Rect rect2) { + + int left = (int) Math.max(rect1.left, rect2.left); + int top = (int) Math.max(rect1.top, rect2.top); + int right = (int) Math.min(rect1.right, rect2.right); + int bottom = (int) Math.min(rect1.bottom, rect2.bottom); + + return new Rect(left, top, right, bottom); + + } + + private static boolean isFilled(int pixel) { + return pixel != Color.TRANSPARENT; + } + +} \ No newline at end of file diff --git a/example/ExampleApp/app/src/main/java/ofenbach/exampleapp/framework/Image.java b/example/ExampleApp/app/src/main/java/ofenbach/exampleapp/framework/Image.java new file mode 100644 index 0000000..e7f3801 --- /dev/null +++ b/example/ExampleApp/app/src/main/java/ofenbach/exampleapp/framework/Image.java @@ -0,0 +1,262 @@ +package ofenbach.exampleapp.framework; // change this to your package name + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Matrix; +import android.graphics.Paint; + +import ofenbach.exampleapp.main.Device; +import ofenbach.exampleapp.main.MainActivity; +import ofenbach.exampleapp.main.MainView; // change this to your package name + +/* able to display .png pictures*/ +/* @creation: February 2014 */ +/* @update: 28.4.2018 */ +/* @author: Tim B. Ofenbach */ + +/* update news 28.4.2018: + + added auomatic positions + + added gravity support + + improved comments + */ + +public class Image { + + // Bitmap & Path + Bitmap bitmap; + int path; + + // Position & Angle + public double x = 0; // width: 1920 + public double y = 0; // height: 1080 + int angle; + + // Matrix & Paint (rotation & transparency) + Matrix m; + Paint p; + + // Gravity + public double gravity_factor; + public double gravity_timer; + + + /* CONSTRUCTOR */ + public Image(int path) { + + this.path = path; // parameter update + + m = new Matrix(); + p = new Paint(); + + // Bitmap Creation + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inScaled = false; + bitmap = BitmapFactory.decodeResource(MainActivity.context.getResources(), path, options); + + } + + + /* DRAW */ + public void draw() { + + // Anglesettings + m.reset(); + m.postRotate(angle, bitmap.getWidth() / 2, bitmap.getHeight() / 2); + m.postTranslate((float) (x/1920)*Device.get_screen_width(), (float) (y/1080)*Device.get_screen_height()); + + // Gravity + if (gravity_factor != 0) { + this.applyGravity(); + } + + // Draw + MainView.global_canvas.drawBitmap(bitmap, m, p); + + } + + + /* SCALING */ + public void scale(double factor) { + + // Calculation + double relativewidth = 1080 / (factor * bitmap.getWidth()); + double ratio = (double) bitmap.getHeight() / (double) bitmap.getWidth(); + double width = Device.get_screen_width() / relativewidth; + double height = ratio * width; + + // Scaling + bitmap = Bitmap.createScaledBitmap(bitmap, (int) width, (int) height, false); + + } + public void scaleFullscreen() { + bitmap = Bitmap.createScaledBitmap(bitmap, Device.get_screen_width(), Device.get_screen_height(), false); + } + public void scale() { + + // Calculation + double ratio = (double) bitmap.getHeight() / (double) bitmap.getWidth(); + double realwidth = Device.get_screen_width() * ((double) bitmap.getWidth()*2 / 480); + double realheight = realwidth * ratio;; + + // Scaling + bitmap = Bitmap.createScaledBitmap(bitmap, (int) realwidth, (int) realheight, false); + + } + public void scaleHalf() { + + // Calculation + double ratio = (double) bitmap.getHeight() / (double) bitmap.getWidth(); + double realwidth = Device.get_screen_width() * ((double) bitmap.getWidth() / 480); + double realheight = realwidth * ratio;; + + // Scaling + bitmap = Bitmap.createScaledBitmap(bitmap, (int) realwidth, (int) realheight, false); + + } + + + /* SET FUNCTIONS */ + public void setAlpha(int alpha) { + p.setAlpha(alpha); + } + public void move(double distance) { + + // Calculation + double distanceX = distance * Math.sin(angle); + double distanceY = distance * Math.cos(angle); + + // Update X Y + x += distanceX; + y += distanceY; + + } + public void goTo(int xPos, int yPos) { + x = xPos; + y = yPos; + } + public void setX(double xPos) { + this.x = xPos; + } + public void setXtoMiddle() { + //this.x = Device.get_screen_width() / 2 - this.getWidth() / 2; // old way + x = 1920 / 2 - getWidth() / 2; + } + public void setY(double yPos) { + this.y = yPos; + } + public void setYtoMiddle() { + //this.y = Device.get_screen_height() / 2 - this.getHeight() / 2; // old way: relative but still absolut + y = 1080 / 2 - getHeight() / 2; // new way: relative/automatic + } + public void setRotation(double angle) { + this.angle = (int) angle; + m.reset(); + m.postRotate((int) angle, bitmap.getWidth() / 2, bitmap.getHeight() / 2); + m.postTranslate((int) x, (int) y); + } + + + /* GET FUNCTIONS */ + public double getX() { + return x; + } + public double getY() { + return y; + } + public int getWidth() { + return bitmap.getWidth(); + } + public int getHeight() { + return bitmap.getHeight(); + } + public int getAngle() { + return angle; + } + public double getAngleTo(Image image) { + + // Vars + double delta_x; + double delta_y; + double hypo; // Pythagoras + double angle = 0; + + // ∆-X + if (image.x > this.x) { + delta_x = image.x - this.x; + } else { + delta_x = this.x - image.x; + } + + // ∆Y + // Wenn Image unter diesem Image + if (image.y > this.y) { + delta_y = image.y - this.y; + } else { // Wenn Image ueber diesem Image + delta_y = this.y - image.y; + } + + // Satz des Pythagoras a^2 + b^2 = c^2 + // <=> sin(alpha) = Gegenkathete (∆x) / Hypothenuse (Wurzel aus (∆x^2 + ∆y^2)) + // <=> alpha = arcsin(∆x / (sqrt(∆x^2+∆y^2) + hypo = Math.sqrt(delta_x*delta_x + delta_y*delta_y); + angle = Math.asin( delta_y / hypo ); // alpha = arcsin(gegenkathete / hypo) + angle = Math.toDegrees(angle); + + // Umkehrung des Winkels wenn Image "tiefer" als dieses Image ist + if (image.y > this.y) { + angle = -angle; + } + + return angle; + } + public int getAlpha() { + return p.getAlpha(); + } + public Bitmap getBitMap() { + return bitmap; + } + + + /* COLLISION */ + public boolean collidesWith(Image image) { + + // See CollisionDetection.java + return CollisionDetection.isCollisionDetected(bitmap, (int) x, (int) y, image.bitmap, (int) image.x, (int) image.y); + + } + + + /* GRAVITY */ + public void setGravity(double factor) { // e.g. factor=9.81, factor = 0 -> false, factor != 0 -> true + this.gravity_factor = factor; + } + public void applyGravity() { // updates gravity movement (put this in your repeat()) + this.y += gravity_timer* gravity_factor; + this.gravity_timer += 0.016*4; + } + public void increaseGravity(int increase) { + this.gravity_timer += increase; + } + + + /* ON SCREEN? */ + public boolean isInScreen() { + if (this.x > -this.getWidth() && this.x < Device.get_screen_width()) { + if (this.y > -this.getHeight() && this.y < Device.get_screen_height()) { + return true; + } else { + return false; + } + } else { + return false; + } + } + + + /* DELETE */ + public void delete() { + bitmap.recycle(); + } + + +} \ No newline at end of file diff --git a/example/ExampleApp/app/src/main/java/ofenbach/exampleapp/framework/Music.java b/example/ExampleApp/app/src/main/java/ofenbach/exampleapp/framework/Music.java new file mode 100644 index 0000000..e01da8f --- /dev/null +++ b/example/ExampleApp/app/src/main/java/ofenbach/exampleapp/framework/Music.java @@ -0,0 +1,69 @@ +package ofenbach.exampleapp.framework; // change this to your package name + +import android.media.MediaPlayer; + +import ofenbach.exampleapp.main.MainActivity; +import ofenbach.exampleapp.main.Settings; // change this to your package name + +/* Music.java to play simple background music in your app */ +/* @creation: May 2014 */ +/* @update: 28.4.2018 */ +/* @author: Tim B. Ofenbach */ + +/* update news 28.4.2018: + + turns off when Settings.sound_on is false + - removed unnecessary comments + */ + +public class Music { + + MediaPlayer mediaplayer; + + int path; + boolean isPrepared; + + public Music(int path) { + + this.path = path; // update path + + mediaplayer = new MediaPlayer(); + mediaplayer = MediaPlayer.create(MainActivity.context, path); // load music + + } + + public void play() { + if (Settings.sound_enabled()) { + mediaplayer.start(); + } + } + + public void stop() { + mediaplayer.stop(); + synchronized (this) { + isPrepared = false; + } + } + + public void pause() { + if (mediaplayer.isPlaying()) { + mediaplayer.pause(); + } + } + + public void setVolume(float volume) { + mediaplayer.setVolume(volume, volume); + } + + public void setLooping(boolean looping) { + mediaplayer.setLooping(looping); + } + + public void delete() { + if (mediaplayer.isPlaying()) { + mediaplayer.stop(); + } + mediaplayer.release(); + } + + +} \ No newline at end of file diff --git a/example/ExampleApp/app/src/main/java/ofenbach/exampleapp/framework/Sound.java b/example/ExampleApp/app/src/main/java/ofenbach/exampleapp/framework/Sound.java new file mode 100644 index 0000000..d5382ba --- /dev/null +++ b/example/ExampleApp/app/src/main/java/ofenbach/exampleapp/framework/Sound.java @@ -0,0 +1,49 @@ +package ofenbach.exampleapp.framework; // change this to your package name + +import android.media.AudioManager; +import android.media.SoundPool; + +import ofenbach.exampleapp.main.MainActivity; +import ofenbach.exampleapp.main.Settings; // change this to your package name + +/* to create simple sounds in your app (e.g. explosions, gunshots). */ +/* @creation: May 2014 */ +/* @update: 25.4.2018 */ +/* @author: Tim B. Ofenbach */ + +/* update news 28.4.2018: + + turns off when Settings.sound_on is false + - removed unnecessary comments + */ + + +public class Sound { + + SoundPool soundPool; + + int path; + + + public Sound(int sound_direction) { + soundPool = new SoundPool(5, AudioManager.STREAM_MUSIC, 0); + this.path = soundPool.load(MainActivity.context, sound_direction, 1); + } + + + public void play() { + if (Settings.sound_enabled()) { + soundPool.play(path, 1, 1, 0, 0, 1); + } + } + + + public void setVolume(double procent) { + soundPool.setVolume(path, (float) procent, (float) procent); + } + + + public void delete() { + soundPool.unload(path); + } + +} \ No newline at end of file diff --git a/example/ExampleApp/app/src/main/java/ofenbach/exampleapp/framework/Sprite.java b/example/ExampleApp/app/src/main/java/ofenbach/exampleapp/framework/Sprite.java new file mode 100644 index 0000000..63d7115 --- /dev/null +++ b/example/ExampleApp/app/src/main/java/ofenbach/exampleapp/framework/Sprite.java @@ -0,0 +1,100 @@ +package ofenbach.exampleapp.framework; // change this to your package name + +import java.util.ArrayList; +import java.util.List; + +/* @creation: 28.4.2018 */ +/* @update: - */ +/* @author: Tim B. Ofenbach */ + +public class Sprite { + + public List images = new ArrayList<>(); // list with pictures + + int current_pic; // current pic to display + double duration; // how long each pic will display / change between the pics (in sec) + double complete_duration; // #pictures*duration + boolean animation; // to start the animation + double timer; // animationtimer + + + public Sprite(int[] pictures, double duration) { + + // parameter update + this.duration = duration; + this.timer = duration; + this.complete_duration = pictures.length * duration; + + // load + for (int i = 0; i screens = new ArrayList<>(); // child list (used by MainView to display the right screen) + + public Screen() { + screens.add(this); // save child + } + + public void repeat() {} // loop 60FPS + + public void load() {} // when the screen starts + + public void touchHold() {} // triggered by touch + + public void touchDown() {} + + public void touchUp() { } + +} diff --git a/example/ExampleApp/app/src/main/java/ofenbach/exampleapp/main/Settings.java b/example/ExampleApp/app/src/main/java/ofenbach/exampleapp/main/Settings.java new file mode 100644 index 0000000..82b13d6 --- /dev/null +++ b/example/ExampleApp/app/src/main/java/ofenbach/exampleapp/main/Settings.java @@ -0,0 +1,30 @@ +package ofenbach.exampleapp.main; // change this to your package name + +/* class with mostly statics, to save your app settings */ +/* @creation: September 2016 */ +/* @update: 28.4.2018 */ +/* @author: Tim B. Ofenbach */ + +public class Settings { + + /* Explanation: */ + /* You should also save your app settings (e.g. sound on) here. */ + + public static boolean sound_on = Device.getSavingBool("sound_on"); + + + public static void set_sound_enabled(boolean bool) { + sound_on = bool; + // save + if (bool) { + Device.setSaving("sound_on", 1); + } else { + Device.setSaving("sound_on", 0); + } + } + public static boolean sound_enabled() { + return sound_on; + } + + +} diff --git a/example/ExampleApp/app/src/main/java/ofenbach/exampleapp/main/TouchEvent.java b/example/ExampleApp/app/src/main/java/ofenbach/exampleapp/main/TouchEvent.java new file mode 100644 index 0000000..51cd2a2 --- /dev/null +++ b/example/ExampleApp/app/src/main/java/ofenbach/exampleapp/main/TouchEvent.java @@ -0,0 +1,24 @@ +package ofenbach.exampleapp.main; // change this to your package name + +import android.view.MotionEvent; + +/* @creation: March 2018 */ +/* @update: 25.4.2018 */ +/* @author: Tim B. Ofenbach */ + +public class TouchEvent { + + /* Explanation: */ + /* touch-events can be accessed now from everywhere thanks to this class */ + + public static MotionEvent touch_event; // to access coordinations, action-event etc. + + public static int getX() { + return (int) touch_event.getX(); + } + + public static int getY() { + return (int) touch_event.getY(); + } + +} diff --git a/example/ExampleApp/app/src/main/java/ofenbach/exampleapp/views/ExampleScreen.java b/example/ExampleApp/app/src/main/java/ofenbach/exampleapp/views/ExampleScreen.java new file mode 100644 index 0000000..b0bfa3c --- /dev/null +++ b/example/ExampleApp/app/src/main/java/ofenbach/exampleapp/views/ExampleScreen.java @@ -0,0 +1,101 @@ +package ofenbach.exampleapp.views; + +import ofenbach.exampleapp.framework.Image; +import ofenbach.exampleapp.framework.Sprite; +import ofenbach.exampleapp.main.R; +import ofenbach.exampleapp.main.Screen; + +/* @creation: 25.4.2018 */ +/* @author: Tim B. Ofenbach */ + +/* update news 28.4.2018: + + added particle animation + + new gravity support used + + automatic positions used + + new touch functions added + */ + + +public class ExampleScreen extends Screen { + + /** FEEL FREE TO EDIT THIS AND PLAY WITH IT! **/ + + // Create Images like this: + Image background; + Image player; + Image floor_1, floor_2, floor_3; + + Sprite particle; + + double gravitytimer, sintimer; // for the players gravity + + public void load() { + + // Load them like this (put your .png in the res/drawable folder + background = new Image(R.drawable.backdrop); + player = new Image(R.drawable.player); + floor_1 = new Image(R.drawable.floor_1); + floor_2 = new Image(R.drawable.floor_2); + floor_3 = new Image(R.drawable.floor_3); + particle = new Sprite(new int[] {R.drawable.dust_1, R.drawable.dust_2, R.drawable.dust_3, + R.drawable.dust_4, R.drawable.dust_5, R.drawable.dust_6, R.drawable.dust_7}, 0.04); + + // Scale them like this (depending on your wish, use different scale functions, see Image.java) + background.scaleFullscreen(); + player.scaleHalf(); + floor_1.scaleHalf(); + floor_2.scaleHalf(); + floor_3.scaleHalf(); + particle.scaleHalf(); + + // Set your positions like this. Now works with the same resolution (virtual) on every device! + player.setXtoMiddle(); + player.setYtoMiddle(); + floor_1.setX(0); + floor_1.setY(1080 - floor_1.getHeight() * 0.65); + floor_2.setX(0); + floor_2.setY(floor_1.getY() - floor_2.getHeight()*0.45); + floor_3.setY(floor_2.getY() - floor_3.getHeight() * 0.45); + for (int i = 0; i < particle.images.size(); i ++) { + particle.setX(i,(int) player.getX() + player.getWidth() / 2 - particle.getWidth(i) / 2); + particle.setY(i,(int) (1080 * 0.81)); + } + + // Apply game functions + player.setGravity(9.81); // 9.81 earth gravity + + } + + + public void repeat() { + + // Bounce Check + if (player.y >= floor_2.y - floor_2.getHeight()) { + player.setGravityTimer(-3); + particle.startAnimation(); + } + + // Floor animation + floor_1.y = floor_1.getY() + Math.sin(sintimer*0.15)*0.8; // 15% Speed, 0.8x Ausschwenkung + floor_3.y = floor_3.getY() - Math.sin(sintimer*0.15)*0.8; + sintimer += 0.5; + + // Draw your images + background.draw(); + floor_3.draw(); + floor_2.draw(); + floor_1.draw(); + player.draw(); + particle.draw(); + + } + + + /* TOUCH FUNCTIONS */ + public void touchDown() { + player.increaseGravity(1); + } + public void touchUp() {} + public void touchHold() {} + +} diff --git a/example/ExampleApp/app/src/main/java/ofenbach/exampleapp/views/GameStart.java b/example/ExampleApp/app/src/main/java/ofenbach/exampleapp/views/GameStart.java new file mode 100644 index 0000000..45bd26b --- /dev/null +++ b/example/ExampleApp/app/src/main/java/ofenbach/exampleapp/views/GameStart.java @@ -0,0 +1,25 @@ +package ofenbach.exampleapp.views; + +/* @creation: 25.4.2018 */ +/* @update: 25.4.2018 */ +/* @author: Tim B. Ofenbach */ + +public class GameStart { + + /** FEEL FREE TO EDIT THIS AND PLAY WITH IT! **/ + + ExampleScreen escreen; // add your costum screens here + + public GameStart() { + + escreen = new ExampleScreen(); // load your own screens here (order important as they will affect there id in Camera.java) + + } + + public void start() { + + escreen.load(); // load/start your own screens here + + } + +} \ No newline at end of file diff --git a/example/ExampleApp/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/example/ExampleApp/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..c7bd21d --- /dev/null +++ b/example/ExampleApp/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/example/ExampleApp/app/src/main/res/drawable/backdrop.png b/example/ExampleApp/app/src/main/res/drawable/backdrop.png new file mode 100644 index 0000000..a3e9663 Binary files /dev/null and b/example/ExampleApp/app/src/main/res/drawable/backdrop.png differ diff --git a/example/ExampleApp/app/src/main/res/drawable/dust_1.png b/example/ExampleApp/app/src/main/res/drawable/dust_1.png new file mode 100644 index 0000000..d1757ff Binary files /dev/null and b/example/ExampleApp/app/src/main/res/drawable/dust_1.png differ diff --git a/example/ExampleApp/app/src/main/res/drawable/dust_2.png b/example/ExampleApp/app/src/main/res/drawable/dust_2.png new file mode 100644 index 0000000..146c0bf Binary files /dev/null and b/example/ExampleApp/app/src/main/res/drawable/dust_2.png differ diff --git a/example/ExampleApp/app/src/main/res/drawable/dust_3.png b/example/ExampleApp/app/src/main/res/drawable/dust_3.png new file mode 100644 index 0000000..47cfceb Binary files /dev/null and b/example/ExampleApp/app/src/main/res/drawable/dust_3.png differ diff --git a/example/ExampleApp/app/src/main/res/drawable/dust_4.png b/example/ExampleApp/app/src/main/res/drawable/dust_4.png new file mode 100644 index 0000000..7d2e777 Binary files /dev/null and b/example/ExampleApp/app/src/main/res/drawable/dust_4.png differ diff --git a/example/ExampleApp/app/src/main/res/drawable/dust_5.png b/example/ExampleApp/app/src/main/res/drawable/dust_5.png new file mode 100644 index 0000000..f04d640 Binary files /dev/null and b/example/ExampleApp/app/src/main/res/drawable/dust_5.png differ diff --git a/example/ExampleApp/app/src/main/res/drawable/dust_6.png b/example/ExampleApp/app/src/main/res/drawable/dust_6.png new file mode 100644 index 0000000..f9ead5b Binary files /dev/null and b/example/ExampleApp/app/src/main/res/drawable/dust_6.png differ diff --git a/example/ExampleApp/app/src/main/res/drawable/dust_7.png b/example/ExampleApp/app/src/main/res/drawable/dust_7.png new file mode 100644 index 0000000..6f20e02 Binary files /dev/null and b/example/ExampleApp/app/src/main/res/drawable/dust_7.png differ diff --git a/example/ExampleApp/app/src/main/res/drawable/floor_1.png b/example/ExampleApp/app/src/main/res/drawable/floor_1.png new file mode 100644 index 0000000..f547eb5 Binary files /dev/null and b/example/ExampleApp/app/src/main/res/drawable/floor_1.png differ diff --git a/example/ExampleApp/app/src/main/res/drawable/floor_2.png b/example/ExampleApp/app/src/main/res/drawable/floor_2.png new file mode 100644 index 0000000..3481095 Binary files /dev/null and b/example/ExampleApp/app/src/main/res/drawable/floor_2.png differ diff --git a/example/ExampleApp/app/src/main/res/drawable/floor_3.png b/example/ExampleApp/app/src/main/res/drawable/floor_3.png new file mode 100644 index 0000000..381b51c Binary files /dev/null and b/example/ExampleApp/app/src/main/res/drawable/floor_3.png differ diff --git a/example/ExampleApp/app/src/main/res/drawable/ic_launcher_background.xml b/example/ExampleApp/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..d5fccc5 --- /dev/null +++ b/example/ExampleApp/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example/ExampleApp/app/src/main/res/drawable/player.png b/example/ExampleApp/app/src/main/res/drawable/player.png new file mode 100644 index 0000000..9eadae1 Binary files /dev/null and b/example/ExampleApp/app/src/main/res/drawable/player.png differ diff --git a/example/ExampleApp/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/example/ExampleApp/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/example/ExampleApp/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/example/ExampleApp/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/example/ExampleApp/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/example/ExampleApp/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/example/ExampleApp/app/src/main/res/mipmap-hdpi/ic_launcher.png b/example/ExampleApp/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..a2f5908 Binary files /dev/null and b/example/ExampleApp/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/example/ExampleApp/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/example/ExampleApp/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..1b52399 Binary files /dev/null and b/example/ExampleApp/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/example/ExampleApp/app/src/main/res/mipmap-mdpi/ic_launcher.png b/example/ExampleApp/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..ff10afd Binary files /dev/null and b/example/ExampleApp/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/example/ExampleApp/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/example/ExampleApp/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..115a4c7 Binary files /dev/null and b/example/ExampleApp/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/example/ExampleApp/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/example/ExampleApp/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..dcd3cd8 Binary files /dev/null and b/example/ExampleApp/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/example/ExampleApp/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/example/ExampleApp/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..459ca60 Binary files /dev/null and b/example/ExampleApp/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/example/ExampleApp/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/example/ExampleApp/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..8ca12fe Binary files /dev/null and b/example/ExampleApp/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/example/ExampleApp/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/example/ExampleApp/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..8e19b41 Binary files /dev/null and b/example/ExampleApp/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/example/ExampleApp/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/example/ExampleApp/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..b824ebd Binary files /dev/null and b/example/ExampleApp/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/example/ExampleApp/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/example/ExampleApp/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..4c19a13 Binary files /dev/null and b/example/ExampleApp/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/example/ExampleApp/app/src/main/res/values/colors.xml b/example/ExampleApp/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..3ab3e9c --- /dev/null +++ b/example/ExampleApp/app/src/main/res/values/colors.xml @@ -0,0 +1,6 @@ + + + #3F51B5 + #303F9F + #FF4081 + diff --git a/example/ExampleApp/app/src/main/res/values/strings.xml b/example/ExampleApp/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..ae4d3e2 --- /dev/null +++ b/example/ExampleApp/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + ExampleApp + diff --git a/example/ExampleApp/app/src/main/res/values/styles.xml b/example/ExampleApp/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..ff6c9d2 --- /dev/null +++ b/example/ExampleApp/app/src/main/res/values/styles.xml @@ -0,0 +1,8 @@ + + + + + + diff --git a/example/ExampleApp/app/src/test/java/ofenbach/exampleapp/main/ExampleUnitTest.java b/example/ExampleApp/app/src/test/java/ofenbach/exampleapp/main/ExampleUnitTest.java new file mode 100644 index 0000000..0b48fea --- /dev/null +++ b/example/ExampleApp/app/src/test/java/ofenbach/exampleapp/main/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package ofenbach.exampleapp.main; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/example/ExampleApp/build.gradle b/example/ExampleApp/build.gradle new file mode 100644 index 0000000..1a3d812 --- /dev/null +++ b/example/ExampleApp/build.gradle @@ -0,0 +1,27 @@ +// 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:3.1.2' + + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + google() + jcenter() + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/example/ExampleApp/gradle.properties b/example/ExampleApp/gradle.properties new file mode 100644 index 0000000..743d692 --- /dev/null +++ b/example/ExampleApp/gradle.properties @@ -0,0 +1,13 @@ +# 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 diff --git a/example/ExampleApp/gradle/wrapper/gradle-wrapper.jar b/example/ExampleApp/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..7a3265e Binary files /dev/null and b/example/ExampleApp/gradle/wrapper/gradle-wrapper.jar differ diff --git a/example/ExampleApp/gradle/wrapper/gradle-wrapper.properties b/example/ExampleApp/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..13e5665 --- /dev/null +++ b/example/ExampleApp/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Tue Apr 24 14:33:05 CEST 2018 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip diff --git a/example/ExampleApp/gradlew b/example/ExampleApp/gradlew new file mode 100644 index 0000000..cccdd3d --- /dev/null +++ b/example/ExampleApp/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/example/ExampleApp/gradlew.bat b/example/ExampleApp/gradlew.bat new file mode 100644 index 0000000..f955316 --- /dev/null +++ b/example/ExampleApp/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/example/ExampleApp/settings.gradle b/example/ExampleApp/settings.gradle new file mode 100644 index 0000000..e7b4def --- /dev/null +++ b/example/ExampleApp/settings.gradle @@ -0,0 +1 @@ +include ':app'