Android Studio ブロック崩しアプリ制作(動画有り)

今回はブロック崩しアプリを制作しました。
YouTubeに作っている動画をアップしています。
https://www.youtube.com/watch?v=LO1qsMSMY-4&list=PLhg2PHSq8bjjav93XL0ycJSu2g7rD7f80

```java:Ball.java
package com.example.breakoutapp;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.View;

public class Ball extends View {
    public int x ,y ,radius;
    Paint paint;

    public Ball(Context context){
        super(context);
        radius = 20;
        x = 0;
        y = 0;
        paint = new Paint();
        paint.setColor(Color.WHITE);
        paint.setStyle(Paint.Style.FILL);
    }
    protected void onDraw(Canvas canvas){
        super.onDraw(canvas);
        canvas.drawCircle(x , y , radius ,paint);
    }
}
```

```java:Block.java
package com.example.breakoutapp;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.View;

public class Block extends View {
    public int left,top,right,bottom;
    public Paint paint;
    public Block(Context context) {
        super(context);
        left = 0;
        top = 0;
        right = 0;
        bottom = 0;
        paint = new Paint();
        paint.setColor(Color.WHITE);
        paint.setStyle(Paint.Style.FILL_AND_STROKE);
    }

    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Rect rect = new Rect(left,top,right,bottom);
        canvas.drawRect(rect,paint);
    }
}
```

```java:MainActivity.java
package com.example.breakoutapp;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.graphics.Color;
import android.graphics.Point;
import android.os.Bundle;
import android.os.Handler;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    Block[][] block;
    Ball ball;
    Handler handler = new Handler();
    Runnable runnable;
    int width, height, dx = 10, dy = 10, tap, WC = ViewGroup.LayoutParams.WRAP_CONTENT, breakBlocks = 0;
    int colSize = 8, rowSize = 6;//サイズ変更可能
    Block bar;
    RelativeLayout relativeLayout;
    TextView text;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

//        レイアウト作成
        relativeLayout = new RelativeLayout(this);
        relativeLayout.setBackgroundColor(Color.LTGRAY);
        setContentView(relativeLayout);

//        中心テキストをセット
        text = new TextView(this);
        text.setText("START");
        text.setTextSize(36);
        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(WC, WC);
        params.addRule(RelativeLayout.CENTER_IN_PARENT);
        relativeLayout.addView(text, params);

//        スクリーンのサイズを取得
        WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
        Display display = windowManager.getDefaultDisplay();
        Point point = new Point();
        display.getSize(point);
        width = point.x;
        height = point.y;

//        Ballを生成
        ball = new Ball(MainActivity.this);
        ball.x = width / 2;
        ball.y = height / 2;
        relativeLayout.addView(ball);

//        barを生成
        bar = new Block(MainActivity.this);
        bar.left = width / 3;
        bar.right = width / 3 * 2;
        bar.top = height / 5 * 4;
        bar.bottom = height / 5 * 4 + 20;
        relativeLayout.addView(bar);

//        blockを生成
        block = new Block[colSize][rowSize];
        for (int row = 0; row < rowSize; row++) {
            for (int col = 0; col < colSize; col++) {
                block[col][row] = new Block(MainActivity.this);
                switch (row) {
                    case 0:
                        block[col][row].paint.setColor(Color.rgb(251, 139, 255));
                        break;
                    case 1:
                        block[col][row].paint.setColor(Color.rgb(255, 77, 23));
                        break;
                    case 2:
                        block[col][row].paint.setColor(Color.rgb(255, 180, 139));
                        break;
                    case 3:
                        block[col][row].paint.setColor(Color.rgb(239, 253, 51));
                        break;
                    case 4:
                        block[col][row].paint.setColor(Color.rgb(148, 225, 47));
                        break;
                    case 5:
                        block[col][row].paint.setColor(Color.rgb(0, 180, 240));
                        break;
                }
                block[col][row].left = (width - (colSize - 1) * 2) / colSize * col + col * 2;
                block[col][row].right = (width - (colSize - 1) * 2) / colSize * (col + 1) + col * 2;
                block[col][row].top = height / 36 * (row + 3) + row * 2;
                block[col][row].bottom = height / 36 * (row + 4) + row * 2;
                relativeLayout.addView(block[col][row]);
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
//        タッチされたときにテキストを隠す
        text.setText("");

//        指のX座標を取得
        tap = (int) event.getX();

//        繰り返し処理
        runnable = new Runnable() {
            @Override
            public void run() {
//                指のX座標をもとにbarを動かす
                bar.left = tap - (width / 6);
                bar.right = tap + (width / 6);

//                ballの位置を動かす
                ball.x += dx;
                ball.y += dy;

//                画面端、barにぶつかった時、跳ね返らす
                if (ball.x <= ball.radius) {
                    dx = -dx;
                } else if (ball.x >= width - ball.radius) {
                    dx = -dx;
                }
                if (ball.y <= ball.radius) {
                    dy = -dy;
                } else if ((ball.y + ball.radius >= bar.top - 5) &&
                        (ball.y + ball.radius <= bar.top + 5) &&
                        (ball.x + ball.radius <= bar.right) &&
                        (ball.x - ball.radius >= bar.left)) {
                    dy = -dy;
                } else if (ball.y >= height - ball.radius) {
//                    GAMEOVER処理、
                    dy = 0;
                    dx = 0;
                    text.setText("GAMEOVER");
                    text.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            Intent intent = new Intent(MainActivity.this, MainActivity.class);
                            startActivity(intent);
                        }
                    });
                }
//                ブロックの当たり判定と、ぶつかった時の処理はbreakBlockメソッドを実行
                for (int row = 0; row < rowSize; row++) {
                    for (int col = 0; col < colSize; col++) {
                        if ((ball.x + ball.radius <= block[col][row].left + 5) &&
                                (ball.x + ball.radius >= block[col][row].left - 5) &&
                                (ball.y <= block[col][row].bottom) &&
                                (ball.y >= block[col][row].top)) {
                            dx = -dx;
                            breakBlock(col, row);
                        }
                        if ((ball.x - ball.radius <= block[col][row].right + 5) &&
                                (ball.x - ball.radius >= block[col][row].right - 5) &&
                                (ball.y - ball.radius < block[col][row].bottom) &&
                                (ball.y + ball.radius > block[col][row].top)) {
                            dx = -dx;
                            breakBlock(col, row);
                        }
                        if ((ball.y - ball.radius <= block[col][row].bottom + 5) &&
                                (ball.y - ball.radius >= block[col][row].bottom - 5) &&
                                (ball.x >= block[col][row].left) &&
                                (ball.x <= block[col][row].right)) {
                            dy = -dy;
                            breakBlock(col, row);
                        }
                        if ((ball.y + ball.radius <= block[col][row].top + 5) &&
                                (ball.y + ball.radius >= block[col][row].top - 5) &&
                                (ball.x >= block[col][row].left) &&
                                (ball.x <= block[col][row].right)) {
                            dy = -dy;
                            breakBlock(col, row);
                        }
                        double leftSpace = Math.pow(block[col][row].left - ball.x, 2);
                        double bottomSpace = Math.pow(block[col][row].bottom - ball.y, 2);
                        double rightSpace = Math.pow(block[col][row].right - ball.x, 2);
                        double topSpace = Math.pow(block[col][row].top - ball.y, 2);
                        if (leftSpace + bottomSpace <= Math.pow(ball.radius, 2)) {
                            dy = -dy;
                            dx = -dx;
                            breakBlock(col, row);
                        }
                        if (leftSpace + topSpace <= Math.pow(ball.radius, 2)) {
                            dy = -dy;
                            dx = -dx;
                            breakBlock(col, row);
                        }
                        if (rightSpace + bottomSpace <= Math.pow(ball.radius, 2)) {
                            dy = -dy;
                            dx = -dx;
                            breakBlock(col, row);
                        }
                        if (rightSpace + topSpace <= Math.pow(ball.radius, 2)) {
                            dy = -dy;
                            dx = -dx;
                            breakBlock(col, row);
                        }
                    }
                }
                handler.removeCallbacks(runnable);
                relativeLayout.removeView(bar);
                relativeLayout.removeView(ball);
                relativeLayout.addView(ball);
                relativeLayout.addView(bar);
                handler.postDelayed(runnable, 10);
            }
        };
        handler.postDelayed(runnable, 10);
        return super.onTouchEvent(event);
    }

    public void breakBlock(int col, int row) {
//        blockにballがぶつかった時の処理
        block[col][row].top = -10;
        block[col][row].bottom = -10;
        block[col][row].setVisibility(View.GONE);

//        GAMECLEARの処理
        breakBlocks++;
        if (breakBlocks == rowSize * colSize) {
            dx = 0;
            dy = 0;
            text.setText("CLEAR!!");
        }
    }
}
```

YouTubeに作っている動画をアップしています。
https://www.youtube.com/watch?v=LO1qsMSMY-4&list=PLhg2PHSq8bjjav93XL0ycJSu2g7rD7f80
以上。