public void draw(Sprite sprite, int x, int y, int dir) {
        if (x >= -sprite.getWidth() && y >= -sprite.getHeight() && x <= w + sprite.getWidth() && y <= h + sprite.getHeight()) {
            BufferedImage flippedImage = new BufferedImage(sprite.getWidth(), sprite.getHeight(), sprite.getImage().getType());
            Graphics2D g = this.getGraphics(), ig = (Graphics2D) flippedImage.getGraphics();
            AffineTransform tx = null, fx = null;
            switch (dir) {
                case 0:
                    ig.drawImage(sprite.getImage(), 0, 0, null);
                    ig.dispose();
                    break;
                case FLIP_HORIZONTAL:
                    tx = AffineTransform.getTranslateInstance(sprite.getWidth(), 0);
                    fx = AffineTransform.getScaleInstance(-1D, 1D);
                    tx.concatenate(fx);

                    ig.setTransform(tx);
                    ig.drawImage(sprite.getImage(), 0, 0, null);
                    ig.dispose();
                    break;
                case FLIP_VERTICAL:
                    tx = AffineTransform.getTranslateInstance(0, sprite.getHeight());
                    fx = AffineTransform.getScaleInstance(1D, -1D);
                    tx.concatenate(fx);

                    ig.setTransform(tx);
                    ig.drawImage(sprite.getImage(), 0, 0, null);
                    ig.dispose();
                    break;
                case FLIP_BOTH:
                    tx = AffineTransform.getTranslateInstance(sprite.getWidth(), sprite.getHeight());
                    fx = AffineTransform.getScaleInstance(-1D, -1D);
                    tx.concatenate(fx);

                    ig.setTransform(tx);
                    ig.drawImage(sprite.getImage(), 0, 0, null);
                    ig.dispose();
                    break;
            }
            g.drawImage(flippedImage, x, y, null);
            g.dispose();
        }
    }