Skip to content

Commit abec6aa

Browse files
committed
feat(ui): add UI system for all screens
1 parent 93a687d commit abec6aa

File tree

18 files changed

+606
-71
lines changed

18 files changed

+606
-71
lines changed

client/src/main/java/io/exterminator3618/client/Constants.java

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,16 @@ public class Constants {
4343
public static final String BACKGROUND_MUSIC = "sound/test_bgr.mp3";
4444
public static final String BUFF_SOUND = "sound/buff_sound.mp3";
4545

46+
/**
47+
* Path to backgounds
48+
*/
49+
public static final String MENU_BACKGROUND_PATH = "assets/Background_Tiles.png";
50+
public static final String GAME_BACKGROUND_PATH = "assets/gameScreen.png";
4651
/**
4752
* Path to the texture atlas file.
4853
*/
4954
public static final String ATLAS_PATH = "assets/textures.atlas";
50-
55+
public static final String UI_PATH = "assets/uitextures.atlas";
5156
/**
5257
* Brick texture region names.
5358
*/
@@ -79,7 +84,7 @@ public class Constants {
7984
public static final int BRICK_WIDTH = 64;
8085
public static final int BRICK_HEIGHT = 32;
8186
public static final int BRICK_SPACING = 5;
82-
public static final int BRICK_START_X = 100;
87+
public static final int BRICK_START_X = 80;
8388
public static final int BRICK_START_Y = 100;
8489
public static final int BRICK_ROW_HEIGHT = BRICK_HEIGHT;
8590

@@ -114,4 +119,21 @@ public enum GameState {
114119
// PowerUp duration constants
115120
public static final float WIDEN_PADDLE_DURATION = 5.0f; // 5 seconds
116121

122+
public static final String BUTTON_LEFT_REGION = "tile_82";
123+
public static final String BUTTON_MIDDLE_REGION = "tile_83";
124+
public static final String BUTTON_RIGHT_REGION = "tile_84";
125+
126+
public static final String HEADER_LEFT_REGION = "tile_43";
127+
public static final String HEADER_MIDDLE_REGION = "tile_44";
128+
public static final String HEADER_RIGHT_REGION = "tile_45";
129+
130+
public static int BUTTON_WIDTH = 300;
131+
public static int BUTTON_HEIGHT = 75;
132+
/**
133+
* game borders
134+
*/
135+
public static final int PLAY_AREA_X_MAX = 1410;
136+
public static final int PLAY_AREA_X_MIN = 55;
137+
public static final int PLAY_AREA_Y_MAX = 985;
138+
public static final int PLAY_AREA_Y_MIN = 85;
117139
}

client/src/main/java/io/exterminator3618/client/Physics.java

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,12 +113,13 @@ public static boolean checkBallPaddleCollision(Ball ball, Paddle paddle, int pre
113113
*
114114
* @param ball the ball to handle screen collision for
115115
*/
116+
/**
116117
public static void handleScreenCollision(Ball ball) {
117118
int screenWidth = Constants.WINDOW_WIDTH;
118119
int screenHeight = Constants.WINDOW_HEIGHT;
119120
boolean bounced = false;
120121
//double epsilon = Constants.BALL_EPSILON;
121-
122+
122123
// Check wall collisions
123124
if (ball.getX() <= 0) {
124125
// Left wall
@@ -131,7 +132,7 @@ public static void handleScreenCollision(Ball ball) {
131132
ball.velocityX = -Math.abs(ball.velocityX);
132133
bounced = true;
133134
}
134-
135+
135136
// Check top and bottom walls
136137
if (ball.getY() <= 0) {// Bottom wall
137138
} else if (ball.getY() + ball.getHeight() >= screenHeight) {
@@ -140,6 +141,49 @@ public static void handleScreenCollision(Ball ball) {
140141
ball.velocityY = -Math.abs(ball.velocityY);
141142
bounced = true;
142143
}
144+
145+
// Add small random deviation to prevent infinite 90-degree bouncing
146+
if (bounced) {
147+
// không cần
148+
// double randomDeviationX = (Math.random() - 0.5) * epsilon * 2; // Range: [-epsilon, epsilon]
149+
// double randomDeviationY = (Math.random() - 0.5) * epsilon * 2; // Range: [-epsilon, epsilon]
150+
//
151+
// // Apply deviation to velocity components
152+
// ball.velocityX += randomDeviationX;
153+
// ball.velocityY += randomDeviationY;
154+
//
155+
// Maintain constant speed after collision
156+
normalizeBallVelocity(ball);
157+
158+
}
159+
}
160+
*/
161+
public static void handleScreenCollision(Ball ball) {
162+
int screenWidth = Constants.WINDOW_WIDTH;
163+
int screenHeight = Constants.WINDOW_HEIGHT;
164+
boolean bounced = false;
165+
//double epsilon = Constants.BALL_EPSILON;
166+
167+
// Check wall collisions
168+
if (ball.getX() <= Constants.PLAY_AREA_X_MIN) {
169+
// Left wall
170+
ball.setPosition(Constants.PLAY_AREA_X_MIN, ball.getY());
171+
ball.velocityX = Math.abs(ball.velocityX);
172+
bounced = true;
173+
} else if (ball.getX() + ball.getWidth() >= Constants.PLAY_AREA_X_MAX) {
174+
// Right wall
175+
ball.setPosition(Constants.PLAY_AREA_X_MAX - ball.getWidth(), ball.getY());ball.velocityX = -Math.abs(ball.velocityX);
176+
bounced = true;
177+
}
178+
179+
// Check top and bottom walls
180+
if (ball.getY() <= Constants.PLAY_AREA_Y_MIN) {// Bottom wall
181+
} else if (ball.getY() + ball.getHeight() >= Constants.PLAY_AREA_Y_MAX) {
182+
// Top wall
183+
ball.setPosition(ball.getX(), Constants.PLAY_AREA_Y_MAX - ball.getHeight());
184+
ball.velocityY = -Math.abs(ball.velocityY);
185+
bounced = true;
186+
}
143187

144188
// Add small random deviation to prevent infinite 90-degree bouncing
145189
if (bounced) {
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// DialogBox.java
2+
package io.exterminator3618.client.components;
3+
4+
import com.badlogic.gdx.graphics.Color;
5+
import com.badlogic.gdx.graphics.g2d.TextureRegion;
6+
import com.badlogic.gdx.math.Rectangle;
7+
import io.exterminator3618.client.Constants;
8+
import io.exterminator3618.client.utils.Assets;
9+
import io.exterminator3618.client.utils.Renderer;
10+
11+
public class Box {
12+
13+
private int x = Constants.WINDOW_WIDTH / 2;
14+
private int y = Constants.WINDOW_HEIGHT / 2;
15+
private int width, height;
16+
private String title, content;
17+
private String leftRegion = Constants.HEADER_LEFT_REGION;
18+
private String rightRegion = Constants.HEADER_RIGHT_REGION;
19+
private String middleRegion = Constants.HEADER_MIDDLE_REGION;
20+
private Rectangle bounds = new Rectangle(x, y, Constants.BUTTON_WIDTH, Constants.BUTTON_HEIGHT);
21+
22+
public Box(int width, int height, String title, String content) {
23+
this.x = Constants.WINDOW_WIDTH / 2 - width / 2;
24+
this.y = Constants.WINDOW_HEIGHT / 2 - height / 2;
25+
this.width = width;
26+
this.height = height;
27+
this.title = title;
28+
this.content = content;
29+
30+
}
31+
32+
public Box(int width, int height, String title) {
33+
this.x = Constants.WINDOW_WIDTH / 2 - width / 2;
34+
this.y = Constants.WINDOW_HEIGHT / 2 - height / 2;
35+
this.width = width;
36+
this.height = height;
37+
this.title = title;
38+
}
39+
40+
public void draw(Renderer renderer) {
41+
renderer.drawUi("tile_1",x,y,width,height);
42+
renderer.drawTextMiddle(title, x + width / 2, y + height - 50);
43+
}
44+
45+
}

client/src/main/java/io/exterminator3618/client/components/Paddle.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ public Paddle(int x, int y, int width, int height, String regionName) {
2222
super(x, y, width, height, regionName);
2323
}
2424

25+
2526
/**
2627
* Update vị trí trên trục hoành của paddle, chỉ trục hoành, CHỈ TRỤC HOÀNH
2728
* hiêện đang dùng chuột, dùng phím đang bị phế
@@ -42,8 +43,11 @@ public void update(float deltaTime) {
4243
desiredX += (int) keyboardDelta;
4344
*/
4445

46+
int minX = Constants.PLAY_AREA_X_MIN;
47+
int maxX = Constants.PLAY_AREA_X_MAX;
4548
//nhét paddle vào đúng trong màn hình
46-
int clampedX = Math.max(0, Math.min(desiredX, Constants.WINDOW_WIDTH - getWidth()));
49+
//int clampedX = Math.max(0, Math.min(desiredX, Constants.WINDOW_WIDTH - getWidth()));
50+
int clampedX = Math.max(minX, Math.min(desiredX, maxX - getWidth()));
4751
setPosition(clampedX, getY());
4852
}
4953

client/src/main/java/io/exterminator3618/client/components/TextButton.java

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,34 @@
22

33
import com.badlogic.gdx.graphics.Color;
44
import com.badlogic.gdx.math.Rectangle;
5+
import com.badlogic.gdx.graphics.g2d.TextureRegion;
56
import com.badlogic.gdx.graphics.OrthographicCamera;
7+
import io.exterminator3618.client.Constants;
68
import io.exterminator3618.client.utils.Renderer;
9+
import io.exterminator3618.client.utils.Assets;
710
public class TextButton {
811

912
public String text;
1013
public Rectangle bounds;
1114

15+
public String leftRegion;
16+
public String middleRegion;
17+
public String rightRegion;
18+
19+
public TextButton(String text, float x, float y, float width, float height, boolean hasFrame) {
20+
this.text = text;
21+
this.bounds = new Rectangle(x, y, width, height);
22+
23+
if (hasFrame) {
24+
this.leftRegion = Constants.BUTTON_LEFT_REGION;
25+
this.middleRegion = Constants.BUTTON_MIDDLE_REGION;
26+
this.rightRegion = Constants.BUTTON_RIGHT_REGION;
27+
} else {
28+
this.leftRegion = null;
29+
this.middleRegion = null;
30+
this.rightRegion = null;
31+
}
32+
}
1233
/**
1334
* Tạo một TextButton mới.
1435
*
@@ -27,8 +48,37 @@ public TextButton(String text, float x, float y, float width, float height) {
2748
* Vẽ button này bằng Renderer.
2849
*/
2950
public void draw(Renderer renderer) {
30-
float y_topLeft = bounds.y + bounds.height;
31-
renderer.drawText(text, bounds.x, y_topLeft);
51+
52+
if (leftRegion != null && middleRegion != null && rightRegion != null) {
53+
54+
TextureRegion leftTex = Assets.getUiRegion(leftRegion);
55+
TextureRegion rightTex = Assets.getUiRegion(rightRegion);
56+
57+
if (leftTex != null && rightTex != null) {
58+
int leftWidth = leftTex.getRegionWidth();
59+
int rightWidth = rightTex.getRegionWidth();
60+
61+
int x = (int)bounds.x;
62+
int y = (int)bounds.y;
63+
int width = (int)bounds.width;
64+
int height = (int)bounds.height;
65+
66+
renderer.drawUi(leftRegion, x, y, leftWidth, height);
67+
68+
renderer.drawUi(rightRegion, (x + width) - rightWidth, y, rightWidth, height);
69+
70+
int middleX = x + leftWidth;
71+
int middleWidth = width - leftWidth - rightWidth;
72+
73+
if (middleWidth > 0) {
74+
renderer.drawUiTiledX(middleRegion, middleX, y, middleWidth, height);
75+
}
76+
}
77+
}
78+
79+
int centerX = (int)(bounds.x + bounds.width / 2);
80+
int centerY = (int)(bounds.y + bounds.height / 2);
81+
renderer.drawTextMiddle(text, centerX, centerY);
3282
}
3383

3484
/**
@@ -42,4 +92,5 @@ public boolean isClicked(float touchX, float touchY) {
4292
return bounds.contains(touchX, touchY);
4393
}
4494

95+
4596
}

client/src/main/java/io/exterminator3618/client/screens/GameOverScreen.java

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
import com.badlogic.gdx.math.Vector3;
1111
import io.exterminator3618.client.Constants;
1212
import io.exterminator3618.client.Exterminator3618;
13+
import io.exterminator3618.client.components.Box;
1314
import io.exterminator3618.client.components.TextButton;
15+
import io.exterminator3618.client.utils.Assets;
1416
import io.exterminator3618.client.utils.Renderer;
1517

1618
public final class GameOverScreen implements Screen {
@@ -25,13 +27,21 @@ public final class GameOverScreen implements Screen {
2527
private TextButton playAgainButton;
2628
private TextButton backButton;
2729

30+
private Box box;
31+
2832
public GameOverScreen(Exterminator3618 game) {
2933
this.game = game;
3034
this.renderer = game.getRenderer();
3135
camera = new OrthographicCamera();
3236
viewport = new FitViewport(Constants.WINDOW_WIDTH, Constants.WINDOW_HEIGHT, camera);
33-
backButton = new TextButton("Main Menu", 100, 300, 200, 50);
34-
playAgainButton = new TextButton("Play Again", 100, 240, 200, 50);
37+
38+
final int CENTER_X = (Constants.WINDOW_WIDTH / 2) - (Constants.BUTTON_WIDTH / 2);
39+
final int BACK_Y = (Constants.WINDOW_HEIGHT / 2) + Constants.BUTTON_HEIGHT - 20;
40+
final int PLAY_Y = BACK_Y - Constants.BUTTON_HEIGHT - 20;
41+
42+
backButton = new TextButton("Main Menu", CENTER_X, BACK_Y, Constants.BUTTON_WIDTH, Constants.BUTTON_HEIGHT, true);
43+
playAgainButton = new TextButton("Play Again", CENTER_X, PLAY_Y, Constants.BUTTON_WIDTH, Constants.BUTTON_HEIGHT, true);
44+
box = new Box(800,500,"GAME OVER:(");
3545
}
3646

3747
@Override
@@ -44,11 +54,13 @@ public void render(float delta) {
4454
// Render game over screen
4555
Gdx.gl.glClearColor(0.2f, 0, 0, 1);
4656
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
57+
viewport.apply();
58+
camera.update();
4759
renderer.begin(camera);
60+
renderer.drawBackground(Assets.menuBackground);
4861
// Draw game over text here
49-
renderer.drawTextMiddle("Day la Game Over Screen", Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2);
50-
camera.update();
51-
viewport.apply();
62+
box.draw(renderer);
63+
5264
//renderer.begin(camera);
5365
playAgainButton.draw(renderer);
5466
backButton.draw(renderer);

client/src/main/java/io/exterminator3618/client/screens/GameScreen.java

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ public void show() {
123123
viewport = new FitViewport(Constants.WINDOW_WIDTH, Constants.WINDOW_HEIGHT, camera);
124124
camera.position.set(Constants.WINDOW_WIDTH / 2, Constants.WINDOW_HEIGHT / 2, 0);
125125
touchPos = new Vector3();
126-
pauseButton = new TextButton("Pause", 100, 300, 200, 50);
126+
pauseButton = new TextButton("Pause", 1545, 900, 300, 75, true);
127127
}
128128

129129
/**
@@ -189,7 +189,10 @@ public void render(float deltaTime) {
189189
}
190190

191191
// Render game objects
192+
viewport.apply();
193+
camera.update();
192194
renderer.begin(camera);
195+
renderer.drawBackground(Assets.gameBackground);
193196
renderer.draw(ball);
194197
renderer.draw(paddle);
195198
for (PowerUp powerUp : powerUps) {
@@ -205,19 +208,21 @@ public void render(float deltaTime) {
205208
renderer.draw(brick);
206209
}
207210

208-
209-
210-
renderer.setFontSize(24);
211-
renderer.drawText("Score: " + score, 20, WINDOW_HEIGHT - 20);
212-
renderer.drawText("Combo: " + ball.getComboCount(), 20, 30);
211+
renderer.setFontSize(50);
212+
renderer.drawTextMiddle("SCORE: " + score, 1680, WINDOW_HEIGHT - 600);
213+
renderer.drawTextMiddle("COMBO: " + ball.getComboCount(), 1680, WINDOW_HEIGHT - 460);
214+
renderer.drawTextMiddle("POWER UP", 1680, WINDOW_HEIGHT - 750);
215+
renderer.setFontSize(40);
216+
renderer.drawTextMiddle("LIVES", 1680, WINDOW_HEIGHT - 290);
213217
for (int i = 0; i < lives; i++) {
214-
renderer.drawLives(20 + i * 30, WINDOW_HEIGHT - 70);
218+
renderer.drawLives(1600 + i * 30, WINDOW_HEIGHT - 350);
215219
}
216-
camera.update();
217-
viewport.apply();
220+
221+
218222
pauseButton.draw(renderer);
219223
// (Optional) Could display active power-up timers here if desired
220224

225+
renderer.setFontSize(36);
221226
renderer.end();
222227
// Handle sticky paddle space key input
223228
if (Gdx.input.isKeyJustPressed(Input.Keys.SPACE)) {
@@ -286,9 +291,9 @@ private void gotoVictoryScreen() {
286291
}
287292

288293
private void gotoGameOverScreen() {
289-
//game.launchScreen(new GameOverScreen(game));
294+
game.launchScreen(new GameOverScreen(game));
290295
soundManager.dispose();
291-
game.replaceCurrentScreen(new GameOverScreen(game));
296+
//game.replaceCurrentScreen(new GameOverScreen(game));
292297
}
293298

294299
/**

0 commit comments

Comments
 (0)