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

Commit 299026d

Browse files
committed
chore: commit tạm để chuyển máy (merge conflict PowerUpFactory)
2 parents b024a20 + ba79775 commit 299026d

25 files changed

Lines changed: 462 additions & 128 deletions
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package com.github.codestorm.bounceverse.components.behaviors;
2+
3+
import com.almasb.fxgl.dsl.FXGL;
4+
import com.almasb.fxgl.entity.Entity;
5+
import com.almasb.fxgl.entity.component.Component;
6+
import com.almasb.fxgl.physics.PhysicsComponent;
7+
import com.github.codestorm.bounceverse.typing.enums.EntityType;
8+
9+
import javafx.geometry.Point2D;
10+
11+
/**
12+
* Cho phép bóng dính paddle và di chuyển cùng paddle.
13+
*/
14+
public class BaseAttachmentComponent extends Component {
15+
16+
protected Entity paddle;
17+
protected PhysicsComponent physics;
18+
protected boolean attached = false;
19+
20+
private double offsetX;
21+
private double offsetY;
22+
private double lastPaddleX;
23+
24+
@Override
25+
public void onAdded() {
26+
paddle = FXGL.getGameWorld().getSingleton(EntityType.PADDLE);
27+
physics = getEntity().getComponent(PhysicsComponent.class);
28+
29+
// FIX: Dừng hoàn toàn chuyển động khi mới spawn
30+
physics.setLinearVelocity(Point2D.ZERO);
31+
physics.getBody().setAwake(false); // tắt vật lý để không bị nảy
32+
33+
// FIX: Cho biết đang gắn paddle
34+
attached = true;
35+
36+
lastPaddleX = paddle.getX();
37+
offsetX = getEntity().getX() - paddle.getX();
38+
offsetY = getEntity().getY() - paddle.getY();
39+
}
40+
41+
@Override
42+
public void onUpdate(double tpf) {
43+
if (!attached || paddle == null)
44+
return;
45+
46+
double deltaX = paddle.getX() - lastPaddleX;
47+
lastPaddleX = paddle.getX();
48+
49+
double newX = getEntity().getX() + deltaX;
50+
double newY = paddle.getY() + offsetY;
51+
52+
physics.overwritePosition(new Point2D(newX, newY));
53+
physics.setLinearVelocity(Point2D.ZERO);
54+
55+
// FIX: đảm bảo physics không bị wake lại bởi va chạm
56+
physics.getBody().setAwake(false);
57+
}
58+
59+
/** Khi bóng vừa dính paddle – đặt lại offset chuẩn. */
60+
public void snapToPaddle(Entity ball) {
61+
if (paddle == null)
62+
return;
63+
64+
attached = true; // FIX: gắn lại
65+
physics.setLinearVelocity(Point2D.ZERO);
66+
physics.getBody().setAwake(false);
67+
68+
lastPaddleX = paddle.getX();
69+
offsetX = ball.getX() - paddle.getX();
70+
offsetY = ball.getY() - paddle.getY();
71+
72+
physics.overwritePosition(ball.getPosition());
73+
}
74+
75+
/** Thả bóng ra khỏi paddle với góc và tốc độ nhất định. */
76+
public void releaseBall(double angleDeg, double speed) {
77+
if (!attached)
78+
return;
79+
80+
attached = false;
81+
physics.getBody().setAwake(true); // kích hoạt lại vật lý
82+
83+
double angle = Math.toRadians(angleDeg);
84+
double dir = (getEntity().getCenter().getX() >= paddle.getCenter().getX()) ? 1 : -1;
85+
double vx = speed * Math.sin(angle) * dir;
86+
double vy = -speed * Math.cos(angle);
87+
88+
physics.setLinearVelocity(new Point2D(vx, vy));
89+
}
90+
91+
public void setAttached(boolean value) {
92+
this.attached = value;
93+
94+
if (physics != null) {
95+
if (value) {
96+
physics.setLinearVelocity(Point2D.ZERO);
97+
physics.getBody().setAwake(false);
98+
} else {
99+
physics.getBody().setAwake(true);
100+
}
101+
}
102+
}
103+
104+
public boolean isAttached() {
105+
return attached;
106+
}
107+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.github.codestorm.bounceverse.components.behaviors;
2+
3+
import com.almasb.fxgl.entity.component.Component;
4+
5+
/**
6+
* Cho Power-Up rơi thẳng xuống với tốc độ cố định.
7+
*/
8+
public final class FallingComponent extends Component {
9+
10+
private static final double SPEED = 150;
11+
12+
@Override
13+
public void onUpdate(double tpf) {
14+
entity.translateY(SPEED * tpf);
15+
}
16+
}
Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
package com.github.codestorm.bounceverse.components.behaviors;
22

3-
import com.almasb.fxgl.dsl.FXGL;
4-
import com.almasb.fxgl.entity.component.Component;
53
import com.github.codestorm.bounceverse.data.meta.entities.ForEntity;
64
import com.github.codestorm.bounceverse.data.types.EntityType;
5+
import com.github.codestorm.bounceverse.systems.init.PowerUpSpawner;
76
import javafx.util.Duration;
7+
import com.almasb.fxgl.dsl.FXGL;
8+
import com.almasb.fxgl.entity.component.Component;
89

910
/**
1011
* Khi brick bị phá thì spawn PowerUp.
@@ -16,7 +17,7 @@ public class Special extends Component {
1617
public void onRemoved() {
1718
var pos = getEntity().getCenter();
1819

19-
// ✅ Delay spawn 1 frame + offset xuống dưới 10px để tránh overlap brick
20-
FXGL.runOnce(() -> FXGL.spawn("powerUp", pos.add(0, 10)), Duration.seconds(0.017));
20+
// ✅ Delay 1 frame rồi gọi spawner random
21+
FXGL.runOnce(() -> PowerUpSpawner.spawnRandom(pos.add(0, 10)), Duration.seconds(0.017));
2122
}
2223
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package com.github.codestorm.bounceverse.components.behaviors.paddle;
2+
3+
import java.util.Optional;
4+
5+
import com.almasb.fxgl.entity.Entity;
6+
import com.github.codestorm.bounceverse.components.behaviors.BaseAttachmentComponent;
7+
8+
/**
9+
* Power-Up Magnet: Paddle bắt bóng và giữ theo paddle.
10+
*/
11+
public final class MagnetComponent extends BaseAttachmentComponent {
12+
13+
private Optional<Entity> attachedBall = Optional.empty();
14+
private boolean waitingToRelease = false;
15+
16+
/** Khi paddle chạm bóng – thử bắt bóng lại. */
17+
public void tryAttachBall(Entity ball) {
18+
if (attachedBall.isPresent())
19+
return;
20+
21+
attachedBall = Optional.of(ball);
22+
23+
ball.getComponentOptional(BaseAttachmentComponent.class)
24+
.ifPresent(ballAttach -> {
25+
ballAttach.setAttached(true);
26+
ballAttach.snapToPaddle(ball); // gắn đúng vị trí va chạm
27+
});
28+
29+
waitingToRelease = true;
30+
}
31+
32+
/** Thả bóng ra khi người chơi nhấn SPACE. */
33+
public void releaseBallExternal() {
34+
if (attachedBall.isEmpty())
35+
return;
36+
37+
var ball = attachedBall.get();
38+
ball.getComponentOptional(BaseAttachmentComponent.class)
39+
.ifPresent(c -> c.releaseBall(45, 300));
40+
41+
attachedBall = Optional.empty();
42+
waitingToRelease = false;
43+
}
44+
45+
public boolean hasBallAttached() {
46+
return attachedBall.isPresent() && waitingToRelease;
47+
}
48+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.github.codestorm.bounceverse.components.behaviors.paddle;
2+
3+
import com.almasb.fxgl.entity.component.Component;
4+
5+
/**
6+
* Component đảo ngược điều khiển của paddle trong thời gian ngắn.
7+
*/
8+
public final class ReverseControlComponent extends Component {
9+
10+
/** Nếu true thì đảo ngược hướng điều khiển. */
11+
private boolean reversed = true;
12+
13+
public boolean isReversed() {
14+
return reversed;
15+
}
16+
17+
public void setReversed(boolean reversed) {
18+
this.reversed = reversed;
19+
}
20+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package com.github.codestorm.bounceverse.components.properties.powerup.types.paddle;
2+
3+
import com.almasb.fxgl.dsl.FXGL;
4+
import com.almasb.fxgl.entity.Entity;
5+
import com.github.codestorm.bounceverse.components.behaviors.paddle.PaddleShooting;
6+
import com.github.codestorm.bounceverse.components.properties.powerup.types.PowerUp;
7+
import javafx.scene.paint.Color;
8+
import javafx.scene.shape.Rectangle;
9+
import javafx.util.Duration;
10+
11+
/**
12+
* Power-Up: tạo 2 nòng súng trên paddle và tự động bắn trong 10s.
13+
*/
14+
public final class GunPowerUp extends PowerUp {
15+
16+
private static final Duration DURATION = Duration.seconds(10);
17+
private static final double GUN_WIDTH = 6;
18+
private static final double GUN_HEIGHT = 10;
19+
private static final double OFFSET_Y = -10;
20+
21+
public GunPowerUp() {
22+
super("Gun");
23+
}
24+
25+
@Override
26+
public void apply(Entity paddle) {
27+
// Thêm khả năng bắn nếu chưa có
28+
paddle.getComponentOptional(PaddleShooting.class)
29+
.orElseGet(() -> {
30+
var shooting = new PaddleShooting(0.25);
31+
paddle.addComponent(shooting);
32+
return shooting;
33+
});
34+
35+
// Tạo 2 nòng súng
36+
var leftGun = FXGL.entityBuilder()
37+
.view(new Rectangle(GUN_WIDTH, GUN_HEIGHT, Color.DARKRED))
38+
.zIndex(paddle.getZIndex() + 1)
39+
.build();
40+
41+
var rightGun = FXGL.entityBuilder()
42+
.view(new Rectangle(GUN_WIDTH, GUN_HEIGHT, Color.DARKRED))
43+
.zIndex(paddle.getZIndex() + 1)
44+
.build();
45+
46+
FXGL.getGameWorld().addEntities(leftGun, rightGun);
47+
48+
// Gắn theo paddle
49+
var pT = paddle.getTransformComponent();
50+
var lT = leftGun.getTransformComponent();
51+
var rT = rightGun.getTransformComponent();
52+
double rightOffsetX = paddle.getWidth() - GUN_WIDTH - 4;
53+
54+
lT.xProperty().bind(pT.xProperty().add(4));
55+
lT.yProperty().bind(pT.yProperty().add(OFFSET_Y));
56+
57+
rT.xProperty().bind(pT.xProperty().add(rightOffsetX));
58+
rT.yProperty().bind(pT.yProperty().add(OFFSET_Y));
59+
60+
// Bắn liên tục mỗi 0.25s
61+
var shooting = paddle.getComponent(PaddleShooting.class);
62+
var shootingTask = FXGL.getGameTimer().runAtInterval(() -> shooting.execute(null), Duration.seconds(0.25));
63+
64+
// Sau DURATION: dừng bắn và gỡ súng
65+
FXGL.runOnce(() -> {
66+
shootingTask.expire();
67+
lT.xProperty().unbind();
68+
lT.yProperty().unbind();
69+
rT.xProperty().unbind();
70+
rT.yProperty().unbind();
71+
leftGun.removeFromWorld();
72+
rightGun.removeFromWorld();
73+
paddle.removeComponent(PaddleShooting.class);
74+
}, DURATION);
75+
}
76+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.github.codestorm.bounceverse.components.properties.powerup.types.paddle;
2+
3+
import com.github.codestorm.bounceverse.components.behaviors.paddle.MagnetComponent;
4+
import com.github.codestorm.bounceverse.components.properties.powerup.PowerUpManager;
5+
import com.github.codestorm.bounceverse.components.properties.powerup.types.PowerUp;
6+
import com.almasb.fxgl.entity.Entity;
7+
import javafx.util.Duration;
8+
9+
/**
10+
* Power-Up: Paddle có thể "bắt dính" bóng (Magnet effect).
11+
*/
12+
public final class MagnetPowerUp extends PowerUp {
13+
14+
private static final Duration DURATION = Duration.seconds(15);
15+
16+
public MagnetPowerUp() {
17+
super("Magnet");
18+
}
19+
20+
@Override
21+
public void apply(Entity paddle) {
22+
PowerUpManager.getInstance().activate(
23+
name,
24+
DURATION,
25+
() -> paddle.addComponent(new MagnetComponent()),
26+
() -> paddle.removeComponent(MagnetComponent.class));
27+
}
28+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.github.codestorm.bounceverse.components.properties.powerup.types.paddle;
2+
3+
import com.github.codestorm.bounceverse.components.behaviors.paddle.ReverseControlComponent;
4+
import com.github.codestorm.bounceverse.components.properties.powerup.PowerUpManager;
5+
import com.github.codestorm.bounceverse.components.properties.powerup.types.PowerUp;
6+
import com.almasb.fxgl.entity.Entity;
7+
import javafx.util.Duration;
8+
9+
/**
10+
* Power-Up: Đảo ngược điều khiển của paddle trong thời gian ngắn.
11+
*/
12+
public final class ReversePaddlePowerUp extends PowerUp {
13+
14+
private static final Duration DURATION = Duration.seconds(10);
15+
16+
public ReversePaddlePowerUp() {
17+
super("ReversePaddle");
18+
}
19+
20+
@Override
21+
public void apply(Entity paddle) {
22+
PowerUpManager.getInstance().activate(
23+
name,
24+
DURATION,
25+
() -> paddle.addComponent(new ReverseControlComponent()),
26+
() -> paddle.removeComponent(ReverseControlComponent.class)
27+
);
28+
}
29+
}

src/main/java/com/github/codestorm/bounceverse/data/types/PowerUpType.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
public enum PowerUpType {
44
EXPAND_PADDLE,
55
SHRINK_PADDLE,
6+
REVERSE_PADDLE,
67
MULTI_BALL,
78
SLOW_BALL,
89
FAST_BALL,
10+
BIG_BALL,
911
SHIELD,
10-
LASER,
12+
GUN,
1113
MAGNET,
1214
EXTRA_LIFE,
1315
SCORE_BOOST

0 commit comments

Comments
 (0)