Skip to content
This repository was archived by the owner on Dec 24, 2025. It is now read-only.

Commit aa9a394

Browse files
committed
feat: enhance brick spawning with noise-based color selection
Updated the brick spawning method to accept a seed for generating noise, allowing for dynamic color selection based on the noise value. This improves the visual variety of bricks in the game.
1 parent 904b391 commit aa9a394

1 file changed

Lines changed: 99 additions & 30 deletions

File tree

src/main/java/com/github/codestorm/bounceverse/systems/init/GameSystem.java

Lines changed: 99 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.almasb.fxgl.entity.SpawnData;
77
import com.almasb.fxgl.profile.DataFile;
88
import com.almasb.fxgl.profile.SaveLoadHandler;
9+
import com.github.codestorm.bounceverse.AssetsPath;
910
import com.github.codestorm.bounceverse.factory.entities.BallFactory;
1011
import com.github.codestorm.bounceverse.factory.entities.BrickFactory;
1112
import com.github.codestorm.bounceverse.factory.entities.BulletFactory;
@@ -17,9 +18,14 @@
1718
import com.github.codestorm.bounceverse.ui.ingame.Hearts;
1819

1920
import javafx.geometry.Point2D;
21+
import javafx.scene.paint.Color;
22+
23+
import libs.FastNoiseLite;
2024

2125
import org.jetbrains.annotations.NotNull;
2226

27+
import java.util.ArrayList;
28+
import java.util.Comparator;
2329
import java.util.Map;
2430

2531
public final class GameSystem extends InitialSystem {
@@ -100,37 +106,98 @@ public static void walls() {
100106
FXGL.spawn("wallRight");
101107
}
102108

103-
public static void brick() {
104-
var rows = 6;
105-
var cols = 10;
106-
double startX = 85;
107-
double startY = 50;
108-
double brickWidth = 80;
109-
double brickHeight = 30;
110-
double spacingX = 5;
111-
double spacingY = 5;
112-
113-
for (var y = 0; y < rows; y++) {
114-
for (var x = 0; x < cols; x++) {
115-
var posX = startX + x * (brickWidth + spacingX);
116-
var posY = startY + y * (brickHeight + spacingY);
117-
118-
// Xác định loại brick theo hàng (bạn có thể chỉnh lại tuỳ ý)
119-
String type;
120-
switch (y) {
121-
case 0 -> type = "shieldBrick"; // Hàng đầu có khiên
122-
// case 1 -> type = "explodingBrick"; // Hàng thứ 2
123-
// nổ
124-
// case 2 -> type = "specialBrick"; // Hàng thứ 3 rơi
125-
// power-up
126-
case 3 -> type = "strongBrick"; // Hàng thứ 4 trâu
127-
default -> type = "normalBrick"; // Còn lại là thường
128-
}
109+
public static void brick(int seed) {
110+
var noise = new FastNoiseLite(seed);
111+
var colors = AssetsPath.Textures.Bricks.COLORS.keySet().toArray(new Color[0]);
112+
var color = colors[Math.floorMod(seed, colors.length)];
113+
114+
noise.SetNoiseType(FastNoiseLite.NoiseType.OpenSimplex2);
115+
noise.SetFrequency(0.2f);
116+
noise.SetFractalType(FastNoiseLite.FractalType.FBm);
117+
noise.SetFractalOctaves(4);
118+
noise.SetFractalLacunarity(2.1f);
119+
noise.SetFractalGain(0.6f);
120+
noise.SetDomainWarpType(FastNoiseLite.DomainWarpType.OpenSimplex2);
121+
noise.SetDomainWarpAmp(6.0f);
122+
123+
final var rows = 5;
124+
final var cols = 10;
125+
final var amount = 36;
126+
127+
final var appWidth = FXGL.getAppWidth();
128+
final var appHeight = FXGL.getAppHeight();
129+
final double marginX = 40;
130+
final double startY = 60;
131+
final var verticalCoverageRatio = 0.30;
132+
final double spacingX = 5;
133+
final double spacingY = 5;
134+
final var aspect = 30.0 / 80.0;
135+
136+
var availableWidth = appWidth - 2 * marginX;
137+
var wFromWidth = (availableWidth - (cols - 1) * spacingX) / cols;
138+
var hFromWidth = wFromWidth * aspect;
139+
140+
var targetBrickAreaHeight = appHeight * verticalCoverageRatio;
141+
var hMaxByHeight = (targetBrickAreaHeight - (rows - 1) * spacingY) / rows;
142+
143+
var brickW = wFromWidth;
144+
var brickH = hFromWidth;
145+
146+
if (brickH > hMaxByHeight) {
147+
brickH = hMaxByHeight;
148+
brickW = brickH / aspect;
149+
}
129150

130-
var data = new SpawnData();
131-
data.put("pos", new Point2D(posX, posY));
132-
FXGL.spawn(type, data);
151+
double minW = 40, maxW = 160;
152+
if (brickW < minW) brickW = minW;
153+
if (brickW > maxW) brickW = maxW;
154+
brickH = brickW * aspect;
155+
156+
var totalH = rows * brickH + (rows - 1) * spacingY;
157+
if (totalH > targetBrickAreaHeight) {
158+
brickH = hMaxByHeight;
159+
brickW = brickH / aspect;
160+
}
161+
162+
var brickWidth = (int) Math.round(brickW);
163+
var brickHeight = (int) Math.round(brickH);
164+
165+
var totalW = cols * brickWidth + (cols - 1) * spacingX;
166+
var startX = Math.max(marginX, (appWidth - totalW) / 2.0);
167+
168+
// Lấy ra amount phần tử có độ cao cao nhất
169+
record Cell(int gx, int gy, double x, double y, float n) {}
170+
var cells = new ArrayList<Cell>(rows * cols);
171+
for (var gy = 0; gy < rows; gy++) {
172+
for (var gx = 0; gx < cols; gx++) {
173+
var posX = startX + gx * (brickWidth + spacingX);
174+
var posY = startY + gy * (brickHeight + spacingY);
175+
var n = noise.GetNoise(gx, gy);
176+
cells.add(new Cell(gx, gy, posX, posY, n));
177+
}
178+
}
179+
cells.sort(Comparator.comparing(Cell::n).reversed());
180+
var target = Math.min(amount, cells.size());
181+
182+
for (var i = 0; i < target; i++) {
183+
var c = cells.get(i);
184+
var n = c.n();
185+
186+
final String type;
187+
if (n > 0.5f) {
188+
type = "shieldBrick";
189+
} else if (n > 0.3f) {
190+
type = "strongBrick";
191+
} else {
192+
type = "normalBrick";
133193
}
194+
195+
var data = new SpawnData();
196+
data.put("pos", new Point2D(c.x(), c.y()));
197+
data.put("width", brickWidth);
198+
data.put("height", brickHeight);
199+
data.put("color", color);
200+
FXGL.spawn(type, data);
134201
}
135202
}
136203

@@ -202,6 +269,7 @@ public void addAll() {
202269
if (isInitialized) {
203270
return;
204271
}
272+
// TODO: issue sau khi reset màn chơi thì không thêm lại UI
205273

206274
addScoreDisplay();
207275
addHeartsDisplay();
@@ -247,7 +315,8 @@ private static final class Holder {
247315
public void apply() {
248316
EntitySpawn.addFactory();
249317
EntitySpawn.walls();
250-
EntitySpawn.brick();
318+
EntitySpawn.brick(
319+
(int) (System.currentTimeMillis() & 0x7FFFFFFF)); // TODO: Custom chọn seed
251320
EntitySpawn.paddle();
252321
EntitySpawn.ball();
253322

0 commit comments

Comments
 (0)