Setup is better and small changes.

This commit is contained in:
Kapendev 2024-11-15 00:52:05 +02:00
parent 8f084526e1
commit ec4e7d2eb0
7 changed files with 141 additions and 122 deletions

View file

@ -14,13 +14,11 @@ bool update(float dt) {
// Move the camera. // Move the camera.
cameraTarget += wasd * Vec2(cameraSpeed * dt); cameraTarget += wasd * Vec2(cameraSpeed * dt);
camera.followPositionWithSlowdown(cameraTarget, 0.15); camera.followPositionWithSlowdown(cameraTarget, 0.15);
// Draw the game world. // Draw the game world.
camera.attach(); camera.attach();
drawDebugText("Move with arrow keys.", Vec2(8)); drawDebugText("Move with arrow keys.", Vec2(8));
drawRect(camera.area.subAll(3), Color(50, 50, 40, 130)); drawRect(camera.area.subAll(3), Color(50, 50, 40, 130));
camera.detach(); camera.detach();
// Draw the game UI. // Draw the game UI.
drawDebugText("I am UI!", Vec2(8)); drawDebugText("I am UI!", Vec2(8));
drawDebugText("+", resolution * Vec2(0.5)); drawDebugText("+", resolution * Vec2(0.5));

View file

@ -24,12 +24,10 @@ bool update(float dt) {
mapOptions.scale = Vec2(2); mapOptions.scale = Vec2(2);
auto tileOptions = mapOptions; auto tileOptions = mapOptions;
tileOptions.flip = tileLookDirection > 0 ? Flip.x : Flip.none; tileOptions.flip = tileLookDirection > 0 ? Flip.x : Flip.none;
// Move the tile and camera. // Move the tile and camera.
tile.position += wasd * Vec2(tileSpeed * dt); tile.position += wasd * Vec2(tileSpeed * dt);
camera.position = tile.position; camera.position = tile.position;
if (wasd.x != 0) tileLookDirection = cast(int) wasd.normalize.round.x; if (wasd.x != 0) tileLookDirection = cast(int) wasd.normalize.round.x;
// Check for collisions. // Check for collisions.
auto collisionArea = Rect(); auto collisionArea = Rect();
foreach (gridPosition; map.gridPositions(camera.area, mapOptions)) { foreach (gridPosition; map.gridPositions(camera.area, mapOptions)) {

View file

@ -13,8 +13,11 @@ bool update(float dt) {
// Resize the viewport when the window is resized. // Resize the viewport when the window is resized.
if (isWindowResized) viewport.resize(resolutionWidth / 2, resolutionHeight / 2); if (isWindowResized) viewport.resize(resolutionWidth / 2, resolutionHeight / 2);
// Draw the mouse position inside the viewport. // Draw the mouse position inside the viewport.
auto viewportCenter = viewport.size * Vec2(0.5);
auto viewportMousePosition = mouseScreenPosition - Rect(resolution * Vec2(0.5), viewport.size).centerArea.position;
viewport.attach(); viewport.attach();
drawVec2(mouseScreenPosition - Rect(resolution * Vec2(0.5), viewport.size).centerArea.position, 24); drawVec2(viewportCenter, 20);
drawVec2(viewportMousePosition, 20);
viewport.detach(); viewport.detach();
// Draw the viewport and other things inside the window. // Draw the viewport and other things inside the window.
drawViewport(viewport, resolution * Vec2(0.5), DrawOptions(Hook.center)); drawViewport(viewport, resolution * Vec2(0.5), DrawOptions(Hook.center));

View file

@ -6,13 +6,38 @@ import std;
enum assetsDir = buildPath(".", "assets"); enum assetsDir = buildPath(".", "assets");
enum webDir = buildPath(".", "web"); enum webDir = buildPath(".", "web");
enum readmeFile = buildPath(".", "README.md");
enum appFile = buildPath(".", "source", "app.d");
enum dubFile = buildPath(".", "dub.json");
enum dubCopyFile = buildPath(".", ".__dub_copy__.json");
enum dubLockFile = buildPath(".", "dub.selections.json");
enum dubLockCopyFile = buildPath(".", ".__dub_selections_copy__.json");
enum gitignoreFile = buildPath(".", ".gitignore"); enum gitignoreFile = buildPath(".", ".gitignore");
enum dubFile = buildPath(".", "dub.json");
enum dubLockFile = buildPath(".", "dub.selections.json");
enum readmeFileContent = "# Game Title
This game was created using [Parin](https://github.com/Kapendev/parin).
To compile the game, run:
```sh
command arg1 arg2 ...
```
";
enum gitignoreFileContent = `.dub
game
lib*
test*
*.wasm
*.so
*.dylib
*.dll
*.a
*.lib
*.exe
*.pdb
*.o
*.obj
*.lst
`;
enum appFileContent = `import parin; enum appFileContent = `import parin;
@ -86,94 +111,99 @@ enum dubFileContent = `{
} }
`; `;
enum gitignoreFileContent = `.dub /// Creates the assets and web folders inside the current folder.
game void makeFolders() {
web if (!exists(assetsDir)) std.file.mkdir(assetsDir);
lib* if (!exists(webDir)) std.file.mkdir(webDir);
*.so std.file.write(buildPath(assetsDir, ".gitkeep"), "");
*.dylib std.file.write(buildPath(webDir, ".gitkeep"), "");
*.dll }
*.a
*.lib
*.exe
*.pdb
*.o
*.obj
*.lst
`;
int main(string[] args) { /// Creates the basic project setup of a parin project inside the current folder.
auto isDubProject = exists(dubFile); void makeBasicSetup() {
auto isFirstRun = !exists(assetsDir); makeFolders();
auto canDownloadLibs = true; if (!exists(readmeFile)) std.file.write(readmeFile, readmeFileContent);
if (!exists(gitignoreFile)) std.file.write(gitignoreFile, gitignoreFileContent);
}
// Sometimes I remove the app.d file and this makes a new one lol. /// The setup code for simple standalone projects.
// Also raylib-d:install does not like it when you don't have one. int runSimpSetup(string[] args, bool isFirstRun) {
if (isDubProject) { makeBasicSetup();
if (!exists(appFile)) std.file.write(appFile, appFileContent); return 0;
if (!isFirstRun) { }
std.file.write(dubCopyFile, std.file.readText(dubFile));
/// The setup code for dub projects.
int runDubSetup(string[] args, bool isFirstRun) {
// Create the backup copies.
auto dubCopyFile = buildPath(".", "._dub_copy");
auto dubLockCopyFile = buildPath(".", "._dub_lock_copy");
if (exists(dubFile)) std.file.write(dubCopyFile, std.file.readText(dubFile));
if (exists(dubLockFile)) std.file.write(dubLockCopyFile, std.file.readText(dubLockFile)); if (exists(dubLockFile)) std.file.write(dubLockCopyFile, std.file.readText(dubLockFile));
} // Create the basic files and folders.
// NOTE: An empty dub project has a gitignore file and we don't want that file.
if (isFirstRun && exists(gitignoreFile)) std.file.remove(gitignoreFile);
makeBasicSetup();
// Find the app file.
auto appDir = buildPath(".", "src");
if (!exists(appDir)) appDir = buildPath(".", "source");
auto appFile = buildPath(appDir, "main.d");
if (!exists(appFile)) appFile = buildPath(appDir, "app.d");
// Replace the app file content if needed.
if (exists(appFile)) {
if (isFirstRun) std.file.write(appFile, appFileContent);
} else {
std.file.write(appFile, appFileContent);
} }
// User input stuff. // Get a yes or no from the user and download the raylib libraries if the user said yes.
if (isDubProject) { auto arg = (args.length != 0) ? args[0] : "?";
auto arg = (args.length == 2) ? args[1] : ""; while (true) {
if (arg.length == 0) { if (arg.length == 0) arg = "Y";
foreach (c; "YyNn") {
if (arg.length != 1) break;
if (arg[0] == c) goto whileExit;
}
write("Would you like to download the raylib libraries? [Y/n] "); write("Would you like to download the raylib libraries? [Y/n] ");
arg = readln().strip(); arg = readln().strip();
} }
canDownloadLibs = arg != "N" && arg != "n"; whileExit:
} if (arg == "Y" || arg == "y") {
// Use the raylib-d script to download the raylib library files.
if (isDubProject && canDownloadLibs) {
writeln("Say \"yes\" to all prompts.\n");
auto dub1 = spawnProcess(["dub", "add", "raylib-d"]).wait(); auto dub1 = spawnProcess(["dub", "add", "raylib-d"]).wait();
if (dub1 != 0) {
if (!isFirstRun) {
std.file.remove(dubCopyFile);
if (exists(dubLockCopyFile)) std.file.remove(dubLockCopyFile);
}
return dub1;
}
auto dub2 = spawnProcess(["dub", "run", "raylib-d:install"]).wait(); auto dub2 = spawnProcess(["dub", "run", "raylib-d:install"]).wait();
if (dub2 != 0) { // Remove the backup copies if something failed.
if (!isFirstRun) { if (dub1 != 0 || dub2 != 0) {
std.file.remove(dubCopyFile); if (exists(dubCopyFile)) std.file.remove(dubCopyFile);
if (exists(dubLockCopyFile)) std.file.remove(dubLockCopyFile); if (exists(dubLockCopyFile)) std.file.remove(dubLockCopyFile);
} return 1;
return dub2;
} }
} }
// Remove old files. // Replace the dub file content if needed.
if (isDubProject) { if (isFirstRun) {
if (isFirstRun && exists(appFile)) std.file.remove(appFile); std.file.write(dubFile, dubFileContent);
if (exists(dubFile)) std.file.remove(dubFile); std.file.remove(dubLockFile);
if (exists(dubLockFile)) std.file.remove(dubLockFile); // Remove the backup copies.
} if (exists(dubCopyFile)) std.file.remove(dubCopyFile);
if (isFirstRun && exists(gitignoreFile)) std.file.remove(gitignoreFile); if (exists(dubLockCopyFile)) std.file.remove(dubLockCopyFile);
} else {
// Create new files. // Replace the "dirty" files with the backup copies.
if (isDubProject) { // NOTE: raylib-d will change the content of the dub file and this is considered dirty.
if (isFirstRun) std.file.write(appFile, appFileContent);
if (exists(dubCopyFile)) { if (exists(dubCopyFile)) {
std.file.write(dubFile, std.file.readText(dubCopyFile)); std.file.write(dubFile, std.file.readText(dubCopyFile));
std.file.remove(dubCopyFile); std.file.remove(dubCopyFile);
if (exists(dubLockCopyFile)) std.file.write(dubLockFile, std.file.readText(dubLockCopyFile)); }
if (exists(dubLockCopyFile)) std.file.remove(dubLockCopyFile); if (exists(dubLockCopyFile)) {
} else { std.file.write(dubLockFile, std.file.readText(dubLockCopyFile));
std.file.write(dubFile, dubFileContent); std.file.remove(dubLockCopyFile);
} }
} }
if (isFirstRun) std.file.write(gitignoreFile, gitignoreFileContent);
// Create folders.
if (!exists(assetsDir)) std.file.mkdir(assetsDir);
if (!exists(webDir)) std.file.mkdir(webDir);
writeln("\nHappy hacking!");
return 0; return 0;
} }
int main(string[] args) {
auto isSimpProject = !exists(dubFile);
auto isFirstRun = !exists(assetsDir);
if (isSimpProject) return runSimpSetup(args[1 .. $], isFirstRun);
else return runDubSetup(args[1 .. $], isFirstRun);
}

View file

@ -883,7 +883,6 @@ struct EngineState {
LStr assetsPath; LStr assetsPath;
LStr tempText; LStr tempText;
Font debugFont;
Color borderColor; Color borderColor;
Filter defaultFilter; Filter defaultFilter;
@ -1236,7 +1235,6 @@ void openWindow(int width, int height, IStr appPath, IStr title = "Parin") {
engineState.viewport.color = gray; engineState.viewport.color = gray;
engineState.fullscreenState.lastWindowWidth = width; engineState.fullscreenState.lastWindowWidth = width;
engineState.fullscreenState.lastWindowHeight = height; engineState.fullscreenState.lastWindowHeight = height;
engineState.debugFont = engineFont;
engineState.assetsPath.append(pathConcat(appPath.pathDir, "assets")); engineState.assetsPath.append(pathConcat(appPath.pathDir, "assets"));
engineState.tempText.reserve(8192); engineState.tempText.reserve(8192);
// NOTE: This line is used for fixing an alpha bug with render textures. // NOTE: This line is used for fixing an alpha bug with render textures.
@ -1469,16 +1467,6 @@ Font engineFont() {
return result; return result;
} }
/// Returns the current debug font. This font should not be freed.
Font debugFont() {
return engineState.debugFont;
}
/// Sets the debug font to the specified value.
void setDebugFont(Font font) {
engineState.debugFont = font;
}
/// Returns the default filter mode for textures. /// Returns the default filter mode for textures.
Filter defaultFilter() { Filter defaultFilter() {
return engineState.defaultFilter; return engineState.defaultFilter;
@ -2109,7 +2097,7 @@ void drawText(FontId font, IStr text, Vec2 position, DrawOptions options = DrawO
/// Draws debug text at the given position with the provided draw options. /// Draws debug text at the given position with the provided draw options.
void drawDebugText(IStr text, Vec2 position, DrawOptions options = DrawOptions()) { void drawDebugText(IStr text, Vec2 position, DrawOptions options = DrawOptions()) {
drawText(engineState.debugFont, text, position, options); drawText(engineFont, text, position, options);
} }
/// Mixes in a game loop template with specified functions for initialization, update, and cleanup, and sets window size and title. /// Mixes in a game loop template with specified functions for initialization, update, and cleanup, and sets window size and title.

View file

@ -65,8 +65,8 @@ struct Tile {
struct TileMap { struct TileMap {
Grid!short data; Grid!short data;
Sz estimatedMaxRowCount; Sz softMaxRowCount;
Sz estimatedMaxColCount; Sz softMaxColCount;
int tileWidth = 16; int tileWidth = 16;
int tileHeight = 16; int tileHeight = 16;
Vec2 position; Vec2 position;
@ -77,8 +77,8 @@ struct TileMap {
this(int tileWidth, int tileHeight, Vec2 position = Vec2()) { this(int tileWidth, int tileHeight, Vec2 position = Vec2()) {
this.tileWidth = tileWidth; this.tileWidth = tileWidth;
this.tileHeight = tileHeight; this.tileHeight = tileHeight;
this.estimatedMaxRowCount = maxRowCount; this.softMaxRowCount = maxRowCount;
this.estimatedMaxColCount = maxColCount; this.softMaxColCount = maxColCount;
this.position = position; this.position = position;
this.data.fill(-1); this.data.fill(-1);
} }
@ -89,11 +89,11 @@ struct TileMap {
} }
int width() { int width() {
return cast(int) (estimatedMaxColCount * tileWidth); return cast(int) (softMaxColCount * tileWidth);
} }
int height() { int height() {
return cast(int) (estimatedMaxRowCount * tileHeight); return cast(int) (softMaxRowCount * tileHeight);
} }
/// Returns the size of the tile map. /// Returns the size of the tile map.
@ -110,21 +110,21 @@ struct TileMap {
if (csv.length == 0) return Fault.invalid; if (csv.length == 0) return Fault.invalid;
this.tileWidth = tileWidth; this.tileWidth = tileWidth;
this.tileHeight = tileHeight; this.tileHeight = tileHeight;
this.estimatedMaxRowCount = 0; this.softMaxRowCount = 0;
this.estimatedMaxColCount = 0; this.softMaxColCount = 0;
this.data.fill(-1); this.data.fill(-1);
auto view = csv; auto view = csv;
while (view.length != 0) { while (view.length != 0) {
estimatedMaxRowCount += 1; softMaxRowCount += 1;
estimatedMaxColCount = 0; softMaxColCount = 0;
if (estimatedMaxRowCount > maxRowCount) return Fault.invalid; if (softMaxRowCount > maxRowCount) return Fault.invalid;
auto line = view.skipLine(); auto line = view.skipLine();
while (line.length != 0) { while (line.length != 0) {
estimatedMaxColCount += 1; softMaxColCount += 1;
if (estimatedMaxColCount > maxColCount) return Fault.invalid; if (softMaxColCount > maxColCount) return Fault.invalid;
auto tile = line.skipValue(',').toSigned(); auto tile = line.skipValue(',').toSigned();
if (tile.isNone) return Fault.invalid; if (tile.isNone) return Fault.invalid;
data[estimatedMaxRowCount - 1, estimatedMaxColCount - 1] = cast(short) tile.get(); data[softMaxRowCount - 1, softMaxColCount - 1] = cast(short) tile.get();
} }
} }
return Fault.none; return Fault.none;
@ -162,8 +162,8 @@ struct TileMap {
auto result = IVec2(); auto result = IVec2();
auto targetTileWidth = cast(int) (tileWidth * options.scale.x); auto targetTileWidth = cast(int) (tileWidth * options.scale.x);
auto targetTileHeight = cast(int) (tileHeight * options.scale.y); auto targetTileHeight = cast(int) (tileHeight * options.scale.y);
result.y = cast(int) floor(clamp((topLeftWorldPosition.y - position.y) / targetTileHeight, 0, estimatedMaxRowCount)); result.y = cast(int) floor(clamp((topLeftWorldPosition.y - position.y) / targetTileHeight, 0, softMaxRowCount));
result.x = cast(int) floor(clamp((topLeftWorldPosition.x - position.x) / targetTileWidth, 0, estimatedMaxColCount)); result.x = cast(int) floor(clamp((topLeftWorldPosition.x - position.x) / targetTileWidth, 0, softMaxColCount));
return result; return result;
} }
@ -172,8 +172,8 @@ struct TileMap {
auto targetTileWidth = cast(int) (tileWidth * options.scale.x); auto targetTileWidth = cast(int) (tileWidth * options.scale.x);
auto targetTileHeight = cast(int) (tileHeight * options.scale.y); auto targetTileHeight = cast(int) (tileHeight * options.scale.y);
auto extraTileCount = options.hook == Hook.topLeft ? 1 : 2; auto extraTileCount = options.hook == Hook.topLeft ? 1 : 2;
result.y = cast(int) floor(clamp((bottomRightWorldPosition.y - position.y) / targetTileHeight + extraTileCount, 0, estimatedMaxRowCount)); result.y = cast(int) floor(clamp((bottomRightWorldPosition.y - position.y) / targetTileHeight + extraTileCount, 0, softMaxRowCount));
result.x = cast(int) floor(clamp((bottomRightWorldPosition.x - position.x) / targetTileWidth + extraTileCount, 0, estimatedMaxColCount)); result.x = cast(int) floor(clamp((bottomRightWorldPosition.x - position.x) / targetTileWidth + extraTileCount, 0, softMaxColCount));
return result; return result;
} }

View file

@ -4,6 +4,8 @@
import std; import std;
// TODO: Clean it! Well... Not right now, but do it.
enum dflags = ["-betterC", "-i", "--release"]; // The compiler flags passed to ldc. Local dependencies can be added here. enum dflags = ["-betterC", "-i", "--release"]; // The compiler flags passed to ldc. Local dependencies can be added here.
enum output = buildPath(".", "web", "index.html"); // The output file that can be run with emrun. enum output = buildPath(".", "web", "index.html"); // The output file that can be run with emrun.