Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create interactive graphic with Vaadin?

I want to develop a simple interactive game (like arcanoid). I already have implemented a menu and different views, and now I need to develop the actually game (draw flying ball, some movable platform) and I don't know how to do this. I need something like canvas where I can draw my graphic each frame.

I have tryed to implement this with Canvas and Timer. But it doesn't want update graphic itself, but only when user clicks on screen or similar. Also I saw com.google.gwt.canvas.client.Canvas, but I cannot understand how to use it in Vaadin application.

So my question is next: is it possible to draw some graphic each frame with high framerate in any way? If possible, how can I do this?

P.S. I use the Vaadin 7.3.3.

like image 414
Crabar Avatar asked Nov 06 '14 12:11

Crabar


1 Answers

ADDED LATER:

Here is a link to my educational project with implementation below. I'll be glad if it helps someone.

ORIGINAL ANSWER:

Well... I found the solution myself. First of all, I have created my own widget - "client side" component (according to this article).

Client side part:

public class GWTMyCanvasWidget extends Composite {

public static final String CLASSNAME = "mycomponent";
private static final int FRAMERATE = 30;

public GWTMyCanvasWidget() {
    canvas = Canvas.createIfSupported();
    initWidget(canvas);
    setStyleName(CLASSNAME);
}

Connector:

@Connect(MyCanvas.class)
public class MyCanvasConnector extends AbstractComponentConnector {    

    @Override
    public Widget getWidget() {
        return (GWTMyCanvasWidget) super.getWidget();
    }

    @Override
    protected Widget createWidget() {
        return GWT.create(GWTMyCanvasWidget.class);
    }
}

Server side part:

public class MyCanvas extends AbstractComponent {

    @Override
    public MyCanvasState getState() {
        return (MyCanvasState) super.getState();
    }
}

Then I just add MyCanvas component on my View:

private void createCanvas() {
    MyCanvas canvas = new MyCanvas();
    addComponent(canvas);
    canvas.setSizeFull();
}

And now I can draw anything on Canvas (on client side in GWTMyCanvasWidget) with great performance =). Example:

public class GWTMyCanvasWidget extends Composite {

    public static final String CLASSNAME = "mycomponent";
    private static final int FRAMERATE = 30;
    private Canvas canvas;
    private Platform platform;
    private int textX;

    public GWTMyCanvasWidget() {
        canvas = Canvas.createIfSupported();
        canvas.addMouseMoveHandler(new MouseMoveHandler() {
            @Override
            public void onMouseMove(MouseMoveEvent event) {
                if (platform != null) {
                    platform.setCenterX(event.getX());
                }
            }
        });
        initWidget(canvas);
        Window.addResizeHandler(new ResizeHandler() {
            @Override
            public void onResize(ResizeEvent resizeEvent) {
                resizeCanvas(resizeEvent.getWidth(), resizeEvent.getHeight());
            }
        });
        initGameTimer();
        resizeCanvas(Window.getClientWidth(), Window.getClientHeight());
        setStyleName(CLASSNAME);
        platform = createPlatform();
    }

    private void resizeCanvas(int width, int height) {
        canvas.setWidth(width + "px");
        canvas.setCoordinateSpaceWidth(width);
        canvas.setHeight(height + "px");
        canvas.setCoordinateSpaceHeight(height);
    }

    private void initGameTimer() {
        Timer timer = new Timer() {
            @Override
            public void run() {
                drawCanvas();
            }
        };

        timer.scheduleRepeating(1000 / FRAMERATE);
    }

    private void drawCanvas() {
        canvas.getContext2d().clearRect(0, 0, canvas.getCoordinateSpaceWidth(), canvas.getCoordinateSpaceHeight());
        drawPlatform();
    }

    private Platform createPlatform() {
        Platform platform = new Platform();
        platform.setY(Window.getClientHeight());
        return platform;
    }

    private void drawPlatform() {
        canvas.getContext2d().fillRect(platform.getCenterX() - platform.getWidth() / 2, platform.getY() - 100, platform.getWidth(), platform.getHeight());
    }
}
like image 100
Crabar Avatar answered Sep 22 '22 00:09

Crabar