Files
novafarma/paint_ldtk_level.py

190 lines
6.7 KiB
Python

import json
import os
PROJECT_ROOT = "/Users/davidkotnik/repos/novafarma"
LDTK_FILE = os.path.join(PROJECT_ROOT, "AutoLayers_2_stamps.ldtk")
def main():
with open(LDTK_FILE, 'r') as f:
data = json.load(f)
# 1. DEFINE ENTITIES (Kai & Cannabis)
# We need to add them to 'defs' -> 'entities'
# Kai (id: Kai_Hoe)
# Cannabis (id: Crop_Cannabis_1)
entities = []
uid_c = 400
# KAI Definition
kai_def = {
"identifier": "Kai_Hoe",
"uid": uid_c,
"width": 256,
"height": 256,
"color": "#FF00FF", # Pink for Kai
"renderMode": "Tile",
"tileRenderMode": "FitInside",
"tileRect": {
"tilesetUid": None, # Will define tileset below if possible, or just color for now to be safe
"x": 0, "y": 0, "w": 256, "h": 256
},
"tilesetId": None,
"tileId": None,
"resizableX": False,
"resizableY": False,
"keepAspectRatio": True,
"fillOpacity": 0.5,
"lineOpacity": 1,
"hollow": False,
"pivotX": 0.5, "pivotY": 1,
"fieldDefs": [], "maxCount": 0, "limitScope": "PerLevel", "limitBehavior": "MoveLastOne"
}
# To connect image to entity, we usually use a tileset defined for entities.
# But let's keep it simple: Just definitions first.
uid_c += 1
# CANNABIS Definition
cannabis_def = {
"identifier": "Crop_Cannabis",
"uid": uid_c,
"width": 32, # Crops are smaller on grid? Or 256 visual? Let's say 32 grid size but visual 256.
"height": 32,
"color": "#00FF00",
"renderMode": "Rectangle", # Simple rectangle for now
"tileRenderMode": "FitInside",
"tileRect": None,
"tilesetId": None, "tileId": None,
"resizableX": False, "resizableY": False, "keepAspectRatio": True,
"fillOpacity": 0.5, "lineOpacity": 1, "hollow": False,
"pivotX": 0.5, "pivotY": 1,
"fieldDefs": [], "maxCount": 0, "limitScope": "PerLevel", "limitBehavior": "MoveLastOne"
}
data['defs']['entities'] = [kai_def, cannabis_def]
# 2. PAINT THE 3x3 FARM (IntGrid)
# 3x3 square in middle of 512x512 map (16x16 grid)
# Middle is roughly x=6,7,8; y=6,7,8
# IntGrid is a 1D CSV array: value 4 (Farm) = Farm
# Grid width = 16
grid_w = 16
grid_h = 16
csv = [0] * (grid_w * grid_h) # Clear all first
# Paint 3x3 Farm
start_x, start_y = 6, 6
for y in range(3):
for x in range(3):
idx = (start_y + y) * grid_w + (start_x + x)
csv[idx] = 4 # 4 = Farmland value defined in IntGrid def
# Update IntGrid Layer Instance
# Find layer with defUid 200 (Terrain_Control)
for level in data['levels']:
for layer in level['layerInstances']:
if layer['__identifier'] == "Terrain_Control":
layer['intGridCsv'] = csv
# 3. PLACE ENTITIES
# Place Cannabis on the 3x3 grid
# Place Kai next to it
entity_instances = []
# 9 Cannabis plants
for y in range(3):
for x in range(3):
# Centered in 32x32 cell
# X pos = (6+x)*32 + 16 (half)
# Y pos = (6+y)*32 + 32 (bottom pivot)
px_x = (start_x + x) * 32 + 16
px_y = (start_y + y) * 32 + 32
inst = {
"__identifier": "Crop_Cannabis",
"__grid": [start_x + x, start_y + y],
"__pivot": [0.5, 1],
"__tags": [],
"__tile": None,
"__smartColor": "#00FF00",
"iid": f"crop_{x}_{y}",
"width": 32, "height": 32,
"defUid": cannabis_def['uid'],
"px": [px_x, px_y],
"fieldInstances": []
}
entity_instances.append(inst)
# Kai standing to the right
# x=10, y=7
kai_pos_x = 10
kai_pos_y = 7
kai_inst = {
"__identifier": "Kai_Hoe",
"__grid": [kai_pos_x, kai_pos_y],
"__pivot": [0.5, 1],
"__tags": [],
"__tile": None,
"__smartColor": "#FF00FF",
"iid": "kai_npc",
"width": 256, "height": 256,
"defUid": kai_def['uid'],
"px": [kai_pos_x * 32 + 16, kai_pos_y * 32 + 32],
"fieldInstances": []
}
entity_instances.append(kai_inst)
# Find Entities Layer Instance (uid 201 was created in first step,
# but wait, do we have an Entities layer instance in the LEVEL?)
# In 'setup_ldtk_atlas', we defined layer defs but maybe didn't add Entity layer instance to level.
# Let's check defs to find Entity Layer Def UID.
entity_layer_def_uid = None
for l_def in data['defs']['layers']:
if l_def['type'] == "Entities" and l_def['identifier'] == "Entities":
entity_layer_def_uid = l_def['uid']
break
# If not found, create one in defs (should be there from first setup, usually 201)
if not entity_layer_def_uid:
# Create Entity Layer Def
entity_layer_def_uid = 201
ent_layer_def = {
"__type": "Entities", "identifier": "Entities", "type": "Entities", "uid": entity_layer_def_uid,
"gridSize": 32, "displayOpacity": 1, "pxOffsetX": 0, "pxOffsetY": 0, "requiredTags": [], "excludedTags": [],
"intGridValues": [], "autoRuleGroups": [], "autoSourceLayerDefUid": None, "tilesetDefUid": None, "tilePivotX": 0, "tilePivotY": 0
}
data['defs']['layers'].append(ent_layer_def)
# Check if Instance exists in Level
found_inst = False
for level in data['levels']:
for layer in level['layerInstances']:
if layer['__identifier'] == "Entities":
layer['entityInstances'] = entity_instances
found_inst = True
if not found_inst:
# Add new layer instance for Entities
new_inst = {
"__identifier": "Entities",
"__type": "Entities",
"__cWid": 16, "__cHei": 16, "__gridSize": 32, "__opacity": 1, "__pxTotalOffsetX": 0, "__pxTotalOffsetY": 0,
"__tilesetDefUid": None, "__tilesetRelPath": None,
"iid": "inst_entities", "levelId": 0, "layerDefUid": entity_layer_def_uid,
"pxOffsetX": 0, "pxOffsetY": 0, "visible": True, "optionalRules": [], "intGridCsv": [], "autoLayerTiles": [], "seed": 0, "overrideTilesetUid": None, "gridTiles": [],
"entityInstances": entity_instances
}
data['levels'][0]['layerInstances'].insert(0, new_inst) # Top layer
with open(LDTK_FILE, 'w') as f:
json.dump(data, f, indent=2)
print("LDtk Level 0 updated: 3x3 Farm, Cannabis, Kai!")
if __name__ == "__main__":
main()