From 60fe11875a06d3d883ec82db08bd97b0e8999862 Mon Sep 17 00:00:00 2001 From: "Somhairle H. Marisol" Date: Mon, 21 Sep 2026 14:34:48 +0800 Subject: feat(desktop): LV_ASSET_PACK=cc0 素材渲染路径 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VillageArt 支持 CC0 素材包切换(环境变量 LV_ASSET_PACK=cc0):Kenney 地块替代草地(棋盘双绿)/石径纹理,Puny 角色图集(与江南人物同 cell 几何)替换五变体角色;水面/屋檐/桥/灯笼/竹丛等江南图块保留并存于同一场景,江南图集仍作为水与建筑纹理源;未设环境变量时行为与既有路径一致(全部既有测试不变)。 --- src/LivingVillage.Desktop/VillageArt.fs | 50 +++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/LivingVillage.Desktop/VillageArt.fs b/src/LivingVillage.Desktop/VillageArt.fs index 6f5af07..efed4ee 100644 --- a/src/LivingVillage.Desktop/VillageArt.fs +++ b/src/LivingVillage.Desktop/VillageArt.fs @@ -1,5 +1,6 @@ namespace LivingVillage.Desktop +open System open Microsoft.Xna.Framework.Graphics open LivingVillage.Kernel open LivingVillage.Kernel.Sim @@ -95,7 +96,8 @@ module VillageArt = type ArtTextures = { TileAtlas: Texture2D CharacterAtlas: Texture2D - InteriorAtlas: Texture2D } + InteriorAtlas: Texture2D + Cc0TileAtlas: Texture2D option } type private TileSprite = | GrassSprite @@ -122,6 +124,16 @@ module VillageArt = type private XnaColor = Microsoft.Xna.Framework.Color type private XnaRectangle = Microsoft.Xna.Framework.Rectangle + + /// CC0 pack ground tiles: 0 grass bright / 1 grass deep (checker) / 2 path / 3 dirt. + let private cc0GroundRect (position: TilePosition) : XnaRectangle = + let index = if (position.X + position.Y) % 2 = 1 then 1 else 0 + XnaRectangle(index * Sim.tilePixels, 0, Sim.tilePixels, Sim.tilePixels) + + let private cc0PathRect : XnaRectangle = XnaRectangle(2 * Sim.tilePixels, 0, Sim.tilePixels, Sim.tilePixels) + + let private drawCc0Tile (spriteBatch: SpriteBatch) (cc0: Texture2D) (tint: XnaColor) (source: XnaRectangle) (screenX: int) (screenY: int) = + spriteBatch.Draw(cc0, XnaRectangle(screenX, screenY, Sim.tilePixels, Sim.tilePixels), Nullable(source), tint) type private XnaVector2 = Microsoft.Xna.Framework.Vector2 let private position x y : TilePosition = @@ -347,10 +359,24 @@ module VillageArt = else texture + let useCc0Pack () : bool = + System.Environment.GetEnvironmentVariable("LV_ASSET_PACK") = "cc0" + + let cc0TileAtlasRelativePath = "Assets/cc0-tiles.png" + let cc0TileAtlasWidth = Sim.tilePixels * 4 + let cc0CharacterAtlasRelativePath = "Assets/cc0-characters.png" + let loadTextures (device: GraphicsDevice) : ArtTextures = + let cc0 = + if useCc0Pack () then + Some(loadTexture device cc0TileAtlasRelativePath cc0TileAtlasWidth Sim.tilePixels) + else + None + let characterPath = if useCc0Pack () then cc0CharacterAtlasRelativePath else characterAtlasRelativePath { TileAtlas = loadTexture device worldAtlasRelativePath worldAtlasWidth worldAtlasHeight - CharacterAtlas = loadTexture device characterAtlasRelativePath characterAtlasWidth characterAtlasHeight - InteriorAtlas = loadTexture device interiorAtlasRelativePath interiorAtlasWidth interiorAtlasHeight } + CharacterAtlas = loadTexture device characterPath characterAtlasWidth characterAtlasHeight + InteriorAtlas = loadTexture device interiorAtlasRelativePath interiorAtlasWidth interiorAtlasHeight + Cc0TileAtlas = cc0 } let atlasTileRectangle (index: int) : Microsoft.Xna.Framework.Rectangle = XnaRectangle(index * Sim.tilePixels, 0, Sim.tilePixels, Sim.tilePixels) @@ -422,21 +448,27 @@ module VillageArt = drawWorldTile spriteBatch textures camera viewportWidth viewportHeight position sprite tint let rippleFrame = waterFrameTick tick + let drawBaseTile (position: TilePosition) = + match textures.Cc0TileAtlas with + | Some cc0 -> drawCc0Tile spriteBatch cc0 tint (cc0GroundRect position) (position.X * Sim.tilePixels - int camera.X) (position.Y * Sim.tilePixels - int camera.Y) + | None -> draw position GrassSprite + let tx0 = max 0 (int camera.X / Sim.tilePixels) let ty0 = max 0 (int camera.Y / Sim.tilePixels) let tx1 = min (Sim.mapWidthTiles - 1) ((int camera.X + viewportWidth) / Sim.tilePixels + 1) let ty1 = min (Sim.mapHeightTiles - 1) ((int camera.Y + viewportHeight) / Sim.tilePixels + 1) for y in ty0 .. ty1 do for x in tx0 .. tx1 do - draw (tilePosition x y) GrassSprite + drawBaseTile (tilePosition x y) for localPosition, kind in plan.Grounds do let position = worldTile plan localPosition - let sprite = - match kind with - | Water -> if rippleFrame = 0 then WaterSprite else WaterSpriteB - | StonePath -> StonePathSprite - draw position sprite + match kind with + | Water -> draw position (if rippleFrame = 0 then WaterSprite else WaterSpriteB) + | StonePath -> + match textures.Cc0TileAtlas with + | Some cc0 -> drawCc0Tile spriteBatch cc0 tint cc0PathRect (position.X * Sim.tilePixels - int camera.X) (position.Y * Sim.tilePixels - int camera.Y) + | None -> draw position StonePathSprite let drawHouse doorTile = let position = worldTile plan doorTile -- cgit v1.2.3