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.