12/08/2018, 10:49

LibGDX Tutorial 4: Xử lý đầu vào phần 1 - Chuột và bàn phím

Chúng ta bắt đầu với việc xử lý thao tác bàn phím, và đây là code: package com . handlinginputdemo . game ; import com . badlogic . gdx . ApplicationAdapter ; import com . badlogic . gdx . Gdx ; import com . badlogic . gdx . Input ; import com . badlogic . gdx . graphics . GL20 ; ...

Chúng ta bắt đầu với việc xử lý thao tác bàn phím, và đây là code:

package com.handlinginputdemo.game;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;

public class HandlingInputDemo extends ApplicationAdapter {
	SpriteBatch batch;
	Texture texture;
    private Sprite sprite;

	@Override
	public void create () {
        float awidth = Gdx.graphics.getWidth();
        float height = Gdx.graphics.getHeight();
        batch = new SpriteBatch();

        texture = new Texture(Gdx.files.internal("dante.png"));
        sprite = new Sprite(texture);
        sprite.setPosition(awidth/2 -sprite.getWidth()/2, height/2 - sprite.getHeight()/2);
	}

    @Override
    public void dispose() {
        batch.dispose();
        texture.dispose();
    }

	@Override
	public void render () {
        Gdx.gl.glClearColor(1, 1, 1, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        if(Gdx.input.isKeyPressed(Input.Keys.LEFT)){
            if(Gdx.input.isKeyPressed(Input.Keys.CONTROL_LEFT))
                sprite.translateX(-1f);
            else
                sprite.translateX(-10.0f);
        }
        if(Gdx.input.isKeyPressed(Input.Keys.RIGHT)){
            if(Gdx.input.isKeyPressed(Input.Keys.CONTROL_LEFT))
                sprite.translateX(1f);
            else
                sprite.translateX(10.0f);
        }
        batch.begin();
        sprite.draw(batch);
        batch.end();
	}
}
		sprite = new Sprite(texture);
        sprite.setPosition(awidth/2 -sprite.getWidth()/2, height/2 - sprite.getHeight()/2);

Với đoạn code trên, chúng ta tạo ra một sprite được hiển thị giữa màn hình.

		if(Gdx.input.isKeyPressed(Input.Keys.LEFT)){
            if(Gdx.input.isKeyPressed(Input.Keys.CONTROL_LEFT))
                sprite.translateX(-1f);
            else
                sprite.translateX(-10.0f);
        }
        if(Gdx.input.isKeyPressed(Input.Keys.RIGHT)){
            if(Gdx.input.isKeyPressed(Input.Keys.CONTROL_LEFT))
                sprite.translateX(1f);
            else
                sprite.translateX(10.0f);

Hàm translateX() sử dụng để thay đổi tọa độ của sprite. Chúng ta kiểm tra xem người dùng nhấn vào nút LEFT hay RIGHT. Khi nhấn những phím này kèm theo phím Ctrl, sprite sẽ di chuyển từ từ qua trái hoặc phải. Nếu không nhấn Ctrl, sprite sẽ di chuyển từng 10px thay vì di chuyển từ từ.

Các bạn cũng có thể sử dụng thêm hàm translateY() dùng để thay đổi vị trí sprite trên dưới, sử dụng các phím Input.Keys.UP và Input.Keys.DOWN để điều khiển sprite di chuyển lên xuống. Ngoài ra bạn cũng có thể sử dụng nhiều phím cùng lúc giống như ví dụ của phím Ctrl phía trên.

Bạn có thể thay thế đoạn code sau đây hoặc thêm vào sau đoạn code xử lý thao tác với bàn phím trong hàm render().

        if(Gdx.input.isButtonPressed(Input.Buttons.LEFT)){
            sprite.setPosition(Gdx.input.getX() - sprite.getWidth()/2,
                    Gdx.graphics.getHeight() - Gdx.input.getY() - sprite.getHeight()/2);
        }
        if(Gdx.input.isButtonPressed(Input.Buttons.RIGHT)){
            sprite.setPosition(Gdx.graphics.getWidth()/2 -sprite.getWidth()/2,
                    Gdx.graphics.getHeight()/2 - sprite.getHeight()/2);
        }

Ở đây chúng ta sử dụng hàm isButtonPressed để kiểm tra phím chuột được nhấn, sử dụng Gdx.input.getX() và Gdx.input.getY() để thiết lập vị trí đưa sprite tới đó. Phép tính toán có vẻ trông hơi rắc rối, tại sao chúng ta không chỉ đơn giản là đưa sprite tới vị trí getX/Y. Có 2 lý do, đầu tiên nếu chúng ta thiết lập sprite ở vị trí đó, tức là đưa sprite tới vị trí đó theo tọa độ của góc trái bên dưới, chúng ta cần có 1 nửa chiều rộng và 1 nửa chiều cao của sprite. Lý do tiếp theo xuất phát từ thực tế là LibGDX đặt gốc đặt ở góc trái bên dưới, nhưng vị trí con chuột là tương đối so với góc trên bên trái. Đơn giản chỉ cần trừ đi các vị trí từ độ cao màn hình sẽ cho bạn biết vị trí của các con chuột trong tọa độ màn hình. Chúng ta cũng kiểm tra xem nếu người dùng nhấn vào nút chuột phải, chúng ta đặt lại vị trí sprite tại vị trí trung tâm.

Bây giờ chúng ta sẽ xem xét việc xử lý cả 2 ví dụ trên bằng cách tiếp cận theo sự kiện:

package com.handlinginputdemo.game;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;

public class HandlingInputDemo implements ApplicationListener, InputProcessor {
    private SpriteBatch batch;
    private Texture texture;
    private Sprite sprite;
    private float positionX, positionY;

	@Override
	public void create () {
        float awidth = Gdx.graphics.getWidth();
        float height = Gdx.graphics.getHeight();
        batch = new SpriteBatch();

        texture = new Texture(Gdx.files.internal("dante.png"));
        sprite = new Sprite(texture);

        positionX = awidth/2 - sprite.getWidth()/2;
        positionY = awidth/2 - sprite.getWidth()/2;
        sprite.setPosition(awidth/2 - sprite.getWidth()/2, height/2 - sprite.getHeight()/2);
        Gdx.input.setInputProcessor(this);
	}

    @Override
    public void resize(int awidth, int height) {

    }

    @Override
    public void dispose() {
        batch.dispose();
        texture.dispose();
    }

	@Override
	public void render () {
        Gdx.gl.glClearColor(1, 1, 1, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        sprite.setPosition(positionX, positionY);
        batch.begin();
        sprite.draw(batch);
        batch.end();
	}

    @Override
    public void pause() {

    }

    @Override
    public void resume() {

    }

    @Override
    public boolean keyDown(int keycode) {
        float moveAmount = 10.0f;
        if(Gdx.input.isKeyPressed(Input.Keys.CONTROL_LEFT))
            moveAmount = 1f;

        if(keycode == Input.Keys.LEFT)
            positionX -= moveAmount;
        if(keycode == Input.Keys.RIGHT)
            positionX += moveAmount;
        return true;
    }

    @Override
    public boolean keyUp(int keycode) {
        return false;
    }

    @Override
    public boolean keyTyped(char character) {
        return false;
    }

    @Override
    public boolean touchDown(int screenX, int screenY, int pointer, int button) {
        if(button == Input.Buttons.LEFT){
            positionX = screenX - sprite.getWidth()/2;
            positionY = Gdx.graphics.getHeight() - screenY - sprite.getHeight()/2;
        }
        if(button == Input.Buttons.RIGHT){
            positionX = Gdx.graphics.getWidth()/2 - sprite.getWidth()/2;
            positionY = Gdx.graphics.getHeight()/2 - sprite.getHeight()/2;
        }
        return false;
    }

    @Override
    public boolean touchUp(int screenX, int screenY, int pointer, int button) {
        return false;
    }

    @Override
    public boolean touchDragged(int screenX, int screenY, int pointer) {
        return false;
    }

    @Override
    public boolean mouseMoved(int screenX, int screenY) {
        return false;
    }

    @Override
    public boolean scrolled(int amount) {
        return false;
    }
}

Các bạn sẽ thấy code khác trước một chút. Chúng ta có thể nhận thấy ngay từ việc khai báo lớp:

public class HandlingInputDemo implements ApplicationListener, InputProcessor {

Chúng ta đang implements một interface khác, đó là InputProcessor, như bạn có thể thấy một số phương thức được ghi đè. Những phương thức quan trọng nhất mà chúng ta cần quan tâm trong ví dụ này là keyDown và touchDown. Ngoài việc cài đặt các phương thức của interface, chúng ta cũng cần phải đăng ký InputProcessor, điều này được thực hiện như sau:

Gdx.input.setInputProcessor(this);

Code trong hàm keyDown hoàn toàn tương tự như code xử lý thao tác với bàn phím phía trên. Code trong hàm touchDown cũng tương tự với code xử lý thao tác với chuột, tuy nhiên điều bạn cần quan tâm là touch có nghĩa là chạm, LibGdx xử lý việc chạm vào màn hình hoàn toàn giống với chuột. Nhưng nếu chạm nhiều ngón tay thì sao? Bạn đừng lo, chúng ta sẽ nhắc lại vấn đề này khi khi xử lý thao tác với màn hình cảm ứng.

Bạn có có thể tham khảo source code của project này tại đây.

0