Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle drag in an android chess app?

I just started with developing android apps (with java, in android studio, if that matters), and I'm doing a little project, just for fun. I want to create my own chess app, and so far I have done quite a few things. I set up a menu to switch to another activity which is the game itself, i made a customview with a self painted board, and I think my model is also almost complete. The only thing I don't understand is how to handle a drag. So, when you move one piece from a position to another position with a dragging gesture, how do you get the begin- and endpoints of that?

As said, I already implemented a move in my model(with a function move(Position start, Position end)), and it also checks if that move is valid for a certain piece, but the only thing I still need is something that lets me drag a piece on the actual board.

I was thinking about putting an onDrag method in my Controller class, but I don't know how to work that out, and can't find good examples on the internet. I already started with that, but don't know if it could ever work.

Could you please help me implementing the drag?

Thanks in advance!

P.S. I will also add the code for the custom view and the (not yet complete)controller in my question, if that helps. If you need more of my code to answer this question, I will also put it here, just let me know.

public class ChessView extends View implements Observer {
    private Game game;
    private static final Paint WHITE_PAINT = new Paint(), BLACK_PAINT = new Paint();

    public ChessView(Context context) {
        super(context);
        init();
    }

    public ChessView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public ChessView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    public void init() {
        WHITE_PAINT.setColor(Color.rgb(200, 159, 77));
        BLACK_PAINT.setColor(Color.rgb(61, 34, 18));
    }

    public void setGame(Game game) {
        if (this.game != null)
            this.game.deleteObserver(this);

        this.game = game;
        this.game.addObserver(this);
    }

    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (game == null)
            return;

        drawBoard(canvas);
        drawPieces(canvas);
    }

    public void drawBoard(Canvas canvas) {
        int tilesize = Math.min(getWidth(), getHeight())/8;

        for (int i = 0; i < 8; i++)
            for (int j = 0; j < 8; j++) {
                Paint paint = ((i + j) % 2 == 0) ? WHITE_PAINT : BLACK_PAINT;

                canvas.drawRect(i*tilesize, j*tilesize,(i+1)*tilesize, (j+1)*tilesize, paint);
            }
    }

    public void drawPieces(Canvas canvas) {
        for (int i = 0; i < game.getBoard().boardSize(); i++)
            for (int j = 0; j < game.getBoard().boardSize(); j++) {
                Position pos = new Position(i, j);
                Piece p = game.getBoard().getPiece(pos);

                if (p != null)
                    drawPiece(canvas, p, pos);
                else
                    clearPos(canvas, pos);
            }
    }

    public void drawPiece(Canvas canvas, Piece piece, Position position) {
        switch (game.getBoard().getPiece(position).getId()) {
            case ("wpawn"): drawPicture(canvas, position, R.drawable.wpawn); break;
            case ("bpawn"): drawPicture(canvas, position, R.drawable.bpawn); break;
            case ("wrook"): drawPicture(canvas, position, R.drawable.wrook); break;
            case ("brook"): drawPicture(canvas, position, R.drawable.brook); break;
            case ("wknight"): drawPicture(canvas, position, R.drawable.wknight); break;
            case ("bknight"): drawPicture(canvas, position, R.drawable.bknight); break;
            case ("wbishop"): drawPicture(canvas, position, R.drawable.wbishop); break;
            case ("bbishop"): drawPicture(canvas, position, R.drawable.bbishop); break;
            case ("wqueen"): drawPicture(canvas, position, R.drawable.wqueen); break;
            case ("bqueen"): drawPicture(canvas, position, R.drawable.bqueen); break;
            case ("wking"): drawPicture(canvas, position, R.drawable.wking); break;
            case ("bking"): drawPicture(canvas, position, R.drawable.bking); break;
            default: break;
        }
    }

    public void drawPicture(Canvas canvas, Position position, int picture) {
        int tilesize = Math.min(getHeight(), getWidth())/8, x = position.getY(), y = position.getX();
        Drawable d = ResourcesCompat.getDrawable(getResources(), picture, null);
        Bitmap b = ((BitmapDrawable) d).getBitmap();

        canvas.drawBitmap(b, null, new Rect(x*tilesize, y*tilesize,(x + 1)*tilesize, (y + 1)*tilesize), null);
    }

    public void clearPos(Canvas canvas, Position position) {
        int tilesize = Math.min(getWidth(), getHeight())/8, x = position.getY(), y = position.getX();

        Paint paint = ((position.getX() + position.getY()) % 2 == 0) ? WHITE_PAINT : BLACK_PAINT;

        canvas.drawRect(x*tilesize, y*tilesize, (x + 1)*tilesize, (y + 1)*tilesize, paint);
    }

    @Override
    public void update(Observable observable, Object data) {
        this.postInvalidate();
    }
}

public class Controller extends Observable implements View.OnDragListener {
    private Game game;

        public Controller(Game game) {
            this.game = game;
        }

        @Override
        public boolean onDrag(View v, DragEvent event) {

            float startx = event.getX();
            float starty = event.getY();

            if (event.getAction() == DragEvent.ACTION_DRAG_ENDED) {

            }

            return false;
        }
    }
like image 489
Peter Avatar asked Apr 27 '16 11:04

Peter


1 Answers

Hopefully something like this would give you the idea:

@Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
        if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
            ...               
            view.startDrag(clipData, dsb, view, 0);
            ...
            return true;
        } else {
            return false;
        }
    }

 @Override
    public boolean onDrag(View view, DragEvent dragEvent) {
        int dragAction = dragEvent.getAction();
        View dragView = (View) dragEvent.getLocalState();
        if (dragAction == DragEvent.ACTION_DRAG_EXITED) {
            containsDragable = false;
        } else if (dragAction == DragEvent.ACTION_DRAG_ENTERED) {
            containsDragable = true;
        } else if (dragAction == DragEvent.ACTION_DROP && containsDragable){
            //your function to move and check valid moves
            dragView.setVisibility(View.VISIBLE);
        }
        return true;
    }

Ref: https://www.javacodegeeks.com/2011/12/android-drag-and-drop-tutorial.html

like image 130
Y.E. Avatar answered Sep 28 '22 08:09

Y.E.