Skip to content

Commit

Permalink
Basic physics; debug info
Browse files Browse the repository at this point in the history
  • Loading branch information
squid233 committed Apr 1, 2023
1 parent 7429893 commit a6dedf8
Show file tree
Hide file tree
Showing 22 changed files with 685 additions and 79 deletions.
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

[{*.yml, *.json}]
[{*.yml,*.json}]
indent_size = 2
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Recx

Recx /rekts/ is a 2D sandbox game.
12 changes: 12 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,18 @@ tasks.withType(JavaCompile).configureEach {
}
}

processResources {
def prop = [
"version" : projVersion,
"isSnapshot": projVersion.endsWith("-SNAPSHOT")
]
inputs.properties(prop)

filesMatching("version.json") {
expand(prop)
}
}

java {
def javaVersion = JavaVersion.toVersion(targetJavaVersion)
if (JavaVersion.current() < javaVersion) {
Expand Down
68 changes: 68 additions & 0 deletions src/main/java/recx/client/GameVersion.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* MIT License
*
* Copyright (c) 2023 XenFork Union
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*/

package recx.client;

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import recx.util.FileUtil;
import recx.util.JsonHelper;

import java.io.IOException;

/**
* @author squid233
* @since 0.1.0
*/
public final class GameVersion {
private static GameVersion instance;
private final String version;
private final boolean isSnapshot;

private GameVersion(String version, boolean isSnapshot) {
this.version = version;
this.isSnapshot = isSnapshot;
}

public static GameVersion getInstance() {
if (instance == null) {
instance = load();
}
return instance;
}

private static GameVersion load() {
try {
final JsonObject object = JsonParser.parseString(FileUtil.readString("version.json")).getAsJsonObject();
return new GameVersion(
JsonHelper.getString(object, "version"),
Boolean.parseBoolean(JsonHelper.getString(object, "isSnapshot"))
);
} catch (IOException e) {
// todo: log
e.printStackTrace();
return new GameVersion("Version Unknown", true);
}
}

public String version() {
return version;
}

public boolean isSnapshot() {
return isSnapshot;
}
}
110 changes: 73 additions & 37 deletions src/main/java/recx/client/RecxClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,10 @@
import org.overrun.glib.util.MemoryStack;
import org.overrun.glib.util.value.Value2;
import org.overrun.timer.Timer;
import org.overrun.unifont.UnifontUtil;
import recx.client.font.Font;
import recx.client.gl.GLStateManager;
import recx.client.render.*;
import recx.client.texture.NativeImage;
import recx.client.texture.Texture2D;
import recx.client.texture.TextureAtlas;
import recx.util.Identifier;
import recx.world.HitResult;
Expand All @@ -42,6 +40,7 @@

import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.text.NumberFormat;
import java.util.HashMap;
import java.util.Map;

Expand All @@ -51,13 +50,16 @@
*/
public final class RecxClient implements Runnable, AutoCloseable {
private static final RecxClient INSTANCE = new RecxClient();
private GameVersion version;
private MemorySegment window;
private Keyboard keyboard;
private Mouse mouse;
private int width;
private int height;
private Timer timer;
private int elapsedTicks;
private GameRenderer gameRenderer;
private Font font;
private World world;
private WorldRenderer worldRenderer;
private PlayerEntity player;
Expand All @@ -73,8 +75,9 @@ private void init() {
GLFW.windowHint(GLFW.CONTEXT_VERSION_MINOR, 2);
GLFW.windowHint(GLFW.OPENGL_PROFILE, GLFW.OPENGL_CORE_PROFILE);
GLFW.windowHint(GLFW.OPENGL_FORWARD_COMPAT, true);
version = GameVersion.getInstance();
try (MemoryStack stack = MemoryStack.stackPush()) {
window = GLFW.createWindow(stack, 864, 480, "Recx", MemorySegment.NULL, MemorySegment.NULL);
window = GLFW.createWindow(stack, 864, 480, "Recx " + version.version(), MemorySegment.NULL, MemorySegment.NULL);
}
if (window.address() == RuntimeHelper.NULL) {
throw new IllegalStateException("Failed to create the window");
Expand Down Expand Up @@ -103,15 +106,29 @@ private void init() {
keyboard = new Keyboard(window);
mouse = new Mouse(window);

initGame();

final Value2.OfInt framebufferSize = GLFW.getFramebufferSize(window);
resize(framebufferSize.x(), framebufferSize.y());

GLFW.showWindow(window);

timer = Timer.ofGetter(20.0, GLFW::getTime);
elapsedTicks = 0;
}

private void initGame() {
// init GL
GL.clearColor(.4f, .6f, .9f, 1f);
GLStateManager.enableBlend();
GLStateManager.blendFunc(GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA);

gameRenderer = new GameRenderer();
gameRenderer.init();
font = Font.unifont();
world = new World(256, 256, 2);
worldRenderer = new WorldRenderer(this, world);
player = new PlayerEntity();
player = new PlayerEntity(world);
player.keyboard = keyboard;

// block atlas
Expand All @@ -124,13 +141,6 @@ private void init() {
Identifier.recx("block/stone")
));
RenderSystem.putTexture2D(TextureAtlas.BLOCK, atlas);

final Value2.OfInt framebufferSize = GLFW.getFramebufferSize(window);
resize(framebufferSize.x(), framebufferSize.y());

GLFW.showWindow(window);

timer = Timer.ofGetter(20.0, GLFW::getTime);
}

private static Map<Identifier, NativeImage> images(Identifier... ids) {
Expand All @@ -143,6 +153,8 @@ private static Map<Identifier, NativeImage> images(Identifier... ids) {

private void tick() {
player.tick();

elapsedTicks++;
}

private void update() {
Expand Down Expand Up @@ -208,6 +220,8 @@ private void renderGui(double partialTick) {
);
final Matrix4fStack view = RenderSystem.viewMatrix();
view.identity();

// render selected block
view.pushMatrix();
RenderSystem.setViewMatrix(view
.scaling(16f * 2f)
Expand All @@ -227,36 +241,34 @@ private void renderGui(double partialTick) {

RenderSystem.setProgram(null);

renderDebugHud(partialTick);
}

private void renderDebugHud(double partialTick) {
final Matrix4fStack view = RenderSystem.viewMatrix();
final Tessellator t = Tessellator.getInstance();

RenderSystem.setViewMatrix(view);
RenderSystem.setProgram(gameRenderer.text());
RenderSystem.bindTexture2D(Font.UNIFONT, id -> {
final Texture2D texture = new Texture2D();
try (NativeImage image = NativeImage.load(id.toAssetPath("fonts", Identifier.PNG), NativeImage.Param.grey())) {
texture.load(image);
}
return texture;
});
RenderSystem.setProgram(gameRenderer.renderTypeText());
RenderSystem.bindTexture2D(Font.UNIFONT);

t.begin();
t.color(0xffffffff);
final String text = "Recx";
int x0 = 0;
for (int i = 0, len = text.codePointCount(0, text.length()); i < len; i++) {
final int cp = text.codePointAt(i);
final int w = UnifontUtil.xAdvance(cp);
final float u0 = UnifontUtil.uv(UnifontUtil.xOffset(cp));
final float v0 = UnifontUtil.uv(UnifontUtil.yOffset(cp));
final float u1 = UnifontUtil.uv(UnifontUtil.xOffset(cp) + w);
final float v1 = UnifontUtil.uv(UnifontUtil.yOffset(cp) + UnifontUtil.yAdvance());
final float x1 = x0 + w;
final float y1 = UnifontUtil.yAdvance();
t.indices(0, 1, 2, 2, 3, 0);
t.texCoords(u0, v0).vertex(x0, y1).emit();
t.texCoords(u0, v1).vertex(x0, 0).emit();
t.texCoords(u1, v1).vertex(x1, 0).emit();
t.texCoords(u1, v0).vertex(x1, y1).emit();
x0 += w;
}
// version info
font.drawText(t, 0, height - font.yAdvance(), "Recx " + version.version());
// fps
font.drawText(t, 0, height - font.yAdvance() * 2, timer.framesPerSecond() + " fps");
// positions
font.drawText(t, 0, height - font.yAdvance() * 4, "Pos: " + player.position.toString(NumberFormat.getNumberInstance()));
// todo: can we use string templates?
font.drawText(t,
0,
height - font.yAdvance() * 5,
"Block: (" +
(int) Math.floor(player.position.x()) + ", " +
(int) Math.floor(player.position.y()) + ", " +
(int) Math.floor(player.position.z()) +
")");
t.end();

RenderSystem.bindTexture2D(0);
Expand Down Expand Up @@ -298,6 +310,10 @@ public void close() {
GLFW.terminate();
}

public GameVersion version() {
return version;
}

public MemorySegment window() {
return window;
}
Expand All @@ -322,10 +338,30 @@ public Timer timer() {
return timer;
}

public int elapsedTicks() {
return elapsedTicks;
}

public GameRenderer gameRenderer() {
return gameRenderer;
}

public Font font() {
return font;
}

public World world() {
return world;
}

public WorldRenderer worldRenderer() {
return worldRenderer;
}

public PlayerEntity player() {
return player;
}

public static RecxClient get() {
return INSTANCE;
}
Expand Down
58 changes: 57 additions & 1 deletion src/main/java/recx/client/font/Font.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,68 @@

package recx.client.font;

import recx.client.render.Batch;
import recx.client.render.RenderSystem;
import recx.client.texture.Texture2D;
import recx.util.Identifier;

/**
* @author squid233
* @since 0.1.0
*/
public final class Font {
public abstract class Font {
public static final Identifier UNIFONT = new Identifier("_overrun", "unifont");
private final Identifier identifier;
private final Texture2D texture;

protected Font(Identifier identifier, Texture2D texture) {
this.identifier = identifier;
this.texture = texture;
RenderSystem.putTexture2D(identifier, texture);
}

public static Font unifont() {
return Unifont.getInstance();
}

public void drawText(Batch batch, float x, float y, String text) {
float x0 = x;
for (int i = 0, c = text.codePointCount(0, text.length()); i < c; i++) {
final int cp = text.codePointAt(i);
final int w = xAdvance(cp);
final int h = yAdvance();
final int xo = xOffset(cp);
final int yo = yOffset(cp);
final float u0 = uv(xo);
final float v0 = uv(yo);
final float u1 = uv(xo + w);
final float v1 = uv(yo + h);
final float x1 = x0 + w;
final float y1 = y + h;
batch.indices(0, 1, 2, 2, 3, 0);
batch.texCoords(u0, v0).vertex(x0, y1).emit();
batch.texCoords(u0, v1).vertex(x0, y).emit();
batch.texCoords(u1, v1).vertex(x1, y).emit();
batch.texCoords(u1, v0).vertex(x1, y1).emit();
x0 += w;
}
}

public abstract int xAdvance(int codePoint);

public abstract int yAdvance();

public abstract int xOffset(int codePoint);

public abstract int yOffset(int codePoint);

public abstract float uv(int offset);

public Identifier identifier() {
return identifier;
}

public Texture2D texture() {
return texture;
}
}
Loading

0 comments on commit a6dedf8

Please sign in to comment.