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

Commit d8def6d

Browse files
committed
Building!
1 parent 02d3bdb commit d8def6d

31 files changed

+551
-44
lines changed

.idea/icon.svg

+71
Loading

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ Nothing much here yet, huh? What will this be? Well, it is heading towards being
66
- WASD: Fly around
77
- Move mouse: Look around
88
- Space: Jump
9+
- 1-9: Select block
10+
- Left click: Place block
11+
- Right click: Break block
912
- Q: No-clip
1013
- R: Teleport to a random position
1114
- F: Halve fog distance

TODO.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ Key:
1414

1515
## Gameplay
1616
- [x] Player entity with physics
17-
- [ ] Block building and destruction
18-
- [ ] 🤔 Block ID flattening? It takes up more memory, but it should not affect performance much.
17+
- [x] Block building and destruction
1918
- [ ] World saving and loading
19+
- [ ] 🤔 Block ID flattening? It takes up more memory, but it should not affect performance much.

client/build.gradle.kts

+1-3
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,6 @@ task("genMetadata") {
5252

5353
fun getaVersion(): String {
5454
var version = providers.gradleProperty("voxelthing.version").get();
55-
if (version == "dev") {
56-
version = "dev ${SimpleDateFormat("yyyyMMdd").format(Date())}"
57-
}
55+
version = version.replace("dev", "dev ${SimpleDateFormat("yyyyMMdd").format(Date())}");
5856
return version;
5957
}

client/src/main/java/io/bluestaggo/voxelthing/Game.java

+41-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
package io.bluestaggo.voxelthing;
22

3+
import io.bluestaggo.voxelthing.gui.GuiScreen;
4+
import io.bluestaggo.voxelthing.gui.IngameGui;
35
import io.bluestaggo.voxelthing.renderer.MainRenderer;
46
import io.bluestaggo.voxelthing.window.ClientPlayerController;
57
import io.bluestaggo.voxelthing.window.Window;
8+
import io.bluestaggo.voxelthing.world.BlockRaycast;
69
import io.bluestaggo.voxelthing.world.ClientWorld;
10+
import io.bluestaggo.voxelthing.world.Direction;
711
import io.bluestaggo.voxelthing.world.World;
812
import io.bluestaggo.voxelthing.world.entity.IPlayerController;
913
import io.bluestaggo.voxelthing.world.entity.Player;
@@ -18,7 +22,8 @@
1822

1923
public class Game {
2024
public static final String VERSION;
21-
public static final float TICK_RATE = 1.0f / 20;
25+
public static final int TICKS_PER_SECOND = 20;
26+
public static final float TICK_RATE = 1.0f / TICKS_PER_SECOND;
2227

2328
static {
2429
String version = "???";
@@ -43,7 +48,7 @@ public class Game {
4348
"floof",
4449
"talon"
4550
};
46-
private int currentSkin;
51+
private int currentSkin = VERSION.contains("dev") ? 1 : 0;
4752
private boolean thirdPerson;
4853
private boolean debugMenu = true;
4954

@@ -56,9 +61,14 @@ public class Game {
5661
public Player player;
5762
public IPlayerController playerController;
5863

64+
private final GuiScreen inGameGui;
65+
66+
private BlockRaycast blockRaycast;
67+
5968
public float mouseSensitivity = 0.25f;
6069

6170
private double tickTime;
71+
private double partialTick;
6272

6373
public Game() {
6474
instance = this;
@@ -73,6 +83,8 @@ public Game() {
7383
world = new ClientWorld(this);
7484
player = new Player(world, playerController);
7585

86+
inGameGui = new IngameGui(this);
87+
7688
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
7789
}
7890

@@ -97,22 +109,39 @@ private void close() {
97109

98110
private void update(double delta) {
99111
tickTime += delta;
112+
113+
inGameGui.handleInput();
100114
player.onGameUpdate();
101115
player.noClip = window.isKeyDown(GLFW_KEY_Q);
102116

103117
if (tickTime >= TICK_RATE) {
104118
tickTime %= TICK_RATE;
119+
inGameGui.tick();
105120
player.tick();
106121
}
107122

108-
world.partialTick = (tickTime % TICK_RATE) / TICK_RATE;
123+
partialTick = tickTime / TICK_RATE;
124+
if (world != null) {
125+
world.partialTick = partialTick;
126+
}
109127
renderer.camera.setPosition((float) player.getPartialX(), (float) (player.getPartialY() + player.height - 0.3), (float) player.getPartialZ());
110128
renderer.camera.setRotation((float) player.rotYaw, (float) player.rotPitch);
111129

112130
if (thirdPerson) {
113131
renderer.camera.moveForward(-4.0f);
114132
}
115133

134+
if (world != null) {
135+
blockRaycast = renderer.camera.getRaycast(5.0f);
136+
if (world.doRaycast(blockRaycast)) {
137+
int x = blockRaycast.getHitX();
138+
int y = blockRaycast.getHitY();
139+
int z = blockRaycast.getHitZ();
140+
int block = world.getBlockId(x, y, z);
141+
Direction face = blockRaycast.getHitFace();
142+
}
143+
}
144+
116145
if (window.isKeyJustPressed(GLFW_KEY_F)) {
117146
int dist = renderer.worldRenderer.renderDistance;
118147
if (window.isKeyDown(GLFW_KEY_LEFT_SHIFT)) {
@@ -163,6 +192,7 @@ private void update(double delta) {
163192

164193
private void draw() {
165194
renderer.draw();
195+
inGameGui.draw();
166196
}
167197

168198
public String getSkin() {
@@ -177,6 +207,14 @@ public boolean showDebug() {
177207
return debugMenu;
178208
}
179209

210+
public double getPartialTick() {
211+
return partialTick;
212+
}
213+
214+
public BlockRaycast getBlockRaycast() {
215+
return blockRaycast;
216+
}
217+
180218
public static void main(String[] args) {
181219
System.setProperty("java.awt.headless", "true");
182220
new Game().run();

client/src/main/java/io/bluestaggo/voxelthing/assets/TextureManager.java

+14-9
Original file line numberDiff line numberDiff line change
@@ -14,33 +14,39 @@ public class TextureManager {
1414
public static final int MAX_TEXTURE_SIZE = 512;
1515

1616
private final Map<String, Texture> textures = new HashMap<>();
17+
private final Map<String, Texture> mipmappedTextures = new HashMap<>();
1718
private final ByteBuffer textureBuffer = MemoryUtil.memAlloc(MAX_TEXTURE_SIZE * MAX_TEXTURE_SIZE * 4);
1819
private boolean useMipmaps = false;
1920

20-
public Texture getTexture(String path) {
21+
private Texture getTextureFromMap(Map<String, Texture> map, String path) {
2122
if (path == null) {
22-
return getTexture("/assets/missing.png");
23+
return getTextureFromMap(map, "/assets/missing.png");
2324
}
2425

2526
if (!textures.containsKey(path)) {
2627
try {
27-
return loadTexture(path);
28+
Texture texture = loadTexture(path);
29+
map.put(path, texture);
30+
return texture;
2831
} catch (IOException e) {
2932
if (path.equals("/assets/missing.png")) {
3033
throw new RuntimeException("Failed to load placeholder texture!");
3134
}
32-
return getTexture("/assets/missing.png");
35+
return getTextureFromMap(map, "/assets/missing.png");
3336
}
3437
}
3538

3639
return textures.get(path);
3740
}
3841

39-
public Texture getWorldTexture(String path) {
40-
useMipmaps = true;
41-
Texture texture = getTexture(path);
42+
public Texture getTexture(String path) {
4243
useMipmaps = false;
43-
return texture;
44+
return getTextureFromMap(textures, path);
45+
}
46+
47+
public Texture getMipmappedTexture(String path) {
48+
useMipmaps = true;
49+
return getTextureFromMap(mipmappedTextures, path);
4450
}
4551

4652
private Texture loadTexture(String path) throws IOException {
@@ -75,7 +81,6 @@ private Texture loadTexture(String path) throws IOException {
7581
? new MipmappedTexture(textureBuffer, width, height)
7682
: new Texture(textureBuffer, width, height);
7783

78-
textures.put(path, texture);
7984
textureBuffer.clear();
8085
return texture;
8186
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package io.bluestaggo.voxelthing.gui;
2+
3+
import io.bluestaggo.voxelthing.Game;
4+
5+
public abstract class GuiScreen {
6+
protected final Game game;
7+
8+
public GuiScreen(Game game) {
9+
this.game = game;
10+
}
11+
12+
public abstract void draw();
13+
14+
public void tick() {
15+
}
16+
17+
public void handleInput() {
18+
for (int key : game.window.getKeysJustPressed()) {
19+
onKeyPressed(key);
20+
}
21+
22+
for (int mouse : game.window.getMouseButtonsJustPressed()) {
23+
onMouseClicked(mouse);
24+
}
25+
}
26+
27+
protected void onKeyPressed(int key) {
28+
}
29+
30+
protected void onMouseClicked(int key) {
31+
}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
package io.bluestaggo.voxelthing.gui;
2+
3+
import io.bluestaggo.voxelthing.Game;
4+
import io.bluestaggo.voxelthing.assets.Texture;
5+
import io.bluestaggo.voxelthing.math.MathUtil;
6+
import io.bluestaggo.voxelthing.renderer.MainRenderer;
7+
import io.bluestaggo.voxelthing.renderer.draw.Quad;
8+
import io.bluestaggo.voxelthing.world.BlockRaycast;
9+
import io.bluestaggo.voxelthing.world.Direction;
10+
import io.bluestaggo.voxelthing.world.block.Block;
11+
import org.joml.Vector2i;
12+
13+
import java.util.ArrayList;
14+
import java.util.List;
15+
16+
import static org.lwjgl.glfw.GLFW.GLFW_KEY_1;
17+
import static org.lwjgl.glfw.GLFW.GLFW_KEY_9;
18+
19+
public class IngameGui extends GuiScreen {
20+
private static final List<Block> blocks = new ArrayList<>();
21+
22+
private int heldIndex = 0;
23+
private int[] prevHoverProgress = new int[9];
24+
private int[] hoverProgress = new int[9];
25+
26+
static {
27+
for (short i = 0; i < 9; i++) {
28+
Block block = Block.fromId(i);
29+
if (block != null) {
30+
blocks.add(block);
31+
}
32+
}
33+
}
34+
35+
public IngameGui(Game game) {
36+
super(game);
37+
}
38+
39+
@Override
40+
protected void onKeyPressed(int key) {
41+
if (key >= GLFW_KEY_1 && key <= GLFW_KEY_9) {
42+
heldIndex = key - GLFW_KEY_1;
43+
}
44+
}
45+
46+
@Override
47+
public void tick() {
48+
for (int i = 0; i < 9; i++) {
49+
int hover = hoverProgress[i];
50+
prevHoverProgress[i] = hover;
51+
52+
if (i == heldIndex) {
53+
hover++;
54+
} else {
55+
hover--;
56+
}
57+
58+
hover = MathUtil.clamp(hover, 0, Game.TICKS_PER_SECOND / 4);
59+
hoverProgress[i] = hover;
60+
}
61+
}
62+
63+
@Override
64+
public void draw() {
65+
MainRenderer r = game.renderer;
66+
67+
Texture hotbarTexture = r.textures.getTexture("/assets/gui/hotbar.png");
68+
Texture blocksTexture = r.textures.getTexture("/assets/blocks.png");
69+
int slotWidth = hotbarTexture.width / 2;
70+
int slotHeight = hotbarTexture.height;
71+
72+
float startX = (r.screen.getWidth() - slotWidth * 9) / 2.0f;
73+
float startY = r.screen.getHeight() - slotHeight - 5;
74+
75+
var hotbarQuad = new Quad()
76+
.at(startX, startY)
77+
.size(slotWidth, slotHeight)
78+
.withTexture(hotbarTexture)
79+
.withUV(0.0f, 0.0f, 0.5f, 1.0f);
80+
var blockQuad = new Quad()
81+
.at(startX + (slotWidth - 16) / 2.0f, startY + (slotHeight - 16) / 2.0f)
82+
.size(16, 16)
83+
.withTexture(blocksTexture);
84+
85+
for (int i = 0; i < 9; i++) {
86+
Block block = i < blocks.size() ? blocks.get(i) : null;
87+
88+
float hover = MathUtil.lerp(prevHoverProgress[i], hoverProgress[i], (float) game.getPartialTick()) / (Game.TICKS_PER_SECOND / 4.0f);
89+
hover = MathUtil.squareOut(hover);
90+
hover *= slotHeight / 4.0f;
91+
92+
hotbarQuad.offset(0, -hover);
93+
blockQuad.offset(0, -hover);
94+
95+
float slotOffset = i == heldIndex ? 0.5f : 0.0f;
96+
r.draw2D.drawQuad(hotbarQuad.withUV(slotOffset, 0.0f, 0.5f + slotOffset, 1.0f));
97+
98+
if (block != null) {
99+
Vector2i texture = block.getTexture().get(Direction.NORTH, null, 0, 0, 0);
100+
101+
float minU = blocksTexture.uCoord(texture.x * 16);
102+
float minV = blocksTexture.vCoord(texture.y * 16);
103+
float maxU = minU + blocksTexture.uCoord(16);
104+
float maxV = minV + blocksTexture.vCoord(16);
105+
106+
r.draw2D.drawQuad(blockQuad.withUV(minU, minV, maxU, maxV));
107+
}
108+
109+
hotbarQuad.offset(slotWidth, hover);
110+
blockQuad.offset(slotWidth, hover);
111+
}
112+
113+
Texture crosshairTexture = r.textures.getTexture("/assets/gui/crosshair.png");
114+
r.draw2D.drawQuad(Quad.shared()
115+
.at((r.screen.getWidth() - crosshairTexture.width) / 2.0f, (r.screen.getHeight() - crosshairTexture.height) / 2.0f)
116+
.withTexture(crosshairTexture));
117+
}
118+
119+
private Block getPlacedBlock() {
120+
if (heldIndex < 0 || heldIndex >= blocks.size()) {
121+
return null;
122+
}
123+
return blocks.get(heldIndex);
124+
}
125+
126+
@Override
127+
protected void onMouseClicked(int button) {
128+
BlockRaycast raycast = game.getBlockRaycast();
129+
if (raycast.blockHit()) {
130+
int x = raycast.getHitX();
131+
int y = raycast.getHitY();
132+
int z = raycast.getHitZ();
133+
Direction face = raycast.getHitFace();
134+
135+
if (button == 0) {
136+
game.world.setBlockId(x, y, z, (short) 0);
137+
} else if (button == 1) {
138+
Block placedBlock = getPlacedBlock();
139+
if (placedBlock != null) {
140+
game.world.setBlock(x + face.X, y + face.Y, z + face.Z, placedBlock);
141+
}
142+
}
143+
}
144+
}
145+
}

client/src/main/java/io/bluestaggo/voxelthing/renderer/MainRenderer.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ private void render3D() {
112112
worldRenderer.drawSky();
113113

114114
setupWorldShader(viewProj);
115-
textures.getWorldTexture("/assets/blocks.png").use();
115+
textures.getMipmappedTexture("/assets/blocks.png").use();
116116
useSkyTexture(1);
117117
worldRenderer.draw();
118118

0 commit comments

Comments
 (0)