diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..16d5e4419f88abcd7c4165573f361b67a67a94c7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,41 @@
+#built application files
+*.apk
+*.ap_
+*.aab
+
+# files for the dex VM
+*.dex
+
+# Java class files
+*.class
+
+# generated files
+bin/
+gen/
+
+# Local configuration file (sdk path, etc)
+local.properties
+
+# Windows thumbnail db
+Thumbs.db
+
+# OSX files
+.DS_Store
+
+# Android Studio
+*.iml
+.idea
+#.idea/workspace.xml - remove # and delete .idea if it better suit your needs.
+.gradle
+build/
+.navigation
+captures/
+output.json
+
+#NDK
+obj/
+<<<<<<< HEAD
+.externalNativeBuild
+=======
+.externalNativeBuild
+>>>>>>> Joystick
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..42afabfd2abebf31384ca7797186a27a4b7dbee8
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..2d8500e213e7e518c42932994dd9124eff8ef14b
--- /dev/null
+++ b/app/build.gradle
@@ -0,0 +1,39 @@
+plugins {
+ id 'com.android.application'
+}
+
+android {
+ namespace 'com.example.a8_bitinvader'
+ compileSdk 33
+
+ defaultConfig {
+ applicationId "com.example.a8_bitinvader"
+ minSdk 21
+ targetSdk 33
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+}
+
+dependencies {
+
+ implementation 'androidx.appcompat:appcompat:1.4.1'
+ implementation 'com.google.android.material:material:1.5.0'
+ implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
+ testImplementation 'junit:junit:4.13.2'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.3'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
+}
\ No newline at end of file
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
new file mode 100644
index 0000000000000000000000000000000000000000..481bb434814107eb79d7a30b676d344b0df2f8ce
--- /dev/null
+++ b/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
\ No newline at end of file
diff --git a/app/src/androidTest/java/com/example/a8_bitinvader/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/example/a8_bitinvader/ExampleInstrumentedTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..9fad12002e488c5ea27430a82450e69081d7d786
--- /dev/null
+++ b/app/src/androidTest/java/com/example/a8_bitinvader/ExampleInstrumentedTest.java
@@ -0,0 +1,26 @@
+package com.example.a8_bitinvader;
+
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.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.getInstrumentation().getTargetContext();
+ assertEquals("com.example.a8_bitinvader", appContext.getPackageName());
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6be8ec67f20c7d92fd7849049e39838a46b9ce7b
--- /dev/null
+++ b/app/src/main/AndroidManifest.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/example/a8_bitinvader/Background.java b/app/src/main/java/com/example/a8_bitinvader/Background.java
new file mode 100644
index 0000000000000000000000000000000000000000..a43bd390f7bc2625f901c0df7b09ecf0ae17e284
--- /dev/null
+++ b/app/src/main/java/com/example/a8_bitinvader/Background.java
@@ -0,0 +1,23 @@
+package com.example.a8_bitinvader;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+
+public class Background {
+
+ int xPos = 0, yPos = 0;
+ Bitmap background;
+
+ /**
+ * Creates a background
+ * @param screenWidth Width of screen in pixels
+ * @param screenHeight Height of screen in pixels
+ * @param res Resource object
+ */
+ Background(int screenWidth, int screenHeight, Resources res) {
+ background = BitmapFactory.decodeResource(res, R.drawable.background);
+ background = Bitmap.createScaledBitmap(background, screenWidth, screenHeight, false);
+ }
+
+}
diff --git a/app/src/main/java/com/example/a8_bitinvader/Bullet.java b/app/src/main/java/com/example/a8_bitinvader/Bullet.java
new file mode 100644
index 0000000000000000000000000000000000000000..0ba71181a999febd731e743c5500cc924dc86244
--- /dev/null
+++ b/app/src/main/java/com/example/a8_bitinvader/Bullet.java
@@ -0,0 +1,19 @@
+package com.example.a8_bitinvader;
+
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+
+public class Bullet extends Sprite {
+
+ /**
+ * Creates Bullet object using Sprite constructor
+ */
+ public Bullet(int xPos, int yPos, int xVel, int yVel, int screenWidth, int screenHeight, Resources res) {
+ super(xPos, yPos, xVel, yVel, screenWidth, screenHeight);
+ spriteImage = BitmapFactory.decodeResource(res, R.drawable.bullet);
+ spriteImage = Bitmap.createScaledBitmap(spriteImage, screenWidth, screenHeight, false);
+ }
+
+}
diff --git a/app/src/main/java/com/example/a8_bitinvader/Enemy.java b/app/src/main/java/com/example/a8_bitinvader/Enemy.java
new file mode 100644
index 0000000000000000000000000000000000000000..130cd140e5f958c18c3a81dc15f80803f847a8d9
--- /dev/null
+++ b/app/src/main/java/com/example/a8_bitinvader/Enemy.java
@@ -0,0 +1,61 @@
+package com.example.a8_bitinvader;
+
+public class Enemy extends Sprite{
+
+ // this will need to vary no?
+ /** Health of player */
+ private int health = 1;
+
+ // speed adjust
+ /** Speed */
+ public final int SPEED_MULTIPLIER = 3;
+
+ //initialize the Xval,Yval. and inital position
+
+ /**
+ * Initialize an enemy with the given coordinates and initial velocity
+ * @param xPos X point
+ * @param yPos Y point
+ * @param xVel X velocity
+ * @param yVel Y velocity
+ */
+ public Enemy(int xPos, int yPos, int xVel, int yVel, int screenWidth, int screenHeight) {
+ super(xPos, yPos, xVel, yVel, screenWidth, screenWidth);
+
+ }
+
+ /**
+ * Checks if the given points are within the sprite and reduce the health if so
+ * @param xx Other X point
+ * @param yy Other Y point
+ * @return True if input xx and yy are within the sprite
+ */
+ @Override //the return doesn't really mean anything all we need is that when any of the point hit within the hit box of player, call the loose health function.
+ public boolean checkForCollision(int xx, int yy)
+ {
+ if( super.checkForCollision(xx,yy) ) {
+ loseHealth();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Decrease the health of the player
+ */
+ // when loseHealth drop the help to 0, call the destroy function. which we will override ltr
+ private void loseHealth() {
+ health -= 1;
+ if (health == 0) {
+ destroy();
+ }
+ }
+
+
+ // will shoot bullets
+ public void shootBullets(){
+
+ }
+
+}
diff --git a/app/src/main/java/com/example/a8_bitinvader/GameActivity.java b/app/src/main/java/com/example/a8_bitinvader/GameActivity.java
new file mode 100644
index 0000000000000000000000000000000000000000..78340a5016aabda2f119b3cb017e002ca43edf83
--- /dev/null
+++ b/app/src/main/java/com/example/a8_bitinvader/GameActivity.java
@@ -0,0 +1,50 @@
+package com.example.a8_bitinvader;
+
+import androidx.appcompat.app.AppCompatActivity;
+import android.os.Bundle;
+
+import android.graphics.Point; // necessary to get ScreenWidth and ScreenHeight
+import android.view.WindowManager;
+
+public class GameActivity extends AppCompatActivity {
+
+ private GameView gameView;
+
+ /**
+ * Create an instance of the activity based on the saved state. Then initialize the gameview and display the gameview onto the screen
+ * @param savedInstanceState The cached game state
+ */
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // puts app into fullscreen when GameActivity is running
+ getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
+
+
+ Point point = new Point();
+ getWindowManager().getDefaultDisplay().getSize(point);
+
+ gameView = new GameView(this, point.x, point.y);
+
+ setContentView(gameView);
+ }
+
+ /**
+ * Pause the game
+ */
+ @Override
+ protected void onPause() {
+ super.onPause();
+ gameView.pause();
+ }
+
+ /**
+ * Resume the game
+ */
+ @Override
+ protected void onResume() {
+ super.onResume();
+ gameView.resume();
+ }
+}
diff --git a/app/src/main/java/com/example/a8_bitinvader/GameView.java b/app/src/main/java/com/example/a8_bitinvader/GameView.java
new file mode 100644
index 0000000000000000000000000000000000000000..2bc1a8ee8b29b89da292590f5cc088cb79516bd7
--- /dev/null
+++ b/app/src/main/java/com/example/a8_bitinvader/GameView.java
@@ -0,0 +1,158 @@
+package com.example.a8_bitinvader;
+
+import android.content.Context;
+import android.view.MotionEvent;
+import android.view.SurfaceView;
+import android.graphics.Canvas;
+import android.graphics.Paint; // necessary when drawing Bitmaps with Canvas objects
+
+public class GameView extends SurfaceView implements Runnable{
+
+ private Thread thread;
+ private boolean isRunning;
+ private int screenWidth, screenHeight;
+ private float screenRatioWidth, screenRatioHeight;
+ private Background background1, background2;
+ private Paint paint;
+
+ /** The {@link Joystick} */
+ Joystick joystick;
+ /** The {@link Player} */
+ Player p1;
+
+ /**
+ * Create a {@link GameView} scaled based on the device size which includes the background, player, and joystick
+ * @param context Context of the device
+ * @param screenWidth Screen width in pixels
+ * @param screenHeight Screen height in pixels
+ */
+ public GameView(Context context, int screenWidth, int screenHeight) {
+ super(context);
+ this.screenWidth = screenWidth;
+ this.screenHeight = screenHeight;
+
+ screenRatioWidth = 1080f / screenWidth;
+ screenRatioHeight = 1920f / screenHeight;
+
+ background1 = new Background(screenWidth, screenHeight, getResources());
+ background2 = new Background(screenWidth, screenHeight, getResources());
+
+ background2.yPos = -screenHeight;
+
+ paint = new Paint();
+
+ joystick = new Joystick(screenWidth/2,screenHeight*9/10,130,40);
+ p1 = new Player(screenWidth/2,screenHeight*7/10,0,0, screenWidth, screenHeight, getResources());
+ }
+
+ /*
+ * Continuously loops through update(), draw(), and sleep() if the app is running
+ * Overrides from Runnable class, which Thread automatically calls once resume() initializes said Thread
+ */
+
+ /**
+ * Runs the app by continuously calling private methods {@link Void update()} and {@link Void draw()} based on whether the app {@link Boolean isRunning}
+ */
+ @Override
+ public void run() {
+
+ while(isRunning) {
+ update();
+ draw();
+
+ // creates 30 millisecond delay in between draw() and update()
+ try {
+ Thread.sleep(30);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /*
+ * updates position of backgrounds.
+ * checks if either background is offscreen. If so, it places that background above the other
+ * giving the illusion of an infinitely moving background.
+ */
+ private void update() {
+ background1.yPos += (int) (5 * screenRatioHeight);
+ background2.yPos += (int) (5 * screenRatioHeight);
+
+ if(background1.yPos > screenHeight) {
+ background1.yPos = -screenHeight;
+ }
+
+ if(background2.yPos > screenHeight) {
+ background2.yPos = -screenHeight;
+ }
+
+ p1.update((int)joystick.XVelocity, (int)joystick.YVelocity);
+ joystick.update(joystick);
+ }
+
+ /*
+ * draws both backgrounds onto the screen given their initialized
+ */
+ private void draw() {
+ if(getHolder().getSurface().isValid()){
+ Canvas canvas = getHolder().lockCanvas();
+ canvas.drawBitmap(background1.background, background1.xPos, background1.yPos, paint);
+ canvas.drawBitmap(background2.background, background2.xPos, background2.yPos, paint);
+
+ canvas.drawBitmap(p1.spriteImage, p1.xPos, p1.yPos, paint);
+ joystick.draw(canvas);
+ getHolder().unlockCanvasAndPost(canvas);
+ }
+ }
+
+ /*
+ * https://developer.android.com/reference/java/lang/Thread#start()
+ * initializes a thread and starts it, automatically calling the overridden run() method above.
+ */
+ public void resume() {
+
+ isRunning = true;
+ thread = new Thread(this);
+ thread.start();
+
+ }
+
+ /*
+ * https://developer.android.com/reference/java/lang/Thread#join()
+ * waits for thread to die if game is paused
+ */
+ public void pause() {
+
+ try {
+ isRunning = false;
+ thread.join();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ switch(event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ if(joystick.isPressed((double)event.getX(), (double)event.getY())){
+ joystick.setIsPressed(true);
+ }
+ return true;
+ case MotionEvent.ACTION_MOVE:
+ if(joystick.getIsPressed()) {
+ joystick.setActuator((double)event.getX(), (double)event.getY());
+ }
+ return true;
+ case MotionEvent.ACTION_UP:
+ joystick.setIsPressed(false);
+ joystick.resetActuator();
+ return true;
+ }
+
+ return super.onTouchEvent(event);
+
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/a8_bitinvader/Joystick.java b/app/src/main/java/com/example/a8_bitinvader/Joystick.java
new file mode 100644
index 0000000000000000000000000000000000000000..599d79947a869d3e4d90ea0cc36a8f0896eaea3b
--- /dev/null
+++ b/app/src/main/java/com/example/a8_bitinvader/Joystick.java
@@ -0,0 +1,164 @@
+package com.example.a8_bitinvader;
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+
+public class Joystick {
+ private static final double MAX_SPEED = 3; //change ltr
+ private int outerCircleCenterX;
+ private int outerCircleCenterY;
+ private int innerCircleCenterX;
+ private int innerCircleCenterY;
+ private int outerCircleRadii;
+ private int innerCircleRadii;
+ private Paint innerCirclePaint;
+ private Paint outerCirclePaint;
+
+ private double joystickCenterToTouchDistance;
+ private boolean isPressed;
+ private double actuatorX;
+ private double actuatorY;
+
+ public double XVelocity;
+ public double YVelocity;
+
+ /**
+ * Constructs a Joystick instance
+ * @param CenterPositionX X position of the joystick
+ * @param CenterPositionY Y position of the joystick
+ * @param outerCircleRad Radius of outer circle of joystick
+ * @param innerCircleRad Radius of inner circle of joystick
+ */
+ public Joystick(int CenterPositionX, int CenterPositionY, int outerCircleRad, int innerCircleRad){
+ outerCircleCenterX = CenterPositionX;
+ outerCircleCenterY = CenterPositionY;
+ innerCircleCenterX = CenterPositionX;
+ innerCircleCenterY = CenterPositionY;
+ outerCircleRadii = outerCircleRad;
+ innerCircleRadii = innerCircleRad;
+
+ outerCirclePaint= new Paint();
+ outerCirclePaint.setColor(Color.CYAN);
+ outerCirclePaint.setStyle(Paint.Style.STROKE);
+ outerCirclePaint.setStrokeWidth(5);
+
+ innerCirclePaint= new Paint();
+ innerCirclePaint.setColor(Color.WHITE);
+ innerCirclePaint.setStyle(Paint.Style.FILL_AND_STROKE);
+ }
+
+ /**
+ * Draws the joystick onto the given canvas
+ * @param canvas The canvas object to draw on
+ */
+ public void draw(Canvas canvas) {
+ //outer
+ canvas.drawCircle(
+ outerCircleCenterX,
+ outerCircleCenterY,
+ outerCircleRadii,
+ outerCirclePaint
+ );
+ //inner
+ canvas.drawCircle(
+ innerCircleCenterX,
+ innerCircleCenterY,
+ innerCircleRadii,
+ innerCirclePaint
+ );
+ }
+
+ /**
+ * Updates the given joystick and updates the x and y velocities that are outputted from user input
+ * @param joystick Joystick instance to update
+ */
+ public void update(Joystick joystick) {
+ XVelocity = joystick.getActuatorX() * MAX_SPEED;
+ YVelocity = joystick.getActuatorY() * MAX_SPEED;
+ updateInnerCirclePosition();
+ }
+
+ /**
+ * Updates the inner circle of the joystick
+ */
+ public void updateInnerCirclePosition() {
+ innerCircleCenterX = (int) (outerCircleCenterX + actuatorX * outerCircleRadii);
+ innerCircleCenterY = (int) (outerCircleCenterY + actuatorY * outerCircleRadii);
+ }
+
+ /**
+ * Checks whether the joystick has been touched by the user
+ * @param TouchPosX X position of the user's touch
+ * @param TouchPosY Y position of the user's touch
+ * @return True if the joystick has been pressed
+ */
+ public boolean isPressed(double TouchPosX,double TouchPosY) {
+ joystickCenterToTouchDistance = Math.sqrt(Math.pow(outerCircleCenterX-TouchPosX,2) +
+ Math.pow(outerCircleCenterY-TouchPosY,2)
+ );
+ return joystickCenterToTouchDistance < outerCircleRadii;
+ }
+
+ /**
+ * Set the joystick to be pressed or not pressed
+ * @param isPressed Boolean for whether the joystick is pressed
+ */
+ public void setIsPressed(boolean isPressed) {
+ this.isPressed = isPressed;
+ }
+
+ /**
+ *
+ * @return True if the joystick is pressed
+ */
+ public boolean getIsPressed() {
+ return isPressed;
+ }
+
+ /**
+ * Sets the value of actuation depending on how far away the user touches from the center
+ * of the joystick.
+ * @param TouchPosX X position of the user touch
+ * @param TouchPosY Y position of the user touch
+ */
+ public void setActuator(double TouchPosX,double TouchPosY) {
+ double deltaX = TouchPosX - outerCircleCenterX;
+ double deltaY = TouchPosY - outerCircleCenterY;
+ double deltaDistance = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY,2));
+
+ if(deltaDistance < outerCircleRadii) {
+ actuatorX = deltaX/outerCircleRadii;
+ actuatorY = deltaY/outerCircleRadii;
+ }else {
+ actuatorX = deltaX/deltaDistance;
+ actuatorY = deltaY/deltaDistance;
+ }
+
+ }
+
+ /**
+ * Resets the value of actuation to 0
+ */
+ public void resetActuator() {
+ actuatorX = 0.0;
+ actuatorY = 0.0;
+ }
+
+ /**
+ *
+ * @return The x value of actuation
+ */
+ public double getActuatorX() {
+ return actuatorX;
+ }
+
+ /**
+ *
+ * @return The Y value of actuation
+ */
+ public double getActuatorY() {
+ return actuatorY;
+ }
+
+}
diff --git a/app/src/main/java/com/example/a8_bitinvader/MainActivity.java b/app/src/main/java/com/example/a8_bitinvader/MainActivity.java
new file mode 100644
index 0000000000000000000000000000000000000000..e9baf03084beb1ce929d32d75f622c91653d0748
--- /dev/null
+++ b/app/src/main/java/com/example/a8_bitinvader/MainActivity.java
@@ -0,0 +1,177 @@
+package com.example.a8_bitinvader;
+
+import androidx.appcompat.app.AppCompatActivity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.Button;
+import android.content.Context;
+import android.media.AudioManager;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.widget.Toast;
+import java.util.Timer;
+import java.util.TimerTask;
+import android.os.Handler;
+
+public class MainActivity extends AppCompatActivity {
+
+ Animation animation;
+ boolean play;
+
+ /**
+ * Displays the menu and checks for user input to click play
+ * @param savedInstanceState The cached state of the game
+ */
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.activity_main);
+
+ // the if statement below hides the action bar
+ // https://www.geeksforgeeks.org/different-ways-to-hide-action-bar-in-android-with-examples/
+ if (getSupportActionBar() != null) {
+ getSupportActionBar().hide();
+ }
+
+
+ // initalizes 8-bit Invaders Logo
+
+ ImageView logo = (ImageView) findViewById(R.id.image_logo);
+ logo.setImageResource(R.drawable.logobit);
+
+ // Creates new Intent and starts GameActivity if 'play' is pressed on MainActivity screen.
+ findViewById(R.id.play_button).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ // animation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.slide_animation);
+ // logo.startAnimation(animation);
+ startActivity(new Intent(MainActivity.this, GameActivity.class));
+ play = true;
+ }
+ });
+
+ // Creates new Intent and Mutes Device Audio if mute button is pressed on MainActivity screen
+ // Reference: https://www.youtube.com/watch?v=_Klq62-me8s&ab_channel=AppleCoders
+ // Reference: https://developer.android.com/reference/android/media/MediaPlayer
+ findViewById(R.id.mute_button).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ // Declare an audio manager
+ AudioManager audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
+ // ADJUST_MUTE => mutes the device
+ // FLAG_SHOW_UI => Show changes made to the volume bar
+ audioManager.adjustVolume (AudioManager.ADJUST_MUTE, AudioManager.FLAG_SHOW_UI);
+
+ }
+
+ });
+
+
+ // Creates new Intent and stars LeaderboardView if the leaderboard button is pressed on the MainActivity Screen
+ // As of 4/14 12:51 AM, this is not implemented with LeaderboardView -- Krish Shah
+
+ findViewById(R.id.leaderboard_button).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ openPopUpWindow();
+ }
+ });
+
+
+ //Code to show the toast every 5 seconds. For Preliminary Issue: Repeated event
+ Timer timer = new Timer();
+ Context context = getApplicationContext();
+ CharSequence text = "Hello toast!";
+ int duration = 5000;
+
+ timer.schedule(new TimerTask() {
+
+ @Override
+ public void run() {
+ runOnUiThread(new Runnable() {
+
+ @Override
+ public void run() {
+ final Toast toast = Toast.makeText(context, text, Toast.LENGTH_SHORT);
+ toast.show();
+ Handler handler = new Handler();
+ handler.postDelayed(new Runnable() {
+
+ @Override
+ public void run() {
+ toast.cancel();
+ }
+ }, duration);
+
+ }
+ });
+ }
+ }, 0, duration);
+ }
+
+ private void openPopUpWindow() {
+ Intent popupwindow = new Intent(MainActivity.this, PopUpWindow.class);
+ startActivity(popupwindow);
+ }
+
+ /**
+ * Start the game
+ */
+ @Override
+ protected void onStart() {
+ super.onStart();
+ }
+
+ /**
+ * Resume the game
+ */
+ @Override
+ protected void onResume() {
+ super.onResume();
+ }
+
+ /**
+ * Pause the game
+ */
+ @Override
+ protected void onPause() {
+ super.onPause();
+ }
+
+ /**
+ * Stop the game
+ */
+ @Override
+ protected void onStop() {
+ super.onStop();
+ }
+
+ /**
+ * Destroy the sprite
+ */
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ }
+
+ /**
+ * Restart the game
+ */
+ @Override
+ protected void onRestart() {
+ super.onRestart();
+ }
+
+ @Override
+ public void onBackPressed() {
+
+ // Call super.onBackPressed() to perform default back button behavior
+ super.onBackPressed();
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/a8_bitinvader/Player.java b/app/src/main/java/com/example/a8_bitinvader/Player.java
new file mode 100644
index 0000000000000000000000000000000000000000..df40dc8ef569b287f7d41dde9ef81b29a9b39d01
--- /dev/null
+++ b/app/src/main/java/com/example/a8_bitinvader/Player.java
@@ -0,0 +1,102 @@
+package com.example.a8_bitinvader;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+
+public class Player extends Sprite{
+
+ /** Health of player */
+ private int health = 3;
+
+ /** Speed */
+ public final int SPEED_MULTIPLIER = 10;
+
+ /**
+ * Constructs a new player at given coordinates and
+ * @param xPos Xposition of player
+ * @param yPos Y position of player
+ * @param xVel X velocity of player
+ * @param yVel Y velocity of player
+ * @param res Resource object
+ */
+ public Player(int xPos, int yPos, int xVel, int yVel, int screenWidth, int screenHeight, Resources res) {
+ super(xPos,yPos,xVel,yVel, screenWidth, screenHeight);
+ this.xPos = xPos;
+ this.yPos = yPos;
+ spriteImage = BitmapFactory.decodeResource(res, R.drawable.player);
+ spriteImage = Bitmap.createScaledBitmap(spriteImage, getSpriteWidth(), getSpriteHeight(), false);
+ }
+
+ //get input from the joystick, and change the location
+
+ // tbh I think this is going to give us an error ltr, because we are going to call update and shoot constantly, I wonder what will happen if we write and deleting at the same time. We'll see tho
+
+ /**
+ * Update the position of the player based on joystick offset
+ * @param joyStickInputX X input from joystick
+ * @param joyStickInputY Y input from joystick
+ */
+ public void update(int joyStickInputX, int joyStickInputY){
+ xVel = joyStickInputX * SPEED_MULTIPLIER;
+ yVel = joyStickInputY * SPEED_MULTIPLIER;
+
+ // calls Sprite update(). Updates xPos and yPos.
+ update();
+
+ // checks if Player is offscreen. If so, repositions them within the screen.
+ if(xPos < 0){
+ xPos = 5;
+ } else if(xPos + getSpriteWidth() > screenWidth){
+ xPos = screenWidth - getSpriteWidth() - 5;
+ }
+
+ if(yPos < 0){
+ yPos = 5;
+ } else if(yPos + getSpriteHeight() > screenHeight){
+ yPos = screenHeight - getSpriteHeight() - 5;
+ }
+
+ }
+
+ /**
+ * Checks if the given points are within the sprite and reduce the health if so
+ * @param xx Other X point
+ * @param yy Other Y point
+ * @return True if input xx and yy are within the sprite
+ */
+ @Override //the return doesn't really mean anything all we need is that when any of the point hit within the hit box of player, call the loose health function.
+ public boolean checkForCollision(int xx, int yy)
+ {
+ if( super.checkForCollision(xx,yy) ) {
+ loseHealth();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Decrease the health of the player
+ */
+ // when loseHealth drop the help to 0, call the destroy function. which we will override ltr
+ private void loseHealth() {
+ health -= 1;
+ if (health == 0) {
+ destroy();
+ }
+ }
+
+
+ public void shoot() {
+
+ }
+
+ @Override
+ public void destroy() {
+ //call animation also.
+ //this should call the pulse function for the game, and manu would pop up.
+ //implement ltr
+ }
+
+}
diff --git a/app/src/main/java/com/example/a8_bitinvader/PopUpWindow.java b/app/src/main/java/com/example/a8_bitinvader/PopUpWindow.java
new file mode 100644
index 0000000000000000000000000000000000000000..f721266c5f92deaeed06175825bfd9e17f5454a0
--- /dev/null
+++ b/app/src/main/java/com/example/a8_bitinvader/PopUpWindow.java
@@ -0,0 +1,38 @@
+package com.example.a8_bitinvader;
+import androidx.appcompat.app.AppCompatActivity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.view.Gravity;
+import android.view.WindowManager;
+import android.widget.ImageView;
+import android.widget.Button;
+import android.content.Context;
+import android.media.AudioManager;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.util.DisplayMetrics;
+public class PopUpWindow extends AppCompatActivity{
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.popup_window);
+
+ DisplayMetrics dm = new DisplayMetrics();
+ getWindowManager().getDefaultDisplay().getMetrics (dm);
+
+ int width = dm.widthPixels;
+ int height = dm.heightPixels;
+
+ getWindow().setLayout((int)(width*.7), (int)(height*.5));
+
+ WindowManager.LayoutParams params = getWindow().getAttributes();
+ params.gravity = Gravity.CENTER;
+ params.x = 0;
+ params.y = -20;
+
+ getWindow().setAttributes(params);
+ }
+
+}
diff --git a/app/src/main/java/com/example/a8_bitinvader/ReverseInterpolator.java b/app/src/main/java/com/example/a8_bitinvader/ReverseInterpolator.java
new file mode 100644
index 0000000000000000000000000000000000000000..1e8898478605092d53c440b0af0d7094522615bf
--- /dev/null
+++ b/app/src/main/java/com/example/a8_bitinvader/ReverseInterpolator.java
@@ -0,0 +1,10 @@
+package com.example.a8_bitinvader;
+
+import android.view.animation.Interpolator;
+
+public class ReverseInterpolator implements Interpolator {
+ @Override
+ public float getInterpolation(float paramFloat) {
+ return Math.abs(paramFloat -1f);
+ }
+}
diff --git a/app/src/main/java/com/example/a8_bitinvader/Sprite.java b/app/src/main/java/com/example/a8_bitinvader/Sprite.java
new file mode 100644
index 0000000000000000000000000000000000000000..23516a2e72e874560e5d01bd492933f60441b2bb
--- /dev/null
+++ b/app/src/main/java/com/example/a8_bitinvader/Sprite.java
@@ -0,0 +1,94 @@
+package com.example.a8_bitinvader;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+
+public class Sprite {
+
+ // public fields
+ // xPos and yPos represent top left corner of Sprite hit box
+ // xVel and yVel represent x and y velocity respectively
+ // image is the Bitmap of the Sprite object
+ /** X and Y position of the sprite */
+ int xPos, yPos;
+
+ /** X and Y velocity of the sprite */
+ int xVel, yVel;
+
+ /** Screen size */
+ int screenWidth, screenHeight;
+
+ /** Image of the sprite */
+ Bitmap spriteImage;
+
+ //private properties
+ private final int spriteHeight = 128, spriteWidth = 128;
+
+ //private properties
+
+ /**
+ * @param xPos initial x position of Sprite
+ * @param yPos initial y position of Sprite
+ * @param xVel initial x velocity of Sprite
+ * @param yVel initial y velocity of Sprite
+ */
+ public Sprite(int xPos, int yPos, int xVel, int yVel, int screenWidth, int screenHeight)
+ {
+ this.xPos = xPos;
+ this.yPos = yPos;
+ this.xVel = xVel;
+ this.yVel = yVel;
+
+ this.screenWidth = screenWidth;
+ this.screenHeight = screenHeight;
+ }
+
+ /**
+ * @return height of the sprite
+ */
+ public int getSpriteHeight()
+ {
+ return spriteHeight;
+ }
+
+ /**
+ * @return width of the sprite
+ */
+ public int getSpriteWidth()
+ {
+ return spriteWidth;
+ }
+
+ /**
+ *
+ * @param xx
+ * @param yy
+ * @return True if xx and yy are in the current sprite
+ */
+ // IMPLEMENT THIS LATER TO CHECK FOR COLLISION WITH PASSING BULLET OBJECTS
+ public boolean checkForCollision(int xx, int yy)
+ {
+ //implement
+ if((xx < (xPos+spriteWidth) && xx > xPos) && (yy < (yPos+spriteHeight) && yy > yPos))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Function to destory the sprite and delete the object
+ */
+ public void destroy() {
+ //this should call the animation, and delete the object
+ }
+
+ /**
+ * Updates the sprite to move according to a given velocity
+ */
+ public void update() {
+ xPos += xVel;
+ yPos += yVel;
+ }
+
+}
diff --git a/app/src/main/java/com/example/a8_bitinvader/TestPositive.java b/app/src/main/java/com/example/a8_bitinvader/TestPositive.java
new file mode 100644
index 0000000000000000000000000000000000000000..41f94f169b05c7eea7dd446e34045a8d42ed0b11
--- /dev/null
+++ b/app/src/main/java/com/example/a8_bitinvader/TestPositive.java
@@ -0,0 +1,8 @@
+package com.example.a8_bitinvader;
+
+class TestPositive {
+ boolean amIPositive(T num) {
+
+ return (num.doubleValue() > 0);
+ }
+}
diff --git a/app/src/main/res/anim/blink_animation.xml b/app/src/main/res/anim/blink_animation.xml
new file mode 100644
index 0000000000000000000000000000000000000000..884eb964b764db4d23fd52914d4d71cba56423ef
--- /dev/null
+++ b/app/src/main/res/anim/blink_animation.xml
@@ -0,0 +1,9 @@
+
+
+
+
diff --git a/app/src/main/res/anim/fade_animation.xml b/app/src/main/res/anim/fade_animation.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5231ee876d8a1b5f545c1802e744d91f750d9b75
--- /dev/null
+++ b/app/src/main/res/anim/fade_animation.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/anim/move_animation.xml b/app/src/main/res/anim/move_animation.xml
new file mode 100644
index 0000000000000000000000000000000000000000..31bb2edf255283e866302f012598a9f6f2cb2eea
--- /dev/null
+++ b/app/src/main/res/anim/move_animation.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
diff --git a/app/src/main/res/anim/slide_animation.xml b/app/src/main/res/anim/slide_animation.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8aa7d185fee29733588b8d282f592442620a3738
--- /dev/null
+++ b/app/src/main/res/anim/slide_animation.xml
@@ -0,0 +1,11 @@
+
+
+
+
diff --git a/app/src/main/res/anim/zoom_animation.xml b/app/src/main/res/anim/zoom_animation.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1c46ddabd1ce6994c962bd28dbfe17c5b66508d1
--- /dev/null
+++ b/app/src/main/res/anim/zoom_animation.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fde1368fc173af0045df850fc4b65501c7536765
--- /dev/null
+++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/axolotel.png b/app/src/main/res/drawable/axolotel.png
new file mode 100644
index 0000000000000000000000000000000000000000..a95c70d87b88cfb741ea358759da6c7c2e16cb10
Binary files /dev/null and b/app/src/main/res/drawable/axolotel.png differ
diff --git a/app/src/main/res/drawable/background.jpeg b/app/src/main/res/drawable/background.jpeg
new file mode 100644
index 0000000000000000000000000000000000000000..62b70aa2b3d9f59132c499b61d33c69292e0c4df
Binary files /dev/null and b/app/src/main/res/drawable/background.jpeg differ
diff --git a/app/src/main/res/drawable/bullet.png b/app/src/main/res/drawable/bullet.png
new file mode 100644
index 0000000000000000000000000000000000000000..ee172dc46e184a1a99b566a2dbd156a9b8872495
Binary files /dev/null and b/app/src/main/res/drawable/bullet.png differ
diff --git a/app/src/main/res/drawable/enemy1.png b/app/src/main/res/drawable/enemy1.png
new file mode 100644
index 0000000000000000000000000000000000000000..145dbb3fc9fa179929f4be206c8213f37b006431
Binary files /dev/null and b/app/src/main/res/drawable/enemy1.png differ
diff --git a/app/src/main/res/drawable/green.png b/app/src/main/res/drawable/green.png
new file mode 100644
index 0000000000000000000000000000000000000000..414c0ac8bb3e3f9702d4454bc942d0fcf6c0d296
Binary files /dev/null and b/app/src/main/res/drawable/green.png differ
diff --git a/app/src/main/res/drawable/green32.png b/app/src/main/res/drawable/green32.png
new file mode 100644
index 0000000000000000000000000000000000000000..0479416ef11fff1fd705841e12cf6ca428e4bc60
Binary files /dev/null and b/app/src/main/res/drawable/green32.png differ
diff --git a/app/src/main/res/drawable/green64.png b/app/src/main/res/drawable/green64.png
new file mode 100644
index 0000000000000000000000000000000000000000..d261c8e9adc67b238ba8370776e3019f0f125951
Binary files /dev/null and b/app/src/main/res/drawable/green64.png differ
diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1e4408cae4a05b8fb4b1be8fa4521edd7e25735b
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/leaderboard.png b/app/src/main/res/drawable/leaderboard.png
new file mode 100644
index 0000000000000000000000000000000000000000..b1829f5b71228b8b96c70c3969c11a75921cf045
Binary files /dev/null and b/app/src/main/res/drawable/leaderboard.png differ
diff --git a/app/src/main/res/drawable/logobit.png b/app/src/main/res/drawable/logobit.png
new file mode 100644
index 0000000000000000000000000000000000000000..5116028f641d62cf52ab06ae37eed0314f8897b6
Binary files /dev/null and b/app/src/main/res/drawable/logobit.png differ
diff --git a/app/src/main/res/drawable/mute.png b/app/src/main/res/drawable/mute.png
new file mode 100644
index 0000000000000000000000000000000000000000..9d994fd893064837580f127f93a2f0faba432e29
Binary files /dev/null and b/app/src/main/res/drawable/mute.png differ
diff --git a/app/src/main/res/drawable/play.png b/app/src/main/res/drawable/play.png
new file mode 100644
index 0000000000000000000000000000000000000000..c99d3867f7eb1e36e13bc9aa84bb26a0ecf8f5ac
Binary files /dev/null and b/app/src/main/res/drawable/play.png differ
diff --git a/app/src/main/res/drawable/playbutton.png b/app/src/main/res/drawable/playbutton.png
new file mode 100644
index 0000000000000000000000000000000000000000..0631d9f75b1e9f5cff0ed09060179aef414fdd9e
Binary files /dev/null and b/app/src/main/res/drawable/playbutton.png differ
diff --git a/app/src/main/res/drawable/player.png b/app/src/main/res/drawable/player.png
new file mode 100644
index 0000000000000000000000000000000000000000..85a80706d0e412ce7c66ce4b15661177b592ded6
Binary files /dev/null and b/app/src/main/res/drawable/player.png differ
diff --git a/app/src/main/res/drawable/red.png b/app/src/main/res/drawable/red.png
new file mode 100644
index 0000000000000000000000000000000000000000..9646866cb79a5e4e655fc83bd43e3653dfe834e3
Binary files /dev/null and b/app/src/main/res/drawable/red.png differ
diff --git a/app/src/main/res/drawable/red32.png b/app/src/main/res/drawable/red32.png
new file mode 100644
index 0000000000000000000000000000000000000000..adb1b83103294a098670f0e0da8fe1f0b0c2102b
Binary files /dev/null and b/app/src/main/res/drawable/red32.png differ
diff --git a/app/src/main/res/drawable/red64.png b/app/src/main/res/drawable/red64.png
new file mode 100644
index 0000000000000000000000000000000000000000..3d02a77800a875066e5eb5f710c14314bb403c3b
Binary files /dev/null and b/app/src/main/res/drawable/red64.png differ
diff --git a/app/src/main/res/drawable/unmute.png b/app/src/main/res/drawable/unmute.png
new file mode 100644
index 0000000000000000000000000000000000000000..d7baac03d01696df64c60f1281358e01bf6bacf4
Binary files /dev/null and b/app/src/main/res/drawable/unmute.png differ
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000000000000000000000000000000000000..32f785340cb7d68fd14a296fb8aab2c0c612c832
--- /dev/null
+++ b/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/popup_window.xml b/app/src/main/res/layout/popup_window.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cceb16ae3847efce8511bcd8b29e6cd801b9cfa4
--- /dev/null
+++ b/app/src/main/res/layout/popup_window.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000000000000000000000000000000000000..eca70cfe52eac1ba66ba280a68ca7be8fcf88a16
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000000000000000000000000000000000000..eca70cfe52eac1ba66ba280a68ca7be8fcf88a16
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v33/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v33/ic_launcher.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6f3b755bf50c6b03d8714a9c6184705e6a08389f
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v33/ic_launcher.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp
new file mode 100644
index 0000000000000000000000000000000000000000..c209e78ecd372343283f4157dcfd918ec5165bb3
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
new file mode 100644
index 0000000000000000000000000000000000000000..b2dfe3d1ba5cf3ee31b3ecc1ced89044a1f3b7a9
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp
new file mode 100644
index 0000000000000000000000000000000000000000..4f0f1d64e58ba64d180ce43ee13bf9a17835fbca
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
new file mode 100644
index 0000000000000000000000000000000000000000..62b611da081676d42f6c3f78a2c91e7bcedddedb
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
new file mode 100644
index 0000000000000000000000000000000000000000..948a3070fe34c611c42c0d3ad3013a0dce358be0
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
new file mode 100644
index 0000000000000000000000000000000000000000..1b9a6956b3acdc11f40ce2bb3f6efbd845cc243f
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
new file mode 100644
index 0000000000000000000000000000000000000000..28d4b77f9f036a47549d47db79c16788749dca10
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
new file mode 100644
index 0000000000000000000000000000000000000000..9287f5083623b375139afb391af71cc533a7dd37
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
new file mode 100644
index 0000000000000000000000000000000000000000..aa7d6427e6fa1074b79ccd52ef67ac15c5637e85
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
new file mode 100644
index 0000000000000000000000000000000000000000..9126ae37cbc3587421d6889eadd1d91fbf1994d4
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ
diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2830ca3de580695605a6510f868806684722030d
--- /dev/null
+++ b/app/src/main/res/values-night/themes.xml
@@ -0,0 +1,16 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f8c6127d327620c93d2b2d00342a68e97b98a48d
--- /dev/null
+++ b/app/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+
+
+ #FFBB86FC
+ #FF6200EE
+ #FF3700B3
+ #FF03DAC5
+ #FF018786
+ #FF000000
+ #FFFFFFFF
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..482cc331e5ca001c707320bac2af969b5930c9dd
--- /dev/null
+++ b/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ 8-bit Invader
+
\ No newline at end of file
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cd280d54e76015e7fc9b6a7478a4038cd2f1bebe
--- /dev/null
+++ b/app/src/main/res/values/themes.xml
@@ -0,0 +1,16 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/xml/backup_rules.xml b/app/src/main/res/xml/backup_rules.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fa0f996d2c2a6bdd11f5371de4268c8389d6c720
--- /dev/null
+++ b/app/src/main/res/xml/backup_rules.xml
@@ -0,0 +1,13 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/xml/data_extraction_rules.xml b/app/src/main/res/xml/data_extraction_rules.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9ee9997b0b4726e57c27b2f7b21462b604ff8a88
--- /dev/null
+++ b/app/src/main/res/xml/data_extraction_rules.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/test/java/com/example/a8_bitinvader/ExampleUnitTest.java b/app/src/test/java/com/example/a8_bitinvader/ExampleUnitTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..b6f060dc1a472d82afdb16f30ef67b5db5a9fc2b
--- /dev/null
+++ b/app/src/test/java/com/example/a8_bitinvader/ExampleUnitTest.java
@@ -0,0 +1,19 @@
+package com.example.a8_bitinvader;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+
+
+/**
+ * Positive number unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void testAmIPositive() {
+ assertTrue(amIPositive(0.3));
+ }
+}
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..f05eacfd34967f6964e795ca3bc78e1421abb1c1
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,5 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+plugins {
+ id 'com.android.application' version '7.4.2' apply false
+ id 'com.android.library' version '7.4.2' apply false
+}
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000000000000000000000000000000000000..1de3156282d142a8d2f8e508fc90691cb6d02d5d
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,22 @@
+# 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=-Xmx2048m -Dfile.encoding=UTF-8
+# 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
+# Enables namespacing of each library's R class so that its R class includes only the
+# resources declared in the library itself and none from the library's dependencies,
+# thereby reducing the size of the R class for that library
+android.nonTransitiveRClass=true
+org.gradle.jvmargs=-Xmx4608m
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000000000000000000000000000000000000..e708b1c023ec8b20f512888fe07c5bd3ff77bb8f
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000000000000000000000000000000000000..9275cb7390213cadeac647aa3f518546c3a3cbd4
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Tue Apr 11 22:14:31 EDT 2023
+distributionBase=GRADLE_USER_HOME
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
+distributionPath=wrapper/dists
+zipStorePath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
diff --git a/gradlew b/gradlew
new file mode 100755
index 0000000000000000000000000000000000000000..4f906e0c811fc9e230eb44819f509cd0627f2600
--- /dev/null
+++ b/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/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000000000000000000000000000000000000..107acd32c4e687021ef32db511e8a206129b88ec
--- /dev/null
+++ b/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/settings.gradle b/settings.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..e72be80bc84f09094d6a826cec58bb59151483d2
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,16 @@
+pluginManagement {
+ repositories {
+ google()
+ mavenCentral()
+ gradlePluginPortal()
+ }
+}
+dependencyResolutionManagement {
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+rootProject.name = "8-bit Invader"
+include ':app'