@startuml
'https://plantuml.com/class-diagram

abstract class AbstractFlyingObject
{
    # locationX:int
    # locationY:int
    # speedX:int
    # speedY:int
    # image:BufferedImage
    # width:int
    # height:int
    # isValid:boolean

    + AbstractFlyingObject(int locationX, int locationY, int speedX, int speedY)
    + forward():void
    + crash(AbstractFlyingObject flyingObject):boolean
    + setLocation(double locationX, double locationY):void
    + getLocationX():int
    + getLocationY():int
    + getSpeedX():int
    + getSpeedY():int
    + getImage():BufferedImage
    + getWidth():int
    + getHeight():int
    + notValid():boolean
    + vanish():void
}
abstract class AbstractAircraft
{
    # hp:int
    + AbstractAircraft(int locationX, int locationY, int speedX, int speedY, int hp)
    + decreaseHp(int decrease):void
    + getHp():int
    + {abstract} shoot():List<BaseBullet>
 }

abstract class BaseBullet
{
    - power:int
    + BaseBullet(int locationX, int locationY, int speedX, int speedY, int power)
    + forward():void
	+ getPower():int
}

abstract class AbstractProp{
    + AbstractProp(int locationX, int locationY, int speedX, int speedY)
    + forward():void
    + {abstract} effect(HeroAircraft hero):void
    + {abstract} effect(List<AbstractAircraft> enemy):void
}

AbstractFlyingObject <|-- AbstractAircraft
AbstractFlyingObject <|-- BaseBullet
AbstractFlyingObject <|-- AbstractProp

AbstractAircraft <|-- HeroAircraft
AbstractAircraft <|-- MobEnemy
AbstractAircraft <|-- EliteEnemy
AbstractAircraft <|-- BossEnemy

BaseBullet <|-- HeroBullet
BaseBullet <|-- EnemyBullet

AbstractProp <|-- PropBomb
AbstractProp <|-- PropFire
AbstractProp <|-- PropHP

PropBomb <.. SimplePropFactory
PropFire <.. SimplePropFactory
PropHP   <.. SimplePropFactory

MobEnemy <.. SimpleEnemyFactory
EliteEnemy <.. SimpleEnemyFactory
BossEnemy <.. SimpleEnemyFactory

BossEnemy o-- EnemyBullet
EliteEnemy o-- EnemyBullet
HeroAircraft o-- HeroBullet

class HeroAircraft {
    - shootNum:int
    - power:int
    - direction:int
    + maxHp:final int
    + maxBullets:final int
    - HeroAircraft(int locationX, int locationY, int speedX, int speedY, int hp)
    + {static} getInstance():HeroAircraft
    + forward():void
    + shoot():List<BaseBullet>
}

class MobEnemy {
    + MobEnemy(int locationX, int locationY, int speedX, int speedY, int hp)
    + forward():void
    + shoot():List<BaseBullet>
}

class EliteEnemy {
    - shootNum:int
    - power:int
    - direction:int
    + EliteEnemy(int locationX, int locationY, int speedX, int speedY, int hp)
    + forward():void
    + shoot():List<BaseBullet>
}

class BossEnemy {
    - shootNum:int
    - power:int
    - direction:int
    + BossEnemy(int locationX, int locationY, int speedX, int speedY, int hp)
    + forward():void
    + shoot():List<BaseBullet>
}

class SimpleEnemyFactory {
    + {static} createEnemy(int num):AbstractAircraft
}

class HeroBullet {
    + HeroBullet(int locationX, int locationY,
     int speedX, int speedY, int power)
}

class EnemyBullet {
    + EnemyBullet(int locationX, int locationY,
     int speedX, int speedY, int power)
}

class PropBomb {
    + PropBomb(int locationX, int locationY, int speedX, int speedY)
    + effect(HeroAircraft hero):void
    + effect(List<AbstractAircraft> enemy):void
}
class PropFire {
    + PropFire(int locationX, int locationY, int speedX, int speedY)
    + effect(HeroAircraft hero):void
    + effect(List<AbstractAircraft> enemy):void
}
class PropHP {
    + PropHP(int locationX, int locationY, int speedX, int speedY)
    + effect(HeroAircraft hero):void
    + effect(List<AbstractAircraft> enemy):void
}

class SimplePropFactory {
    + {static} createProp(int num):AbstractProp
}

@enduml