diff --git a/Assets/Resources/Art/Arena.meta b/Assets/Resources/Art/Arena.meta new file mode 100644 index 0000000..f53ee0c --- /dev/null +++ b/Assets/Resources/Art/Arena.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3cf8146ec3d9b7d0e53f395457eadeb9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/Art/Arena/arena_plain.png b/Assets/Resources/Art/Arena/arena_plain.png new file mode 100644 index 0000000..1638a70 Binary files /dev/null and b/Assets/Resources/Art/Arena/arena_plain.png differ diff --git a/Assets/Resources/Art/Arena/arena_plain.png.meta b/Assets/Resources/Art/Arena/arena_plain.png.meta new file mode 100644 index 0000000..f20cc7c --- /dev/null +++ b/Assets/Resources/Art/Arena/arena_plain.png.meta @@ -0,0 +1,168 @@ +fileFormatVersion: 2 +guid: 1d15c6a489ed8877216a139136f60a82 +TextureImporter: + internalIDToNameTable: + - first: + 213: -3409068656351109566 + second: px_101_0 + externalObjects: {} + serializedVersion: 13 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 1 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 0 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 0 + alignment: 7 + spritePivot: {x: 0.5, y: 0} + spritePixelsToUnits: 32 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 0 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 4 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: iOS + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: + - serializedVersion: 2 + name: px_101_0 + rect: + serializedVersion: 2 + x: 0 + y: 0 + width: 48 + height: 48 + alignment: 0 + pivot: {x: 0, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + customData: + outline: [] + physicsShape: [] + tessellationDetail: -1 + bones: [] + spriteID: 24e164b7e1e80b0d0800000000000000 + internalID: -3409068656351109566 + vertices: [] + indices: + edges: [] + weights: [] + outline: [] + customData: + physicsShape: [] + bones: [] + spriteID: 363893c8d7ed4824a70320dae0b90fa6 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spriteCustomMetadata: + entries: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/Art/Arena/arena_river.png b/Assets/Resources/Art/Arena/arena_river.png new file mode 100644 index 0000000..9595021 Binary files /dev/null and b/Assets/Resources/Art/Arena/arena_river.png differ diff --git a/Assets/Resources/Art/Arena/arena_river.png.meta b/Assets/Resources/Art/Arena/arena_river.png.meta new file mode 100644 index 0000000..e76b9ab --- /dev/null +++ b/Assets/Resources/Art/Arena/arena_river.png.meta @@ -0,0 +1,168 @@ +fileFormatVersion: 2 +guid: 12f19f7d340d8528733eb80f6ad981d3 +TextureImporter: + internalIDToNameTable: + - first: + 213: -3409068656351109566 + second: px_101_0 + externalObjects: {} + serializedVersion: 13 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 1 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 0 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 0 + alignment: 7 + spritePivot: {x: 0.5, y: 0} + spritePixelsToUnits: 32 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 0 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 4 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: iOS + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: + - serializedVersion: 2 + name: px_101_0 + rect: + serializedVersion: 2 + x: 0 + y: 0 + width: 48 + height: 48 + alignment: 0 + pivot: {x: 0, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + customData: + outline: [] + physicsShape: [] + tessellationDetail: -1 + bones: [] + spriteID: 24e164b7e1e80b0d0800000000000000 + internalID: -3409068656351109566 + vertices: [] + indices: + edges: [] + weights: [] + outline: [] + customData: + physicsShape: [] + bones: [] + spriteID: 363893c8d7ed4824a70320dae0b90fa6 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spriteCustomMetadata: + entries: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/View/GameApp.Battle.cs b/Assets/Scripts/View/GameApp.Battle.cs index 2b1a87e..126e822 100644 --- a/Assets/Scripts/View/GameApp.Battle.cs +++ b/Assets/Scripts/View/GameApp.Battle.cs @@ -95,20 +95,33 @@ namespace VS.View float ox = c.view.sideTiles * S; int W = Mathf.RoundToInt((c.arenaW + 2f * c.view.sideTiles) * S), H = Mathf.RoundToInt(c.arenaH * S); var r = new Raster(W, H); - Color32 g0 = new Color32(96, 180, 110, 255), g1 = new Color32(88, 170, 102, 255), e0 = new Color32(66, 132, 78, 255), e1 = new Color32(60, 124, 72, 255); - for (int y = 0; y < H; y++) - for (int x = 0; x < W; x++) - { - float tx = (x - ox) / S; - int k = (Mathf.FloorToInt(tx) + (int)(y / S)) & 1; - r.Px[y * W + x] = tx >= 0f && tx < c.arenaW ? (k == 0 ? g0 : g1) : (k == 0 ? e0 : e1); - } - // 맵 가장자리 돌 턱(클래시 로얄 아레나 옆 벽처럼 — 유닛이 못 나가는 곳) - Color curbDk = new Color32(104, 100, 116, 255), curb = new Color32(156, 152, 166, 255); - foreach (float ex in new[] { ox, W - ox }) + // 2026-10-30 그려진 지형(Resources/Art/Arena/arena_{river|plain}.png · 픽셀 도트 · 칸 ≈ 30 px · Krea 2 + k2-pixel32 · 같은 칸 좌표계) + // 이 그림이 있으면 풀밭·측면 장식·돌 턱·강은 그림으로 · 다리·장애물·앞마당·소환 고리는 맵마다 달라 아래 코드로 계속 그린다 · 없으면 예전 코드 그림 + var bgTex = Resources.Load("Art/Arena/" + (m.River ? "arena_river" : "arena_plain")); + if (bgTex != null && bgTex.isReadable) { - r.RRect(ex - S * 0.3f, -4, ex + S * 0.3f, H + 4, 2, curbDk); - r.RRect(ex - S * 0.18f, -4, ex + S * 0.18f, H + 4, 2, curb); + var bp = bgTex.GetPixels32(); int bw = bgTex.width, bh = bgTex.height; + for (int y = 0; y < H; y++) + for (int x = 0; x < W; x++) + r.Px[y * W + x] = bp[Mathf.Min(bh - 1, y * bh / H) * bw + Mathf.Min(bw - 1, x * bw / W)]; + } + else + { + Color32 g0 = new Color32(96, 180, 110, 255), g1 = new Color32(88, 170, 102, 255), e0 = new Color32(66, 132, 78, 255), e1 = new Color32(60, 124, 72, 255); + for (int y = 0; y < H; y++) + for (int x = 0; x < W; x++) + { + float tx = (x - ox) / S; + int k = (Mathf.FloorToInt(tx) + (int)(y / S)) & 1; + r.Px[y * W + x] = tx >= 0f && tx < c.arenaW ? (k == 0 ? g0 : g1) : (k == 0 ? e0 : e1); + } + // 맵 가장자리 돌 턱(클래시 로얄 아레나 옆 벽처럼 — 유닛이 못 나가는 곳) + Color curbDk = new Color32(104, 100, 116, 255), curb = new Color32(156, 152, 166, 255); + foreach (float ex in new[] { ox, W - ox }) + { + r.RRect(ex - S * 0.3f, -4, ex + S * 0.3f, H + 4, 2, curbDk); + r.RRect(ex - S * 0.18f, -4, ex + S * 0.18f, H + 4, 2, curb); + } } // 성 앞마당 · 소환 자리(아래 가운데 — 내 진영은 평지) r.Circle(ox + m.Castle.x * S, m.Castle.y * S, (c.castle.radius + c.castleSeedPad) * S, new Color32(214, 186, 130, 255)); @@ -118,8 +131,11 @@ namespace VS.View if (m.River) { float ry = c.riverY * S, rh = c.riverHalf * S, hw = c.bridgeHalf * S; - r.RRect(-4, ry - rh, W + 4, ry + rh, 4, new Color32(70, 150, 230, 255)); // 강은 맵 밖 장식까지 이어짐 - r.RRect(-4, ry - rh * 0.35f, W + 4, ry + rh * 0.35f, 3, new Color32(110, 190, 250, 255)); + if (bgTex == null) // 그려진 지형에는 강이 이미 있다 · 다리만 코드로 + { + r.RRect(-4, ry - rh, W + 4, ry + rh, 4, new Color32(70, 150, 230, 255)); // 강은 맵 밖 장식까지 이어짐 + r.RRect(-4, ry - rh * 0.35f, W + 4, ry + rh * 0.35f, 3, new Color32(110, 190, 250, 255)); + } foreach (var bx in m.Bridges) { float x = ox + bx * S, step = (2 * rh + S * 0.6f) / 5f;