diff --git a/examples/intro/map.d b/examples/intro/map.d index 0321c89..a1b8ae7 100644 --- a/examples/intro/map.d +++ b/examples/intro/map.d @@ -5,7 +5,7 @@ import parin; auto atlas = TextureId(); auto map = TileMap(); auto camera = Camera(0, 0, true); -auto tile = Tile(16, 16, 145); +auto tile = Tile(16, 145); auto tileFlip = Flip.none; void ready() { @@ -24,15 +24,15 @@ bool update(float dt) { foreach (point; map.gridPoints(camera.area)) { if (map[point] < 0) continue; auto area = Rect(map.toWorldPoint(point), map.tileSize); - while (area.hasIntersection(tile.area)) { + while (area.hasIntersection(Rect(tile.position, tile.size))) { tile.position -= wasd * Vec2(dt); camera.position = tile.position + tile.size * Vec2(0.5f); } } // Draw the world. camera.attach(); - drawTile(atlas, tile, DrawOptions(tileFlip)); drawTileMap(atlas, map, camera); + drawTile(atlas, tile, DrawOptions(tileFlip)); camera.detach(); return false; } diff --git a/packages/mapy/.closed b/packages/mapy/.closed index 539d571..db302ac 100644 --- a/packages/mapy/.closed +++ b/packages/mapy/.closed @@ -3,6 +3,7 @@ [default] -I=../../source -L=-lraylib +-D=-betterC -R=../../assets/parin_atlas.png # Those lines work for me. Use -s=custom to fix any errors. -I=../../../joka/source @@ -11,3 +12,5 @@ [custom] -I=../../source -L=-lraylib +-D=-betterC +-R=../../assets/parin_atlas.png diff --git a/source/parin/engine.d b/source/parin/engine.d index a028665..48fb038 100644 --- a/source/parin/engine.d +++ b/source/parin/engine.d @@ -30,13 +30,14 @@ enum defaultEngineSoundsCapacity = 64; enum defaultEngineFontsCapacity = 16; enum EngineFlag : EngineFlags { - none = 0x0000, - isUpdating = 0x0001, - isUsingAssetsPath = 0x0002, - isPixelSnapped = 0x0004, - isPixelPerfect = 0x0008, - isFullscreen = 0x0010, - isCursorVisible = 0x0020, + none = 0x0000, + isUpdating = 0x0001, + isUsingAssetsPath = 0x0002, + isPixelSnapped = 0x0004, + isPixelPerfect = 0x0008, + isEmptyTextureVisible = 0x0010, + isFullscreen = 0x0020, + isCursorVisible = 0x0040, } /// Flipping orientations. @@ -1319,7 +1320,7 @@ void openWindow(int width, int height, const(IStr)[] args, IStr title = "Parin") // Engine stuff. engineState = cast(EngineState*) jokaMalloc(EngineState.sizeof); jokaMemset(engineState, 0, EngineState.sizeof); - engineState.flags |= EngineFlag.isUsingAssetsPath; + engineState.flags |= EngineFlag.isUsingAssetsPath | EngineFlag.isEmptyTextureVisible; engineState.borderColor = black; engineState.defaultFilter = Filter.init; engineState.defaultWrap = Wrap.init; @@ -1347,21 +1348,13 @@ void openWindow(int width, int height, const(IStr)[] args, IStr title = "Parin") rl.UnloadImage(monogramImage); } -/// Passes C strings to the window arguments. -/// You should avoid calling this function manually. -extern(C) -void openWindowExtraStep(int argc, ICStr* argv) { - engineState.envArgsBuffer.clear(); - foreach (i; 0 .. argc) engineState.envArgsBuffer.append(argv[i].cStrToStr()); - if (engineState.envArgsBuffer.length) engineState.assetsPath.append(pathConcat(engineState.envArgsBuffer[0].pathDirName, "assets")); -} - /// Opens a window with the specified size and title, using C strings. /// You should avoid calling this function manually. extern(C) void openWindowC(int width, int height, int argc, ICStr* argv, ICStr title = "Parin") { openWindow(width, height, null, title.cStrToStr()); - openWindowExtraStep(argc, argv); + foreach (i; 0 .. argc) engineState.envArgsBuffer.append(argv[i].cStrToStr()); + if (engineState.envArgsBuffer.length) engineState.assetsPath.append(pathConcat(engineState.envArgsBuffer[0].pathDirName, "assets")); } /// Use by the `updateWindow` function. @@ -1543,6 +1536,21 @@ void setIsPixelPerfect(bool value) { : engineState.flags & ~EngineFlag.isPixelPerfect; } + +/// Returns true if drawing is done when an empty texture is used. +extern(C) +bool isEmptyTextureVisible() { + return cast(bool) (engineState.flags & EngineFlag.isEmptyTextureVisible); +} + +/// Sets whether drawing should be done when an empty texture is used. +extern(C) +void setIsEmptyTextureVisible(bool value) { + engineState.flags = value + ? engineState.flags | EngineFlag.isEmptyTextureVisible + : engineState.flags & ~EngineFlag.isEmptyTextureVisible; +} + /// Returns true if the application is currently in fullscreen mode. // NOTE: There is a conflict between the flag and real-window-state, which could potentially cause issues for some users. extern(C) @@ -2267,7 +2275,11 @@ void drawLine(Line area, float size, Rgba color = white) { /// Draws a portion of the specified texture at the given position with the specified draw options. extern(C) void drawTextureAreaX(Texture texture, Rect area, Vec2 position, DrawOptions options = DrawOptions()) { - if (texture.isEmpty || area.size.x <= 0.0f || area.size.y <= 0.0f) return; + if (area.size.x <= 0.0f || area.size.y <= 0.0f) return; + if (texture.isEmpty) { + if (isEmptyTextureVisible) drawRect(Rect(position, area.size * options.scale).area(options.hook), red); + return; + } auto target = Rect(position, area.size * options.scale.abs()); auto origin = options.origin.isZero ? target.origin(options.hook) : options.origin; auto flip = options.flip; @@ -2326,6 +2338,11 @@ void drawTexture(TextureId texture, Vec2 position, DrawOptions options = DrawOpt /// Draws a 9-patch texture from the specified texture area at the given target area. extern(C) void drawTexturePatchX(Texture texture, Rect area, Rect target, bool isTiled, DrawOptions options = DrawOptions()) { + if (texture.isEmpty) { + if (isEmptyTextureVisible) drawRect(target.area(options.hook), red); + return; + } + auto tileSize = (area.size / Vec2(3.0f)).floor(); auto hOptions = options; auto vOptions = options; @@ -2598,10 +2615,9 @@ void drawDebugText(IStr text, Vec2 position, DrawOptions options = DrawOptions() mixin template runGame(alias readyFunc, alias updateFunc, alias finishFunc, int width = 960, int height = 540, IStr title = "Parin") { version (D_BetterC) { extern(C) - int main(int argc, immutable(char)** argv) { + int main(int argc, const(char)** argv) { alias f = extern(C) bool function(float dt); - openWindow(width, height, null, title); - openWindowExtraStep(argc, cast(ICStr*) argv); + openWindowC(width, height, argc, argv, title); readyFunc(); updateWindow(cast(f) &updateFunc); finishFunc(); diff --git a/source/parin/map.d b/source/parin/map.d index 67cc204..35033ac 100644 --- a/source/parin/map.d +++ b/source/parin/map.d @@ -18,26 +18,28 @@ import parin.engine; @safe @nogc nothrow: struct Tile { - int width = 16; - int height = 16; - short id; + int widthHeight = 16; Vec2 position; + short id; @safe @nogc nothrow: - this(int width, int height, short id, Vec2 position = Vec2()) { - this.width = width; - this.height = height; + this(int widthHeight, short id, Vec2 position = Vec2()) { + this.widthHeight = widthHeight; this.id = id; this.position = position; } - Vec2 size() { - return Vec2(width, height); + int width() { + return widthHeight; } - Rect area() { - return Rect(position, size); + int height() { + return widthHeight; + } + + Vec2 size() { + return Vec2(widthHeight, widthHeight); } Sz row(Sz colCount) { @@ -49,7 +51,7 @@ struct Tile { } Rect textureArea(Sz colCount) { - return Rect(col(colCount) * width, row(colCount) * height, width, height); + return Rect(col(colCount) * widthHeight, row(colCount) * widthHeight, widthHeight, widthHeight); } /// Moves the tile to follow the target position at the specified speed. @@ -313,7 +315,11 @@ Fault saveTileMap(IStr path, TileMap map) { } void drawTileX(Texture texture, Tile tile, DrawOptions options = DrawOptions()) { - if (texture.isEmpty || tile.id < 0 || tile.width <= 0 || tile.height <= 0) return; + if (tile.id < 0 || tile.width <= 0 || tile.height <= 0) return; + if (texture.isEmpty) { + if (isEmptyTextureVisible) drawRect(Rect(tile.position, tile.size * options.scale).area(options.hook), green); + return; + } drawTextureAreaX(texture, tile.textureArea(texture.width / tile.width), tile.position, options); } @@ -322,7 +328,12 @@ void drawTile(TextureId texture, Tile tile, DrawOptions options = DrawOptions()) } void drawTileMapX(Texture texture, TileMap map, Camera camera, DrawOptions options = DrawOptions()) { - if (texture.isEmpty || map.softRowCount == 0 || map.softColCount == 0 || map.tileWidth <= 0 || map.tileHeight <= 0) return; + if (map.softRowCount == 0 || map.softColCount == 0 || map.tileWidth <= 0 || map.tileHeight <= 0) return; + if (texture.isEmpty) { + if (isEmptyTextureVisible) drawRect(Rect(map.position, map.size * options.scale).area(options.hook), red); + return; + } + auto topLeftWorldPoint = camera.topLeftPoint; auto bottomRightWorldPoint = camera.bottomRightPoint; auto textureColCount = texture.width / map.tileWidth; diff --git a/source/parin/sprite.d b/source/parin/sprite.d index 4359bea..d144b12 100644 --- a/source/parin/sprite.d +++ b/source/parin/sprite.d @@ -147,6 +147,10 @@ struct Sprite { void drawSpriteX(Texture texture, Sprite sprite, DrawOptions options = DrawOptions()) { if (sprite.width == 0 || sprite.height == 0) return; + if (texture.isEmpty) { + if (isEmptyTextureVisible) drawRect(Rect(sprite.position, sprite.size * options.scale).area(options.hook), green); + return; + } auto top = sprite.atlasTop + sprite.animation.frameRow * sprite.height; auto gridWidth = max(texture.width - sprite.atlasLeft, 0) / sprite.width;