diff --git a/apps/game/assets/maps/zvenets.map b/apps/game/assets/maps/zvenets.map index ae81305..6e37910 100644 --- a/apps/game/assets/maps/zvenets.map +++ b/apps/game/assets/maps/zvenets.map @@ -1 +1 @@ -{"format":"rpg-map","version":1,"width":56,"height":40,"blocked":[2,3,6,7,24,25,26,27,9,10,18,21,28,29,30,31,32,33],"tall":{"3":{"height":1.5,"ground":0},"6":{"height":2.5,"ground":1},"7":{"height":1.75,"ground":4,"shadow":true},"9":{"height":1,"ground":8},"18":{"height":0.6,"ground":4},"21":{"height":2.5,"ground":8},"22":{"height":1.5,"ground":0},"23":{"height":1.5,"ground":0},"24":{"height":1.75,"ground":4,"shadow":true},"25":{"height":1.75,"ground":4,"shadow":true},"26":{"height":2.5,"ground":4,"shadow":true},"27":{"height":2.5,"ground":4,"shadow":true},"28":{"height":1.05,"ground":4},"29":{"height":1.25,"ground":4},"30":{"height":1.25,"ground":4},"31":{"height":0.75,"ground":4},"32":{"height":1,"ground":4},"33":{"height":1.45,"ground":4}},"variants":{"0":[0,11,12],"1":[1,14],"3":[3,22,23],"4":[4,13],"7":[7,24,25,26,27],"28":[28,30,31],"29":[29,32,33]},"decor":[{"id":16,"x":14,"y":0,"dx":1,"dy":1},{"id":16,"x":23,"y":0,"dx":0,"dy":1},{"id":16,"x":26,"y":0,"dx":3,"dy":1},{"id":16,"x":31,"y":0,"dx":0,"dy":0},{"id":16,"x":37,"y":0,"dx":3,"dy":0},{"id":16,"x":39,"y":0,"dx":3,"dy":2},{"id":16,"x":49,"y":0,"dx":-1,"dy":1},{"id":16,"x":3,"y":1,"dx":1,"dy":0},{"id":16,"x":5,"y":1,"dx":4,"dy":1},{"id":15,"x":13,"y":1,"dx":-1,"dy":-2},{"id":16,"x":39,"y":1,"dx":4,"dy":1},{"id":17,"x":45,"y":1,"dx":0,"dy":0},{"id":16,"x":55,"y":2,"dx":3,"dy":-1},{"id":16,"x":21,"y":3,"dx":1,"dy":-1},{"id":16,"x":27,"y":3,"dx":-2,"dy":-2},{"id":16,"x":34,"y":3,"dx":1,"dy":-2},{"id":16,"x":36,"y":3,"dx":0,"dy":0},{"id":16,"x":3,"y":4,"dx":1,"dy":-1},{"id":16,"x":4,"y":4,"dx":3,"dy":2},{"id":16,"x":11,"y":4,"dx":2,"dy":0},{"id":16,"x":13,"y":4,"dx":2,"dy":1},{"id":16,"x":18,"y":4,"dx":1,"dy":0},{"id":16,"x":51,"y":4,"dx":1,"dy":-1},{"id":16,"x":5,"y":5,"dx":0,"dy":2},{"id":16,"x":19,"y":5,"dx":0,"dy":1},{"id":16,"x":31,"y":5,"dx":-3,"dy":-1},{"id":15,"x":5,"y":6,"dx":4,"dy":0},{"id":16,"x":13,"y":6,"dx":2,"dy":2},{"id":16,"x":18,"y":6,"dx":-3,"dy":-1},{"id":16,"x":24,"y":6,"dx":-2,"dy":2},{"id":16,"x":41,"y":6,"dx":1,"dy":0},{"id":16,"x":48,"y":6,"dx":-2,"dy":1},{"id":15,"x":6,"y":7,"dx":-1,"dy":-1},{"id":16,"x":13,"y":7,"dx":3,"dy":1},{"id":16,"x":20,"y":7,"dx":-4,"dy":2},{"id":16,"x":26,"y":8,"dx":3,"dy":-2},{"id":16,"x":47,"y":8,"dx":3,"dy":-2},{"id":15,"x":9,"y":9,"dx":0,"dy":2},{"id":16,"x":17,"y":10,"dx":3,"dy":2},{"id":16,"x":20,"y":10,"dx":-3,"dy":-2},{"id":16,"x":38,"y":10,"dx":-3,"dy":1},{"id":16,"x":45,"y":10,"dx":0,"dy":-2},{"id":16,"x":12,"y":11,"dx":2,"dy":-1},{"id":16,"x":17,"y":11,"dx":-3,"dy":1},{"id":16,"x":46,"y":11,"dx":0,"dy":1},{"id":15,"x":51,"y":11,"dx":2,"dy":0},{"id":16,"x":8,"y":12,"dx":1,"dy":-1},{"id":16,"x":14,"y":12,"dx":-4,"dy":1},{"id":16,"x":41,"y":12,"dx":3,"dy":2},{"id":16,"x":45,"y":12,"dx":3,"dy":0},{"id":16,"x":0,"y":13,"dx":1,"dy":-2},{"id":16,"x":4,"y":13,"dx":-3,"dy":1},{"id":16,"x":8,"y":13,"dx":3,"dy":-1},{"id":16,"x":42,"y":13,"dx":3,"dy":2},{"id":16,"x":44,"y":13,"dx":0,"dy":2},{"id":16,"x":50,"y":13,"dx":-1,"dy":2},{"id":16,"x":54,"y":13,"dx":-1,"dy":2},{"id":16,"x":49,"y":14,"dx":-3,"dy":2},{"id":16,"x":55,"y":14,"dx":-2,"dy":-2},{"id":16,"x":6,"y":15,"dx":0,"dy":1},{"id":16,"x":8,"y":15,"dx":0,"dy":-1},{"id":16,"x":10,"y":15,"dx":-4,"dy":1},{"id":16,"x":30,"y":15,"dx":-1,"dy":-1},{"id":16,"x":47,"y":15,"dx":3,"dy":-1},{"id":16,"x":51,"y":15,"dx":-1,"dy":-1},{"id":16,"x":6,"y":16,"dx":-1,"dy":2},{"id":16,"x":8,"y":16,"dx":3,"dy":2},{"id":16,"x":11,"y":16,"dx":1,"dy":1},{"id":16,"x":38,"y":16,"dx":2,"dy":1},{"id":16,"x":44,"y":16,"dx":0,"dy":1},{"id":16,"x":47,"y":16,"dx":1,"dy":0},{"id":16,"x":3,"y":17,"dx":2,"dy":1},{"id":16,"x":11,"y":17,"dx":3,"dy":-2},{"id":16,"x":1,"y":18,"dx":2,"dy":-2},{"id":16,"x":14,"y":18,"dx":-2,"dy":-1},{"id":16,"x":48,"y":18,"dx":0,"dy":-1},{"id":16,"x":4,"y":19,"dx":-1,"dy":0},{"id":16,"x":6,"y":19,"dx":3,"dy":-1},{"id":17,"x":9,"y":19,"dx":3,"dy":0},{"id":16,"x":14,"y":19,"dx":-1,"dy":2},{"id":16,"x":54,"y":19,"dx":-1,"dy":2},{"id":16,"x":1,"y":20,"dx":-4,"dy":2},{"id":16,"x":29,"y":20,"dx":1,"dy":1},{"id":16,"x":40,"y":20,"dx":-1,"dy":0},{"id":16,"x":4,"y":21,"dx":-1,"dy":1},{"id":16,"x":8,"y":21,"dx":-1,"dy":-2},{"id":17,"x":16,"y":21,"dx":-4,"dy":1},{"id":16,"x":17,"y":21,"dx":4,"dy":-2},{"id":16,"x":13,"y":22,"dx":2,"dy":-1},{"id":16,"x":52,"y":22,"dx":0,"dy":-2},{"id":16,"x":5,"y":23,"dx":0,"dy":-1},{"id":16,"x":46,"y":23,"dx":1,"dy":-1},{"id":16,"x":55,"y":23,"dx":-3,"dy":1},{"id":16,"x":5,"y":24,"dx":-2,"dy":-1},{"id":16,"x":17,"y":24,"dx":-1,"dy":1},{"id":16,"x":49,"y":24,"dx":4,"dy":-1},{"id":15,"x":3,"y":25,"dx":-2,"dy":-1},{"id":15,"x":10,"y":25,"dx":2,"dy":-2},{"id":16,"x":17,"y":25,"dx":-3,"dy":-2},{"id":15,"x":34,"y":25,"dx":-1,"dy":-1},{"id":16,"x":41,"y":25,"dx":-3,"dy":-1},{"id":16,"x":42,"y":25,"dx":-2,"dy":0},{"id":16,"x":3,"y":26,"dx":2,"dy":0},{"id":17,"x":7,"y":26,"dx":-3,"dy":-1},{"id":16,"x":13,"y":26,"dx":-2,"dy":0},{"id":16,"x":45,"y":26,"dx":-4,"dy":0},{"id":16,"x":51,"y":26,"dx":-2,"dy":0},{"id":16,"x":13,"y":27,"dx":-1,"dy":-1},{"id":16,"x":16,"y":27,"dx":-3,"dy":1},{"id":16,"x":46,"y":27,"dx":3,"dy":-2},{"id":16,"x":53,"y":27,"dx":3,"dy":2},{"id":16,"x":12,"y":28,"dx":2,"dy":1},{"id":17,"x":19,"y":28,"dx":-2,"dy":-2},{"id":16,"x":40,"y":28,"dx":0,"dy":-2},{"id":16,"x":41,"y":28,"dx":2,"dy":1},{"id":15,"x":2,"y":29,"dx":0,"dy":-2},{"id":16,"x":6,"y":29,"dx":-4,"dy":-1},{"id":15,"x":20,"y":29,"dx":-2,"dy":-1},{"id":16,"x":46,"y":29,"dx":0,"dy":1},{"id":16,"x":52,"y":29,"dx":-1,"dy":1},{"id":16,"x":53,"y":29,"dx":-4,"dy":0},{"id":16,"x":54,"y":29,"dx":-3,"dy":1},{"id":16,"x":0,"y":30,"dx":3,"dy":-2},{"id":16,"x":1,"y":30,"dx":2,"dy":-2},{"id":16,"x":25,"y":30,"dx":1,"dy":0},{"id":16,"x":34,"y":30,"dx":-2,"dy":1},{"id":16,"x":36,"y":30,"dx":-2,"dy":1},{"id":16,"x":37,"y":30,"dx":0,"dy":-2},{"id":16,"x":41,"y":30,"dx":4,"dy":-1},{"id":16,"x":48,"y":30,"dx":2,"dy":1},{"id":15,"x":20,"y":31,"dx":2,"dy":1},{"id":16,"x":29,"y":31,"dx":0,"dy":-1},{"id":16,"x":36,"y":31,"dx":-1,"dy":-2},{"id":16,"x":48,"y":31,"dx":1,"dy":1},{"id":16,"x":49,"y":31,"dx":3,"dy":-1},{"id":16,"x":32,"y":32,"dx":0,"dy":0},{"id":16,"x":37,"y":32,"dx":-2,"dy":2},{"id":16,"x":41,"y":32,"dx":-1,"dy":-2},{"id":16,"x":52,"y":32,"dx":-1,"dy":-2},{"id":16,"x":54,"y":32,"dx":3,"dy":1},{"id":16,"x":7,"y":33,"dx":1,"dy":1},{"id":16,"x":10,"y":33,"dx":-1,"dy":0},{"id":16,"x":48,"y":33,"dx":-2,"dy":1},{"id":15,"x":0,"y":34,"dx":4,"dy":-1},{"id":16,"x":12,"y":34,"dx":0,"dy":-1},{"id":16,"x":33,"y":34,"dx":2,"dy":-2},{"id":16,"x":38,"y":34,"dx":3,"dy":1},{"id":16,"x":53,"y":34,"dx":0,"dy":-1},{"id":15,"x":20,"y":35,"dx":-1,"dy":1},{"id":16,"x":35,"y":35,"dx":2,"dy":-2},{"id":16,"x":39,"y":35,"dx":-2,"dy":1},{"id":16,"x":47,"y":35,"dx":-3,"dy":-1},{"id":16,"x":55,"y":35,"dx":-2,"dy":-2},{"id":16,"x":11,"y":36,"dx":1,"dy":-1},{"id":16,"x":14,"y":36,"dx":-2,"dy":0},{"id":16,"x":26,"y":36,"dx":0,"dy":2},{"id":16,"x":39,"y":36,"dx":0,"dy":0},{"id":16,"x":42,"y":36,"dx":0,"dy":-2},{"id":16,"x":45,"y":36,"dx":2,"dy":-1},{"id":16,"x":4,"y":37,"dx":-3,"dy":1},{"id":16,"x":10,"y":37,"dx":3,"dy":1},{"id":16,"x":15,"y":37,"dx":-3,"dy":1},{"id":16,"x":34,"y":37,"dx":0,"dy":-2},{"id":16,"x":47,"y":37,"dx":1,"dy":1},{"id":16,"x":49,"y":37,"dx":-2,"dy":1},{"id":16,"x":53,"y":37,"dx":3,"dy":-1},{"id":16,"x":55,"y":37,"dx":-1,"dy":0},{"id":16,"x":6,"y":38,"dx":-3,"dy":2},{"id":16,"x":7,"y":38,"dx":0,"dy":2},{"id":16,"x":38,"y":38,"dx":-3,"dy":-2},{"id":16,"x":41,"y":38,"dx":-1,"dy":-1},{"id":16,"x":45,"y":38,"dx":2,"dy":0},{"id":16,"x":7,"y":39,"dx":2,"dy":1},{"id":16,"x":16,"y":39,"dx":2,"dy":0},{"id":16,"x":19,"y":39,"dx":-3,"dy":0},{"id":16,"x":22,"y":39,"dx":0,"dy":0},{"id":16,"x":26,"y":39,"dx":2,"dy":-1},{"id":16,"x":38,"y":39,"dx":-4,"dy":-1},{"id":16,"x":43,"y":39,"dx":-2,"dy":-2},{"id":16,"x":44,"y":39,"dx":-3,"dy":-2},{"id":16,"x":46,"y":39,"dx":1,"dy":0},{"id":16,"x":52,"y":39,"dx":-1,"dy":1}],"encoding":"rle","tiles":[[4,10],[0,4],[4,5],[0,1],[4,12],[0,2],[4,11],[0,3],[4,17],[0,1],[4,3],[0,1],[4,4],[0,2],[4,10],[0,4],[4,11],[0,3],[4,4],[3,2],[4,7],[3,1],[4,3],[0,1],[4,8],[0,3],[4,10],[0,1],[4,10],[0,2],[4,1],[0,3],[4,18],[0,4],[4,16],[0,1],[4,12],[0,2],[4,11],[3,1],[4,41],[0,4],[4,12],[3,1],[0,1],[4,2],[0,5],[4,33],[0,2],[4,9],[3,1],[0,1],[4,1],[0,7],[4,34],[0,2],[4,1],[0,1],[4,7],[3,1],[4,1],[0,1],[4,4],[3,1],[0,3],[4,1],[0,1],[4,8],[29,1],[4,34],[3,1],[4,1],[0,2],[4,3],[0,5],[4,39],[0,1],[4,2],[0,2],[4,2],[0,1],[4,1],[3,1],[4,1],[3,1],[0,6],[4,39],[0,4],[4,6],[3,1],[0,1],[4,1],[0,2],[4,3],[0,1],[4,19],[0,1],[4,4],[27,1],[4,11],[0,4],[3,1],[4,8],[28,1],[4,3],[0,2],[4,19],[0,3],[4,15],[0,5],[4,6],[3,1],[4,5],[0,1],[4,1],[0,1],[7,1],[4,1],[0,3],[1,7],[4,1],[1,13],[4,10],[0,5],[3,1],[4,16],[0,1],[10,1],[0,1],[1,11],[4,1],[1,5],[4,1],[1,4],[4,9],[0,1],[4,1],[0,1],[4,1],[0,1],[4,6],[3,2],[4,9],[0,2],[4,1],[1,1],[0,1],[1,8],[6,1],[1,11],[4,10],[0,1],[4,1],[0,1],[4,17],[0,3],[4,1],[1,5],[4,1],[1,6],[4,1],[1,8],[4,1],[0,2],[4,28],[0,2],[4,1],[0,1],[1,3],[4,1],[1,16],[4,1],[1,1],[4,1],[0,3],[4,8],[3,1],[4,1],[3,1],[4,16],[0,3],[1,3],[4,1],[1,18],[0,1],[4,1],[0,1],[4,8],[3,2],[4,5],[3,1],[4,5],[0,4],[4,3],[0,2],[4,1],[1,22],[4,1],[0,3],[4,15],[3,1],[4,1],[3,1],[4,2],[0,2],[4,8],[1,5],[4,1],[1,16],[0,3],[26,1],[4,14],[1,21],[4,1],[1,4],[0,1],[4,1],[1,10],[4,11],[3,1],[4,1],[1,2],[4,10],[0,2],[4,5],[0,1],[4,1],[1,22],[4,3],[29,1],[4,12],[0,2],[4,2],[3,1],[4,3],[0,1],[4,2],[0,1],[4,6],[0,1],[1,12],[4,1],[1,2],[4,2],[1,4],[4,11],[3,1],[4,4],[0,2],[4,4],[0,1],[4,2],[0,1],[4,8],[1,12],[4,1],[1,1],[4,1],[1,7],[4,8],[0,3],[4,1],[0,3],[4,1],[0,2],[3,1],[4,4],[0,2],[4,9],[1,8],[4,1],[1,9],[4,1],[1,3],[4,10],[0,1],[3,1],[4,1],[3,1],[0,2],[4,1],[0,1],[4,1],[0,2],[3,1],[0,1],[4,3],[0,1],[4,7],[1,4],[4,1],[1,9],[0,1],[1,1],[0,1],[1,5],[4,8],[0,1],[4,1],[0,1],[3,2],[4,1],[0,1],[3,1],[4,1],[0,1],[3,1],[4,1],[3,1],[4,1],[0,2],[4,1],[0,2],[4,7],[1,16],[4,1],[1,4],[4,9],[0,2],[4,2],[0,2],[4,2],[0,1],[4,1],[0,2],[4,2],[0,1],[4,1],[0,2],[4,8],[0,1],[1,21],[4,9],[0,2],[4,1],[0,1],[4,1],[0,1],[3,1],[0,1],[4,1],[3,1],[0,2],[4,14],[0,4],[24,1],[4,1],[0,1],[4,5],[0,2],[25,1],[4,18],[3,1],[4,3],[0,4],[4,13],[0,1],[4,1],[0,5],[4,7],[0,3],[4,26],[3,1],[4,12],[0,7],[4,7],[0,1],[4,20],[3,1],[4,2],[3,1],[4,2],[3,1],[4,15],[0,1],[4,1],[0,4],[4,2],[0,1],[4,34],[3,1],[4,11],[0,10],[4,24],[3,1],[4,8],[3,1],[4,12],[0,2],[4,2],[0,2],[4,1],[0,1],[4,1],[0,1],[4,11],[29,1],[4,16],[3,1],[0,2],[4,7],[29,1],[4,11],[0,2],[4,1],[0,1],[4,1],[0,1],[4,27],[3,1],[4,1],[0,3],[4,2],[3,1],[4,14],[0,2],[4,1],[0,4],[4,29],[0,3],[4,19],[0,1],[4,34],[3,1],[4,50],[0,1],[4,6],[3,1],[4,9],[28,1],[4,19],[0,2],[4,15],[0,1],[4,1],[0,1],[3,2],[4,4],[3,1],[4,28],[0,3],[4,21]]} \ No newline at end of file +{"format":"rpg-map","version":1,"width":56,"height":40,"blocked":[2,3,6,7,24,25,26,27,9,10,18,21,28,29,30,31,32,33],"tall":{"3":{"height":1.5,"ground":0},"6":{"height":2.5,"ground":1},"7":{"height":1.75,"ground":4,"shadow":true},"9":{"height":1,"ground":8},"18":{"height":0.6,"ground":4},"21":{"height":2.5,"ground":8},"22":{"height":1.5,"ground":0},"23":{"height":1.5,"ground":0},"24":{"height":1.75,"ground":4,"shadow":true},"25":{"height":1.75,"ground":4,"shadow":true},"26":{"height":2.5,"ground":4,"shadow":true},"27":{"height":2.5,"ground":4,"shadow":true},"28":{"height":1.05,"ground":4},"29":{"height":1.25,"ground":4},"30":{"height":1.25,"ground":4},"31":{"height":0.75,"ground":4},"32":{"height":1,"ground":4},"33":{"height":1.45,"ground":4}},"props":[{"id":34,"x":46,"y":24,"w":2,"h":2,"ground":4}],"variants":{"0":[0,11,12],"1":[1,14],"3":[3,22,23],"4":[4,13],"7":[7,24,25,26,27],"28":[28,30,31],"29":[29,32,33]},"decor":[{"id":16,"x":14,"y":0,"dx":1,"dy":1},{"id":16,"x":23,"y":0,"dx":0,"dy":1},{"id":16,"x":26,"y":0,"dx":3,"dy":1},{"id":16,"x":31,"y":0,"dx":0,"dy":0},{"id":16,"x":37,"y":0,"dx":3,"dy":0},{"id":16,"x":39,"y":0,"dx":3,"dy":2},{"id":16,"x":49,"y":0,"dx":-1,"dy":1},{"id":16,"x":3,"y":1,"dx":1,"dy":0},{"id":16,"x":5,"y":1,"dx":4,"dy":1},{"id":15,"x":13,"y":1,"dx":-1,"dy":-2},{"id":16,"x":39,"y":1,"dx":4,"dy":1},{"id":17,"x":45,"y":1,"dx":0,"dy":0},{"id":16,"x":55,"y":2,"dx":3,"dy":-1},{"id":16,"x":21,"y":3,"dx":1,"dy":-1},{"id":16,"x":27,"y":3,"dx":-2,"dy":-2},{"id":16,"x":34,"y":3,"dx":1,"dy":-2},{"id":16,"x":36,"y":3,"dx":0,"dy":0},{"id":16,"x":3,"y":4,"dx":1,"dy":-1},{"id":16,"x":4,"y":4,"dx":3,"dy":2},{"id":16,"x":11,"y":4,"dx":2,"dy":0},{"id":16,"x":13,"y":4,"dx":2,"dy":1},{"id":16,"x":18,"y":4,"dx":1,"dy":0},{"id":16,"x":51,"y":4,"dx":1,"dy":-1},{"id":16,"x":5,"y":5,"dx":0,"dy":2},{"id":16,"x":19,"y":5,"dx":0,"dy":1},{"id":16,"x":31,"y":5,"dx":-3,"dy":-1},{"id":15,"x":5,"y":6,"dx":4,"dy":0},{"id":16,"x":13,"y":6,"dx":2,"dy":2},{"id":16,"x":18,"y":6,"dx":-3,"dy":-1},{"id":16,"x":24,"y":6,"dx":-2,"dy":2},{"id":16,"x":41,"y":6,"dx":1,"dy":0},{"id":16,"x":48,"y":6,"dx":-2,"dy":1},{"id":15,"x":6,"y":7,"dx":-1,"dy":-1},{"id":16,"x":13,"y":7,"dx":3,"dy":1},{"id":16,"x":20,"y":7,"dx":-4,"dy":2},{"id":16,"x":26,"y":8,"dx":3,"dy":-2},{"id":16,"x":47,"y":8,"dx":3,"dy":-2},{"id":15,"x":9,"y":9,"dx":0,"dy":2},{"id":16,"x":17,"y":10,"dx":3,"dy":2},{"id":16,"x":20,"y":10,"dx":-3,"dy":-2},{"id":16,"x":38,"y":10,"dx":-3,"dy":1},{"id":16,"x":45,"y":10,"dx":0,"dy":-2},{"id":16,"x":12,"y":11,"dx":2,"dy":-1},{"id":16,"x":17,"y":11,"dx":-3,"dy":1},{"id":16,"x":46,"y":11,"dx":0,"dy":1},{"id":15,"x":51,"y":11,"dx":2,"dy":0},{"id":16,"x":8,"y":12,"dx":1,"dy":-1},{"id":16,"x":14,"y":12,"dx":-4,"dy":1},{"id":16,"x":41,"y":12,"dx":3,"dy":2},{"id":16,"x":45,"y":12,"dx":3,"dy":0},{"id":16,"x":0,"y":13,"dx":1,"dy":-2},{"id":16,"x":4,"y":13,"dx":-3,"dy":1},{"id":16,"x":8,"y":13,"dx":3,"dy":-1},{"id":16,"x":42,"y":13,"dx":3,"dy":2},{"id":16,"x":44,"y":13,"dx":0,"dy":2},{"id":16,"x":50,"y":13,"dx":-1,"dy":2},{"id":16,"x":54,"y":13,"dx":-1,"dy":2},{"id":16,"x":49,"y":14,"dx":-3,"dy":2},{"id":16,"x":55,"y":14,"dx":-2,"dy":-2},{"id":16,"x":6,"y":15,"dx":0,"dy":1},{"id":16,"x":8,"y":15,"dx":0,"dy":-1},{"id":16,"x":10,"y":15,"dx":-4,"dy":1},{"id":16,"x":30,"y":15,"dx":-1,"dy":-1},{"id":16,"x":47,"y":15,"dx":3,"dy":-1},{"id":16,"x":51,"y":15,"dx":-1,"dy":-1},{"id":16,"x":6,"y":16,"dx":-1,"dy":2},{"id":16,"x":8,"y":16,"dx":3,"dy":2},{"id":16,"x":11,"y":16,"dx":1,"dy":1},{"id":16,"x":38,"y":16,"dx":2,"dy":1},{"id":16,"x":44,"y":16,"dx":0,"dy":1},{"id":16,"x":47,"y":16,"dx":1,"dy":0},{"id":16,"x":3,"y":17,"dx":2,"dy":1},{"id":16,"x":11,"y":17,"dx":3,"dy":-2},{"id":16,"x":1,"y":18,"dx":2,"dy":-2},{"id":16,"x":14,"y":18,"dx":-2,"dy":-1},{"id":16,"x":48,"y":18,"dx":0,"dy":-1},{"id":16,"x":4,"y":19,"dx":-1,"dy":0},{"id":16,"x":6,"y":19,"dx":3,"dy":-1},{"id":17,"x":9,"y":19,"dx":3,"dy":0},{"id":16,"x":14,"y":19,"dx":-1,"dy":2},{"id":16,"x":54,"y":19,"dx":-1,"dy":2},{"id":16,"x":1,"y":20,"dx":-4,"dy":2},{"id":16,"x":29,"y":20,"dx":1,"dy":1},{"id":16,"x":40,"y":20,"dx":-1,"dy":0},{"id":16,"x":4,"y":21,"dx":-1,"dy":1},{"id":16,"x":8,"y":21,"dx":-1,"dy":-2},{"id":17,"x":16,"y":21,"dx":-4,"dy":1},{"id":16,"x":17,"y":21,"dx":4,"dy":-2},{"id":16,"x":13,"y":22,"dx":2,"dy":-1},{"id":16,"x":52,"y":22,"dx":0,"dy":-2},{"id":16,"x":5,"y":23,"dx":0,"dy":-1},{"id":16,"x":46,"y":23,"dx":1,"dy":-1},{"id":16,"x":55,"y":23,"dx":-3,"dy":1},{"id":16,"x":5,"y":24,"dx":-2,"dy":-1},{"id":16,"x":17,"y":24,"dx":-1,"dy":1},{"id":16,"x":49,"y":24,"dx":4,"dy":-1},{"id":15,"x":3,"y":25,"dx":-2,"dy":-1},{"id":15,"x":10,"y":25,"dx":2,"dy":-2},{"id":16,"x":17,"y":25,"dx":-3,"dy":-2},{"id":15,"x":34,"y":25,"dx":-1,"dy":-1},{"id":16,"x":41,"y":25,"dx":-3,"dy":-1},{"id":16,"x":42,"y":25,"dx":-2,"dy":0},{"id":16,"x":3,"y":26,"dx":2,"dy":0},{"id":17,"x":7,"y":26,"dx":-3,"dy":-1},{"id":16,"x":13,"y":26,"dx":-2,"dy":0},{"id":16,"x":45,"y":26,"dx":-4,"dy":0},{"id":16,"x":51,"y":26,"dx":-2,"dy":0},{"id":16,"x":13,"y":27,"dx":-1,"dy":-1},{"id":16,"x":16,"y":27,"dx":-3,"dy":1},{"id":16,"x":46,"y":27,"dx":3,"dy":-2},{"id":16,"x":53,"y":27,"dx":3,"dy":2},{"id":16,"x":12,"y":28,"dx":2,"dy":1},{"id":17,"x":19,"y":28,"dx":-2,"dy":-2},{"id":16,"x":40,"y":28,"dx":0,"dy":-2},{"id":16,"x":41,"y":28,"dx":2,"dy":1},{"id":15,"x":2,"y":29,"dx":0,"dy":-2},{"id":16,"x":6,"y":29,"dx":-4,"dy":-1},{"id":15,"x":20,"y":29,"dx":-2,"dy":-1},{"id":16,"x":46,"y":29,"dx":0,"dy":1},{"id":16,"x":52,"y":29,"dx":-1,"dy":1},{"id":16,"x":53,"y":29,"dx":-4,"dy":0},{"id":16,"x":54,"y":29,"dx":-3,"dy":1},{"id":16,"x":0,"y":30,"dx":3,"dy":-2},{"id":16,"x":1,"y":30,"dx":2,"dy":-2},{"id":16,"x":25,"y":30,"dx":1,"dy":0},{"id":16,"x":34,"y":30,"dx":-2,"dy":1},{"id":16,"x":36,"y":30,"dx":-2,"dy":1},{"id":16,"x":37,"y":30,"dx":0,"dy":-2},{"id":16,"x":41,"y":30,"dx":4,"dy":-1},{"id":16,"x":48,"y":30,"dx":2,"dy":1},{"id":15,"x":20,"y":31,"dx":2,"dy":1},{"id":16,"x":29,"y":31,"dx":0,"dy":-1},{"id":16,"x":36,"y":31,"dx":-1,"dy":-2},{"id":16,"x":48,"y":31,"dx":1,"dy":1},{"id":16,"x":49,"y":31,"dx":3,"dy":-1},{"id":16,"x":32,"y":32,"dx":0,"dy":0},{"id":16,"x":37,"y":32,"dx":-2,"dy":2},{"id":16,"x":41,"y":32,"dx":-1,"dy":-2},{"id":16,"x":52,"y":32,"dx":-1,"dy":-2},{"id":16,"x":54,"y":32,"dx":3,"dy":1},{"id":16,"x":7,"y":33,"dx":1,"dy":1},{"id":16,"x":10,"y":33,"dx":-1,"dy":0},{"id":16,"x":48,"y":33,"dx":-2,"dy":1},{"id":15,"x":0,"y":34,"dx":4,"dy":-1},{"id":16,"x":12,"y":34,"dx":0,"dy":-1},{"id":16,"x":33,"y":34,"dx":2,"dy":-2},{"id":16,"x":38,"y":34,"dx":3,"dy":1},{"id":16,"x":53,"y":34,"dx":0,"dy":-1},{"id":15,"x":20,"y":35,"dx":-1,"dy":1},{"id":16,"x":35,"y":35,"dx":2,"dy":-2},{"id":16,"x":39,"y":35,"dx":-2,"dy":1},{"id":16,"x":47,"y":35,"dx":-3,"dy":-1},{"id":16,"x":55,"y":35,"dx":-2,"dy":-2},{"id":16,"x":11,"y":36,"dx":1,"dy":-1},{"id":16,"x":14,"y":36,"dx":-2,"dy":0},{"id":16,"x":26,"y":36,"dx":0,"dy":2},{"id":16,"x":39,"y":36,"dx":0,"dy":0},{"id":16,"x":42,"y":36,"dx":0,"dy":-2},{"id":16,"x":45,"y":36,"dx":2,"dy":-1},{"id":16,"x":4,"y":37,"dx":-3,"dy":1},{"id":16,"x":10,"y":37,"dx":3,"dy":1},{"id":16,"x":15,"y":37,"dx":-3,"dy":1},{"id":16,"x":34,"y":37,"dx":0,"dy":-2},{"id":16,"x":47,"y":37,"dx":1,"dy":1},{"id":16,"x":49,"y":37,"dx":-2,"dy":1},{"id":16,"x":53,"y":37,"dx":3,"dy":-1},{"id":16,"x":55,"y":37,"dx":-1,"dy":0},{"id":16,"x":6,"y":38,"dx":-3,"dy":2},{"id":16,"x":7,"y":38,"dx":0,"dy":2},{"id":16,"x":38,"y":38,"dx":-3,"dy":-2},{"id":16,"x":41,"y":38,"dx":-1,"dy":-1},{"id":16,"x":45,"y":38,"dx":2,"dy":0},{"id":16,"x":7,"y":39,"dx":2,"dy":1},{"id":16,"x":16,"y":39,"dx":2,"dy":0},{"id":16,"x":19,"y":39,"dx":-3,"dy":0},{"id":16,"x":22,"y":39,"dx":0,"dy":0},{"id":16,"x":26,"y":39,"dx":2,"dy":-1},{"id":16,"x":38,"y":39,"dx":-4,"dy":-1},{"id":16,"x":43,"y":39,"dx":-2,"dy":-2},{"id":16,"x":44,"y":39,"dx":-3,"dy":-2},{"id":16,"x":46,"y":39,"dx":1,"dy":0},{"id":16,"x":52,"y":39,"dx":-1,"dy":1}],"encoding":"rle","tiles":[[4,10],[0,4],[4,5],[0,1],[4,12],[0,2],[4,11],[0,3],[4,17],[0,1],[4,3],[0,1],[4,4],[0,2],[4,10],[0,4],[4,11],[0,3],[4,4],[3,2],[4,7],[3,1],[4,3],[0,1],[4,8],[0,3],[4,10],[0,1],[4,10],[0,2],[4,1],[0,3],[4,18],[0,4],[4,16],[0,1],[4,12],[0,2],[4,11],[3,1],[4,41],[0,4],[4,12],[3,1],[0,1],[4,2],[0,5],[4,33],[0,2],[4,9],[3,1],[0,1],[4,1],[0,7],[4,34],[0,2],[4,1],[0,1],[4,7],[3,1],[4,1],[0,1],[4,4],[3,1],[0,3],[4,1],[0,1],[4,8],[29,1],[4,34],[3,1],[4,1],[0,2],[4,3],[0,5],[4,39],[0,1],[4,2],[0,2],[4,2],[0,1],[4,1],[3,1],[4,1],[3,1],[0,6],[4,39],[0,4],[4,6],[3,1],[0,1],[4,1],[0,2],[4,3],[0,1],[4,19],[0,1],[4,4],[27,1],[4,11],[0,4],[3,1],[4,8],[28,1],[4,3],[0,2],[4,19],[0,3],[4,15],[0,5],[4,6],[3,1],[4,5],[0,1],[4,1],[0,1],[7,1],[4,1],[0,3],[1,7],[4,1],[1,13],[4,10],[0,5],[3,1],[4,16],[0,1],[10,1],[0,1],[1,11],[4,1],[1,5],[4,1],[1,4],[4,9],[0,1],[4,1],[0,1],[4,1],[0,1],[4,6],[3,2],[4,9],[0,2],[4,1],[1,1],[0,1],[1,8],[6,1],[1,11],[4,10],[0,1],[4,1],[0,1],[4,17],[0,3],[4,1],[1,5],[4,1],[1,6],[4,1],[1,8],[4,1],[0,2],[4,28],[0,2],[4,1],[0,1],[1,3],[4,1],[1,16],[4,1],[1,1],[4,1],[0,3],[4,8],[3,1],[4,1],[3,1],[4,16],[0,3],[1,3],[4,1],[1,18],[0,1],[4,1],[0,1],[4,8],[3,2],[4,5],[3,1],[4,5],[0,4],[4,3],[0,2],[4,1],[1,22],[4,1],[0,3],[4,15],[3,1],[4,1],[3,1],[4,2],[0,2],[4,8],[1,5],[4,1],[1,16],[0,3],[26,1],[4,14],[1,21],[4,1],[1,4],[0,1],[4,1],[1,10],[4,11],[3,1],[4,1],[1,2],[4,10],[0,2],[4,5],[0,1],[4,1],[1,22],[4,3],[29,1],[4,12],[0,2],[4,2],[3,1],[4,3],[0,1],[4,2],[0,1],[4,6],[0,1],[1,12],[4,1],[1,2],[4,2],[1,4],[4,11],[3,1],[4,4],[0,2],[4,4],[0,1],[4,2],[0,1],[4,8],[1,12],[4,1],[1,1],[4,1],[1,7],[4,8],[0,3],[4,1],[0,3],[4,1],[0,2],[3,1],[4,4],[0,2],[4,9],[1,8],[4,1],[1,9],[4,1],[1,3],[4,10],[0,1],[3,1],[4,1],[3,1],[0,2],[4,1],[0,1],[4,1],[0,2],[3,1],[0,1],[4,3],[0,1],[4,7],[1,4],[4,1],[1,9],[0,1],[1,1],[0,1],[1,5],[4,8],[0,1],[4,1],[0,1],[3,2],[4,1],[0,1],[3,1],[4,1],[0,1],[3,1],[4,1],[3,1],[4,1],[0,2],[4,1],[0,2],[4,7],[1,16],[4,1],[1,4],[4,9],[0,2],[4,2],[0,2],[4,2],[0,1],[4,1],[0,2],[4,2],[0,1],[4,1],[0,2],[4,8],[0,1],[1,21],[4,9],[0,2],[4,1],[0,1],[4,1],[0,1],[3,1],[0,1],[4,1],[3,1],[0,2],[4,14],[0,4],[24,1],[4,1],[0,1],[4,5],[0,2],[25,1],[4,18],[3,1],[4,3],[0,4],[4,13],[0,1],[4,1],[0,5],[4,7],[0,3],[4,26],[3,1],[4,12],[0,7],[4,7],[0,1],[4,20],[3,1],[4,2],[3,1],[4,2],[3,1],[4,15],[0,1],[4,1],[0,4],[4,2],[0,1],[4,34],[3,1],[4,11],[0,10],[4,24],[3,1],[4,8],[3,1],[4,12],[0,2],[4,2],[0,2],[4,1],[0,1],[4,1],[0,1],[4,11],[29,1],[4,16],[3,1],[0,2],[4,7],[29,1],[4,11],[0,2],[4,1],[0,1],[4,1],[0,1],[4,27],[3,1],[4,1],[0,3],[4,2],[3,1],[4,14],[0,2],[4,1],[0,4],[4,29],[0,3],[4,19],[0,1],[4,34],[3,1],[4,50],[0,1],[4,6],[3,1],[4,9],[28,1],[4,19],[0,2],[4,15],[0,1],[4,1],[0,1],[3,2],[4,4],[3,1],[4,28],[0,3],[4,21]]} \ No newline at end of file diff --git a/apps/game/src/Game.ts b/apps/game/src/Game.ts index f4e49b3..cc7858c 100644 --- a/apps/game/src/Game.ts +++ b/apps/game/src/Game.ts @@ -82,6 +82,7 @@ 'tiles/house_3', 'tiles/house_4', 'tiles/house_5', + 'tiles/house_big', 'tiles/boulder', 'tiles/boulder_2', 'tiles/boulder_3', diff --git a/apps/game/src/data/assetSets.ts b/apps/game/src/data/assetSets.ts index 8822663..ae24885 100644 --- a/apps/game/src/data/assetSets.ts +++ b/apps/game/src/data/assetSets.ts @@ -32,6 +32,7 @@ [TILES.HOUSE_V2, a.texture('tiles/house_3')], [TILES.HOUSE_V3, a.texture('tiles/house_4')], [TILES.HOUSE_V4, a.texture('tiles/house_5')], + [TILES.HOUSE_BIG, a.texture('tiles/house_big')], [TILES.BOULDER, a.texture('tiles/boulder')], [TILES.BOULDER_2, a.texture('tiles/boulder_2')], [TILES.BOULDER_3, a.texture('tiles/boulder_3')], diff --git a/apps/game/src/data/map.ts b/apps/game/src/data/map.ts index 828e0ed..ae420dc 100644 --- a/apps/game/src/data/map.ts +++ b/apps/game/src/data/map.ts @@ -1,4 +1,4 @@ -import { createRng, type TileMapData, type TallSpec, type DecorData } from '@rpg/engine'; +import { createRng, type TileMapData, type TallSpec, type DecorData, type PropData } from '@rpg/engine'; /** id тайлов луга «Пепельные луга». */ export const TILES = { @@ -49,7 +49,9 @@ BOULDER_3: 31, /** Кусты других видов (варианты BUSH): раскидистый и высокий узкий. */ BUSH_2: 32, - BUSH_3: 33 + BUSH_3: 33, + /** Большой дом 2×2 (спрайт-проп 64×80, footprint блокируется движком). */ + HOUSE_BIG: 34 } as const; const BLOCKED = [ @@ -734,6 +736,12 @@ tiles[at(23, 28)] = TILES.HOUSE_V1; tiles[at(33, 28)] = TILES.HOUSE_V2; + // Большой дом 2×2 на юго-востоке: первый проп-объект с footprint в игре + // (коллизия и глубина — по всему прямоугольнику, земля под ним — пепел). + const props: PropData[] = [ + { id: TILES.HOUSE_BIG, x: 46, y: 24, w: 2, h: 2, ground: TILES.ASH } + ]; + // Старый колодец у дома Ирвина: телепорт на луга (см. AREAS, transitions). tiles[at(16, 13)] = TILES.WELL; @@ -761,6 +769,7 @@ blocked: [...BLOCKED], tall: TALL_OBJECTS, variants: TILE_VARIANTS, - decor: buildDecor(tiles, width, height, seed) + decor: buildDecor(tiles, width, height, seed), + props }; } diff --git a/apps/game/src/scenes/MapScene.ts b/apps/game/src/scenes/MapScene.ts index 0377ea7..30df4d9 100644 --- a/apps/game/src/scenes/MapScene.ts +++ b/apps/game/src/scenes/MapScene.ts @@ -37,6 +37,7 @@ [TILES.HOUSE_V2]: 0x5a4a3c, [TILES.HOUSE_V3]: 0x5a4a3c, [TILES.HOUSE_V4]: 0x5a4a3c, + [TILES.HOUSE_BIG]: 0x5a4a3c, [TILES.BOULDER]: 0x767681, // P5 [TILES.BOULDER_2]: 0x767681, [TILES.BOULDER_3]: 0x767681, diff --git a/apps/game/tools/checks/big_house.mjs b/apps/game/tools/checks/big_house.mjs new file mode 100644 index 0000000..19c0b33 --- /dev/null +++ b/apps/game/tools/checks/big_house.mjs @@ -0,0 +1,75 @@ +/** + * Сценарий big_house — большой дом 2×2 в Звенце (первый проп с footprint): + * 1) коллизия: footprint непроходим, соседний тайл проходим; + * 2) scene:walk в дом — false, approach — к соседу; + * 3) глубина: герой с юга (перед домом) и с севера (за домом) — скриншоты. + * Запуск: node tools/agent.mjs run tools/checks/big_house.mjs + */ +import { withChecks } from '../lib.mjs'; + +export default async function () { + return withChecks( + 'big_house', + async (t) => { + const { c } = t; + await c.run('снапшот: проп дома в collision-слое', async () => { + await t.boot(); + await t.sleepEnemies(); + await t.goToArea('zvenets', { x: 54, y: 28 }); + const s = await t.ctx.agent.snapshot(); + // collision-слой снапшота отдаёт пропы без id — ищем по footprint. + const prop = (s.collision.props ?? []).find((p) => p.x === 46 && p.y === 24); + c.expect(!!prop, 'проп (46,24) 2×2 не в collision-слое', s.collision.props); + c.expect(prop && prop.w === 2 && prop.h === 2, 'footprint пропа не 2×2', prop); + const idx = (x, y) => y * s.collision.width + x; + c.expect( + s.collision.blocked[idx(46, 24)] === 1 && s.collision.blocked[idx(47, 25)] === 1, + 'клетки footprint пропа не заблокированы' + ); + return null; + }); + await c.run('scene:walkable: дом непроходим, сосед свободен', async () => { + const walk = (x, y) => t.ctx.agent.command('scene:walkable', { x, y }); + c.expect((await walk(46, 24)) === false, 'северо-запад дома проходим'); + c.expect((await walk(47, 25)) === false, 'юго-восток дома проходим'); + c.expect((await walk(48, 24)) === true, 'тайл восточнее дома заблокирован'); + return null; + }); + await c.run('scene:walk в дом — false, approach — к соседу', async () => { + await t.ctx.agent.command('scene:teleport', { x: 48, y: 24 }); + await t.ctx.agent.waitFor('!s.transitioning', { timeoutTicks: 60 }); + const walked = await t.ctx.agent.command('scene:walk', { x: 46, y: 24 }); + c.expect(walked === false, 'scene:walk провёл героя в дом', walked); + const dest = await t.ctx.agent.approach(46, 24); + c.expect(dest !== null, 'approach к дому не нашёл соседа'); + return null; + }); + await c.run('глубина: герой с юга и с севера дома', async () => { + const shot = async (name) => { + await t.ctx.agent.step(2, { render: true }); + await t.ctx.page.screenshot({ path: `/tmp/rpg_big_house_${name}.png` }); + }; + const teleport = async (x, y) => { + await t.ctx.agent.command('scene:teleport', { x, y }); + await t.ctx.agent.waitFor('!s.transitioning', { timeoutTicks: 60 }); + const s = await t.ctx.agent.snapshot(); + c.expect( + s.hero.tile.x === x && s.hero.tile.y === y, + `телепорт в (${x},${y}) не удался`, + s.hero.tile + ); + }; + // Юг: герой вплотную перед домом — перекрывает его низ. + await teleport(46, 26); + await shot('south'); + // Север: дом ближе к камере — перекрывает героя целиком. + await teleport(46, 23); + await shot('north'); + return null; + }); + const inv = await t.ctx.agent.invariants(); + const errs = inv.filter((i) => i.severity === 'error'); + c.expect(errs.length === 0, 'инварианты с пропом не чисты', errs); + } + ); +} \ No newline at end of file diff --git a/apps/game/tools/maps/gen.test.ts b/apps/game/tools/maps/gen.test.ts index 843dcaa..450213c 100644 --- a/apps/game/tools/maps/gen.test.ts +++ b/apps/game/tools/maps/gen.test.ts @@ -56,6 +56,7 @@ expect(back.blocked).toEqual(data.blocked); expect(back.tiles).toEqual(data.tiles); expect(back.tall).toEqual(data.tall); + expect(back.props).toEqual(data.props); }); } diff --git a/docs/demo.md b/docs/demo.md index 5cb629b..ed60ec6 100644 --- a/docs/demo.md +++ b/docs/demo.md @@ -15,9 +15,9 @@ | SceneManager (replace/push/pop, fade) | меню → локация → сумка/сейвы; переходы локаций | готово | | InputManager (действия, геймпад, мульти-биндинг) | advance/attack/menu/inventory/debug; геймпад-карта | готово | | VirtualJoystick | тач в локациях (включается при первом касании) | готово | -| IsometricTileMap + A* | карты локаций ×2 (внешние области 48–56 тайлов), движение кнопками (мост: scene:walk); tall-объекты: деревья, изометрические дома (5 видов, две стены + крыша), башня, колодцы, валун и куст | готово | +| IsometricTileMap + A* | карты локаций ×2 (внешние области 48–56 тайлов), движение кнопками (мост: scene:walk); tall-объекты: деревья, изометрические дома (5 видов, две стены + крыша), башня, колодцы, валун и куст; пропы с footprint — большой дом 2×2 в Звенце (коллизия и глубина по прямоугольнику, земля под ним) | готово | | mapFormat (JSON+RLE) | карты — файлы `assets/maps/*.map`, генерация `npm run maps` | готово | -| renderMinimap (чистый рендер карты → RGBA) | предмет «Карта окрестностей» (Ирвин даёт с квестом): оверлей `MapScene` — **карта мира «Низина Звенца»**: композит миниатюр 5 внешних областей (cell = 1) на одном листе, дороги между переходами, подписи областей, маркеры переходов/NPC текущей области, мигающий герой; интерьеры и зал Машины не показаны | готово | +| renderMinimap (чистый рендер карты → RGBA) | предмет «Карта окрестностей» (Ирвин даёт с квестом): оверлей `MapScene` — **карта мира «Низина Звенца»**: композит миниатюр 5 внешних областей (cell = 1) на одном листе, дороги между переходами, подписи областей, маркеры переходов/NPC текущей области, мигающий герой; пропы красятся footprint'ом цветом `colors[prop.id]`; интерьеры и зал Машины не показаны | готово | | Tiled-импорт | не задействован (дока + тест есть) | резерв | | EventBus | `combat:hurt/attack/playerHit`, `quest:flower` | готово | | GameState (флаги/вары) | прогресс квеста, hp/kills/motes/deaths; сериализация в сейвы | готово | diff --git a/docs/plan.md b/docs/plan.md index 9a0b085..52f9815 100644 --- a/docs/plan.md +++ b/docs/plan.md @@ -22,7 +22,7 @@ | 3 | AI-генерация аудио (работа A, ниже) | 📋 спланировано, отложено | | 4 | Акт 2: новые локации/сюжет по `docs/world.md` | очередь после акта 1+AI-ассетов | | 5 | Замена сгенерированных плейсхолдеров арта на AI/ручной арт | в составе работы B | -| 6 | Крупные объекты: footprint в движке, слоты арта (работа C, ниже) | в работе | +| 6 | Крупные объекты: footprint в движке, слоты арта (работа C, ниже) | ✅ сделано (2026-09-09): C0–C2 см. работу C; додержано в игре — большой дом 2×2 в Звенце (первый проп на карте), минимапа красит footprint пропа (`renderMinimap`), чек `checks/big_house.mjs` (коллизия, approach, глубина севера/юга) | | 7 | Возможности аудио-движка (работа D, ниже): sfx-хендл, полифония, наблюдаемость, буферы | ✅ D0–D2 сделаны (2026-09-07) | | 8 | Синтез звука по запросу для агента (работа E, ниже) | ✅ E1–E4 сделаны (2026-09-07) | | 9 | Инфраструктура аудио + музыкальный слой (работы F/G, ниже) | ✅ сделаны (2026-09-07) | diff --git a/packages/engine/src/map/__tests__/minimap.test.ts b/packages/engine/src/map/__tests__/minimap.test.ts index 1b609a7..5ef36f6 100644 --- a/packages/engine/src/map/__tests__/minimap.test.ts +++ b/packages/engine/src/map/__tests__/minimap.test.ts @@ -63,4 +63,29 @@ }); expect(px(img, 0, 0)).toEqual([16, 16, 16]); }); + + it('проп красит весь footprint своим цветом поверх тайлов', () => { + const map = { ...tinyMap(), props: [{ id: 7, x: 0, y: 0, w: 2, h: 2 }] }; + const img = renderMinimap(map, { colors: { 1: 0xff0000, 2: 0x00ff00, 7: 0x0000ff }, cell: 3 }); + // Клетки (0,0) и (1,1) — под пропом, тайл 1/2 перекрашен синим. + expect(px(img, 0, 0)).toEqual([0, 0, 255]); + expect(px(img, 4, 4)).toEqual([0, 0, 255]); + // Клетка вне footprint осталась цветом своего тайла (id 1 — красный). + expect(px(img, 7, 0)).toEqual([255, 0, 0]); + }); + + it('проп без записи в colors — fallbackColor', () => { + const map = { ...tinyMap(), props: [{ id: 7, x: 2, y: 1, w: 1, h: 1 }] }; + const img = renderMinimap(map, { colors: { 1: 0x101010, 2: 0x101010 }, fallbackColor: 0x3c3c48, cell: 3 }); + expect(px(img, 8, 4)).toEqual([60, 60, 72]); + }); + + it('footprint у края карты не выходит за границы', () => { + // Проп 3×3 от (1,0): правый столбец клеток вылезает за ширину 3. + const map = { ...tinyMap(), props: [{ id: 7, x: 1, y: 0, w: 3, h: 3 }] }; + const img = renderMinimap(map, { colors: { 1: 0x101010, 7: 0x0000ff }, cell: 3 }); + expect(() => px(img, 8, 5)).not.toThrow(); + // Клетка (2,0) под пропом покрашена, выход за карту не рисуется. + expect(px(img, 8, 0)).toEqual([0, 0, 255]); + }); }); \ No newline at end of file diff --git a/packages/engine/src/map/minimap.ts b/packages/engine/src/map/minimap.ts index 77ec112..50eef23 100644 --- a/packages/engine/src/map/minimap.ts +++ b/packages/engine/src/map/minimap.ts @@ -5,6 +5,7 @@ * не знает про текстуры; в пиксельную текстуру картинку превращает игра). * Схема «вид сверху»: клетка сетки = тайл, цвет — из палитры вызывающей * стороны (Record). Незаданные тайлы — fallbackColor. + * Пропы рисуются поверх — весь footprint цветом `colors[prop.id]`. */ export interface MinimapMarker { @@ -63,6 +64,20 @@ } } } + // Пропы: весь footprint цветом пропа — крупный объект читается схемой, + // а не только цветом земли под ним. + for (const p of data.props ?? []) { + const color = rgbOf(opts.colors[p.id] ?? opts.fallbackColor ?? 0x1a1a20); + const w = p.w ?? 1; + const h = p.h ?? 1; + for (let ty = p.y; ty < p.y + h && ty < data.height; ty++) { + for (let tx = p.x; tx < p.x + w && tx < data.width; tx++) { + for (let dy = 0; dy < cell; dy++) { + for (let dx = 0; dx < cell; dx++) put(tx * cell + dx, ty * cell + dy, color); + } + } + } + } // Маркеры: закрашенная клетка с рамкой цвета фона — читается на любом поле. for (const m of opts.markers ?? []) { if (m.x < 0 || m.y < 0 || m.x >= data.width || m.y >= data.height) continue;