Арканоид(10)
Что мы будем делать с Canvas?
Мы будем рисовать на нем (в его матрице).
Поэтому нам понадобятся два метода
void setPoint(double x, double y, char c)
void drawMatrix(double x, double y, int[][] matrix, char c)

Первый метод — setPoint будет «ставить точку в координатах x,y цветом c«.

В методе надо:
а) округлить x и y до целых чисел
б) занести в matrix[y][x] значение с
в) ничего не делать, если x < 0 или y < 0 или y > matrix.length или x > matrix[0].length

Второй метод — drawMatrix копирует переданную ему картинку (матрицу) в матрицу Canvas.
И не просто копирует, а начиная с координат x, y

В методе надо:
а) с помощью двух вложенных циклов пройтись по всем ячейкам переданной картинки
б) если значение ячейки элемента [i][j] полученной матрицы не равно 0, то покрасить в матрице объекта Canvas точку (x+j, y+i) в цвет c:
setPoint(x+j, y+i, c)

Арканоид(9)
Теперь займемся классом Canvas.
Он у нас будет содержать матрицу (двумерный массив), куда мы будем «рисовать«.
У матрицы есть ширина и высота.
А еще будем в ней хранить не числа (int), а символы (char).

Надо:
а) Добавить в класс два приватных поля width и height.
б) Добавить в класс приватное поле matrix (char[][]).
в) Добавить конструктор с двумя параметрами типа int (width и height), поле matrix должно быть инициализировано пустым массивом размерностью [height+2][width+2].
г) Добавить геттеры и сеттеры для всех приватных полей класса.

Арканоид(8)
Но и это еще не все.
Классу BaseObject нужны еще методы.
Пока это будут пустые методы draw(Canvas canvas) и move().
Классы-наследники должны будут переопределить их у себя и реализовать необходимую функциональность (пока можешь оставить их пустыми, просто чтобы код компилировался).
Объяви эти методы, но сделай их абстрактными.
Также сделай абстрактным сам класс BaseObject.

А еще нам нужно будет определять попал шарик в кирпич или в подставку.
Это будем делать так:
В этом же классе, создадим специальный метод: boolean isIntersec(BaseObject o)
Он будет определять — «пересеклись» объекты или нет. Если пересеклись — возвращать true, если нет — false.

Т.к. объекты мы условно считаем кругами, то предлагаю такую формулу взаимодействия
Если центр круга одного объекта попал в круг другого, то будем считать, что они столкнулись.

Или еще проще:
дистанция_между_объектами <= max (радиус_первого_объекта, радиус_второго_объекта)

Арканоид(7)
Теперь перейдем к классу BaseObject.
Я хочу сделать несколько предложений.

Во-первых для простоты считать все объекты у нас будут круглыми.
Нет, отрисовывать их мы будем фигурными, как и раньше.
А вот при расчетах из взаимодействия исходить из того, что они круглые.
Так — гораздо проще.

Во-вторых. Пусть координаты объектов и радиус будут вещественными числами.
Это придаст плавность движениям и точность всем вычислениям.
А при отрисовке мы будем их округлять.

Итак:
а) Добавь в класс BaseObject приватные поля x (double), y (double), radius (double).
б) Добавь геттеры и сеттеры.
в) Добавь конструктор BaseObject(double x, double y, double radius).
г) Пройдись по все классам-наследникам и поправь у них конструкторы.

Если вы пользуйтесь Intellij IDEA — Alt+Insert вам в помощь.

Арканоид(6)
У нас будут «кирпичи«, «шарик» и «подставка» и у них будет много общего.
Они будут перемещаться по полю и отрисовываться.
Значит у них у всех будут координаты и размер.
А еще методы move() — для перемещения и draw() для отрисовки.

Есть интересное предложение: давай введем один базовый класс для все объектов.
Пусть это будет класс BaseObject.
А классы Ball, Stand, Brick от него наследуются.

Создай класс BaseObject и добавь его родителем к классам Ball, Stand, Brick

Еще нам понадобится класс Canvas
Он будет ответственным за «отрисовку» объектов.
С помощью его они будут отрисовывать себя.
Вернее даже на нем, но детали я сообщу позднее.

Создай и этот класс.

Арканоид(5)
Чего еще не хватает классу Arkanoid?
Во-первых ему нужен метод run(), в котором будет описана основная логика программы.
Еще нужен метод move() — который будет двигать на один шаг все объекты требующие движения.
Создай методы run() и move().

Еще нам понадобится НЕ приватная статическая переменная game типа Arkanoid, которая будет хранить ссылку на созданный экземпляр класса Arkanoid.

Выглядеть это должно примерно так:
static Arkanoid game;

Арканоид(4)
Также классу Arkanoid нужно будет хранить ссылку на шарик (Ball), «подставку» Stand и список «кирпичей«.

Надо:
а) создать в классе Arkanoid два private поля: ball типа Ball и stand типа Stand
б) добавить private поле bricks типа List<Brick>
в) добавь для них публичные геттеры и сеттеры

Арканоид(3)
Пожалуй, пора добавить конструктор в класс Arkanoid.
Конструктор должен принимать два параметра типа int (width и height) и корректно устанавливать значения соответствующих полей класса.

Арканоид(2)
Главному классу (Arkanoid) нужно будет хранить информацию о размерах поля, где будут происходить все действия.

Поэтому:
а) добавь в класс Arkanoid два приватных поля width(ширина) и height(высота) типа int
б) создай для них публичные геттеры и сеттеры

Арканоид(1)
Давай сегодня напишем игру Арканоид.

В оригинале это выглядит примерно так http://www.youtube.com/watch?v=Th-Z6QQ5AOQ
Для начала мы напишем упрощенную версию этой игры.
У нас будут кубики, шарик и летающая «подставка«, которая не дает шарику упасть.

Поэтому нам понадобятся классы:
а) Arkanoid — класс в котором происходят основные действия. Также в нем будет наша точка входа в программу, метод main.
б) Ball — шарик.
в) Brick — «кирпичи«, которые мы сбиваем шариком.
г) Stand — летающая подставка.

Создай их, и не забудь о методе public static void main (String[] args) в класе Arkanoid.

 

package com.javarush.task.task24.task2413;

import java.util.ArrayList;

/**
 * Created by promoscow on 26.01.17.
 */
public class Arcanoid {
    public static Arcanoid game;

    ArrayList<Brick> bricks;
    private int width;
    private int height;
    private Ball ball;
    private Stand stand;

    public Arcanoid(int width, int height) {
        this.width = width;
        this.height = height;
    }

    public static void main(String[] args) {

    }

    public Ball getBall() {

        return ball;
    }

    public void setBall(Ball ball) {
        this.ball = ball;
    }

    public Stand getStand() {
        return stand;
    }

    public void setStand(Stand stand) {
        this.stand = stand;
    }

    public ArrayList<Brick> getBricks() {
        return bricks;
    }

    public void setBricks(ArrayList<Brick> bricks) {
        this.bricks = bricks;
    }

    public int getWidth() {

        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public void run() {

    }

    public void move() {

    }
}

 

package com.javarush.task.task24.task2413;

/**
 * Created by promoscow on 26.01.17.
 */
public class Ball extends BaseObject {
    public Ball(double x, double y, double radius) {
        super(x, y, radius);
    }

    @Override
    public void draw(Canvas canvas) {

    }

    public void draw() {

    }

    @Override
    public void move() {

    }
}

 

package com.javarush.task.task24.task2413;

/**
 * Базовый класс для всех объектов игры.
 */
public abstract class BaseObject {
    //координаты
    protected double x;
    protected double y;
    //радиус объекта
    protected double radius;

    protected BaseObject(double x, double y, double radius) {
        this.x = x;
        this.y = y;
        this.radius = radius;
    }

    public double getX() {
        return x;
    }

    public void setX(double x) {
        this.x = x;
    }

    public double getY() {
        return y;
    }

    public void setY(double y) {
        this.y = y;
    }

    public double getRadius() {
        return radius;
    }

    public void setRadius(double radius) {
        this.radius = radius;
    }

    /**
     * Метод рисует свой объект на "канвасе".
     */
    public abstract void draw(Canvas canvas);

    /**
     * Двигаем себя на один ход.
     */
    public abstract void move();

    /**
     * Проверяем - не выходит ли (x,y) за границы.
     */
    public void checkBorders(double minx, double maxx, double miny, double maxy) {
        if (x < minx) x = minx;
        if (x > maxx) x = maxx;
        if (y < miny) y = miny;
        if (y > maxy) y = maxy;
    }

    /**
     * Проверяем - пересекаются ли переданный(o) и наш(this) объекты.
     */
    public boolean isIntersec(BaseObject o) {
        double dx = x - o.x;
        double dy = y - o.y;
        double destination = Math.sqrt(dx * dx + dy * dy);
        double destination2 = Math.max(radius, o.radius);
        return destination <= destination2;
    }
}

 

package com.javarush.task.task24.task2413;

/**
 * Created by promoscow on 26.01.17.
 */
public class Brick extends BaseObject {
    public Brick(double x, double y, double radius) {
        super(x, y, radius);
    }

    @Override
    public void draw(Canvas canvas) {

    }

    public void draw() {

    }

    @Override
    public void move() {

    }
}

 

package com.javarush.task.task24.task2413;

/**
 * Created by promoscow on 28.01.17.
 */
public class Canvas {
    private int width;
    private int height;

    private char[][] matrix;

    public Canvas(int width, int height) {

        this.width = width;
        this.height = height;
    }

    public int getWidth() {
        return width;
    }

    public int getHeight() {
        return height;
    }

    public char[][] getMatrix() {
        return matrix;
    }

    public void setPoint(double x, double y, char c) {
        if (x >= 0 && y >= 0 && y <= matrix.length && x <= matrix[0].length) {
            int a = (int) Math.round(x);
            int b = (int) Math.round(y);
            matrix[a][b] = c;
        }
    }

    public void drawMatrix(double x, double y, int[][] matrix, char c) {
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[i].length; j++) {
                if (matrix[i][j] != 0) setPoint(x + j, y + i, c);
            }
        }
    }
}

 

package com.javarush.task.task24.task2413;

/**
 * Created by promoscow on 26.01.17.
 */
public class Stand extends BaseObject {
    public Stand(double x, double y, double radius) {
        super(x, y, radius);
    }

    @Override
    public void draw(Canvas canvas) {

    }

    public void draw() {

    }

    @Override
    public void move() {

    }
}
Задание 10
Что мы будем делать с Canvas?
Мы будем рисовать на нем (в его матрице).
Поэтому нам понадобятся два метода
public void setPoint(double x, double y, char c)
public void drawMatrix(double x, double y, int[][] matrix, char c)

Первый метод - setPoint будет "ставить точку в координатах x,y цветом c".
В методе надо:
а) округлить x и y до целых чисел
б) занести в matrix[y][x] значение с
в) ничего не делать, если x<0 или y<0 или y>matrix.length или x>matrix[0].length

Второй метод - drawMatrix копирует переданную ему картинку (матрицу) в матрицу Canvas.
И не просто копирует, а начиная с координат x, y
В методе надо:
а) с помощью двух вложенных циклов пройтись по всем ячейкам переданной картинки
б) если значение ячейки matrix[i][j] не равно 0, то покрасить в матрице объекта Canvas точку (x+j, y+i) в цвет c:
 setPoint(x+j, y+i, c)

 

package com.javarush.test.level24.lesson14.big01;

/**
 * Created by promoscow on 28.01.17.
 */
public class Canvas {
    private int width;
    private int height;

    private char[][] matrix;

    public Canvas(int width, int height) {

        this.width = width;
        this.height = height;
        this.matrix = new char[height][width];
    }

    public int getWidth() {
        return width;
    }

    public int getHeight() {
        return height;
    }

    public char[][] getMatrix() {
        return matrix;
    }

    public void setPoint(double x, double y, char c) {
//        if ((x % (int) x) >= 0.5) x += 1;
//        if ((y % (int) y >= 0.5)) y += 1;
        if (x >= 0 && y >= 0 && y <= matrix.length && x <= matrix[0].length) matrix[(int) y][(int) x] = c;
    }

    public void drawMatrix(double x, double y, int[][] matrix, char c) {
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[i].length; j++) {
                if (matrix[i][j] != 0) setPoint(x + j, y + i, c);
            }
        }
    }
}
Задание 11
Еще Canvas понадобится два метода, напиши их.
а) метод clear()
Этот метод будет очищать матрицу, чтобы на ней снова можно было рисовать.
Например заменить все символы матрицы на пробелы.

б) метод print()
Этот метод отрисовывает матрицу на экран.
Тут уже ты должен сам разобраться: вывести набор символов не так уж и сложно.
Не забудь добавить пару пустых строк в конце, чтобы матрицы выведенные в разное время не слипались.

 

package com.javarush.test.level24.lesson14.big01;

/**
 * Created by promoscow on 28.01.17.
 */
public class Canvas {
    private int width;
    private int height;

    private char[][] matrix;

    public Canvas(int width, int height) {

        this.width = width;
        this.height = height;
        this.matrix = new char[height][width];
    }

    public int getWidth() {
        return width;
    }

    public int getHeight() {
        return height;
    }

    public char[][] getMatrix() {
        return matrix;
    }

    public void setPoint(double x, double y, char c) {
        if (x >= 0 && y >= 0 && y <= matrix.length && x <= matrix[0].length) matrix[(int) y][(int) x] = c;
    }

    public void drawMatrix(double x, double y, int[][] matrix, char c) {
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[i].length; j++) {
                if (matrix[i][j] != 0) setPoint(x + j, y + i, c);
            }
        }
    }

    public void clear() {
        for (int i = 0; i < getHeight(); i++) {
            for (int j = 0; j < getWidth(); j++) {
                this.matrix[i][j] = ' ';
            }
        }
    }

    public void print() {
        for (int i = 0; i < getHeight(); i++) {
            for (int j = 0; j < getWidth(); j++) {
                System.out.print(matrix[i][j]);
            }
            System.out.println();
        }
        System.out.println();
        System.out.println();
    }
}
Задание 12
Теперь напишем класс Brick
Во-первых займемся конструктором и в нем точно зададим радиус всех "кирпичей".
Путь он выглядит так:
public Brick(double x, double y)
{
        super(x,y,3);
}

Еще нам нужно переопределить два метода move() и draw(Canvas canvas)
Метод move() не делает ничего (не содержит кода), т.к. кирпич никуда не двигается.

Напиши еще метод draw(Canvas canvas).
Его кодом я займусь сам.

 

package com.javarush.test.level24.lesson14.big01;

/**
 * Created by promoscow on 26.01.17.
 */
public class Brick extends BaseObject {
    public Brick(double x, double y, double radius) {
        super(x, y, radius);
    }

    public Brick(double x, double y) {
        super(x, y, 3);
    }

    @Override
    public void draw(Canvas canvas) {

    }

    public void draw() {

    }

    @Override
    public void move() {

    }
}
Задание 13
Класс Ball уже посложнее - шарик же двигается.
Нам понадобятся переменные
а) speed (скорость шарика) типа double
б) direction (направление движения в градусах: от 0 до 360) типа double
в) dx (расстояние по x, которое проходит шарик за один шаг. вычисляется на основе speed и direction) типа double.
г) dy (расстояние по y, которое проходит шарик за один шаг. вычисляется на основе speed и direction) типа double.
д) isFrozen ("истина" если шарик "заморожен" - не двигается) типа boolean
е) добавь геттеры для всех переменных этого класса

А еще сделай-ка конструктор:
а) в конструктор передаются x,y, speed, direction
б) радиус (для родительского класса) всегда равен 1
в) не забудь установить isFrozen в true - в начале игры шарик никуда не летит.

 

package com.javarush.test.level24.lesson14.big01;

/**
 * Created by promoscow on 26.01.17.
 */
public class Ball extends BaseObject {
    private double speed;
    private double direction;
    private double dx;
    private double dy;
    boolean isFrozen;

    public Ball(double x, double y, double speed, double direction) {
        super(x, y, speed);
        this.dx = x;
        this.dy = y;
        this.speed = speed;
        this.direction = direction;
        radius = 1;
        isFrozen = true;
    }

    public Ball(double x, double y, double radius) {
        super(x, y, radius);
    }

    public double getSpeed() {
        return speed;
    }

    public double getDirection() {
        return direction;
    }

    public double getDx() {
        return dx;
    }

    public double getDy() {
        return dy;
    }

    public boolean isFrozen() {
        return isFrozen;
    }

    @Override
    public void draw(Canvas canvas) {

    }

    public void draw() {

    }

    @Override
    public void move() {

    }
}
Задание 14
Чего-то не хватает:

Во-первых надо переопределить метод move(), который наследуется от BaseObject
а) объявить такой же метод как и в BaseObject, только без ключевого слова abstract
б) написать его реализацию
x должен увеличиваться на dx каждый ход
y должен увеличиваться на dy каждый ход
если шарик "заморожен", то x и y меняться не должны

Во-вторых надо переопределить метод draw(Canvas canvas)
а) объявить такой же метод как и в BaseObject, только без ключевого слова abstract
б) написать его реализацию. Выглядеть она должна примерно так:
canvas.setPoint(x, y, 'O');

В третьих надо реализовать метод start()
Именно его вызов "размораживает" шарик.
Что для этого надо сделать - это ты уже сам реши.

 

package com.javarush.test.level24.lesson14.big01;

/**
 * Created by promoscow on 26.01.17.
 */
public class Ball extends BaseObject {
    private double speed;
    private double direction;
    private double dx;
    private double dy;
    boolean isFrozen;

    public Ball(double x, double y, double speed, double direction) {
        super(x, y, speed);
        this.dx = x;
        this.dy = y;
        this.speed = speed;
        this.direction = direction;
        radius = 1;
        isFrozen = true;
    }

    public Ball(double x, double y, double radius) {
        super(x, y, radius);
    }

    public double getSpeed() {
        return speed;
    }

    public double getDirection() {
        return direction;
    }

    public double getDx() {
        return dx;
    }

    public double getDy() {
        return dy;
    }

    public boolean isFrozen() {
        return isFrozen;
    }

    @Override
    public void draw(Canvas canvas) {
        canvas.setPoint(x, y, 'O');
    }

    @Override
    public void move() {
        if (!isFrozen) {
            x += dx;
            y += dy;
        }
    }

    public void start() {
        isFrozen = false;
    }
}
Задание 15
Не поверишь, но и это еще не все.

Во-первых нужен метод setDirection
Который не только устанавливает значение переменной direction,
но и вычисляет новые значения переменных x & y
Код должен выглядеть примерно так:
this.direction = direction;
double angel = Math.toRadians(direction);
dx = Math.cos(angel) * speed;
dy = -Math.sin(angel) * speed;

Во-вторых шарик может удариться о стенку.
При этом он должен от нее отскочить.
Для этого нам понадобится еще один метод:
public void checkRebound(int minx, int maxx, int miny, int maxy)
Создай его, кодом я займусь сам

 

package com.javarush.test.level24.lesson14.big01;

/**
 * Created by promoscow on 26.01.17.
 */
public class Ball extends BaseObject {
    private double speed;
    private double direction;
    private double dx;
    private double dy;
    boolean isFrozen;

    public Ball(double x, double y, double speed, double direction) {
        super(x, y, speed);
        this.dx = x;
        this.dy = y;
        this.speed = speed;
        this.direction = direction;
        radius = 1;
        isFrozen = true;
    }

    public Ball(double x, double y, double radius) {
        super(x, y, radius);
    }

    public double getSpeed() {
        return speed;
    }

    public double getDirection() {
        return direction;
    }

    public double getDx() {
        return dx;
    }

    public double getDy() {
        return dy;
    }

    public boolean isFrozen() {
        return isFrozen;
    }

    @Override
    public void draw(Canvas canvas) {
        canvas.setPoint(x, y, 'O');
    }

    @Override
    public void move() {
        if (!isFrozen) {
            x += dx;
            y += dy;
        }
    }

    public void start() {
        isFrozen = false;
    }

    public void setDirection(double direction) {
        this.direction = direction;
        double angel = Math.toRadians(direction);
        dx = Math.cos(angel) * speed;
        dy = -Math.sin(angel) * speed;
    }

    public void checkRebound(int minx, int maxx, int miny, int maxy) {

    }
}
Задание 16
И наконец "подставка"!
Ей понадобятся такие переменные
а) speed (скорость шарика) типа double
б) direction (направление движения по оси x: 1 - вправо, -1 - влево) типа double
в) создай для них геттеры


А еще с тебя конструктор, примерно вот такой:
public Stand(double x, double y)
{
    super(x,y,3);
    speed = 1;
    direction = 0;
}

 

package com.javarush.test.level24.lesson14.big01;

/**
 * Created by promoscow on 26.01.17.
 */
public class Stand extends BaseObject {
    private double speed;
    private double direction;

    public Stand(double x, double y) {
        super(x, y, 3);
        speed = 1;
        direction = 0;
    }

    public Stand(double x, double y, double radius) {
        super(x, y, radius);
    }

    public double getSpeed() {
        return speed;
    }

    public double getDirection() {
        return direction;
    }

    @Override
    public void draw(Canvas canvas) {

    }

    public void draw() {

    }

    @Override
    public void move() {

    }
}
Задание 17
Но и это еще не все
Еще нужны методы:
а) move  - см. move в BaseObject
Движение доски осуществляется горизонтально, поэтому мы меняем только координату х.
Подумай, как координата х зависит от направления (direction) и скорости (speed). Реализуй зависимость.
б) draw  - см. draw в BaseObject
Его кодом я займусь сам.
в) moveLeft() - задает постоянное движение "подставки" влево
Просто присвой правильное значение переменной direction и все.
г) moveRight() - задает постоянное движение "подставки" вправо
Просто присвой правильное значение переменной direction и все.

 

package com.javarush.test.level24.lesson14.big01;

/**
 * Created by promoscow on 26.01.17.
 */
public class Stand extends BaseObject {
    private double speed;
    private double direction;

    public Stand(double x, double y) {
        super(x, y, 3);
        speed = 1;
        direction = 0;
    }

    public Stand(double x, double y, double radius) {
        super(x, y, radius);
    }

    public double getSpeed() {
        return speed;
    }

    public double getDirection() {
        return direction;
    }

    @Override
    public void draw(Canvas canvas) {

    }

    public void draw() {

    }

    @Override
    public void move() {
        x += speed * direction;
    }

    public void moveLeft() {
        direction = -1;
    }

    public void moveRight() {
        direction = 1;
    }
}
Задание 18
Теперь вернемся к классу Arcanoid
Реализуй методы:
а) move()
В этом методе нужно двигать все движимые объекты (stand, ball)
б) draw(Canvas canvas)
В этом методе надо вызвать метод draw всех существующих объектов, которые его имеют.

 

package com.javarush.test.level24.lesson14.big01;

import java.awt.event.KeyEvent;
import java.util.ArrayList;

/**
 * Главный класс игры
 */
public class Arcanoid {
    public static Arcanoid game;
    //ширина и высота
    private int width;
    private int height;
    //список кирпичей
    private ArrayList<Brick> bricks = new ArrayList<Brick>();
    //шарик
    private Ball ball;
    //подставка
    private Stand stand;
    //игра закончена?
    private boolean isGameOver = false;

    public Arcanoid(int width, int height) {
        this.width = width;
        this.height = height;
    }

    public static void main(String[] args) throws Exception {
        game = new Arcanoid(20, 30);

        Ball ball = new Ball(10, 29, 2, 95);
        game.setBall(ball);

        Stand stand = new Stand(10, 30);
        game.setStand(stand);

        game.getBricks().add(new Brick(3, 3));
        game.getBricks().add(new Brick(7, 5));
        game.getBricks().add(new Brick(12, 5));
        game.getBricks().add(new Brick(16, 3));

        game.run();
    }

    public ArrayList<Brick> getBricks() {
        return bricks;
    }

    public Ball getBall() {
        return ball;
    }

    public void setBall(Ball ball) {
        this.ball = ball;
    }

    public Stand getStand() {
        return stand;
    }

    public void setStand(Stand stand) {
        this.stand = stand;
    }

    /**
     * Рисуем на холсте границы и все объекты.
     */
    public void draw(Canvas canvas) {
        //отрисуй границы
        //отрисуй кирпичи
        //отрисуй шарик
        //отрисуй подставку
        this.drawBoders(canvas);
        this.ball.draw(canvas);
        this.stand.draw(canvas);
        for (Brick brick : bricks) {
            brick.draw(canvas);
        }
    }

    /**
     * Рисуем на холсте границы
     */
    private void drawBoders(Canvas canvas) {
        //draw game
        for (int i = 0; i < width + 2; i++) {
            for (int j = 0; j < height + 2; j++) {
                canvas.setPoint(i, j, '.');
            }
        }

        for (int i = 0; i < width + 2; i++) {
            canvas.setPoint(i, 0, '-');
            canvas.setPoint(i, height + 1, '-');
        }

        for (int i = 0; i < height + 2; i++) {
            canvas.setPoint(0, i, '|');
            canvas.setPoint(width + 1, i, '|');
        }
    }

    /**
     * Основной цикл программы.
     * Тут происходят все важные действия
     */
    public void run() throws Exception {
        //Создаем холст для отрисовки.
        Canvas canvas = new Canvas(width, height);

        //Создаем объект "наблюдатель за клавиатурой" и стартуем его.
        KeyboardObserver keyboardObserver = new KeyboardObserver();
        keyboardObserver.start();

        //Исполняем цикл, пока игра не окончека
        while (!isGameOver) {
            //"наблюдатель" содержит события о нажатии клавиш?
            if (keyboardObserver.hasKeyEvents()) {
                KeyEvent event = keyboardObserver.getEventFromTop();

                //Если "стрелка влево" - сдвинуть фигурку влево
                if (event.getKeyCode() == KeyEvent.VK_LEFT)
                    stand.moveLeft();
                    //Если "стрелка вправо" - сдвинуть фигурку вправо
                else if (event.getKeyCode() == KeyEvent.VK_RIGHT)
                    stand.moveRight();
                    //Если "пробел" - запускаем шарик
                else if (event.getKeyCode() == KeyEvent.VK_SPACE)
                    ball.start();
            }

            //двигаем все объекты
            move();

            //проверяем столкновения
            checkBricksBump();
            checkStandBump();

            //проверяем, что шарик мог улететь через дно.
            checkEndGame();

            //отрисовываем все объекты
            canvas.clear();
            draw(canvas);
            canvas.print();

            //пауза
            Thread.sleep(300);
        }

        //Выводим сообщение "Game Over"
        System.out.println("Game Over!");
    }

    /**
     * Двигаем шарик и подставку.
     */
    public void move() {
        //двигай шарик
        //двигай подставку
        ball.move();
        stand.move();
    }

    /**
     * Проверяем столкновение с кирпичами.
     * Если столкновение было - шарик отлетает в случайном направлении 0..360 градусов
     */
    public void checkBricksBump() {
        //Тут проверь - столкнулся ли шарик с кирпичем.
        //Если да - кирпичь удалить, а шарик запустить в случайно направлении.
    }

    /**
     * Проверяем столкновение с подставкой.
     * Если столкновение было - шарик отлетает в случайном направлении  вверх 80..100 градусов.
     */
    public void checkStandBump() {
        //Тут проверь - столкнулся ли шарик с подставкой.
        //Если да - запустить шарик  вверх на 80..100 градусов.
    }

    /**
     * Проверяем - не улетел ли шарик через дно.
     * Если да - игра окончена (isGameOver = true)
     */
    public void checkEndGame() {
        //Если шарик улетел за нижнюю границы - игра окончена.
    }

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }
}
Задание 19
Осталось совсем чуть-чуть

Реализовать метод checkBricksBump
В этом методе надо проверить - не столкнулся ли шарик с каким-нибудь из "кирпичей"
Для проверки столкновения используй метод isIntersec
Если шарик все-таки попал в кирпич, то
а) шарик отлетает в случайном направлении (0..360 градусов)
double angel = Math.random() * 360;
ball.setDirection(angel);
б) кирпич умирает - надо удалить его из списка всех кирпичей

Реализовать метод checkStandBump
В этом методе надо проверить - не ударился ли шарик о подставку
Для проверки столкновения используй метод isIntersec
Если шарик все-таки ударился о подставку, то:
шарик отлетает в случайным направлении строго вверх (80..100 градусов)
double angel = 80 + Math.random()*20;
ball.setDirection(angel);

Реализовать метод checkEndGame
Если координата y шарика больше чем высота поля игры (height), значит шарик улетел вниз за границу экрана
В этом случае надо переменную isGameOver установить в true

 

package com.javarush.test.level24.lesson14.big01;

import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Iterator;

/**
 * Главный класс игры
 */
public class Arcanoid {
    public static Arcanoid game;
    //ширина и высота
    private int width;
    private int height;
    //список кирпичей
    private ArrayList<Brick> bricks = new ArrayList<Brick>();
    //шарик
    private Ball ball;
    //подставка
    private Stand stand;
    //игра закончена?
    private boolean isGameOver = false;

    public Arcanoid(int width, int height) {
        this.width = width;
        this.height = height;
    }

    public static void main(String[] args) throws Exception {
        game = new Arcanoid(20, 30);

        Ball ball = new Ball(10, 29, 2, 95);
        game.setBall(ball);

        Stand stand = new Stand(10, 30);
        game.setStand(stand);

        game.getBricks().add(new Brick(3, 3));
        game.getBricks().add(new Brick(7, 5));
        game.getBricks().add(new Brick(12, 5));
        game.getBricks().add(new Brick(16, 3));

        game.run();
    }

    public ArrayList<Brick> getBricks() {
        return bricks;
    }

    public Ball getBall() {
        return ball;
    }

    public void setBall(Ball ball) {
        this.ball = ball;
    }

    public Stand getStand() {
        return stand;
    }

    public void setStand(Stand stand) {
        this.stand = stand;
    }

    /**
     * Рисуем на холсте границы и все объекты.
     */
    public void draw(Canvas canvas) {
        //отрисуй границы
        //отрисуй кирпичи
        //отрисуй шарик
        //отрисуй подставку
        this.drawBoders(canvas);
        this.ball.draw(canvas);
        this.stand.draw(canvas);
        for (Brick brick : bricks) {
            brick.draw(canvas);
        }
    }

    /**
     * Рисуем на холсте границы
     */
    private void drawBoders(Canvas canvas) {
        //draw game
        for (int i = 0; i < width + 2; i++) {
            for (int j = 0; j < height + 2; j++) {
                canvas.setPoint(i, j, '.');
            }
        }

        for (int i = 0; i < width + 2; i++) {
            canvas.setPoint(i, 0, '-');
            canvas.setPoint(i, height + 1, '-');
        }

        for (int i = 0; i < height + 2; i++) {
            canvas.setPoint(0, i, '|');
            canvas.setPoint(width + 1, i, '|');
        }
    }

    /**
     * Основной цикл программы.
     * Тут происходят все важные действия
     */
    public void run() throws Exception {
        //Создаем холст для отрисовки.
        Canvas canvas = new Canvas(width, height);

        //Создаем объект "наблюдатель за клавиатурой" и стартуем его.
        KeyboardObserver keyboardObserver = new KeyboardObserver();
        keyboardObserver.start();

        //Исполняем цикл, пока игра не окончека
        while (!isGameOver) {
            //"наблюдатель" содержит события о нажатии клавиш?
            if (keyboardObserver.hasKeyEvents()) {
                KeyEvent event = keyboardObserver.getEventFromTop();

                //Если "стрелка влево" - сдвинуть фигурку влево
                if (event.getKeyCode() == KeyEvent.VK_LEFT)
                    stand.moveLeft();
                    //Если "стрелка вправо" - сдвинуть фигурку вправо
                else if (event.getKeyCode() == KeyEvent.VK_RIGHT)
                    stand.moveRight();
                    //Если "пробел" - запускаем шарик
                else if (event.getKeyCode() == KeyEvent.VK_SPACE)
                    ball.start();
            }

            //двигаем все объекты
            move();

            //проверяем столкновения
            checkBricksBump();
            checkStandBump();

            //проверяем, что шарик мог улететь через дно.
            checkEndGame();

            //отрисовываем все объекты
            canvas.clear();
            draw(canvas);
            canvas.print();

            //пауза
            Thread.sleep(300);
        }

        //Выводим сообщение "Game Over"
        System.out.println("Game Over!");
    }

    /**
     * Двигаем шарик и подставку.
     */
    public void move() {
        //двигай шарик
        //двигай подставку
        ball.move();
        stand.move();
    }

    /**
     * Проверяем столкновение с кирпичами.
     * Если столкновение было - шарик отлетает в случайном направлении 0..360 градусов
     */
    public void checkBricksBump() {
        //Тут проверь - столкнулся ли шарик с кирпичом.
        //Если да - кирпичь удалить, а шарик запустить в случайно направлении.
        Iterator<Brick> iterator = bricks.iterator();
        while (iterator.hasNext()) {
            if (iterator.next().isIntersec(ball)) {
                iterator.remove();
                double angel = Math.random() * 360;
                ball.setDirection(angel);
            }
        }
    }

    /**
     * Проверяем столкновение с подставкой.
     * Если столкновение было - шарик отлетает в случайном направлении  вверх 80..100 градусов.
     */
    public void checkStandBump() {
        //Тут проверь - столкнулся ли шарик с подставкой.
        //Если да - запустить шарик  вверх на 80..100 градусов.
        if (ball.isIntersec(stand)) {
            double angel = 80 + Math.random()*20;
            ball.setDirection(angel);
        }
    }

    /**
     * Проверяем - не улетел ли шарик через дно.
     * Если да - игра окончена (isGameOver = true)
     */
    public void checkEndGame() {
        //Если шарик улетел за нижнюю границы - игра окончена.
        if (ball.y > height) isGameOver = true;
    }

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }
}