5
\$\begingroup\$

I have created a mini Android game. The aim is to catch aliens in space. You score points for each aliens, there is a pause function and you can change the level of difficulty and change spaceships.

enter image description here

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.view.MotionEventCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import java.util.Random;

public class MainActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener {
    public void onItemSelected(AdapterView<?> parent, View view,
                               int pos, long id) {
        // An item was selected. You can retrieve the selected item using
        Log.d("myTag", "This is my message" + parent.getItemAtPosition(pos));
        String name = "Purple";
        String str = parent.getItemAtPosition(pos).toString();
        if (str.equals("Rookie")) {
            mainLayout = new LinearLayout(this);
            mainLayout.setOrientation(LinearLayout.VERTICAL);

            LinearLayout menuLayout = new LinearLayout(this);
            menuLayout.setBackgroundColor(Color.parseColor("#FFFFFF"));

            textView = new TextView(this);
            textView.setVisibility(View.VISIBLE);
            str = "Score: 0";
            textView.setText(str);
            menuLayout.addView(textView);

            Button button = new Button(this);
            button.setText("Pause");
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    togglePausePlay();
                }
            });
            menuLayout.addView(button);
            Spinner spinner2 = new Spinner(this);
            spinner2.setOnItemSelectedListener(this);
            ArrayAdapter<String> adapter = new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_list_item_1, spinnerValue);
            spinner2.setAdapter(adapter);
            menuLayout.addView(spinner2);

            mainLayout.addView(menuLayout);

            cg = new CatchGame(this, 3, "Purple", onScoreListener);
            cg.setBackground(getResources().getDrawable(R.drawable.bg_land_hdpi));
            mainLayout.addView(cg);
            getSupportActionBar().hide();
            setContentView(mainLayout);
            Log.d("game", "Started Advanced game");

        } else if (str.equals("Advanced")) {
            mainLayout = new LinearLayout(this);
            mainLayout.setOrientation(LinearLayout.VERTICAL);

            LinearLayout menuLayout = new LinearLayout(this);
            menuLayout.setBackgroundColor(Color.parseColor("#FFFFFF"));

            textView = new TextView(this);
            textView.setVisibility(View.VISIBLE);
            str = "Score: 0";
            textView.setText(str);
            menuLayout.addView(textView);

            Button button = new Button(this);
            button.setText("Pause");
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    togglePausePlay();
                }
            });
            menuLayout.addView(button);
            Spinner spinner2 = new Spinner(this);
            spinner2.setOnItemSelectedListener(this);
            ArrayAdapter<String> adapter = new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_list_item_1, spinnerValue);
            spinner2.setAdapter(adapter);
            menuLayout.addView(spinner2);

            mainLayout.addView(menuLayout);

            cg = new CatchGame(this, 5, "Purple", onScoreListener);
            cg.setBackground(getResources().getDrawable(R.drawable.bg_land_hdpi));
            mainLayout.addView(cg);
            getSupportActionBar().hide();
            setContentView(mainLayout);
            Log.d("game", "Started Advanced game");
        } else if (str.equals("Expert")) {
            mainLayout = new LinearLayout(this);
            mainLayout.setOrientation(LinearLayout.VERTICAL);

            LinearLayout menuLayout = new LinearLayout(this);
            menuLayout.setBackgroundColor(Color.parseColor("#FFFFFF"));

            textView = new TextView(this);
            textView.setVisibility(View.VISIBLE);
            str = "Score: 0";
            textView.setText(str);
            menuLayout.addView(textView);

            Button button = new Button(this);
            button.setText("Pause");
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    togglePausePlay();
                }
            });
            menuLayout.addView(button);
            Spinner spinner2 = new Spinner(this);
            spinner2.setOnItemSelectedListener(this);
            ArrayAdapter<String> adapter = new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_list_item_1, spinnerValue);
            spinner2.setAdapter(adapter);
            menuLayout.addView(spinner2);

            mainLayout.addView(menuLayout);

            cg = new CatchGame(this, 7, "Purple", onScoreListener);
            cg.setBackground(getResources().getDrawable(R.drawable.bg_land_hdpi));
            mainLayout.addView(cg);
            getSupportActionBar().hide();
            setContentView(mainLayout);
            Log.d("game", "Started Advanced game");
        } else if (str.equals("Master")) {
            mainLayout = new LinearLayout(this);
            mainLayout.setOrientation(LinearLayout.VERTICAL);

            LinearLayout menuLayout = new LinearLayout(this);
            menuLayout.setBackgroundColor(Color.parseColor("#FFFFFF"));

            textView = new TextView(this);
            textView.setVisibility(View.VISIBLE);
            str = "Score: 0";
            textView.setText(str);
            menuLayout.addView(textView);

            Button button = new Button(this);
            button.setText("Pause");
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    togglePausePlay();
                }
            });
            menuLayout.addView(button);
            Spinner spinner2 = new Spinner(this);
            spinner2.setOnItemSelectedListener(this);
            ArrayAdapter<String> adapter = new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_list_item_1, spinnerValue);
            spinner2.setAdapter(adapter);
            menuLayout.addView(spinner2);

            mainLayout.addView(menuLayout);

            cg = new CatchGame(this, 9, "Purple", onScoreListener);
            cg.setBackground(getResources().getDrawable(R.drawable.bg_land_hdpi));
            mainLayout.addView(cg);
            getSupportActionBar().hide();
            setContentView(mainLayout);
            Log.d("game", "Started Advanced game");
        } else if (str.equals("Orange")) {







            mainLayout = new LinearLayout(this);
            mainLayout.setOrientation(LinearLayout.VERTICAL);

            LinearLayout menuLayout = new LinearLayout(this);
            menuLayout.setBackgroundColor(Color.parseColor("#FFFFFF"));

            textView = new TextView(this);
            textView.setVisibility(View.VISIBLE);
            str = "Score: 0";
            textView.setText(str);
            menuLayout.addView(textView);

            Button button = new Button(this);
            button.setText("Pause");
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    togglePausePlay();
                }
            });
            menuLayout.addView(button);
            Spinner spinner2 = new Spinner(this);
            spinner2.setOnItemSelectedListener(this);
            ArrayAdapter<String> adapter = new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_list_item_1, spinnerValue);
            spinner2.setAdapter(adapter);
            menuLayout.addView(spinner2);
            Spinner spinner3 = new Spinner(this);
            spinner3.setOnItemSelectedListener(this);
            ArrayAdapter<String> adapter2 = new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_list_item_1, spinnerValue2);
            spinner3.setAdapter(adapter2);
            menuLayout.addView(spinner3);
            mainLayout.addView(menuLayout);

            cg = new CatchGame(this, 7, "Orange", onScoreListener);
            cg.setBackground(getResources().getDrawable(R.drawable.bg_land_hdpi));
            mainLayout.addView(cg);
            getSupportActionBar().hide();
            setContentView(mainLayout);
            Log.d("game", "Started Advanced game");










        } else if (str.equals("Yellow")) {







            mainLayout = new LinearLayout(this);
            mainLayout.setOrientation(LinearLayout.VERTICAL);

            LinearLayout menuLayout = new LinearLayout(this);
            menuLayout.setBackgroundColor(Color.parseColor("#FFFFFF"));

            textView = new TextView(this);
            textView.setVisibility(View.VISIBLE);
            str = "Score: 0";
            textView.setText(str);
            menuLayout.addView(textView);

            Button button = new Button(this);
            button.setText("Pause");
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    togglePausePlay();
                }
            });
            menuLayout.addView(button);
            Spinner spinner2 = new Spinner(this);
            spinner2.setOnItemSelectedListener(this);
            ArrayAdapter<String> adapter = new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_list_item_1, spinnerValue);
            spinner2.setAdapter(adapter);
            menuLayout.addView(spinner2);
            Spinner spinner3 = new Spinner(this);
            spinner3.setOnItemSelectedListener(this);
            ArrayAdapter<String> adapter2 = new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_list_item_1, spinnerValue2);
            spinner3.setAdapter(adapter2);
            menuLayout.addView(spinner3);
            mainLayout.addView(menuLayout);

            cg = new CatchGame(this, 7, "Yellow", onScoreListener);
            cg.setBackground(getResources().getDrawable(R.drawable.bg_land_hdpi));
            mainLayout.addView(cg);
            getSupportActionBar().hide();
            setContentView(mainLayout);
            Log.d("game", "Started Advanced game");










        }else if (str.equals("Purple")) {







            mainLayout = new LinearLayout(this);
            mainLayout.setOrientation(LinearLayout.VERTICAL);

            LinearLayout menuLayout = new LinearLayout(this);
            menuLayout.setBackgroundColor(Color.parseColor("#FFFFFF"));

            textView = new TextView(this);
            textView.setVisibility(View.VISIBLE);
            str = "Score: 0";
            textView.setText(str);
            menuLayout.addView(textView);

            Button button = new Button(this);
            button.setText("Pause");
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    togglePausePlay();
                }
            });
            menuLayout.addView(button);
            Spinner spinner2 = new Spinner(this);
            spinner2.setOnItemSelectedListener(this);
            ArrayAdapter<String> adapter = new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_list_item_1, spinnerValue);
            spinner2.setAdapter(adapter);
            menuLayout.addView(spinner2);
            Spinner spinner3 = new Spinner(this);
            spinner3.setOnItemSelectedListener(this);
            ArrayAdapter<String> adapter2 = new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_list_item_1, spinnerValue2);
            spinner3.setAdapter(adapter2);
            menuLayout.addView(spinner3);
            mainLayout.addView(menuLayout);

            cg = new CatchGame(this, 7, "Purple", onScoreListener);
            cg.setBackground(getResources().getDrawable(R.drawable.bg_land_hdpi));
            mainLayout.addView(cg);
            getSupportActionBar().hide();
            setContentView(mainLayout);
            Log.d("game", "Started Advanced game");










        }
    }

    public void onNothingSelected(AdapterView<?> parent) {
        // Another interface callback
    }

    CatchGame cg;
    public TextView textView;
    public LinearLayout mainLayout;
    String[] spinnerValue = {"Difficulty", "Rookie", "Advanced", "Expert", "Master"};
    String[] spinnerValue2 = {"Ship", "Purple", "Orange", "Yellow"};
    // start app
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mainLayout = new LinearLayout(this);
        mainLayout.setOrientation(LinearLayout.VERTICAL);

        LinearLayout menuLayout = new LinearLayout(this);
        menuLayout.setBackgroundColor(Color.parseColor("#FFFFFF"));

        textView = new TextView(this);
        textView.setVisibility(View.VISIBLE);
        String str = "Score: 0";
        textView.setText(str);
        menuLayout.addView(textView);

        Button button = new Button(this);
        button.setText("Pause");
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                togglePausePlay();
            }
        });
        menuLayout.addView(button);

        Spinner spinner2 = new Spinner(this);
        spinner2.setOnItemSelectedListener(this);
        ArrayAdapter<String> adapter = new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_list_item_1, spinnerValue);
        spinner2.setAdapter(adapter);
        menuLayout.addView(spinner2);

        Spinner spinner3 = new Spinner(this);
        spinner3.setOnItemSelectedListener(this);
        ArrayAdapter<String> adapter2 = new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_list_item_1, spinnerValue2);
        spinner3.setAdapter(adapter2);
        menuLayout.addView(spinner3);

        mainLayout.addView(menuLayout);

        cg = new CatchGame(this, 7, "Purple", onScoreListener);
        cg.setBackground(getResources().getDrawable(R.drawable.bg_land_hdpi));
        mainLayout.addView(cg);
        getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
        getSupportActionBar().hide();
        setContentView(mainLayout);
    }

    private void togglePausePlay() {
        if (cg.paused) {
            // play
            //  getSupportActionBar().hide();
            Toast.makeText(MainActivity.this, "Play", Toast.LENGTH_SHORT).show();
        } else {
            // pause
            //    getSupportActionBar().show();
            Toast.makeText(MainActivity.this, "Pause", Toast.LENGTH_SHORT).show();
        }

        cg.paused = !cg.paused;
    }

    private OnScoreListener onScoreListener = new OnScoreListener() {
        @Override
        public void onScore(int score) {
            textView.setText("Score: " + score);
        }
    };

    interface OnScoreListener {
        void onScore(int score);
    }

    class CatchGame extends View {
        int NBRSTEPS; // number of discrete positions in the x-dimension; must be uneven
        String heroName;
        int screenW;
        int screenH;
        int[] x; // x-coordinates for falling objects
        int[] y; // y-coordinates for falling objects
        int[] hero_positions; // x-coordinates for hero
        Random random = new Random();
        int ballW; // width of each falling object
        int ballH; // height of ditto
        float dY; //vertical speed
        Bitmap falling, hero, jamie2, jamieleft, jamieright, falling2, falling3;
        int heroXCoord;
        int heroYCoord;
        int xsteps;
        int score;
        int offset;
        boolean gameOver; // default value is false
        boolean toastDisplayed;
        boolean paused = false;

        OnScoreListener onScoreListener;

        // constructor, load images and get sizes
        public CatchGame(Context context, int difficulty, String name, OnScoreListener onScoreListener) {
            super(context);
            NBRSTEPS = difficulty;
            heroName = name;
            this.onScoreListener = onScoreListener;

            x = new int[NBRSTEPS];
            y = new int[NBRSTEPS];
            hero_positions = new int[NBRSTEPS];
            int resourceIdFalling = 0;
            int resourceIdFalling2 = 0;
            int resourceIdFalling3 = 0;
            int resourceIdHero = 0;
            if (heroName.equals("Purple")) {
                resourceIdFalling = R.drawable.object2_hdpi;
                resourceIdFalling2 = R.drawable.object1_hdpi;
                resourceIdHero = R.drawable.right_side_hdpi;
                setBackground(getResources().getDrawable(R.drawable.bg_land_hdpi));
            }   else         if (heroName.equals("Orange")) {
                resourceIdFalling = R.drawable.object2_hdpi;
                resourceIdFalling2 = R.drawable.object1_hdpi;
                resourceIdHero = R.drawable.spaceship3_hdpi;
                setBackground(getResources().getDrawable(R.drawable.bg_land_hdpi));
            }   else         if (heroName.equals("Yellow")) {
                resourceIdFalling = R.drawable.object2_hdpi;
                resourceIdFalling2 = R.drawable.object1_hdpi;
                resourceIdHero = R.drawable.spaceship2_hdpi;
                setBackground(getResources().getDrawable(R.drawable.bg_land_hdpi));
            }
            resourceIdFalling3 = R.drawable.object3_hdpi;
            falling = BitmapFactory.decodeResource(getResources(), resourceIdFalling); //load a falling image
            falling2 = BitmapFactory.decodeResource(getResources(), resourceIdFalling2); //load a falling image
            falling3 = BitmapFactory.decodeResource(getResources(), resourceIdFalling3); //load a falling image
            hero = BitmapFactory.decodeResource(getResources(), resourceIdHero); //load a hero image
            jamieleft = BitmapFactory.decodeResource(getResources(), R.drawable.right_side_hdpi); //load a hero image
            jamieright = BitmapFactory.decodeResource(getResources(), R.drawable.right_side_hdpi); //load a hero image
            ballW = falling.getWidth();
            ballH = falling.getHeight();
        }

        // set coordinates, etc.
        void initialize() {
            if (!gameOver) { // run only once, when the game is first started
                int maxOffset = (NBRSTEPS - 1) / 2;
                for (int i = 0; i < x.length; i++) {
                    int origin = (screenW / 2) + xsteps * (i - maxOffset);
                    x[i] = origin - (ballW / 2);
                    hero_positions[i] = origin - hero.getWidth();
                }
                int heroWidth = hero.getWidth();
                int heroHeight = hero.getHeight();

                hero = Bitmap.createScaledBitmap(hero, heroWidth * 2, heroHeight * 2, true);
                hero = Bitmap.createScaledBitmap(hero, heroWidth * 2, heroHeight * 2, true);
                jamieleft = Bitmap.createScaledBitmap(jamieleft, jamieleft.getWidth() * 2, jamieright.getWidth() * 2, true);
                jamieright = Bitmap.createScaledBitmap(jamieright, jamieright.getWidth() * 2, jamieright.getWidth() * 2, true);

                heroYCoord = screenH - 2 * heroHeight; // bottom of screen

            }
            for (int i = 0; i < y.length; i++) {
                y[i] = -random.nextInt(1000); // place items randomly in vertical direction
            }

            offset = (NBRSTEPS - 1) / 2; // place hero at centre of the screen
            heroXCoord = hero_positions[offset];

            // initialize or reset global attributes
            dY = 2.0f;
            score = 0;
            gameOver = false;
            toastDisplayed = false;
        }

        // method called when the screen opens
        @Override
        public void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            screenW = w;
            screenH = h;
            xsteps = w / NBRSTEPS;
            initialize();
        }

        // method called when the "game over" toast has finished displaying
        void restart(Canvas canvas) {
            toastDisplayed = true;
            initialize();
            draw(canvas);
        }

        // update the canvas in order to display the game action
        @Override
        public void onDraw(Canvas canvas) {
            if (toastDisplayed) {
                restart(canvas);
                return;
            }
            super.onDraw(canvas);

            int heroHeight = hero.getHeight();
            int heroWidth = hero.getWidth();
            int heroCentre = heroXCoord + heroWidth / 2;

            Context context = this.getContext();

            // compute locations of falling objects
            for (int i = 0; i < y.length; i++) {
                if (!paused) {
                    y[i] += (int) dY;
                }
                // if falling object hits bottom of screen
                if (y[i] > (screenH - ballH) && !gameOver) {
                    dY = 0;
                    gameOver = true;
                    paused = true;
                    int duration = Toast.LENGTH_SHORT;

                    final Toast toast = Toast.makeText(context, "GAME OVER!\nScore: " + score, duration);
                    toast.show();
                    Handler handler = new Handler();
                    handler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            toast.cancel();
                            toastDisplayed = true;
                        }
                    }, 3000);
                    //Vibrator v = (Vibrator) context.getSystemService(context.VIBRATOR_SERVICE);
                    // Vibrate for 3000 milliseconds
                    //v.vibrate(3000);

                }
                // if the hero catches a falling object
                if (x[i] < heroCentre && x[i] + ballW > heroCentre &&
                        y[i] > screenH - ballH - heroHeight) {

                    y[i] = -random.nextInt(1000); // reset to new vertical position
                    score += 1;
                    onScoreListener.onScore(score);
                }

            }

            canvas.save(); //Save the position of the canvas.
            Random rand = new Random();
            int randomNum = 1 + rand.nextInt((3 - 1) + 1);
            for (int i = 0; i < y.length; i++) {
                if (i % 3 == 1)
                    canvas.drawBitmap(falling2, x[i], y[i], null); //Draw the falling on the canvas.
                else if  (i % 3 == 2)
                    canvas.drawBitmap(falling, x[i], y[i], null); //Draw the falling on the canvas.
                else if  (i % 3 == 0)
                    canvas.drawBitmap(falling3, x[i], y[i], null); //Draw the falling on the canvas.

            }
            canvas.drawBitmap(hero, heroXCoord, heroYCoord, null); //Draw the hero on the canvas.
            canvas.restore();
            //Call the next frame.
            invalidate();
        }

        // event listener for when the user touches the screen
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            if (paused) {
                paused = false;
            }
            int action = MotionEventCompat.getActionMasked(event);
            if (action != MotionEvent.ACTION_DOWN || gameOver) { // non-touchdown event or gameover
                return true; // do nothing
            }
            int coordX = (int) event.getX();
            int xCentre = (screenW / 2) - (hero.getWidth() / 2);
            int maxOffset = hero_positions.length - 1; // can't move outside right edge of screen
            int minOffset = 0; // ditto left edge of screen

            if (coordX < xCentre && offset > minOffset) { // touch event left of the centre of screen
                offset--; // move hero to the left

                if (coordX < heroXCoord)// + heroWidth / 2)
                    hero = Bitmap.createScaledBitmap(hero, hero.getWidth(), hero.getHeight(), true);

            }
            if (coordX > xCentre && offset < maxOffset) { // touch event right of the centre of screen
                offset++; // move hero to the right

                if (coordX > heroXCoord)
                    hero = Bitmap.createScaledBitmap(hero, hero.getWidth(), hero.getHeight(), true);

            }
            heroXCoord = hero_positions[offset];
            return true;
        }
    }
}

This is my first Android project and I'd like to learn how to improve my code.

\$\endgroup\$

1 Answer 1

4
\$\begingroup\$

You really need to split your code. You have methods that are hundreds of lines long, they should be more like under 10 lines.

Then, you can also benefit by trying going more OO. The sequence of if-elses after String str = parent.getItemAtPosition(pos).toString();, could be streamlined using polymorphism.

The biggest problem that I see is code repetition. If you take the block after (str.equals("Rookie")) { and the block after if (str.equals("Advanced")) {, you'll see that there are 35 lines of which only 1 is different:

cg = new CatchGame(this, 3, "Purple", onScoreListener);

and in this line, only the number changes. This is a huge violation of DRY. Start by extracting that into a method.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.