mirror of
https://github.com/Kapendev/parin.git
synced 2025-04-26 21:19:56 +03:00
Setup is better and small changes.
This commit is contained in:
parent
8f084526e1
commit
ec4e7d2eb0
7 changed files with 141 additions and 122 deletions
|
@ -14,13 +14,11 @@ bool update(float dt) {
|
|||
// Move the camera.
|
||||
cameraTarget += wasd * Vec2(cameraSpeed * dt);
|
||||
camera.followPositionWithSlowdown(cameraTarget, 0.15);
|
||||
|
||||
// Draw the game world.
|
||||
camera.attach();
|
||||
drawDebugText("Move with arrow keys.", Vec2(8));
|
||||
drawRect(camera.area.subAll(3), Color(50, 50, 40, 130));
|
||||
camera.detach();
|
||||
|
||||
// Draw the game UI.
|
||||
drawDebugText("I am UI!", Vec2(8));
|
||||
drawDebugText("+", resolution * Vec2(0.5));
|
||||
|
|
|
@ -24,12 +24,10 @@ bool update(float dt) {
|
|||
mapOptions.scale = Vec2(2);
|
||||
auto tileOptions = mapOptions;
|
||||
tileOptions.flip = tileLookDirection > 0 ? Flip.x : Flip.none;
|
||||
|
||||
// Move the tile and camera.
|
||||
tile.position += wasd * Vec2(tileSpeed * dt);
|
||||
camera.position = tile.position;
|
||||
if (wasd.x != 0) tileLookDirection = cast(int) wasd.normalize.round.x;
|
||||
|
||||
// Check for collisions.
|
||||
auto collisionArea = Rect();
|
||||
foreach (gridPosition; map.gridPositions(camera.area, mapOptions)) {
|
||||
|
|
|
@ -13,8 +13,11 @@ bool update(float dt) {
|
|||
// Resize the viewport when the window is resized.
|
||||
if (isWindowResized) viewport.resize(resolutionWidth / 2, resolutionHeight / 2);
|
||||
// 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();
|
||||
drawVec2(mouseScreenPosition - Rect(resolution * Vec2(0.5), viewport.size).centerArea.position, 24);
|
||||
drawVec2(viewportCenter, 20);
|
||||
drawVec2(viewportMousePosition, 20);
|
||||
viewport.detach();
|
||||
// Draw the viewport and other things inside the window.
|
||||
drawViewport(viewport, resolution * Vec2(0.5), DrawOptions(Hook.center));
|
||||
|
|
|
@ -4,15 +4,40 @@
|
|||
|
||||
import std;
|
||||
|
||||
enum assetsDir = buildPath(".", "assets");
|
||||
enum webDir = buildPath(".", "web");
|
||||
enum assetsDir = buildPath(".", "assets");
|
||||
enum webDir = buildPath(".", "web");
|
||||
enum readmeFile = buildPath(".", "README.md");
|
||||
enum gitignoreFile = buildPath(".", ".gitignore");
|
||||
enum dubFile = buildPath(".", "dub.json");
|
||||
enum dubLockFile = buildPath(".", "dub.selections.json");
|
||||
|
||||
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 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;
|
||||
|
||||
|
@ -86,94 +111,99 @@ enum dubFileContent = `{
|
|||
}
|
||||
`;
|
||||
|
||||
enum gitignoreFileContent = `.dub
|
||||
game
|
||||
web
|
||||
lib*
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
*.a
|
||||
*.lib
|
||||
*.exe
|
||||
*.pdb
|
||||
*.o
|
||||
*.obj
|
||||
*.lst
|
||||
`;
|
||||
/// Creates the assets and web folders inside the current folder.
|
||||
void makeFolders() {
|
||||
if (!exists(assetsDir)) std.file.mkdir(assetsDir);
|
||||
if (!exists(webDir)) std.file.mkdir(webDir);
|
||||
std.file.write(buildPath(assetsDir, ".gitkeep"), "");
|
||||
std.file.write(buildPath(webDir, ".gitkeep"), "");
|
||||
}
|
||||
|
||||
int main(string[] args) {
|
||||
auto isDubProject = exists(dubFile);
|
||||
auto isFirstRun = !exists(assetsDir);
|
||||
auto canDownloadLibs = true;
|
||||
/// Creates the basic project setup of a parin project inside the current folder.
|
||||
void makeBasicSetup() {
|
||||
makeFolders();
|
||||
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.
|
||||
// Also raylib-d:install does not like it when you don't have one.
|
||||
if (isDubProject) {
|
||||
if (!exists(appFile)) std.file.write(appFile, appFileContent);
|
||||
if (!isFirstRun) {
|
||||
std.file.write(dubCopyFile, std.file.readText(dubFile));
|
||||
if (exists(dubLockFile)) std.file.write(dubLockCopyFile, std.file.readText(dubLockFile));
|
||||
}
|
||||
}
|
||||
/// The setup code for simple standalone projects.
|
||||
int runSimpSetup(string[] args, bool isFirstRun) {
|
||||
makeBasicSetup();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// User input stuff.
|
||||
if (isDubProject) {
|
||||
auto arg = (args.length == 2) ? args[1] : "";
|
||||
if (arg.length == 0) {
|
||||
write("Would you like to download the raylib libraries? [Y/n] ");
|
||||
arg = readln().strip();
|
||||
}
|
||||
canDownloadLibs = arg != "N" && arg != "n";
|
||||
}
|
||||
|
||||
// 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();
|
||||
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();
|
||||
if (dub2 != 0) {
|
||||
if (!isFirstRun) {
|
||||
std.file.remove(dubCopyFile);
|
||||
if (exists(dubLockCopyFile)) std.file.remove(dubLockCopyFile);
|
||||
}
|
||||
return dub2;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove old files.
|
||||
if (isDubProject) {
|
||||
if (isFirstRun && exists(appFile)) std.file.remove(appFile);
|
||||
if (exists(dubFile)) std.file.remove(dubFile);
|
||||
if (exists(dubLockFile)) std.file.remove(dubLockFile);
|
||||
}
|
||||
/// 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));
|
||||
// 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();
|
||||
|
||||
// Create new files.
|
||||
if (isDubProject) {
|
||||
// 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);
|
||||
}
|
||||
|
||||
// Get a yes or no from the user and download the raylib libraries if the user said yes.
|
||||
auto arg = (args.length != 0) ? args[0] : "?";
|
||||
while (true) {
|
||||
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] ");
|
||||
arg = readln().strip();
|
||||
}
|
||||
whileExit:
|
||||
if (arg == "Y" || arg == "y") {
|
||||
auto dub1 = spawnProcess(["dub", "add", "raylib-d"]).wait();
|
||||
auto dub2 = spawnProcess(["dub", "run", "raylib-d:install"]).wait();
|
||||
// Remove the backup copies if something failed.
|
||||
if (dub1 != 0 || dub2 != 0) {
|
||||
if (exists(dubCopyFile)) std.file.remove(dubCopyFile);
|
||||
if (exists(dubLockCopyFile)) std.file.remove(dubLockCopyFile);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Replace the dub file content if needed.
|
||||
if (isFirstRun) {
|
||||
std.file.write(dubFile, dubFileContent);
|
||||
std.file.remove(dubLockFile);
|
||||
// Remove the backup copies.
|
||||
if (exists(dubCopyFile)) std.file.remove(dubCopyFile);
|
||||
if (exists(dubLockCopyFile)) std.file.remove(dubLockCopyFile);
|
||||
} else {
|
||||
// Replace the "dirty" files with the backup copies.
|
||||
// NOTE: raylib-d will change the content of the dub file and this is considered dirty.
|
||||
if (exists(dubCopyFile)) {
|
||||
std.file.write(dubFile, std.file.readText(dubCopyFile));
|
||||
std.file.remove(dubCopyFile);
|
||||
if (exists(dubLockCopyFile)) std.file.write(dubLockFile, std.file.readText(dubLockCopyFile));
|
||||
if (exists(dubLockCopyFile)) std.file.remove(dubLockCopyFile);
|
||||
} else {
|
||||
std.file.write(dubFile, dubFileContent);
|
||||
}
|
||||
if (exists(dubLockCopyFile)) {
|
||||
std.file.write(dubLockFile, std.file.readText(dubLockCopyFile));
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -883,7 +883,6 @@ struct EngineState {
|
|||
|
||||
LStr assetsPath;
|
||||
LStr tempText;
|
||||
Font debugFont;
|
||||
|
||||
Color borderColor;
|
||||
Filter defaultFilter;
|
||||
|
@ -1236,7 +1235,6 @@ void openWindow(int width, int height, IStr appPath, IStr title = "Parin") {
|
|||
engineState.viewport.color = gray;
|
||||
engineState.fullscreenState.lastWindowWidth = width;
|
||||
engineState.fullscreenState.lastWindowHeight = height;
|
||||
engineState.debugFont = engineFont;
|
||||
engineState.assetsPath.append(pathConcat(appPath.pathDir, "assets"));
|
||||
engineState.tempText.reserve(8192);
|
||||
// NOTE: This line is used for fixing an alpha bug with render textures.
|
||||
|
@ -1469,16 +1467,6 @@ Font engineFont() {
|
|||
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.
|
||||
Filter 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.
|
||||
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.
|
||||
|
|
|
@ -65,8 +65,8 @@ struct Tile {
|
|||
|
||||
struct TileMap {
|
||||
Grid!short data;
|
||||
Sz estimatedMaxRowCount;
|
||||
Sz estimatedMaxColCount;
|
||||
Sz softMaxRowCount;
|
||||
Sz softMaxColCount;
|
||||
int tileWidth = 16;
|
||||
int tileHeight = 16;
|
||||
Vec2 position;
|
||||
|
@ -77,8 +77,8 @@ struct TileMap {
|
|||
this(int tileWidth, int tileHeight, Vec2 position = Vec2()) {
|
||||
this.tileWidth = tileWidth;
|
||||
this.tileHeight = tileHeight;
|
||||
this.estimatedMaxRowCount = maxRowCount;
|
||||
this.estimatedMaxColCount = maxColCount;
|
||||
this.softMaxRowCount = maxRowCount;
|
||||
this.softMaxColCount = maxColCount;
|
||||
this.position = position;
|
||||
this.data.fill(-1);
|
||||
}
|
||||
|
@ -89,11 +89,11 @@ struct TileMap {
|
|||
}
|
||||
|
||||
int width() {
|
||||
return cast(int) (estimatedMaxColCount * tileWidth);
|
||||
return cast(int) (softMaxColCount * tileWidth);
|
||||
}
|
||||
|
||||
int height() {
|
||||
return cast(int) (estimatedMaxRowCount * tileHeight);
|
||||
return cast(int) (softMaxRowCount * tileHeight);
|
||||
}
|
||||
|
||||
/// Returns the size of the tile map.
|
||||
|
@ -110,21 +110,21 @@ struct TileMap {
|
|||
if (csv.length == 0) return Fault.invalid;
|
||||
this.tileWidth = tileWidth;
|
||||
this.tileHeight = tileHeight;
|
||||
this.estimatedMaxRowCount = 0;
|
||||
this.estimatedMaxColCount = 0;
|
||||
this.softMaxRowCount = 0;
|
||||
this.softMaxColCount = 0;
|
||||
this.data.fill(-1);
|
||||
auto view = csv;
|
||||
while (view.length != 0) {
|
||||
estimatedMaxRowCount += 1;
|
||||
estimatedMaxColCount = 0;
|
||||
if (estimatedMaxRowCount > maxRowCount) return Fault.invalid;
|
||||
softMaxRowCount += 1;
|
||||
softMaxColCount = 0;
|
||||
if (softMaxRowCount > maxRowCount) return Fault.invalid;
|
||||
auto line = view.skipLine();
|
||||
while (line.length != 0) {
|
||||
estimatedMaxColCount += 1;
|
||||
if (estimatedMaxColCount > maxColCount) return Fault.invalid;
|
||||
softMaxColCount += 1;
|
||||
if (softMaxColCount > maxColCount) return Fault.invalid;
|
||||
auto tile = line.skipValue(',').toSigned();
|
||||
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;
|
||||
|
@ -162,8 +162,8 @@ struct TileMap {
|
|||
auto result = IVec2();
|
||||
auto targetTileWidth = cast(int) (tileWidth * options.scale.x);
|
||||
auto targetTileHeight = cast(int) (tileHeight * options.scale.y);
|
||||
result.y = cast(int) floor(clamp((topLeftWorldPosition.y - position.y) / targetTileHeight, 0, estimatedMaxRowCount));
|
||||
result.x = cast(int) floor(clamp((topLeftWorldPosition.x - position.x) / targetTileWidth, 0, estimatedMaxColCount));
|
||||
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, softMaxColCount));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -172,8 +172,8 @@ struct TileMap {
|
|||
auto targetTileWidth = cast(int) (tileWidth * options.scale.x);
|
||||
auto targetTileHeight = cast(int) (tileHeight * options.scale.y);
|
||||
auto extraTileCount = options.hook == Hook.topLeft ? 1 : 2;
|
||||
result.y = cast(int) floor(clamp((bottomRightWorldPosition.y - position.y) / targetTileHeight + extraTileCount, 0, estimatedMaxRowCount));
|
||||
result.x = cast(int) floor(clamp((bottomRightWorldPosition.x - position.x) / targetTileWidth + extraTileCount, 0, estimatedMaxColCount));
|
||||
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, softMaxColCount));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
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 output = buildPath(".", "web", "index.html"); // The output file that can be run with emrun.
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue