package com.lmweav.schoolquest; import androidx.constraintlayout.widget.ConstraintLayout; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.FloatEvaluator; import android.animation.ObjectAnimator; import android.app.Activity; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.res.AssetFileDescriptor; import android.graphics.Typeface; import android.media.AudioManager; import android.media.MediaPlayer; import android.media.SoundPool; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.view.View; import android.view.Window; import android.view.WindowManager; import android.view.animation.AccelerateInterpolator; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; import android.widget.ImageView; import com.android.billingclient.api.BillingClient; import com.android.billingclient.api.SkuDetails; import com.android.billingclient.api.SkuDetailsResponseListener; import com.google.android.flexbox.FlexboxLayout; import com.lmweav.schoolquest.utilities.BGMFader; import com.lmweav.schoolquest.utilities.GameTextView; import com.lmweav.schoolquest.utilities.billing.BillingManager; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.util.ArrayList; import java.util.List; import static android.graphics.Typeface.NORMAL; import static com.lmweav.schoolquest.Constants.SFX_CLICK; import static com.lmweav.schoolquest.Constants.SFX_DEBUFF; /* * School Quest: TitleActivity * This class is the Android activity that runs the title screen and main menu. * * Methods in this class set up, alter and display UI elements found in the main menu. * * @author Luke Weaver * @version 1.0.9 * @since 2019-10-16 */ public class TitleActivity extends Activity { private static TitleActivity instance; private int currentLoadingTime = 0; private int loadingTime = 6; private boolean loading; private ObjectAnimator textAnimator1; private ObjectAnimator textAnimator2; private Runnable displayInputTextBox; private Runnable closeTextBox; private Runnable nameConfirm; private Runnable submitName; private Runnable deleteConfirm; private Runnable aboutGame; private String playerName; private String fileName; private MediaPlayer bgm; private transient static SoundPool sfx; private static int[] sfxIds; private BillingManager billingManager; List<String> skuList = new ArrayList<>(); /*--------------------------------------------------------------------------------------------- | Getters and Setters ----------------------------------------------------------------------------------------------*/ public static TitleActivity getInstance() { return instance; } /*--------------------------------------------------------------------------------------------- | Methods ----------------------------------------------------------------------------------------------*/ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); this.requestWindowFeature(Window.FEATURE_NO_TITLE); setVolumeControlStream(AudioManager.STREAM_MUSIC); setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); setContentView(R.layout.activity_title); instance = this; skuList.add("donation"); billingManager = new BillingManager(this); bgm = MediaPlayer.create(this, R.raw._music_theme); bgm.setLooping(true); bgm.start(); loadSFX(); ConstraintLayout titleScreen = findViewById(R.id.title_screen); final ConstraintLayout mainMenu = findViewById(R.id.main_menu); final ConstraintLayout mainMenuButtons = findViewById(R.id.main_menu_buttons); final ConstraintLayout dataButtons = findViewById(R.id.data_buttons); titleScreen.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { playSFX(SFX_CLICK); mainMenu.setVisibility(View.VISIBLE); mainMenuButtons.setVisibility(View.VISIBLE); changeBGM(R.raw._music_results); setLoadingScreen(true); } }); ConstraintLayout newGameButton = findViewById(R.id.new_game_button); ConstraintLayout continueButton = findViewById(R.id.continue_button); final ConstraintLayout data1Button = findViewById(R.id.data1_button); final ConstraintLayout data2Button = findViewById(R.id.data2_button); final ConstraintLayout data3Button = findViewById(R.id.data3_button); final ConstraintLayout data4Button = findViewById(R.id.data4_button); final ImageView aboutButton = findViewById(R.id.about_button); final ImageView shareButton = findViewById(R.id.share_button); final ImageView donateButton = findViewById(R.id.donate_button); final ConstraintLayout textBox = findViewById(R.id.textbox); final ConstraintLayout textBoxInput = findViewById(R.id.textbox_box_input); final FlexboxLayout textBoxButton = findViewById(R.id.textbox_box_buttons); final GameTextView textBoxText = findViewById(R.id.textbox_box_text); newGameButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { playSFX(SFX_CLICK); mainMenuButtons.setVisibility(View.GONE); dataButtons.setVisibility(View.VISIBLE); setDataClickListener(data1Button, true, "schoolQuest1.dat"); setDataClickListener(data2Button, true, "schoolQuest2.dat"); setDataClickListener(data3Button, true, "schoolQuest3.dat"); setDataClickListener(data4Button, true, "schoolQuest4.dat"); } }); continueButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { playSFX(SFX_CLICK); mainMenuButtons.setVisibility(View.GONE); dataButtons.setVisibility(View.VISIBLE); setDataClickListener(data1Button, false, "schoolQuest1.dat"); setDataClickListener(data2Button, false, "schoolQuest2.dat"); setDataClickListener(data3Button, false, "schoolQuest3.dat"); setDataClickListener(data4Button, false, "schoolQuest4.dat"); } }); aboutButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { playSFX(SFX_CLICK); textBox.setVisibility(View.VISIBLE); textBoxButton.setVisibility(View.VISIBLE); findViewById(R.id.textbox_box_buttons_no).setVisibility(View.GONE); ((GameTextView) findViewById(R.id.textbox_box_buttons_yes_text)). setText("Full Attributions"); findViewById(R.id.textbox_box_buttons_yes).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { aboutGame.run(); } }); textBoxInput.setVisibility(View.GONE); textBoxText.setText(R.string.credits); textBox.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { textBox.setVisibility(View.GONE); findViewById(R.id.textbox_box_buttons_no).setVisibility(View.VISIBLE); ((GameTextView) findViewById(R.id.textbox_box_buttons_yes_text)). setText("Yes"); textBox.setOnClickListener(null); } }); } }); shareButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { playSFX(SFX_CLICK); share(); } }); donateButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { playSFX(SFX_CLICK); billingManager.querySkuDetailsAsync(BillingClient.SkuType.INAPP, skuList, new SkuDetailsResponseListener() { @Override public void onSkuDetailsResponse(int responseCode, List<SkuDetails> skuDetailsList) { billingManager.startPurchaseFlow(skuDetailsList.get(0)); } }); } }); setUpStartTextAnimation(); GameTextView data1Text = findViewById(R.id.data1_text); GameTextView data1NGPlus = findViewById(R.id.data1_ngplus); GameTextView data1SubText = findViewById(R.id.data1_info); GameTextView data2Text = findViewById(R.id.data2_text); GameTextView data2NGPlus = findViewById(R.id.data2_ngplus); GameTextView data2SubText = findViewById(R.id.data2_info); GameTextView data3Text = findViewById(R.id.data3_text); GameTextView data3NGPlus = findViewById(R.id.data3_ngplus); GameTextView data3SubText = findViewById(R.id.data3_info); GameTextView data4Text = findViewById(R.id.data4_text); GameTextView data4NGPlus = findViewById(R.id.data4_ngplus); GameTextView data4SubText = findViewById(R.id.data4_info); setDataInfo(data1Text, data1SubText, data1NGPlus, "schoolQuest1.dat", "1."); setDataInfo(data2Text, data2SubText, data2NGPlus, "schoolQuest2.dat", "2."); setDataInfo(data3Text, data3SubText, data3NGPlus, "schoolQuest3.dat", "3."); setDataInfo(data4Text, data4SubText, data4NGPlus, "schoolQuest4.dat", "4."); EditText nameInput = findViewById(R.id.textbox_box_input_text); Typeface tf = Typeface.createFromAsset(getAssets(), "fonts/press_start_2p.ttf"); nameInput.setTypeface(tf ,NORMAL); setTextBoxRunnables(); final Handler handler = new Handler(); class MyRunnable implements Runnable { private Handler handler; private MyRunnable(Handler handler) { this.handler = handler; } @Override public void run() { this.handler.postDelayed(this, 50); if (loading) { if (loadingTime <= 0) { return; } if (currentLoadingTime > loadingTime) { setLoadingScreen(false); currentLoadingTime = 0; } else { currentLoadingTime++; } } } } handler.post(new MyRunnable(handler)); } private void setUpStartTextAnimation() { GameTextView startText = findViewById(R.id.startText); textAnimator1 = ObjectAnimator.ofFloat(startText, "alpha", 0f, 1f); textAnimator1.setEvaluator(new FloatEvaluator()); textAnimator1.setDuration(0); textAnimator1.addListener(new AnimatorListenerAdapter(){ @Override public void onAnimationEnd(Animator animation) { new Handler().postDelayed(new Runnable() { @Override public void run() { textAnimator2.start(); } }, 500); } }); textAnimator2 = ObjectAnimator.ofFloat(startText, "alpha", 1f, 0f); textAnimator2.setEvaluator(new FloatEvaluator()); textAnimator2.setDuration(0); textAnimator2.addListener(new AnimatorListenerAdapter(){ @Override public void onAnimationEnd(Animator animation) { new Handler().postDelayed(new Runnable() { @Override public void run() { textAnimator1.start(); } }, 500); } }); textAnimator1.start(); } public void setDataInfo(GameTextView dataText, GameTextView dataSubText, GameTextView NGPlus, String fileName, String fileNumber) { Game data; try { FileInputStream saveData = openFileInput(fileName); ObjectInputStream in = new ObjectInputStream(saveData); data = (Game) in.readObject(); in.close(); saveData.close(); String time = Game.getTimeKey(data.getTime()); time = time.substring(0,1).toUpperCase() + time.substring(1); String data1Name = fileNumber + data.getPlayer().getName(); int days = (Constants.NUMBER_OF_DAYS - data.getDay()); if (days < 0) { days = 0; } String data1Info = (days + " days/" + time); if (data.isNGPlus()) { NGPlus.setVisibility(View.VISIBLE);} else { NGPlus.setVisibility(View.GONE); } dataText.setText(data1Name); dataSubText.setText(data1Info); } catch (NullPointerException e) { e.printStackTrace(); dataText.setText("CORRUPTED"); dataSubText.setText(" "); } catch (Exception e) { dataText.setText("No Data"); dataSubText.setText(" "); e.printStackTrace(); } } public void setDataClickListener(final ConstraintLayout button, final boolean newGame, final String fileName) { final File file = new File(getApplicationContext().getFilesDir(),fileName); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { playSFX(SFX_CLICK); instance.fileName = fileName; if (newGame) { if (file.exists()) { deleteConfirm.run(); } else { displayInputTextBox.run(); } } else { Intent intent = new Intent(instance, GameActivity.class); Bundle bundle = new Bundle(); bundle.putBoolean("newGame", false); bundle.putString("data", fileName); playerName = ((GameTextView) button.getChildAt(0)).getText(). toString().substring(2); bundle.putString("name", playerName); intent.putExtras(bundle); BGMFader.stop(bgm, 100); setLoadingScreen(true, -1); startActivity(intent); } } }); if (!newGame) { if(!file.exists()){ button.setAlpha(0.5f); button.setEnabled(false); } } else { button.setAlpha(1f); button.setEnabled(true); } } public void setTextBoxRunnables() { final ConstraintLayout textBox = findViewById(R.id.textbox); final ConstraintLayout textBoxInput = findViewById(R.id.textbox_box_input); final FlexboxLayout textBoxButton = findViewById(R.id.textbox_box_buttons); final GameTextView textBoxText = findViewById(R.id.textbox_box_text); final ConstraintLayout textBoxInputButton = findViewById(R.id.textbox_box_input_button); final ConstraintLayout textBoxYesButton = findViewById(R.id.textbox_box_buttons_yes); final ConstraintLayout textBoxNoButton = findViewById(R.id.textbox_box_buttons_no); final EditText nameInput = findViewById(R.id.textbox_box_input_text); displayInputTextBox = new Runnable() { @Override public void run() { textBox.setVisibility(View.VISIBLE); textBoxInput.setVisibility(View.VISIBLE); textBoxButton.setVisibility(View.GONE); textBoxText.setText("What is your name?"); textBoxInputButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { playSFX(SFX_CLICK); submitName.run(); } }); } }; closeTextBox = new Runnable() { @Override public void run() { textBox.setVisibility(View.GONE); textBoxInput.setVisibility(View.GONE); textBoxButton.setVisibility(View.GONE); } }; submitName = new Runnable() { @Override public void run() { playerName = nameInput.getText().toString(); if (playerName.length() > 0) { InputMethodManager inputMethodManager = (InputMethodManager) instance. getSystemService(Activity.INPUT_METHOD_SERVICE); View view = instance.getCurrentFocus(); assert inputMethodManager != null; assert view != null; inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0); textBox.setVisibility(View.VISIBLE); textBoxInput.setVisibility(View.GONE); textBoxButton.setVisibility(View.VISIBLE); textBoxText.setText("Your name is " + playerName + "?"); textBoxYesButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { playSFX(SFX_CLICK); nameInput.setText(""); nameConfirm.run(); } }); textBoxNoButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { playSFX(SFX_CLICK); displayInputTextBox.run(); } }); } else { playSFX(SFX_DEBUFF); } } }; deleteConfirm = new Runnable() { @Override public void run() { textBox.setVisibility(View.VISIBLE); textBoxInput.setVisibility(View.GONE); textBoxButton.setVisibility(View.VISIBLE); textBoxText.setText("Your existing save data will be overwritten. Is that ok?"); textBoxYesButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { playSFX(SFX_CLICK); displayInputTextBox.run(); } }); textBoxNoButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { playSFX(SFX_CLICK); closeTextBox.run(); } }); } }; nameConfirm = new Runnable() { @Override public void run() { Intent intent = new Intent(instance, GameActivity.class); Bundle bundle = new Bundle(); bundle.putBoolean("newGame", true); bundle.putString("data", fileName); bundle.putString("name", playerName); intent.putExtras(bundle); BGMFader.stop(bgm, 100); setLoadingScreen(true, -1); startActivity(intent); } }; aboutGame = new Runnable() { @Override public void run() { Intent browserIntent = new Intent( Intent.ACTION_VIEW, Uri.parse("http://miniweav.com/create/school-quest#attributions")); startActivity(browserIntent); } }; } public void reset() { GameTextView data1Text = findViewById(R.id.data1_text); GameTextView data1NGPlus = findViewById(R.id.data1_ngplus); GameTextView data1SubText = findViewById(R.id.data1_info); GameTextView data2Text = findViewById(R.id.data2_text); GameTextView data2NGPlus = findViewById(R.id.data2_ngplus); GameTextView data2SubText = findViewById(R.id.data2_info); GameTextView data3Text = findViewById(R.id.data3_text); GameTextView data3NGPlus = findViewById(R.id.data3_ngplus); GameTextView data3SubText = findViewById(R.id.data3_info); GameTextView data4Text = findViewById(R.id.data4_text); GameTextView data4NGPlus = findViewById(R.id.data4_ngplus); GameTextView data4SubText = findViewById(R.id.data4_info); setDataInfo(data1Text, data1SubText, data1NGPlus, "schoolQuest1.dat", "1."); setDataInfo(data2Text, data2SubText, data2NGPlus, "schoolQuest2.dat", "2."); setDataInfo(data3Text, data3SubText, data3NGPlus, "schoolQuest3.dat", "3."); setDataInfo(data4Text, data4SubText, data4NGPlus, "schoolQuest4.dat", "4."); changeBGM(R.raw._music_theme); findViewById(R.id.textbox).setVisibility(View.GONE); findViewById(R.id.data_buttons).setVisibility(View.GONE); findViewById(R.id.main_menu_buttons).setVisibility(View.GONE); findViewById(R.id.main_menu).setVisibility(View.GONE); setLoadingScreen(false); } public void loadSFX() { sfx = new SoundPool(5, AudioManager.STREAM_MUSIC, 0); sfxIds = new int[10]; sfxIds[SFX_CLICK] = sfx.load(this, R.raw._sfx_click, 0); sfxIds[SFX_DEBUFF] = sfx.load(this, R.raw._sfx_debuff, 1); } public void playSFX(int id) { sfx.play(sfxIds[id], 1, 1, 1, 0, 1.0f); } public void changeBGM(final int newBGM, final int... pos) { BGMFader.stop(bgm, 400, new Runnable() { @Override public void run() { bgm.reset(); AssetFileDescriptor afd = getResources().openRawResourceFd(newBGM); if (afd == null) return; try { bgm.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength()); afd.close(); bgm.prepare(); } catch (IOException | IllegalStateException e) { e.printStackTrace(); } bgm.setLooping(true); if (pos.length > 0) { bgm.seekTo(pos[0]); } } }); } public void enableLoadingScreen() { ImageView loadingScreen = findViewById(R.id.loading_screen); loadingScreen.setVisibility(View.VISIBLE); } public void disableLoadingScreen() { final ImageView loadingScreen = findViewById(R.id.loading_screen); Animation fadeOut = new AlphaAnimation(1, 0); fadeOut.setInterpolator(new AccelerateInterpolator()); fadeOut.setDuration(400); fadeOut.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { loading = false; BGMFader.start(bgm, 100); } @Override public void onAnimationRepeat(Animation animation) { } }); loadingScreen.setAnimation(fadeOut); loadingScreen.getAnimation().start(); loadingScreen.setVisibility(View.GONE); } public void setLoadingScreen(boolean loading, int... frames) { currentLoadingTime = 0; if (frames.length == 0) { loadingTime = 6; } else { loadingTime = frames[0]; } if (loading) { this.loading = true; enableLoadingScreen(); } else { disableLoadingScreen(); } } public void share() { Intent sharingIntent = new Intent(Intent.ACTION_SEND); sharingIntent.setType("text/plain"); sharingIntent.putExtra(Intent.EXTRA_SUBJECT, "Play School Quest for FREE!"); sharingIntent.putExtra(Intent.EXTRA_TEXT, getResources().getString(R.string.share)); startActivity(Intent.createChooser(sharingIntent, "Share via")); } @Override public void onBackPressed() { if (findViewById(R.id.textbox).getVisibility() == View.VISIBLE) { playSFX(SFX_CLICK); findViewById(R.id.textbox).setVisibility(View.GONE); } else if (findViewById(R.id.data_buttons).getVisibility() == View.VISIBLE) { playSFX(SFX_CLICK); findViewById(R.id.data_buttons).setVisibility(View.GONE); findViewById(R.id.main_menu_buttons).setVisibility(View.VISIBLE); } else if (findViewById(R.id.main_menu_buttons).getVisibility() == View.VISIBLE) { playSFX(SFX_CLICK); findViewById(R.id.main_menu_buttons).setVisibility(View.GONE); findViewById(R.id.main_menu).setVisibility(View.GONE); changeBGM(R.raw._music_theme); setLoadingScreen(true); } else { super.onBackPressed(); } } @Override public void onPause() { super.onPause(); bgm.pause(); } @Override public void onResume() { super.onResume(); if (!bgm.isPlaying()) { bgm.start(); } } }