@startuml skinparam linetype ortho package utils { class PathFinder { static List findPath(Board, TileVec2, TileVec2) } class Matrix { static int getWidth(...) static int getHeight(...) static boolean isShapeValid(...) } } package viewer { class Viewer { Game Stage void main(String[]) void eventLoop(ApplicationContext) void renderFrame(Graphics2D,ApplicationContext) } } package context { class Context { Context(Stage,List,GraphicsContext) final Stage final List final GraphicsContext } class GraphicsContext { final Graphics2D final ScreenInfo paintCircle(Color, Vec2, float) paintSquare(Color, Vec2, float, float) } class InputHandler { private final ApplicationContext InputHandler(ApplicationContext) List getEvents() } class ScreenManager { private final ApplicationContext private final Graphics2D ScreenManager(ApplicationContext,Graphics2D) GraphicsContext clearScreen() } class Game { final GameController int index final List Game(GameController,List) } } package event { interface Event interface InputEvent implements Event interface GameEvent implements Event class DropBombEvent implements InputEvent class AddBombEvent implements InputEvent { final TileVec2 AddBombEvent(TileVec2) TileVec2 getTile() } class MoveRobotEvent implements InputEvent { final TileVec2 MoveRobotEvent(TileVec2) TileVec2 getTile() } class ConfirmEvent implements InputEvent class ExplosionEvent implements GameEvent { Block source Body source } } package board { class Board { Board(width, height) BlockType getBlockTypeAt(TileVec2) BlockType setBlockTypeAt(TileVec2, BlockType) } class BoardParser { static Board parse(File) } class BoardValidator { static bool validate(Board) } class BoardConverter { static Board worldToBoard(List) static List boardToWorld(Board) } class TileVec2 { static final int TILE_DIM static TileVec2 fromVec2(Vec2) Vec2 TileVec2(col, row) Vec2 toPixelPos() } } package model { enum BlockType { FREE WALL TRASH GARBAGE ROBOT BOMB boolean isBounding() boolean mustBeReachable() boolean isTraversable() boolean isMovableByExplosion() } class BlockFactory { Block build(BlockType, TileVec2) } abstract class Block { BlockType List Vec2 Block(BlockType, List, Vec2) void setPos(Vec2) BlockType getBlockType() Vec2 getPos() TileVec2 getTile() List update(Context) } class WallBlock extends Block class TrashBlock extends Block class BombBlock extends Block class GarbageBlock extends Block class RobotBlock extends Block class Stage { StageController List Stage(Board) List getBlocks() List update(Context) bool isCleared() } } package controller { interface Controller { List update(Context) } abstract class BlockController implements Controller { Block Controller(Block) } class BlockControllerFactory { BlockController build(Block) } class GameController implements Controller class StageController implements Controller abstract class PhysicsController extends BlockController abstract class DisplayController extends BlockController class WallPhysicsController extends PhysicsController class WallDisplayController extends DisplayController class TrashPhysicsController extends PhysicsController class TrashDisplayController extends DisplayController class GarbagePhysicsController extends PhysicsController class GarbageDisplayController extends DisplayController class RobotPhysicsController extends PhysicsController { List path } class RobotDisplayController extends DisplayController class BombPhysicsController extends PhysicsController class BombDisplayController extends DisplayController } RobotPhysicsController --> PathFinder RobotPhysicsController --> BoardConverter Stage --> BoardConverter PhysicsController --() JBox2D Zen5 ()-- Viewer viewer --> context viewer --> model context --> event model --> controller board --> model @enduml