summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSomhairle H. Marisol <[email protected]>2026-09-21 14:34:48 +0800
committerSomhairle H. Marisol <[email protected]>2026-09-21 14:34:48 +0800
commit60fe11875a06d3d883ec82db08bd97b0e8999862 (patch)
treecea5e3463a27454ba581749f42522ddee79ce985
parent2c1127e1522dca89c6710dda0b5e64d8ab89686d (diff)
downloadliving-village-60fe11875a06d3d883ec82db08bd97b0e8999862.tar.gz
feat(desktop): LV_ASSET_PACK=cc0 素材渲染路径
VillageArt 支持 CC0 素材包切换(环境变量 LV_ASSET_PACK=cc0):Kenney 地块替代草地(棋盘双绿)/石径纹理,Puny 角色图集(与江南人物同 cell 几何)替换五变体角色;水面/屋檐/桥/灯笼/竹丛等江南图块保留并存于同一场景,江南图集仍作为水与建筑纹理源;未设环境变量时行为与既有路径一致(全部既有测试不变)。
-rw-r--r--src/LivingVillage.Desktop/VillageArt.fs50
1 files changed, 41 insertions, 9 deletions
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