Automatic y sorting with z buffer, 3d!

main
Cameron Murphy Reikes 2 years ago
parent 399152796a
commit cf3994901e

@ -54,6 +54,10 @@
{ {
filepath: "bullet.png", filepath: "bullet.png",
} }
@image props_atlas:
{
filepath: "copyrighted/props.png"
}
@image drop_shadow: @image drop_shadow:
{ {
filepath: "drop_shadow.png", filepath: "drop_shadow.png",

@ -370,8 +370,8 @@
"rotation":0, "rotation":0,
"visible":true, "visible":true,
"width":32, "width":32,
"x":1009, "x":1478.33333333333,
"y":974.833333333333 "y":736.166666666666
}, },
{ {
"class":"", "class":"",
@ -416,6 +416,17 @@
"width":32, "width":32,
"x":1019.66666666667, "x":1019.66666666667,
"y":917.666666666667 "y":917.666666666667
},
{
"class":"PROP",
"height":32,
"id":11,
"name":"TREE0",
"rotation":0,
"visible":true,
"width":32,
"x":780,
"y":917.333333333333
}], }],
"opacity":1, "opacity":1,
"type":"objectgroup", "type":"objectgroup",
@ -424,7 +435,7 @@
"y":0 "y":0
}], }],
"nextlayerid":8, "nextlayerid":8,
"nextobjectid":11, "nextobjectid":12,
"orientation":"orthogonal", "orientation":"orthogonal",
"renderorder":"right-down", "renderorder":"right-down",
"tiledversion":"1.9.2", "tiledversion":"1.9.2",

@ -2,9 +2,11 @@
@REM https://learn.microsoft.com/en-us/cpp/build/reference/compiler-options-listed-by-category?view=msvc-170 @REM https://learn.microsoft.com/en-us/cpp/build/reference/compiler-options-listed-by-category?view=msvc-170
remedybg.exe stop-debugging
call run_codegen.bat || goto :error call run_codegen.bat || goto :error
cl /DDEVTOOLS /Igen /Ithirdparty /W3 /Zi /WX main.c || goto :error cl /DDEVTOOLS /Igen /Ithirdparty /W3 /Zi /WX main.c || goto :error
@REM cl /Igen /Ithirdparty /W3 /Zi /WX main.c || goto :error @REM cl /Igen /Ithirdparty /W3 /Zi /WX main.c || goto :error
remedybg.exe start-debugging
goto :EOF goto :EOF
:error :error

@ -205,7 +205,12 @@ int main(int argc, char **argv) {
if(has_decimal(x_string)) x_string = MD_S8Fmt(cg_arena, "%.*sf", MD_S8VArg(x_string)); if(has_decimal(x_string)) x_string = MD_S8Fmt(cg_arena, "%.*sf", MD_S8VArg(x_string));
if(has_decimal(y_string)) y_string = MD_S8Fmt(cg_arena, "%.*sf", MD_S8VArg(y_string)); if(has_decimal(y_string)) y_string = MD_S8Fmt(cg_arena, "%.*sf", MD_S8VArg(y_string));
if(MD_S8Match(name, MD_S8Lit("PLAYER"), 0)) MD_String8 class = MD_ChildFromString(object, MD_S8Lit("class"), 0)->first_child->string;
if(MD_S8Match(class, MD_S8Lit("PROP"), 0))
{
fprintf(output, "{ .exists = true, .is_prop = true, .pos = { .X=%.*s, .Y=%.*s }, }, ", MD_S8VArg(x_string), MD_S8VArg(y_string));
}
else if(MD_S8Match(name, MD_S8Lit("PLAYER"), 0))
{ {
fprintf(output, "{ .exists = true, .is_character = true, .pos = { .X=%.*s, .Y=%.*s }, }, ", MD_S8VArg(x_string), MD_S8VArg(y_string)); fprintf(output, "{ .exists = true, .is_character = true, .pos = { .X=%.*s, .Y=%.*s }, }, ", MD_S8VArg(x_string), MD_S8VArg(y_string));
} }

189
main.c

@ -36,6 +36,15 @@
#define Log(...) { printf("Log %d | ", __LINE__); printf(__VA_ARGS__); } #define Log(...) { printf("Log %d | ", __LINE__); printf(__VA_ARGS__); }
double clamp(double d, double min, double max) {
const double t = d < min ? min : d;
return t > max ? max : t;
}
float clampf(float d, float min, float max) {
const float t = d < min ? min : d;
return t > max ? max : t;
}
// so can be grep'd and removed // so can be grep'd and removed
#define dbgprint(...) { printf("Debug | %s:%d | ", __FILE__, __LINE__); printf(__VA_ARGS__); } #define dbgprint(...) { printf("Debug | %s:%d | ", __FILE__, __LINE__); printf(__VA_ARGS__); }
Vec2 RotateV2(Vec2 v, float theta) Vec2 RotateV2(Vec2 v, float theta)
@ -112,15 +121,6 @@ typedef enum CharacterState
CHARACTER_TALKING, CHARACTER_TALKING,
} CharacterState; } CharacterState;
typedef enum EntityKind
{
ENTITY_INVALID, // zero initialized is invalid entity
ENTITY_PLAYER,
ENTITY_OLD_MAN,
ENTITY_BULLET,
} EntityKind;
#ifdef DEVTOOLS #ifdef DEVTOOLS
#define SERVER_URL "http://localhost:8090" #define SERVER_URL "http://localhost:8090"
#else #else
@ -174,6 +174,9 @@ typedef struct Entity
bool is_bullet; bool is_bullet;
// props
bool is_prop;
// npcs // npcs
bool is_npc; bool is_npc;
double character_say_timer; double character_say_timer;
@ -574,11 +577,12 @@ SwordToDamage entity_sword_to_do_damage(Entity *from, Overlapping o)
return to_return; return to_return;
} }
// aabb advice by iRadEntertainment
Vec2 entity_aabb_size(Entity *e) Vec2 entity_aabb_size(Entity *e)
{ {
if(e->is_character == ENTITY_PLAYER) if(e->is_character)
{ {
return V2(TILE_SIZE, TILE_SIZE); return V2(TILE_SIZE, TILE_SIZE*0.5f);
} }
else if(e->is_npc) else if(e->is_npc)
{ {
@ -608,6 +612,10 @@ Vec2 entity_aabb_size(Entity *e)
{ {
return V2(TILE_SIZE*0.25f, TILE_SIZE*0.25f); return V2(TILE_SIZE*0.25f, TILE_SIZE*0.25f);
} }
else if(e->is_prop)
{
return V2(TILE_SIZE*0.5f, TILE_SIZE*0.5f);
}
else else
{ {
assert(false); assert(false);
@ -900,7 +908,7 @@ void reset_level()
void init(void) void init(void)
{ {
Log("Size of entity struct: %zu\n", sizeof(Entity)); Log("Size of entity struct: %zu\n", sizeof(Entity));
Log("Size of %lld entities: %zu kb\n", ARRLEN(entities), sizeof(entities)/1024); Log("Size of %d entities: %zu kb\n", (int)ARRLEN(entities), sizeof(entities)/1024);
sg_setup(&(sg_desc){ sg_setup(&(sg_desc){
.context = sapp_sgcontext(), .context = sapp_sgcontext(),
}); });
@ -976,10 +984,14 @@ void init(void)
state.pip = sg_make_pipeline(&(sg_pipeline_desc) state.pip = sg_make_pipeline(&(sg_pipeline_desc)
{ {
.shader = shd, .shader = shd,
.depth = {
.compare = SG_COMPAREFUNC_LESS_EQUAL,
.write_enabled = true
},
.layout = { .layout = {
.attrs = .attrs =
{ {
[ATTR_quad_vs_position].format = SG_VERTEXFORMAT_FLOAT2, [ATTR_quad_vs_position].format = SG_VERTEXFORMAT_FLOAT3,
[ATTR_quad_vs_texcoord0].format = SG_VERTEXFORMAT_FLOAT2, [ATTR_quad_vs_texcoord0].format = SG_VERTEXFORMAT_FLOAT2,
} }
}, },
@ -1090,6 +1102,14 @@ AABB aabb_at(Vec2 at, Vec2 size)
}; };
} }
AABB aabb_at_yplusdown(Vec2 at, Vec2 size)
{
return (AABB){
.upper_left = at,
.lower_right = AddV2(at, V2(size.x, size.y)),
};
}
Quad quad_at(Vec2 at, Vec2 size) Quad quad_at(Vec2 at, Vec2 size)
{ {
Quad to_return; Quad to_return;
@ -1227,6 +1247,7 @@ AABB world_cam_aabb()
int num_draw_calls = 0; int num_draw_calls = 0;
#define FLOATS_PER_VERTEX (3 + 2)
float cur_batch_data[1024*10] = {0}; float cur_batch_data[1024*10] = {0};
int cur_batch_data_index = 0; int cur_batch_data_index = 0;
// @TODO check last tint as well, do this when factor into drawing parameters // @TODO check last tint as well, do this when factor into drawing parameters
@ -1239,10 +1260,10 @@ void flush_quad_batch()
state.bind.fs_images[SLOT_quad_tex] = cur_batch_image; state.bind.fs_images[SLOT_quad_tex] = cur_batch_image;
sg_apply_bindings(&state.bind); sg_apply_bindings(&state.bind);
sg_apply_uniforms(SG_SHADERSTAGE_FS, SLOT_quad_fs_params, &SG_RANGE(cur_batch_params)); sg_apply_uniforms(SG_SHADERSTAGE_FS, SLOT_quad_fs_params, &SG_RANGE(cur_batch_params));
assert(cur_batch_data_index % 4 == 0); assert(cur_batch_data_index % FLOATS_PER_VERTEX == 0);
sg_draw(0, cur_batch_data_index/4, 1); sg_draw(0, cur_batch_data_index/FLOATS_PER_VERTEX, 1);
num_draw_calls += 1; num_draw_calls += 1;
memset(cur_batch_data, 0, cur_batch_data_index); memset(cur_batch_data, 0, cur_batch_data_index*sizeof(*cur_batch_data));
cur_batch_data_index = 0; cur_batch_data_index = 0;
} }
@ -1255,6 +1276,8 @@ typedef struct DrawParams
Color tint; Color tint;
AABB clip_to; // if world space is in world space, if screen space is in screen space - Lao Tzu AABB clip_to; // if world space is in world space, if screen space is in screen space - Lao Tzu
float y_coord_sorting;
float alpha_clip_threshold;
} DrawParams; } DrawParams;
@ -1275,6 +1298,7 @@ void draw_quad(DrawParams d)
params.tint[1] = d.tint.G; params.tint[1] = d.tint.G;
params.tint[2] = d.tint.B; params.tint[2] = d.tint.B;
params.tint[3] = d.tint.A; params.tint[3] = d.tint.A;
params.alpha_clip_threshold = d.alpha_clip_threshold;
if(aabb_is_valid(d.clip_to) && LenV2(aabb_size(d.clip_to)) > 0.1) if(aabb_is_valid(d.clip_to) && LenV2(aabb_size(d.clip_to)) > 0.1)
{ {
@ -1334,7 +1358,7 @@ void draw_quad(DrawParams d)
continue; // cull out of screen quads continue; // cull out of screen quads
} }
float new_vertices[ (2 + 2)*4 ] = {0}; float new_vertices[ FLOATS_PER_VERTEX*4 ] = {0};
Vec2 region_size = SubV2(d.image_region.lower_right, d.image_region.upper_left); Vec2 region_size = SubV2(d.image_region.lower_right, d.image_region.upper_left);
assert(region_size.X > 0.0); assert(region_size.X > 0.0);
assert(region_size.Y > 0.0); assert(region_size.Y > 0.0);
@ -1355,13 +1379,28 @@ void draw_quad(DrawParams d)
for(int i = 0; i < 4; i++) for(int i = 0; i < 4; i++)
{ {
Vec2 in_clip_space = into_clip_space(points[i]); Vec2 in_clip_space = into_clip_space(points[i]);
new_vertices[i*4] = in_clip_space.X; new_vertices[i*FLOATS_PER_VERTEX + 0] = in_clip_space.X;
new_vertices[i*4 + 1] = in_clip_space.Y; new_vertices[i*FLOATS_PER_VERTEX + 1] = in_clip_space.Y;
new_vertices[i*4 + 2] = tex_coords[i].X; if(d.y_coord_sorting == 0.0f)
new_vertices[i*4 + 3] = tex_coords[i].Y; {
new_vertices[i*FLOATS_PER_VERTEX + 2] = 1.0f;
//new_vertices[i*FLOATS_PER_VERTEX + 2] = 0.5f;
}
else
{
//new_vertices[i*FLOATS_PER_VERTEX + 2] = (float)clamp(world_to_screen(V2(0.0f, d.y_coord_sorting)).y/screen_size().y, 0.0f, 1.0f);
new_vertices[i*FLOATS_PER_VERTEX + 2] = clampf(d.y_coord_sorting, 0.0f, 0.98f); // y sorted things always in front of non y sorted things
//new_vertices[i*FLOATS_PER_VERTEX + 2] = -0.5f;
//new_vertices[i*FLOATS_PER_VERTEX + 2] = 0.1f;
}
//new_vertices[i*FLOATS_PER_VERTEX + 2] = 0.0f;
new_vertices[i*FLOATS_PER_VERTEX + 3] = tex_coords[i].X;
new_vertices[i*FLOATS_PER_VERTEX + 4] = tex_coords[i].Y;
} }
size_t total_size = ARRLEN(new_vertices)*sizeof(new_vertices); // two triangles drawn, six vertices
size_t total_size = 6*FLOATS_PER_VERTEX;
// batched a little too close to the sun // batched a little too close to the sun
if(cur_batch_data_index + total_size >= ARRLEN(cur_batch_data)) if(cur_batch_data_index + total_size >= ARRLEN(cur_batch_data))
@ -1371,13 +1410,13 @@ void draw_quad(DrawParams d)
cur_batch_params = params; cur_batch_params = params;
} }
#define PUSH_VERTEX(vert) { memcpy(&cur_batch_data[cur_batch_data_index], &vert, 4*sizeof(float)); cur_batch_data_index += 4; } #define PUSH_VERTEX(vert) { memcpy(&cur_batch_data[cur_batch_data_index], &vert, FLOATS_PER_VERTEX*sizeof(float)); cur_batch_data_index += FLOATS_PER_VERTEX; }
PUSH_VERTEX(new_vertices[0*4]); PUSH_VERTEX(new_vertices[0*FLOATS_PER_VERTEX]);
PUSH_VERTEX(new_vertices[1*4]); PUSH_VERTEX(new_vertices[1*FLOATS_PER_VERTEX]);
PUSH_VERTEX(new_vertices[2*4]); PUSH_VERTEX(new_vertices[2*FLOATS_PER_VERTEX]);
PUSH_VERTEX(new_vertices[0*4]); PUSH_VERTEX(new_vertices[0*FLOATS_PER_VERTEX]);
PUSH_VERTEX(new_vertices[2*4]); PUSH_VERTEX(new_vertices[2*FLOATS_PER_VERTEX]);
PUSH_VERTEX(new_vertices[3*4]); PUSH_VERTEX(new_vertices[3*FLOATS_PER_VERTEX]);
#undef PUSH_VERTEX #undef PUSH_VERTEX
} }
@ -1395,37 +1434,6 @@ double anim_sprite_duration(AnimatedSprite *s)
return s->num_frames * s->time_per_frame; return s->num_frames * s->time_per_frame;
} }
void draw_animated_sprite(AnimatedSprite *s, double elapsed_time, bool flipped, Vec2 pos, Color tint)
{
pos = AddV2(pos, s->offset);
sg_image spritesheet_img = *s->img;
int index = (int)floor(elapsed_time/s->time_per_frame) % s->num_frames;
if(s->no_wrap)
{
index = (int)floor(elapsed_time/s->time_per_frame);
if(index >= s->num_frames) index = s->num_frames - 1;
}
Quad q = quad_centered(pos, s->region_size);
if(flipped)
{
swap(&q.points[0], &q.points[1]);
swap(&q.points[3], &q.points[2]);
}
AABB region;
region.upper_left = AddV2(s->start, V2(index * s->horizontal_diff_btwn_frames, 0.0f));
float width = img_size(spritesheet_img).X;
while(region.upper_left.X >= width)
{
region.upper_left.X -= width;
region.upper_left.Y += s->region_size.Y;
}
region.lower_right = AddV2(region.upper_left, s->region_size);
draw_quad((DrawParams){true, q, spritesheet_img, region, tint});
}
@ -1620,7 +1628,7 @@ AABB draw_text(TextParams t)
{ {
col = t.colors[i]; col = t.colors[i];
} }
draw_quad((DrawParams){t.world_space, to_draw, image_font, font_atlas_region, col, t.clip_to}); draw_quad((DrawParams){t.world_space, to_draw, image_font, font_atlas_region, col, t.clip_to, .y_coord_sorting = 1.0f});
} }
} }
} }
@ -1630,6 +1638,52 @@ AABB draw_text(TextParams t)
return bounds; return bounds;
} }
float y_coord_sorting_at(Vec2 pos)
{
float y_coord_sorting = world_to_screen(pos).y / screen_size().y;
// debug draw the y cord sorting value
#if 0
char *to_draw = tprint("%f", y_coord_sorting);
draw_text((TextParams){true, false, to_draw, pos, BLACK, 1.0f});
#endif
return y_coord_sorting;
}
void draw_animated_sprite(AnimatedSprite *s, double elapsed_time, bool flipped, Vec2 pos, Color tint)
{
float y_sort_pos = y_coord_sorting_at(pos);
pos = AddV2(pos, s->offset);
sg_image spritesheet_img = *s->img;
int index = (int)floor(elapsed_time/s->time_per_frame) % s->num_frames;
if(s->no_wrap)
{
index = (int)floor(elapsed_time/s->time_per_frame);
if(index >= s->num_frames) index = s->num_frames - 1;
}
Quad q = quad_centered(pos, s->region_size);
if(flipped)
{
swap(&q.points[0], &q.points[1]);
swap(&q.points[3], &q.points[2]);
}
AABB region;
region.upper_left = AddV2(s->start, V2(index * s->horizontal_diff_btwn_frames, 0.0f));
float width = img_size(spritesheet_img).X;
while(region.upper_left.X >= width)
{
region.upper_left.X -= width;
region.upper_left.Y += s->region_size.Y;
}
region.lower_right = AddV2(region.upper_left, s->region_size);
draw_quad((DrawParams){true, q, spritesheet_img, region, tint, .y_coord_sorting = y_sort_pos, .alpha_clip_threshold = 0.2f});
}
// gets aabbs overlapping the input aabb, including entities and tiles // gets aabbs overlapping the input aabb, including entities and tiles
Overlapping get_overlapping(Level *l, AABB aabb) Overlapping get_overlapping(Level *l, AABB aabb)
{ {
@ -1903,11 +1957,13 @@ void frame(void)
sg_apply_pipeline(state.pip); sg_apply_pipeline(state.pip);
//colorquad(false, quad_at(V2(0.0, 100.0), V2(100.0f, 100.0f)), RED); //colorquad(false, quad_at(V2(0.0, 100.0), V2(100.0f, 100.0f)), RED);
sg_image img = image_wonky_mystery_tile; sg_image img = image_white_square;
AABB region = full_region(img); AABB region = full_region(img);
//region.lower_right.X *= 0.5f; //region.lower_right.X *= 0.5f;
draw_quad((DrawParams){false,quad_at(V2(0.0, 100.0), V2(100.0f, 100.0f)), img, region, WHITE}); draw_quad((DrawParams){false,quad_at(V2(0.0, 100.0), V2(100.0f, 100.0f)), img, region, WHITE});
flush_quad_batch();
sg_end_pass(); sg_end_pass();
sg_commit(); sg_commit();
reset(&scratch); reset(&scratch);
@ -2291,6 +2347,11 @@ void frame(void)
else if(it->is_character) else if(it->is_character)
{ {
} }
else if(it->is_prop)
{
Vec2 prop_size = V2(126.0f, 180.0f);
draw_quad((DrawParams){true, quad_centered(AddV2(it->pos, V2(0.0f, 70.0)), prop_size), image_props_atlas, aabb_at_yplusdown(V2(3.0f, 295.0f), prop_size), WHITE, .y_coord_sorting = y_coord_sorting_at(AddV2(it->pos, V2(0.0f, 20.0f))), .alpha_clip_threshold = 0.4f});
}
else else
{ {
assert(false); assert(false);
@ -2515,9 +2576,9 @@ draw_dialog_panel(talking_to);
total_height -= (total_height - (vertical_spacing + HELPER_SIZE)); total_height -= (total_height - (vertical_spacing + HELPER_SIZE));
const float padding = 50.0f; const float padding = 50.0f;
float y = screen_size().y/2.0f + total_height/2.0f; float y = screen_size().y/2.0f + total_height/2.0f;
draw_quad((DrawParams){false, quad_at(V2(padding, y), V2(HELPER_SIZE,HELPER_SIZE)), IMG(image_shift_icon), (Color){1.0f,1.0f,1.0f,fmaxf(0.0f, 1.0f-learned_shift)}}); draw_quad((DrawParams){false, quad_at(V2(padding, y), V2(HELPER_SIZE,HELPER_SIZE)), IMG(image_shift_icon), (Color){1.0f,1.0f,1.0f,fmaxf(0.0f, 1.0f-learned_shift)}, .y_coord_sorting = 0.0f});
y -= vertical_spacing; y -= vertical_spacing;
draw_quad((DrawParams){false, quad_at(V2(padding, y), V2(HELPER_SIZE,HELPER_SIZE)), IMG(image_space_icon), (Color){1.0f,1.0f,1.0f,fmaxf(0.0f, 1.0f-learned_space)}}); draw_quad((DrawParams){false, quad_at(V2(padding, y), V2(HELPER_SIZE,HELPER_SIZE)), IMG(image_space_icon), (Color){1.0f,1.0f,1.0f,fmaxf(0.0f, 1.0f-learned_space)}, .y_coord_sorting = 0.0f});
PROFILE_SCOPE("flush rendering") PROFILE_SCOPE("flush rendering")
{ {

@ -1,15 +1,15 @@
@module quad @module quad
@vs vs @vs vs
in vec2 position; in vec3 position;
in vec2 texcoord0; in vec2 texcoord0;
out vec2 uv; out vec2 uv;
out vec2 pos; out vec2 pos;
void main() { void main() {
gl_Position = vec4(position, 0.0, 1.0); gl_Position = vec4(position.xyz, 1.0);
uv = texcoord0; uv = texcoord0;
pos = position; pos = position.xy;
} }
@end @end
@ -21,6 +21,8 @@ uniform fs_params {
// both in clip space // both in clip space
vec2 clip_ul; vec2 clip_ul;
vec2 clip_lr; vec2 clip_lr;
float alpha_clip_threshold;
}; };
in vec2 uv; in vec2 uv;
@ -32,6 +34,10 @@ void main() {
// clip space is from [-1,1] [left, right]of screen on X, and [-1,1] [bottom, top] of screen on Y // clip space is from [-1,1] [left, right]of screen on X, and [-1,1] [bottom, top] of screen on Y
if(pos.x < clip_ul.x || pos.x > clip_lr.x || pos.y < clip_lr.y || pos.y > clip_ul.y) discard; if(pos.x < clip_ul.x || pos.x > clip_lr.x || pos.y < clip_lr.y || pos.y > clip_ul.y) discard;
frag_color = texture(tex, uv) * tint; frag_color = texture(tex, uv) * tint;
if(frag_color.a <= alpha_clip_threshold)
{
discard;
}
//frag_color = vec4(pos.x,0.0,0.0,1.0); //frag_color = vec4(pos.x,0.0,0.0,1.0);
} }
@end @end

@ -12,6 +12,7 @@ copy "EPIC RPG World Pack - Ancient Ruins V 1.7\EPIC RPG World Pack - Ancient Ru
copy "EPIC RPG World Pack - Ancient Ruins V 1.7\EPIC RPG World Pack - Ancient Ruins V 1.7\TiledMap Editor\Ancient Ruins-Animated Terrains-16 frames.tsx" "assets\copyrighted\ruins_animated.tsx" || goto :error copy "EPIC RPG World Pack - Ancient Ruins V 1.7\EPIC RPG World Pack - Ancient Ruins V 1.7\TiledMap Editor\Ancient Ruins-Animated Terrains-16 frames.tsx" "assets\copyrighted\ruins_animated.tsx" || goto :error
copy "EPIC RPG World Pack - Ancient Ruins V 1.7\EPIC RPG World Pack - Ancient Ruins V 1.7\TiledMap Editor\Terrain - Ancient Ruins.tsx" "assets\copyrighted\ruins_ancient.tsx" || goto :error copy "EPIC RPG World Pack - Ancient Ruins V 1.7\EPIC RPG World Pack - Ancient Ruins V 1.7\TiledMap Editor\Terrain - Ancient Ruins.tsx" "assets\copyrighted\ruins_ancient.tsx" || goto :error
copy "EPIC RPG World Pack - Ancient Ruins V 1.7\EPIC RPG World Pack - Ancient Ruins V 1.7\Tilesets\Tileset-Terrain.png" "assets\copyrighted\ruins_ancient.png" || goto :error copy "EPIC RPG World Pack - Ancient Ruins V 1.7\EPIC RPG World Pack - Ancient Ruins V 1.7\Tilesets\Tileset-Terrain.png" "assets\copyrighted\ruins_ancient.png" || goto :error
copy "EPIC RPG World Pack - Ancient Ruins V 1.7\EPIC RPG World Pack - Ancient Ruins V 1.7\Props\Atlas-Props.png" "assets\copyrighted\props.png" || goto :error
copy "Undead - Pixel Art Characters\Undead - Pixel Art Characters\Sprites\Wraith_Red.png" "assets\copyrighted\wraith.png" || goto :error copy "Undead - Pixel Art Characters\Undead - Pixel Art Characters\Sprites\Wraith_Red.png" "assets\copyrighted\wraith.png" || goto :error
copy "Undead - Pixel Art Characters\Undead - Pixel Art Characters\Sprites\Skeleton_Blue.png" "assets\copyrighted\skeleton.png" || goto :error copy "Undead - Pixel Art Characters\Undead - Pixel Art Characters\Sprites\Skeleton_Blue.png" "assets\copyrighted\skeleton.png" || goto :error

Loading…
Cancel
Save