Scene2D: Drag Drop, snap ke target

Ini lanjutan dari tutorial sebelumnya mengenai drag drop

Sekarang kita lengkapi code drag drop sebelumnya dengan penanganan drop ke target yang telah ditentukan. Jadi pengguna dapat mendrag kotak ke target, jika kotak overlap dengan target dalam batasan overlap tertentu maka warna akan berubah dan saat dilepas maka kotak akan berpindah ke tempat baru. Batasan overlap artinya jika kotak hanya menyentuh sedikit target, ini belum diakui sebagai hit.

Untuk menangani overlap digunakan class Intersector dan Rectangle. Code untuk kelas Kotak menjadi seperti ini:

public class Kotak extends Actor {

    private Pixmap pm;
    private Sprite sp;
    private Texture img;

    //target drop
    private Kotak ktkTarget;

    //rect untuk kotak ini, digunakan untuk menentukan overlap
    public Rectangle rect;

    //apakah drop tepat kena target?
    public boolean dropSukses =false;


    /** method ini dipanggil otomatis setiap ada perubahan lokasi
     * setiap posisi kotak berubah, rect juga diubah */
    protected void positionChanged () {
        rect.setX(getX());
        rect.setY(getY());
    }

    /** Method ini dipanggil otoamatis setiap ukuran berubah
     *  ukuran rect diubah sesuai dengan perubahan ukuran kotak
     * */
    protected void sizeChanged () {
        rect.setHeight(getHeight());
        rect.setWidth(getWidth());
    }

    //kelas listener
    private class ListTouchDown extends InputListener {
        float xAwal,yAwal;

        //pointer digunakan untuk multitouch. berisi nol untuk touch jari pertama,
        //1 untuk jari kedua dst
        public boolean touchDown (InputEvent event, float x, float y,
                                  int pointer, int button) {
            Gdx.app.log("yw","touch down; pointer="+pointer);
            xAwal = x;
            yAwal = y;
            return true;
        }

        public void touchUp (InputEvent event, float x, float y,
                             int pointer, int button) {

            Gdx.app.log("yw","touch up");

            //sukses drop diatas target, pindahkan ke tempat target
            if (dropSukses) {
                setX(ktkTarget.getX());
                setY(ktkTarget.getY());
            }
            //meleset, kembalikan ke posisi awal
            else {
               //ada animasi biar tidak terlihat meloncat
               addAction(Actions.moveTo(xAwal, yAwal, 0.1f));
            }
        }

        public void touchDragged (InputEvent event, float x,
                                  float y, int pointer) {
            Gdx.app.log("yw","touch dragged");

            //update posisi
            float newX = getX()+x-xAwal;
            float newY = getY()+y-yAwal;
            setPosition(newX,newY);

            //cek apakah overlap dengan target
            //rectIntersect adalah wilayah yang overlap antar source dan target
            Rectangle rectIntersect = new Rectangle();
            boolean overlap = Intersector.intersectRectangles(rect,ktkTarget.rect,rectIntersect);

            //kotak sudah overlap
            if (overlap) {
                Gdx.app.log("yw","overlap");

                //hitung luas intersect
                float luasIntersect = rectIntersect.getWidth()*rectIntersect.getHeight();
                float luasKotak = rect.getWidth() * rect.getHeight();

                // nyatakan sukses jika luas intersect sudah lebih besar daripada separuh kotak
                // artinya kalau baru menyentuh sedikit, masih dianggap meleset

                if (luasIntersect>=luasKotak*0.5) {
                    ktkTarget.gantiWarna(Color.BLUE);
                    dropSukses = true;
                }
            } else {
                ktkTarget.gantiWarna(Color.RED);
                dropSukses = false;
            }

        }
    }

    public void addTarget(Kotak k) {
        ktkTarget = k;
    }

    public void gantiWarna(Color warna) {
        //siapkan gambar kotak dgn line hitam
        pm  = new Pixmap(200,200,Pixmap.Format.RGBA8888);
        pm.setColor(warna);
        pm.fill();
        pm.setColor(Color.BLACK);
        pm.drawRectangle(0,0, pm.getWidth(), pm.getHeight());

        //buat texture dari pixmap, kemudian buat sprite
        img = new Texture(pm);
        pm.dispose();
        sp = new Sprite(img);
    }

    public Kotak  () {
        rect = new Rectangle ();
        gantiWarna(Color.RED); //default warna merah
        setWidth(200f);
        setHeight(200f);
        rect.set(getX(), getY(), getWidth(), getHeight());
        addListener(new ListTouchDown());
    }

    @Override
    public void draw (Batch batch, float parentAlpha) {
         ... sama dengan sebelumnya
    }

}

Sedangkan untuk kelas utama tidak terlalu banyak perubahan, hanya di bagian create saja:

@Override
public void create () {

        stg = new Stage(new ExtendViewport(wWorld, hWorld));

        //siapkan Actor
        Kotak kSumber = new Kotak();
        Kotak kTarget = new Kotak();

        stg.addActor(kSumber);
        stg.addActor(kTarget);

        //terima input dari user (nanti)
        Gdx.input.setInputProcessor(stg);

        //letakkan di atas
        kSumber.setPosition(100, 200);
        kTarget.setPosition(700,500);

        //setTarget
        kSumber.addTarget(kTarget);
    }

Leave a Reply

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload CAPTCHA.