SHAPEMATRIX
package com.codegym.games.spaceinvaders;

public class ShapeMatrix {
    public static final int[][] ENEMY = new int[][]{
            {7, 0, 7},
            {7, 7, 7},
            {0, 7, 0}
    };

    public static final int[][] PLAYER = new int[][]{
            {0, 0, 6, 0, 0},
            {0, 6, 6, 6, 0},
            {6, 6, 6, 6, 6}
    };

    public static final int[][] DEAD_PLAYER = new int[][]{
            {0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0}
    };

    public static final int[][] WIN_PLAYER = new int[][]{
            {0, 0, 5, 0, 0},
            {0, 5, 5, 5, 0},
            {5, 5, 5, 5, 5}
    };

    public static final int[][] BULLET = new int[][]{
            {2},
            {2}
    };

    public static final int[][] KILL_ENEMY_ANIMATION_FIRST = new int[][]{
            {4, 4, 4},
            {4, 4, 4},
            {4, 4, 4}
    };

    public static final int[][] KILL_ENEMY_ANIMATION_SECOND = new int[][]{
            {4, 0, 4},
            {0, 4, 0},
            {4, 0, 4}
    };

    public static final int[][] KILL_ENEMY_ANIMATION_THIRD = new int[][]{
            {0, 0, 0},
            {0, 4, 0},
            {0, 0, 0}
    };

    public static final int[][] KILL_PLAYER_ANIMATION_FIRST = new int[][]{
            {4, 4, 4, 4, 4},
            {4, 4, 4, 4, 4},
            {4, 4, 4, 4, 4}
    };

    public static final int[][] KILL_PLAYER_ANIMATION_SECOND = new int[][]{
            {4, 0, 4, 0, 4},
            {0, 4, 0, 4, 0},
            {4, 0, 4, 0, 4}
    };

    public static final int[][] KILL_PLAYER_ANIMATION_THIRD = new int[][]{
            {0, 4, 0, 4, 0},
            {4, 0, 4, 0, 4},
            {0, 4, 0, 4, 0}
    };

    public static final int[][] KILL_BOSS_ANIMATION_FIRST = new int[][]{
            {4, 4, 4, 4, 4, 4, 4},
            {4, 4, 4, 4, 4, 4, 4},
            {4, 4, 4, 4, 4, 4, 4},
            {4, 4, 4, 4, 4, 4, 4},
            {4, 4, 4, 4, 4, 4, 4},
            {4, 4, 4, 4, 4, 4, 4}
    };

    public static final int[][] KILL_BOSS_ANIMATION_SECOND = new int[][]{
            {4, 0, 0, 4, 0, 0, 4},
            {0, 4, 0, 4, 0, 4, 0},
            {0, 0, 4, 4, 4, 0, 0},
            {0, 0, 4, 4, 4, 0, 0},
            {0, 4, 0, 4, 0, 4, 0},
            {4, 0, 0, 4, 0, 0, 4}
    };

    public static final int[][] KILL_BOSS_ANIMATION_THIRD = new int[][]{
            {0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0},
            {0, 0, 4, 4, 4, 0, 0},
            {0, 0, 4, 4, 4, 0, 0},
            {0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0}
    };

    public static final int[][] BOSS_ANIMATION_FIRST = new int[][]{
            {0, 0, 4, 0, 4, 0, 0},
            {0, 2, 2, 2, 2, 2, 0},
            {4, 2, 0, 2, 0, 2, 0},
            {4, 2, 2, 2, 2, 2, 4},
            {0, 0, 4, 4, 4, 0, 4},
            {0, 0, 4, 0, 4, 0, 0}
    };

    public static final int[][] BOSS_ANIMATION_SECOND = new int[][]{
            {0, 0, 4, 0, 4, 0, 0},
            {0, 2, 2, 2, 2, 2, 0},
            {0, 2, 0, 2, 0, 2, 4},
            {4, 2, 2, 2, 2, 2, 4},
            {4, 0, 4, 4, 4, 0, 0},
            {0, 0, 4, 0, 4, 0, 0}
    };
}
SpaceInvaders Game
package com.codegym.games.spaceinvaders;

import java.util.*;
import com.codegym.engine.cell.*;
import com.codegym.games.spaceinvaders.gameobjects.Star;
import com.codegym.games.spaceinvaders.gameobjects.EnemyFleet;
import com.codegym.games.spaceinvaders.gameobjects.Bullet;
import com.codegym.games.spaceinvaders.gameobjects.PlayerShip;



public class SpaceInvadersGame extends Game{

    public static final int WIDTH = 64;
    public static final int HEIGHT = 64;

    private List<Star> stars;

    // final Random random = new Random();

    private EnemyFleet enemyFleet;

    public static final int DIFFICULTY = 5;

    private List<Bullet> enemyBullets;

    private PlayerShip playerShip;

    private boolean isGameStopped;

    private int animationsCount;

    private List<Bullet> playerBullets;

    private static final int PLAYER_BULLETS_MAX = 1;

    private int score;

    @Override
    public void setCellValueEx(int x, int y, Color cellcolor, String value) {

        if(x > WIDTH - 1 || x < 0 || y > HEIGHT - 1 || y < 0) {
            return;
        }

        super.setCellValueEx(x, y, cellcolor, value);
    }

    public void onKeyReleased(Key a) {
        if(a == Key.LEFT && playerShip.getDirection() == Direction.LEFT ) {
            playerShip.setDirection(Direction.UP);
        }

        if(a == Key.RIGHT && playerShip.getDirection() == Direction.RIGHT) {
            playerShip.setDirection(Direction.UP);
        }
    }

    public void onKeyPress(Key a) {
        Bullet pb;

        if(a == Key.SPACE) {
           pb = playerShip.fire();
           if(pb != null && playerBullets.size() < PLAYER_BULLETS_MAX) {
              playerBullets.add(pb);
           }
        }


        if (a == Key.SPACE && isGameStopped == true ) {
            createGame();
            return;
        }
       else if(a == Key.LEFT) {
            playerShip.setDirection(Direction.LEFT);
        }
       else if(a == Key.RIGHT) {
           playerShip.setDirection(Direction.RIGHT);
       }

    }

    private void stopGameWithDelay() {
        animationsCount++;
        if(animationsCount >= 10) {
        stopGame(playerShip.isAlive);
        }
    }

    private void stopGame(boolean isWin) {
        isGameStopped = true;
        stopTurnTimer();
        if(isWin == true) {
            showMessageDialog(Color.NONE, "YOU WIN", Color.GREEN, 50);
        }
        else {
            showMessageDialog(Color.NONE, "YOU LOSE", Color.RED, 50);
        }
    }

    private void check() {

        score += enemyFleet.checkHit(playerBullets);

        if(enemyFleet.getBottomBorder() >= playerShip.y) {
            playerShip.kill();
        }

        if(enemyFleet.getShipCount() == 0) {
          playerShip.win();
          stopGameWithDelay();
        }


        playerShip.checkHit(enemyBullets);

        enemyFleet.checkHit(playerBullets);
        enemyFleet.deleteHiddenShips();

        removeDeadBullets();

        if(playerShip.isAlive == false) {
            stopGameWithDelay();
        }
    }

    private void removeDeadBullets() {
        for(int i = 0; i<enemyBullets.size(); i++) {
            if(enemyBullets.get(i).isAlive == false || enemyBullets.get(i).y >= HEIGHT - 1) {
                enemyBullets.remove(i);
            }
        }

        //for(int pb = 0; pb < playerBullets.size(); pb++) {
        //    if(playerBullets.get(pb).isAlive == false || playerBullets.get(pb).y + playerBullets.get(pb).height < 0) {
        //        playerBullets.remove(pb);
        //    }
        //}




        Iterator itr = playerBullets.iterator();

        while (itr.hasNext())

        {
            Bullet h = (Bullet)itr.next();
            if (!h.isAlive || h.y + h.height < 0)
                itr.remove();
        }
    }

    private void moveSpaceObjects() {

        for(Bullet a : playerBullets) {
            a.move();
        }

        for(Bullet a : enemyBullets) {
            a.move();
        }
        enemyFleet.move();
        playerShip.move();
    }

    public void onTurn(int a) {
        moveSpaceObjects();
        check();

        Bullet abc = enemyFleet.fire(this);
        if(abc != null) {
            enemyBullets.add(abc);
        }
        setScore(score);
        drawScene();
    }

    private void createStars() {
        stars = new ArrayList<Star>();

        int x = 0;
        int y = 0;

        int xd = 0;
        int yd = 0;

        int xa = 1;
        int xb = 15;
        int ya = 1;
        int yb = 15;

        for(int z = 0; z < 16; z++) {

            x  =  xd + xa + getRandomNumber( xb - xa + 1);  //random.nextInt(xb - xa + 1);
            y  =  ya +  getRandomNumber( yb - ya + 1);   //random.nextInt(yb - ya + 1);

            stars.add(z, new Star(x, y));

            xd += 16;

            if (z == 3) {
                    xd = 0;
                }
            else if (z == 7) {
                xd = 0;
            }
            else if (z == 11) {
                xd = 0;
            }

            if (z == 3) {
                    ya += 15;
                    yb += 15;
                }
            else if (z == 7) {
                ya += 15;
                yb += 15;
            }
            else if (z == 11) {
                ya += 15;
                yb += 15;
            }
        }
    }

    public void initialize() {
        setScreenSize(WIDTH, HEIGHT);
        createGame();
    }

    private void createGame() {

        playerShip = new PlayerShip();
        enemyBullets = new ArrayList<Bullet>();
        setTurnTimer(40);
        createStars();
        enemyFleet = new EnemyFleet();
        isGameStopped = false;
        animationsCount = 0;
        playerBullets = new ArrayList<Bullet>();
        this.score = 0;
        drawScene();
    }

    private void drawScene() {
        drawField();

        for(Bullet a : playerBullets) {
            a.draw(this);
        }

        playerShip.draw(this);

        for(Bullet a : enemyBullets) {
            a.draw(this);
        }
        enemyFleet.draw(this);
    }

    private void drawField() {
            for (int y = 0; y < HEIGHT; y++) {
            for (int x = 0; x < WIDTH; x++) {
        setCellValueEx(x, y, Color.BLACK, "");
            }
        }

        for(Star a : stars) {
            a.draw(this);
        }
    }

}
GAMEOBJECT
package com.codegym.games.spaceinvaders.gameobjects;

import com.codegym.engine.cell.*;

public class GameObject {

    public double x;
    public double y;

    public int[][] matrix;

    public int width;
    public int height;

    public GameObject(double a, double b) {
        x = a;
        y = b;
    }

    public boolean isCollision(GameObject gameObject) {
    for (int gameObjectX = 0; gameObjectX < gameObject.width; gameObjectX++)
      for (int gameObjectY = 0; gameObjectY < gameObject.height; gameObjectY++)
         if (gameObject.matrix[gameObjectY][gameObjectX] > 0)
            if (isCollision(gameObjectX + gameObject.x, gameObjectY + gameObject.y)) {
               return true;
            }
    return false;
    }

    private boolean isCollision(double x, double y) {
    for (int matrixX = 0; matrixX < width; matrixX++)
      for (int matrixY = 0; matrixY < height; matrixY++)
         if (matrix[matrixY][matrixX] > 0
            && matrixX + (int) this.x == (int) x
            && matrixY + (int) this.y == (int) y) {
            return true;
         }
    return false;
    }

    public void setMatrix(int[][] a) {
        matrix = a;
        width = matrix[0].length;
        height = matrix.length;
    }

    public void draw(Game a) {

        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
            a.setCellValueEx( (int)(this.x + x), (int)(this.y + y), Color.values()[matrix[y][x]], "");
            }
        }
    }

}
STAR
package com.codegym.games.spaceinvaders.gameobjects;

import com.codegym.engine.cell.*;

public class Star extends GameObject {

    private static final String STAR_SIGN = "\u2605";

    public Star(double a, double b) {
        super(a, b);
    }

    public void draw(Game a) {
        a.setCellValueEx( (int)x, (int)y, Color.NONE, STAR_SIGN, Color.WHITE, 100);
    }
}
SHIP
package com.codegym.games.spaceinvaders.gameobjects;

import java.util.*;
import com.codegym.engine.cell.Game;

public class Ship extends GameObject {

    public boolean isAlive = true;

    private List<int[][]> frames;

    private int frameIndex;

    private boolean loopAnimation = false;

    public Ship (double a , double b) {
        super(a, b);
    }

    public void setAnimatedView(boolean isLoopAnimation, int[][]... viewFrames) {
        loopAnimation = isLoopAnimation;
    }

    public boolean isVisible() {
        if(! isAlive && frameIndex >= frames.size() ) {
        return false;
        }
        else {
            return true;
        }

    }

    public void draw(Game a) {
        super.draw(a);
        nextFrame();
    }

    public void nextFrame() {
        frameIndex++;

        if(frameIndex >= frames.size() && loopAnimation == false) {
            return;
        }
        else if(frameIndex >= frames.size() && loopAnimation == true) {
            frameIndex = 0;
        }

        matrix = frames.get(frameIndex);
    }

    /*public void setAnimatedView(int[][]... viewFrames) {
        setMatrix(viewFrames[0]);
        frames = Arrays.asList(viewFrames);
        frameIndex = 0;

    }*/

    public void kill(){
        isAlive = false;
    }

    public Bullet fire() {
        return null;
    }

    public void setStaticView(int[][] viewFrame) {
        frames = new ArrayList<int[][]>();
        frames.add(viewFrame);
        frameIndex = 0;
        setMatrix(viewFrame);
    }
}
ENEMYSHIP
package com.codegym.games.spaceinvaders.gameobjects;

import com.codegym.games.spaceinvaders.ShapeMatrix;
import com.codegym.games.spaceinvaders.Direction;

public class EnemyShip extends Ship{

    public int score = 15;

    public EnemyShip (double a, double b) {
        super(a , b);
        setStaticView(ShapeMatrix.ENEMY);
    }

    public void kill() {
        if(isAlive == false) {
            return;
        }

        isAlive = false;

        setAnimatedView(false, ShapeMatrix.KILL_ENEMY_ANIMATION_FIRST, ShapeMatrix.KILL_ENEMY_ANIMATION_SECOND, ShapeMatrix.KILL_ENEMY_ANIMATION_THIRD);

    }

    public Bullet fire() {
        return new Bullet(x + 1, y + height, Direction.DOWN);
    }

    public void move(Direction direction, double speed) {

        switch(direction) {
            case RIGHT : x = x + speed; break;
            case LEFT : x = x - speed; break;
            case DOWN : y = y + 2; break;
        }
    }
}
ENEMYFLEET
package com.codegym.games.spaceinvaders.gameobjects;

import java.util.*;
import com.codegym.games.spaceinvaders.ShapeMatrix;
import com.codegym.engine.cell.Game;
import com.codegym.games.spaceinvaders.gameobjects.GameObject;
import com.codegym.games.spaceinvaders.Direction;
import com.codegym.games.spaceinvaders.SpaceInvadersGame;
import com.codegym.games.spaceinvaders.gameobjects.EnemyShip;
import com.codegym.games.spaceinvaders.gameobjects.Boss;


public class EnemyFleet {

    private static final int ROWS_COUNT = 3;
    private static final int COLUMNS_COUNT = 10;
    private static final int STEP = ShapeMatrix.ENEMY.length + 1;

    GameObject gameobject;
    SpaceInvadersGame b;

    private List<EnemyShip> ships;

    private Direction direction = Direction.RIGHT;

    public EnemyFleet () {
        createShips();
    }

    public int checkHit(List<Bullet> bullets) {

        int score = 0;

        if(bullets.isEmpty()) {
                return 0;
        }

        for(EnemyShip a : ships) {
            for (Bullet b : bullets) {
                if(a.isAlive == true) {
                if(b.isAlive == true) {
                boolean collision = a.isCollision(b);
                if(collision == true) {
                b.kill();
                a.kill();
                score += a.score;
            }
            }
            }
        }
        }

        return score;
    }

    public double getBottomBorder() {
        double largest = 0;

        if(!ships.isEmpty()) {
            largest = ships.get(0).y + ships.get(0).height;
            for(int i = 1; i < ships.size(); i++) {
                if(ships.get(i).y + ships.get(i).height > largest) {
                    largest = ships.get(i).y + ships.get(i).height;
                }
            }
        }
        return largest;
    }

    public int getShipCount() {
        return ships.size();
    }

    public void deleteHiddenShips() {
        for(int i = 0; i < ships.size(); i++) {
            if(ships.get(i).isVisible() == false) {
                ships.remove(i);
            }
        }
    }

    public Bullet fire(Game a) {
        if(ships.isEmpty()) {
        return null;
        }
        else if(a.getRandomNumber(100 / b.DIFFICULTY) > 0) {
            return null;
        }

        return ships.get(a.getRandomNumber(ships.size())).fire();
    }

    public void move() {
        if(ships.isEmpty()) {
            return;
        }
        else if(direction == direction.LEFT && getLeftBorder() < 0.0) {
            direction = Direction.RIGHT;
            for(EnemyShip a : ships) {
            a.move(Direction.DOWN, getSpeed());
            }
        }
        else if(direction == direction.RIGHT && getRightBorder() > b.WIDTH) {
            direction = Direction.LEFT;
            for(EnemyShip a : ships) {
            a.move(Direction.DOWN, getSpeed());
            }
        }
        else {
          for(EnemyShip a : ships) {
            a.move(direction, getSpeed());
            }
        }

        getSpeed();
    }

    private double getSpeed() {
        double a = 2.0;
        double b = 3.0 / ships.size();
        if(a > b) {
            return b;
        }
        else {
            return a;
        }
    }

    private double getRightBorder() {
        double o = ships.get(0).x + ships.get(0).width;
        for (int i = 1;i < ships.size();i++){
            if (o < ships.get(i).x + ships.get(i).width){
                o = ships.get(i).x + ships.get(i).width;
            }
        }
        return o;
    }

    private double getLeftBorder() {
        double o = ships.get(0).x;
        for (int i = 1;i < ships.size();i++){
            if (o > ships.get(i).x){
                o = ships.get(i).x;
            }
        }
        return o;
    }

    public void draw(Game game) {
        for(EnemyShip a : ships) {
        a.draw(game);
        }
    }

    private void createShips() {

       ships = new ArrayList<EnemyShip>();
       Boss boss = new Boss(STEP * COLUMNS_COUNT / 2 - ShapeMatrix.BOSS_ANIMATION_FIRST.length / 2 - 1 , 5);
       ships.add(boss);

        for(double y = 0; y < ROWS_COUNT; y++) {
            for(double x = 0; x < COLUMNS_COUNT; x++) {
                ships.add(new EnemyShip(x * STEP, y * STEP + 12));
                }
            }
    }
}
DIRECTION
package com.codegym.games.spaceinvaders;


public enum Direction {
    RIGHT, LEFT, UP, DOWN;
}
BULLET
package com.codegym.games.spaceinvaders.gameobjects;

import com.codegym.games.spaceinvaders.Direction;
import com.codegym.games.spaceinvaders.ShapeMatrix;

public class Bullet extends GameObject {

    private int dy;

    public boolean isAlive = true;

    public Bullet(double x, double y, Direction direction) {
        super(x, y);
        setMatrix(ShapeMatrix.BULLET);
        if(direction == Direction.UP) {
        dy = -1;
        }
        else if(direction != Direction.UP) {
            dy = 1;
        }
    }

    public void kill(){
        isAlive = false;
    }

    public void move() {
        y = y + dy;
    }
}
PLAYERSHIP
package com.codegym.games.spaceinvaders.gameobjects;

import com.codegym.games.spaceinvaders.SpaceInvadersGame;
import com.codegym.games.spaceinvaders.ShapeMatrix;
import com.codegym.games.spaceinvaders.Direction;
import java.util.*;

public class PlayerShip extends Ship {

    PlayerShip ship;

    private Direction direction = Direction.UP;

    public PlayerShip() {
     super(SpaceInvadersGame.WIDTH / 2.0, SpaceInvadersGame.HEIGHT - ShapeMatrix.PLAYER.length - 1);
     setStaticView(ShapeMatrix.PLAYER);
    }

    public void win() {
        setStaticView(ShapeMatrix.WIN_PLAYER);
    }

    public Bullet fire() {
        if(isAlive == false) {
        return null;
        }
        return new Bullet( x + 2, y - ShapeMatrix.BULLET.length, Direction.UP);
    }

    public Direction getDirection() {
        return direction;
    }

    public void move() {
        if(isAlive == false) {
            return;
        }
        else if(direction == Direction.LEFT) {
            x--;
        }
        else if(direction == Direction.RIGHT) {
            x++;
        }

        if(x < 0) {
            x = 0;
        }

        if(x + width > SpaceInvadersGame.WIDTH) {
            x = SpaceInvadersGame.WIDTH - width;
        }
    }

    public void setDirection(Direction a) {
        if(a != Direction.DOWN) {
        direction = a;
        }
    }

    public void kill() {
        if(isAlive == false) {
            return;
        }
        isAlive = false;
        setAnimatedView(false, ShapeMatrix.KILL_PLAYER_ANIMATION_FIRST,ShapeMatrix.KILL_PLAYER_ANIMATION_SECOND, ShapeMatrix.KILL_PLAYER_ANIMATION_THIRD, ShapeMatrix.DEAD_PLAYER);
    }

    public void checkHit(List<Bullet> bullets){
        if(bullets.isEmpty()) {
            return;
        }
        else if(isAlive == true) {
        for(Bullet a : bullets) {
            if(a.isAlive == true) {
            boolean collision = isCollision(a);
            if(collision == true) {
                kill();
                a.kill();
            }
            }
        }
        }
    }
}
BOSS
package com.codegym.games.spaceinvaders.gameobjects;

import com.codegym.games.spaceinvaders.ShapeMatrix;
import com.codegym.games.spaceinvaders.gameobjects.Bullet;
import com.codegym.games.spaceinvaders.Direction;


public class Boss extends EnemyShip {

    private int frameCount = 0;

    public Boss(double a, double b) {
        super(a, b);
        score = 100;
        setAnimatedView(true, ShapeMatrix.BOSS_ANIMATION_FIRST, ShapeMatrix.BOSS_ANIMATION_SECOND);
    }

    @Override
    public void kill() {

        if( !isAlive ) {
            return;
        }
        isAlive = false;
        setAnimatedView(false, ShapeMatrix.KILL_BOSS_ANIMATION_FIRST, ShapeMatrix.KILL_BOSS_ANIMATION_SECOND, ShapeMatrix.KILL_BOSS_ANIMATION_THIRD);

    }

    @Override
    public Bullet fire() {

       Bullet bullet;

       if( !isAlive ) {
           return null;
       }
       if(matrix == ShapeMatrix.BOSS_ANIMATION_FIRST) {
         bullet = new Bullet( x + 6, y + height, Direction.DOWN);
         return bullet;
       }
       else if( matrix != ShapeMatrix.BOSS_ANIMATION_FIRST) {
         bullet = new Bullet( x, y + height, Direction.DOWN);
         return bullet;
       }

       return null;
    }

    @Override
    public void nextFrame() {
        frameCount++;
        if(frameCount%10 == 0 || isAlive == false) {
            super.nextFrame();
        }
    }
}