Devahoy Logo
PublishedAt

Game Development

เขียนเกมด้วย LibGDX 6 – Simple Game ภาคพิเศษ

เขียนเกมด้วย LibGDX 6 – Simple Game ภาคพิเศษ

กลับมาพบกับซีรีย์เขียนเกมด้วย LibGDX กันต่อครับ บทความนี้เป็นบทความที่ 6 แล้วครับ จะมาพูดต่อ จากบทความที่แล้ว คือ เขียนเกมด้วย LibGDX #5 – Simple Game ตอนจบ โดยในบทความนี้จะทำการเพิ่มหน้า เมนู และระบบต่างๆที่ทำให้เกมดูสมจริงขึ้นครับ

บทความตอนอื่นๆ ในซีรีย์ เขียนเกมด้วย LibGDX ติดตามอ่านได้ตามลิงค์ข้างล่างเลยครับ


เริ่มกันเลยครับ มาพูดถึงคลาสในเกมของเราก่อนดีกว่า เริ่มจาก

The Screen interface

Screens ถือเป็นพื้นฐานของทุกๆเกมส์เลยก็ว่าได้ครับ Screens นั้นมีเมธอดให้เลือกใช้จาก ออปเจ็ค ApplicationListener รวมถึงเมธอด show และ hide ที่จะถูกเรียกเมื่อเวลาโฟกัสและไม่ได้โฟกัสหน้าจอ

The Game Class

abstract คลาส Game นั้น implement ApplicationListener สำหรับใช้เป็น helper เมธอด สำหรับจัดการการเรนเดอร์ต่างๆของหน้าจอครับ

ทั้งออปเจ็ค Screen และ Game ใช้สำหรับเป็นโครงสร้างพื้นฐานสำหรับเขียนเกมครับ เราจะมาเริ่มโดยการสร้างออปเจ็ค Game กันครับ จากบทความเก่า คลาส Drop ของเรา ทีแรกจะ implements ApplicationListener ใช่มั้ย มาอันนี้เราจะให้ทำการ extends Game ครับ ซึ่งออปเจ็คเกมนั้นก็ implements ApplicationListener มาอีกทีครับ เวลาเรา extends เราก็ไม่จำเป้นต้อง implement ทุกเมธอดครับ สนใจเฉพาะ create, render และ dispose

1
package com.badlogic.drop;
2
3
import com.badlogic.gdx.Game;
4
import com.badlogic.gdx.graphics.g2d.BitmapFont;
5
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
6
7
8
public class Drop extends Game {
9
10
public SpriteBatch batch;
11
public BitmapFont font;
12
13
public void create() {
14
batch = new SpriteBatch();
15
//LibGDX ใช้ฟ้อน Arial เป้นฟ้อนหลักครับ
16
font = new BitmapFont();
17
this.setScreen(new MainMenuScreen(this));
18
}
19
20
public void render() {
21
super.render(); //important!
22
}
23
24
public void dispose() {
25
batch.dispose();
26
font.dispose();
27
}
28
29
}

เราเริ่มต้นด้วยการสร้างแอพพลิเคชัน โดยสร้างออปเจ็ค SpriteBatch และ BitmapFont ใหม่ (มันอาจจะเป็นตัวอย่างที่ไม่ดีนัก หากพูดถึงกฎเรื่อง DRY Don’t Repeat Yourself. ออปเจ็ค SpriteBatch ใช้สำหรับเรนเดอร์ออปเจ็คบนหน้าจอ เช่น Texture ส่วน BitmapFont ใช้สำหรับเรนเดอร์ข้อความบนหน้าจอครับ โดยใช้ร่วมกับ SpriteBatch

ถัดมา เราทำการสร้าง Screen ของเกมครับ โดยใช้คลาส MainMenuScreen จะใช้เป็นหน้าจอเมนูตอนเริ่มเข้าสู่เกม โดยรับคลาส Drop เป็น parameter ครับ (คลาส MainMenuScreen ยังไม่ได้สร้างนะครับ หากว่าตอนนี้มี error ก็ปล่อยไปก่อน)

อย่าลืมเรียก super.render() ในเมธอด render ที่เรา implement คลาส Game มาด้วยนะครับ ไม่อย่างนั้น Screen ที่เราทำการสร้างตรงเมธอด create() จะไม่เรนเดอร์อะไรออกมาเลย

สุดท้าย อย่าลืมเมธอด dispose() ครับ อ่านเพิ่มเติม การจัดการ Assets

The Main Menu

มาถึงการสร้างคลาส MainMenuScreen แล้วครับ โดยทำการ implement Screen ก่อนเลยครับ

1
package com.badlogic.drop;
2
3
import com.badlogic.gdx.Gdx;
4
import com.badlogic.gdx.Screen;
5
import com.badlogic.gdx.graphics.GL20;
6
import com.badlogic.gdx.graphics.OrthographicCamera;
7
8
public class MainMenuScreen implements Screen {
9
10
final Drop game;
11
12
OrthographicCamera camera;
13
14
public MainMenuScreen(final Drop gam) {
15
game = gam;
16
17
camera = new OrthographicCamera();
18
camera.setToOrtho(false, 800, 480);
19
20
}
21
22
23
//...Rest of class omitted for succinctness.
24
25
}

จากโค๊ดด้านบน เราได้สร้าง constructor สำหรับคลาส MainMenuScreen ที่ implements อินเตอร์เฟส Screen. อินเตอร์เฟส Screen นั้นไม่มีเมธอด create() มาให้นะครับ นั่นจึงเป็นเหตุผลว่าทำไมเราต้องสร้าง Constructor ของเราขึ้นเอง สำหรับ constructor เราก็รับออปเจ็ค Drop เข้ามาครับ ตัวที่ส่งมาจากคลาส Drop ตรงเมธอด create#setScreen

ถัดมาทำการ override เมธอด render ครับ หากยังจำโค๊ดจากบทความเก่าได้ เมธอด render ของ ApplicationListener จะไม่มี parameter เลย ขณะที่ เมธอด render อันนี้รับ parameter เป็น float ครับ ซึ่งก็คือ deltaTime เราไม่ต้องไปใช้ Gdx.graphics.getDeltaTime() แล้ว

1
public class MainMenuScreen implements Screen {
2
3
//public MainMenuScreen(final Drop gam)....
4
5
@Override
6
public void render(float delta) {
7
Gdx.gl.glClearColor(0, 0, 0.2f, 1);
8
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
9
10
camera.update();
11
game.batch.setProjectionMatrix(camera.combined);
12
13
game.batch.begin();
14
game.font.draw(game.batch, "Welcome to Drop!!! ", 100, 150);
15
game.font.draw(game.batch, "Tap anywhere to begin!", 100, 100);
16
game.batch.end();
17
18
if (Gdx.input.isTouched()) {
19
game.setScreen(new GameScreen(game));
20
dispose();
21
}
22
}
23
24
//Rest of class still omitted...
25
}

โค๊ดด้านบน สังเกตที่ SpriteBatch และ BitmapFont เราไม่ได้สร้างออปเจ็คมันขึ้นมา แต่เราใช้อ้อปเจ็คทั้งสองที่ได้สร้างจากคลาส Game สำหรับ game.font.draw(SpriteBatch, String, float, float) คือเมธอดที่ใช้สำหรับแสดงข้อความบทหน้าจอ สำหรับฟ้อนพื้นฐานที่มีมาให้คือฟ้อน Arial ครับ

ถัดมาก็ทำการเช็คว่ามีการแตะที่หน้าจอหรือไม่ ถ้ามี ก็ให้ setScreen คือเปลี่ยนหน้าจอ ไปที่หน้าจอ GameScreen ครับ โดยส่งอ็อปเจ็ค game ไปเป็น parameter ด้วย ครับ (ลองนึกถึง เวลาเข้าเกมมาครับ หน้าแรก จะโชว์หน้าจอนี้ แล้วเมื่อผู้เล่นทำการแตะหน้าจอ ก็จะไปหน้าจอเล่นเกมครับ)

หน้าตาที่ได้ก็จะได้ประมาณนี้

MenuScreen

The Game Screen

มาถึง Game Screen บ้างครับหลังจากที่ทำหน้า Menu เสร็จไปแล้ว ตัว GameScreen อันนี้จะเป็นหน้าจอหลักที่ไว้สำหรับเล่นเกมเลยครับ โค๊ดส่วนใหญ่ก็เหมือน บทความที่แล้วครับ ต่างกันที่ GameScreen จะทำการ implements Screen แล้วรับออปเจ็ค Game เป็น parameter ในขณะที่โค๊ดเก่า เราสร้างคลาส Drop โดย implements ApplicationListener

1
package com.badlogic.drop;
2
3
import java.util.Iterator;
4
5
import com.badlogic.gdx.Gdx;
6
import com.badlogic.gdx.Input.Keys;
7
import com.badlogic.gdx.Screen;
8
import com.badlogic.gdx.audio.Music;
9
import com.badlogic.gdx.audio.Sound;
10
import com.badlogic.gdx.graphics.GL20;
11
import com.badlogic.gdx.graphics.OrthographicCamera;
12
import com.badlogic.gdx.graphics.Texture;
13
import com.badlogic.gdx.math.MathUtils;
14
import com.badlogic.gdx.math.Rectangle;
15
import com.badlogic.gdx.math.Vector3;
16
import com.badlogic.gdx.utils.Array;
17
import com.badlogic.gdx.utils.TimeUtils;
18
19
public class GameScreen implements Screen {
20
final Drop game;
21
22
Texture dropImage;
23
Texture bucketImage;
24
Sound dropSound;
25
Music rainMusic;
26
OrthographicCamera camera;
27
Rectangle bucket;
28
Array<Rectangle> raindrops;
29
long lastDropTime;
30
int dropsGathered;
31
32
public GameScreen(final Drop gam) {
33
this.game = gam;
34
35
// โหลดไฟล์รูปถังน้ำและเม็ดฝน ขนาด 64x64
36
dropImage = new Texture(Gdx.files.internal("droplet.png"));
37
bucketImage = new Texture(Gdx.files.internal("bucket.png"));
38
39
// โหลดเสียงเม็ดฝน และ effect
40
dropSound = Gdx.audio.newSound(Gdx.files.internal("drop.wav"));
41
rainMusic = Gdx.audio.newMusic(Gdx.files.internal("rain.mp3"));
42
rainMusic.setLooping(true);
43
44
// สร้าง camera และ SpriteBatch
45
camera = new OrthographicCamera();
46
camera.setToOrtho(false, 800, 480);
47
48
// สร้างออปเจ็ค bucket จากคลาส Rectangle
49
bucket = new Rectangle();
50
bucket.x = 800 / 2 - 64 / 2; // center the bucket horizontally
51
bucket.y = 20;
52
bucket.width = 64;
53
bucket.height = 64;
54
55
// สร้าง array เม็ดฝน และเริ่มโปรยเม็ดฝนเม็ดแรก
56
raindrops = new Array<Rectangle>();
57
spawnRaindrop();
58
59
}
60
61
private void spawnRaindrop() {
62
Rectangle raindrop = new Rectangle();
63
raindrop.x = MathUtils.random(0, 800 - 64);
64
raindrop.y = 480;
65
raindrop.width = 64;
66
raindrop.height = 64;
67
raindrops.add(raindrop);
68
lastDropTime = TimeUtils.nanoTime();
69
}
70
71
@Override
72
public void render(float delta) {
73
// เคลียร์หน้าจอ ด้วยสี Dark Blue
74
// โดย argument ของ glClearColor คือ red, green, blue, alpha
75
// ค่าอยู่ระหว่าง [0, 1] (float)
76
Gdx.gl.glClearColor(0, 0, 0.2f, 1);
77
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
78
79
// camera อัพเดท matrix
80
camera.update();
81
82
// ให้ SpriteBatch ทำการเรนเดอร์พิกัดทั้งหมดของระบบ
83
game.batch.setProjectionMatrix(camera.combined);
84
85
// เริ่มวาด เรนเดอร์ ตะกร้าและเม็ดฝน รวมถึงนับจำนวนเม็ดฝนที่เก็บได้
86
game.batch.begin();
87
game.font.draw(game.batch, "Drops Collected: " + dropsGathered, 0, 480);
88
game.batch.draw(bucketImage, bucket.x, bucket.y);
89
for (Rectangle raindrop : raindrops) {
90
game.batch.draw(dropImage, raindrop.x, raindrop.y);
91
}
92
game.batch.end();
93
94
// เช็คว่า มีการคลิกเมาท์หรือแตะหน้าจอหรือไม่
95
if (Gdx.input.isTouched()) {
96
Vector3 touchPos = new Vector3();
97
touchPos.set(Gdx.input.getX(), Gdx.input.getY(), 0);
98
camera.unproject(touchPos);
99
bucket.x = touchPos.x - 64 / 2;
100
}
101
102
// เช็คว่า มีการกดคีย์บอร์ดปุ่มลูกศรซ้าย/ขวา หรือไม่
103
if (Gdx.input.isKeyPressed(Keys.LEFT))
104
bucket.x -= 200 * Gdx.graphics.getDeltaTime();
105
if (Gdx.input.isKeyPressed(Keys.RIGHT))
106
bucket.x += 200 * Gdx.graphics.getDeltaTime();
107
108
// เช็คไม่ให้ถังน้ำมันล้นหน้าจอ
109
if (bucket.x < 0)
110
bucket.x = 0;
111
if (bucket.x > 800 - 64)
112
bucket.x = 800 - 64;
113
114
// เช็คว่าถึงเวลาที่จะโปรยเม็ดฝนเม็ดถัดไปหรือยัง
115
if (TimeUtils.nanoTime() - lastDropTime > 1000000000)
116
spawnRaindrop();
117
118
// ทำให้เม็ดฝนขยับ โดยลบเม็ดฝนทุกครั้งที่ตกลงพ้นขอบจอหรือว่าไปชนกับถังน้ำ
119
// รวมถึงให้มันเล่นเสียงเวลาโดนถังน้ำ
120
Iterator<Rectangle> iter = raindrops.iterator();
121
while (iter.hasNext()) {
122
Rectangle raindrop = iter.next();
123
raindrop.y -= 200 * Gdx.graphics.getDeltaTime();
124
if (raindrop.y + 64 < 0)
125
iter.remove();
126
if (raindrop.overlaps(bucket)) {
127
dropsGathered++;
128
dropSound.play();
129
iter.remove();
130
}
131
}
132
}
133
134
@Override
135
public void resize(int width, int height) {
136
}
137
138
@Override
139
public void show() {
140
// เริ่มเล่นเสียงเพลง (เสียงฝนตก) เมื่อหน้าจอนี้แสดง
141
rainMusic.play();
142
}
143
144
@Override
145
public void hide() {
146
}
147
148
@Override
149
public void pause() {
150
}
151
152
@Override
153
public void resume() {
154
}
155
156
@Override
157
public void dispose() {
158
dropImage.dispose();
159
bucketImage.dispose();
160
dropSound.dispose();
161
rainMusic.dispose();
162
}
163
}

โค๊ดด้านบนนั้น 95% นั้นเหมือนกับโค๊ดจากคลาส Drop ในบทความที่แล้ว ต่างกันที่เราใช้ constructor แทนที่เมธอด create() ของ ApplicationListener แล้วก็ส่งค่าออปเจ็ค Drop เหมือนอย่างคลาส MainMenuScreen สุดท้ายก็ทำการเล่นเสียงเพลง เมื่อหน้า GameScreen นี้แสดง

รวมถึงได้เพิ่มข้อความที่มุมุซ้ายบนของหน้าจอเกม เพื่อเก็บบันทึกว่าเก็บเม็ดฝนไปกี่เม็ดแล้ว

เอาละ สุดท้ายตัวเกมก็เสร็จเรียบร้อยแล้วครับ ตอนนี้ถ้าได้อ่านมาถึงบทความนี้ เชื่อว่าหลายๆคนต้องพอรู้พื้นฐาน LibGDX รวมถึงรู้ ในเรื่องอินเตอร์เฟซ Screen , abstract คลาส Game และ Game State ต่างๆมากขึ้นครับ

สำหรับหน้าจอตัวอย่างเกมก็จะได้แบบนี้ ลองนำโค๊ดที่ได้ไปปรับใช้ แล้วลองเรียนรู้ ลองเล่นกันดูนะครับ การเรียนโปรแกรมมิ่งที่ดีที่สุด ไม่ใช่การอ่านหรือทำตาม Tutorial ครับ แต่มันคือการทดลอง ลองผิดลองถูกกับมันครับ

GameScreen

โค๊ดทั้งหมด

Drop.java

1
package com.badlogic.drop;
2
3
import com.badlogic.gdx.Game;
4
import com.badlogic.gdx.graphics.g2d.BitmapFont;
5
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
6
7
public class Drop extends Game {
8
9
SpriteBatch batch;
10
BitmapFont font;
11
12
public void create() {
13
batch = new SpriteBatch();
14
// LibGDX ใช้ฟ้อน Arial เป้นฟ้อนหลักครับ
15
font = new BitmapFont();
16
this.setScreen(new MainMenuScreen(this));
17
}
18
19
public void render() {
20
super.render(); // important!
21
}
22
23
public void dispose() {
24
batch.dispose();
25
font.dispose();
26
}
27
28
}

GameScreen.java

1
package com.badlogic.drop;
2
3
import java.util.Iterator;
4
5
import com.badlogic.gdx.Gdx;
6
import com.badlogic.gdx.Input.Keys;
7
import com.badlogic.gdx.Screen;
8
import com.badlogic.gdx.audio.Music;
9
import com.badlogic.gdx.audio.Sound;
10
import com.badlogic.gdx.graphics.GL20;
11
import com.badlogic.gdx.graphics.OrthographicCamera;
12
import com.badlogic.gdx.graphics.Texture;
13
import com.badlogic.gdx.math.MathUtils;
14
import com.badlogic.gdx.math.Rectangle;
15
import com.badlogic.gdx.math.Vector3;
16
import com.badlogic.gdx.utils.Array;
17
import com.badlogic.gdx.utils.TimeUtils;
18
19
public class GameScreen implements Screen {
20
final Drop game;
21
22
Texture dropImage;
23
Texture bucketImage;
24
Sound dropSound;
25
Music rainMusic;
26
OrthographicCamera camera;
27
Rectangle bucket;
28
Array<Rectangle> raindrops;
29
long lastDropTime;
30
int dropsGathered;
31
32
public GameScreen(final Drop gam) {
33
this.game = gam;
34
35
// โหลดไฟล์รูปถังน้ำและเม็ดฝน ขนาด 64x64
36
dropImage = new Texture(Gdx.files.internal("droplet.png"));
37
bucketImage = new Texture(Gdx.files.internal("bucket.png"));
38
39
// โหลดเสียงเม็ดฝน และ effect
40
dropSound = Gdx.audio.newSound(Gdx.files.internal("drop.wav"));
41
rainMusic = Gdx.audio.newMusic(Gdx.files.internal("rain.mp3"));
42
rainMusic.setLooping(true);
43
44
// สร้าง camera และ SpriteBatch
45
camera = new OrthographicCamera();
46
camera.setToOrtho(false, 800, 480);
47
48
// สร้างออปเจ็ค bucket จากคลาส Rectangle
49
bucket = new Rectangle();
50
bucket.x = 800 / 2 - 64 / 2; // center the bucket horizontally
51
bucket.y = 20;
52
bucket.width = 64;
53
bucket.height = 64;
54
55
// สร้าง array เม็ดฝน และเริ่มโปรยเม็ดฝนเม็ดแรก
56
raindrops = new Array<Rectangle>();
57
spawnRaindrop();
58
59
}
60
61
private void spawnRaindrop() {
62
Rectangle raindrop = new Rectangle();
63
raindrop.x = MathUtils.random(0, 800 - 64);
64
raindrop.y = 480;
65
raindrop.width = 64;
66
raindrop.height = 64;
67
raindrops.add(raindrop);
68
lastDropTime = TimeUtils.nanoTime();
69
}
70
71
@Override
72
public void render(float delta) {
73
// เคลียร์หน้าจอ ด้วยสี Dark Blue
74
// โดย argument ของ glClearColor คือ red, green, blue, alpha
75
// ค่าอยู่ระหว่าง [0, 1] (float)
76
Gdx.gl.glClearColor(0, 0, 0.2f, 1);
77
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
78
79
// camera อัพเดท matrix
80
camera.update();
81
82
// ให้ SpriteBatch ทำการเรนเดอร์พิกัดทั้งหมดของระบบ
83
game.batch.setProjectionMatrix(camera.combined);
84
85
// เริ่มวาด เรนเดอร์ ตะกร้าและเม็ดฝน รวมถึงนับจำนวนเม็ดฝนที่เก็บได้
86
game.batch.begin();
87
game.font.draw(game.batch, "Drops Collected: " + dropsGathered, 0, 480);
88
game.batch.draw(bucketImage, bucket.x, bucket.y);
89
for (Rectangle raindrop : raindrops) {
90
game.batch.draw(dropImage, raindrop.x, raindrop.y);
91
}
92
game.batch.end();
93
94
// เช็คว่า มีการคลิกเมาท์หรือแตะหน้าจอหรือไม่
95
if (Gdx.input.isTouched()) {
96
Vector3 touchPos = new Vector3();
97
touchPos.set(Gdx.input.getX(), Gdx.input.getY(), 0);
98
camera.unproject(touchPos);
99
bucket.x = touchPos.x - 64 / 2;
100
}
101
102
// เช็คว่า มีการกดคีย์บอร์ดปุ่มลูกศรซ้าย/ขวา หรือไม่
103
if (Gdx.input.isKeyPressed(Keys.LEFT))
104
bucket.x -= 200 * Gdx.graphics.getDeltaTime();
105
if (Gdx.input.isKeyPressed(Keys.RIGHT))
106
bucket.x += 200 * Gdx.graphics.getDeltaTime();
107
108
// เช็คไม่ให้ถังน้ำมันล้นหน้าจอ
109
if (bucket.x < 0)
110
bucket.x = 0;
111
if (bucket.x > 800 - 64)
112
bucket.x = 800 - 64;
113
114
// เช็คว่าถึงเวลาที่จะโปรยเม็ดฝนเม็ดถัดไปหรือยัง
115
if (TimeUtils.nanoTime() - lastDropTime > 1000000000)
116
spawnRaindrop();
117
118
// ทำให้เม็ดฝนขยับ
119
// โดยลบเม็ดฝนทุกครั้งที่ตกลงพ้นขอบจอหรือว่าไปชนกับถังน้ำ
120
// รวมถึงให้มันเล่นเสียงเวลาโดนถังน้ำ
121
Iterator<Rectangle> iter = raindrops.iterator();
122
while (iter.hasNext()) {
123
Rectangle raindrop = iter.next();
124
raindrop.y -= 200 * Gdx.graphics.getDeltaTime();
125
if (raindrop.y + 64 < 0)
126
iter.remove();
127
if (raindrop.overlaps(bucket)) {
128
dropsGathered++;
129
dropSound.play();
130
iter.remove();
131
}
132
}
133
}
134
135
@Override
136
public void resize(int width, int height) {
137
}
138
139
@Override
140
public void show() {
141
// เริ่มเล่นเสียงเพลง (เสียงฝนตก) เมื่อหน้าจอนี้แสดง
142
rainMusic.play();
143
}
144
145
@Override
146
public void hide() {
147
}
148
149
@Override
150
public void pause() {
151
}
152
153
@Override
154
public void resume() {
155
}
156
157
@Override
158
public void dispose() {
159
dropImage.dispose();
160
bucketImage.dispose();
161
dropSound.dispose();
162
rainMusic.dispose();
163
}
164
}

MainMenuScreen.java

1
package com.badlogic.drop;
2
3
import com.badlogic.gdx.Gdx;
4
import com.badlogic.gdx.Screen;
5
import com.badlogic.gdx.graphics.GL20;
6
import com.badlogic.gdx.graphics.OrthographicCamera;
7
8
public class MainMenuScreen implements Screen {
9
10
final Drop game;
11
12
OrthographicCamera camera;
13
14
public MainMenuScreen(final Drop gam) {
15
game = gam;
16
17
camera = new OrthographicCamera();
18
camera.setToOrtho(false, 800, 480);
19
20
}
21
22
@Override
23
public void render(float delta) {
24
Gdx.gl.glClearColor(0, 0, 0.2f, 1);
25
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
26
27
camera.update();
28
game.batch.setProjectionMatrix(camera.combined);
29
30
game.batch.begin();
31
game.font.draw(game.batch, "Welcome to Drop!!! ", 100, 150);
32
game.font.draw(game.batch, "Tap anywhere to begin!", 100, 100);
33
game.batch.end();
34
35
if (Gdx.input.isTouched()) {
36
game.setScreen(new GameScreen(game));
37
dispose();
38
}
39
}
40
41
@Override
42
public void resize(int width, int height) {
43
}
44
45
@Override
46
public void show() {
47
}
48
49
@Override
50
public void hide() {
51
}
52
53
@Override
54
public void pause() {
55
}
56
57
@Override
58
public void resume() {
59
}
60
61
@Override
62
public void dispose() {
63
}
64
}

Reference :

Authors
avatar

Chai Phonbopit

เป็น Web Dev ในบริษัทแห่งหนึ่ง ทำงานมา 10 ปีกว่าๆ ด้วยภาษาและเทคโนโลยี เช่น JavaScript, Node.js, React, Vue และปัจจุบันกำลังสนใจในเรื่องของ Blockchain และ Crypto กำลังหัดเรียนภาษา Rust

Related Posts