From b7f31cdeafb47bb04781f3c28ddae507aaf50a59 Mon Sep 17 00:00:00 2001 From: immibis Date: Tue, 18 Feb 2025 23:11:20 +0100 Subject: [PATCH] Object bounding boxes are defined in the tiled map editor, alongside navmeshes. --- Makefile | 5 ++- compile_navmesh.py | 78 +++++++++++++++++++++++++------------ compiled_structures.h | 16 +++++++- engine.h | 8 ++-- game.cpp | 43 ++++++++------------ navmesh/basement.tmx | 33 +--------------- navmesh/lobby.tmx | 34 +--------------- navmesh/managers_office.tmx | 38 +++++------------- objids.h | 12 ++++++ pinetab2_framework.cpp | 31 ++++++++++++--- 10 files changed, 141 insertions(+), 157 deletions(-) create mode 100644 objids.h diff --git a/Makefile b/Makefile index 5e6ce20..83e1928 100644 --- a/Makefile +++ b/Makefile @@ -58,7 +58,10 @@ sprite_%.o: $(PROJECT_ROOT)sprites/%.xcf @# symbols are _binary_sprite_%_raw_start / _end / _size navmesh_%.c: $(PROJECT_ROOT)navmesh/%.tmx $(PROJECT_ROOT)compile_navmesh.py - python3 "$(PROJECT_ROOT)compile_navmesh.py" "$<" "$@" "$(basename $@)" + python3 "$(PROJECT_ROOT)compile_navmesh.py" "$<" "$@" "$(patsubst navmesh_%.c,%,$@)" + @# symbols are navmesh_% and predef_% + +navmesh_%.o: $(PROJECT_ROOT)compiled_structures.h $(PROJECT_ROOT)objids.h %.png: $(PROJECT_ROOT)sprites/%.xcf gimp -in -b '(let ((image (car (gimp-xcf-load 0 "$<" "$(notdir $<)")))) ;\ diff --git a/compile_navmesh.py b/compile_navmesh.py index 5f49df6..cdbc2c2 100644 --- a/compile_navmesh.py +++ b/compile_navmesh.py @@ -14,16 +14,21 @@ def points_to_edges(points): points = points + [points[0]] return zip(points[:-1], points[1:]) -for polygon in tree.findall("objectgroup[@name='navmesh']/object/polygon"): - basex = int(polygon.getparent().attrib["x"]) - basey = int(polygon.getparent().attrib["y"]) - points=[] - for point in polygon.attrib["points"].split(" "): - x,y=point.split(",") - x,y=int(x)+basex,int(y)+basey - points.append((x,y)) - #print(points) - +def parse_object_polygon_points(object): + polygon_data = object.find("polygon") + basex = int(object.attrib["x"]) + basey = int(object.attrib["y"]) + if polygon_data is None: + # It's a rectangle by default + width = float(object.attrib["width"]) + height = float(object.attrib["height"]) + points = [(basex, basey), (basex + width, basey), (basex + width, basey + height), (basex, basey + height)] + else: + points = [] + for point in polygon_data.attrib["points"].split(" "): + x,y=point.split(",") + points.append((int(x)+basex, int(y)+basey)) + # check winding order ax,ay=points[0] bx,by=points[1] cx,cy=points[2] @@ -33,6 +38,23 @@ for polygon in tree.findall("objectgroup[@name='navmesh']/object/polygon"): # positive for clockwise winding order. Example clockwise winding order: (0,0), (1,0), (0,1) if cross < 0: points = points[::-1] + return points + +# Returns P,Q,R such that Px+Qy+R=0 for points on the edge, and >0 for points on the right (inside polygon for clockwise winding order) +def get_edge_equation(a, b): + (ax,ay),(bx,by)=a,b + # Line equation Px+Qy+R=0 from https://math.stackexchange.com/questions/422602/convert-two-points-to-line-eq-ax-by-c-0 + P,Q,R=ay-by,bx-ax,ax*by-bx*ay + # Line equation >0 for points inside the triangle. + # Normalize so that P^2+Q^2=1 so that the equation result tells us the distance. This can be used to find the closest triangle to a point. + norm=1/math.sqrt(P*P+Q*Q) + P *= norm + Q *= norm + R *= norm + return P,Q,R + +for object in tree.findall("objectgroup[@name='navmesh']/object"): + points = parse_object_polygon_points(object) poly_id = len(polys) polys.append(points) @@ -69,23 +91,14 @@ for dest in range(len(polys)): out = open(outpath,"w") out.write("#include \"compiled_structures.h\"\n") +out.write("#include \"objids.h\"\n") out.write(f"static const struct navmesh_tri {basename}_triangles[{len(polys)}] = {{\n"); for poly_id,points in enumerate(polys): out.write("\t{\n") out.write("\t\t"+str(len(points))+",\n") out.write("\t\t(const struct navmesh_tri_edge[]){\n") for a,b in points_to_edges(points): - (ax,ay),(bx,by) = a,b - # edge a-b and c is the other point - # Line equation Px+Qy+R=0 from https://math.stackexchange.com/questions/422602/convert-two-points-to-line-eq-ax-by-c-0 - P,Q,R=ay-by,bx-ax,ax*by-bx*ay - # Line equation >0 for points inside the triangle. - # Normalize so that P^2+Q^2=1 so that the equation result tells us the distance. This can be used to find the closest triangle to a point. - norm=1/math.sqrt(P*P+Q*Q) - P *= norm - Q *= norm - R *= norm - + P,Q,R = get_edge_equation(a,b) edge_id = tuple(sorted((a,b))) polys_on_edge = edge2poly[edge_id] assert len(polys_on_edge) in (1,2) @@ -95,12 +108,10 @@ for poly_id,points in enumerate(polys): else: other_poly_id = -1 + (ax,ay),(bx,by)=a,b centx, centy = (ax+bx)/2, (ay+by)/2 out.write(f"\t\t\t{{{P},{Q},{R},{other_poly_id},{{{int(centx)},{int(centy)}}}}},\n") - - - out.write("\t\t},\n") out.write("\t\t(const struct navmesh_point[]){" + ",".join(f"{{{x},{y}}}" for x,y in points) + "},\n") out.write("\t},\n"); @@ -112,4 +123,21 @@ for dest in range(len(polys)): out.write(str(pathfind_matrix[source][dest])+",") out.write("\n") out.write("};\n") -out.write(f"extern const struct navmesh {basename} = {{{len(polys)}, {basename}_triangles, {basename}_pathfind}};\n") +out.write(f"extern const struct navmesh navmesh_{basename} = {{{len(polys)}, {basename}_triangles, {basename}_pathfind}};\n") + +out.write("extern const struct level_predef_data predef_"+basename+" = {\n") +out.write("\t(const struct level_clickregion[]){\n") # clickregions start +for object in tree.findall("objectgroup[@name='clickable']/object"): + out.write("\t\t{\n"); + points = parse_object_polygon_points(object) + out.write("\t\t\t"+object.attrib["name"]+",\n") + out.write("\t\t\t" + str(len(points)) + ",\n") + out.write("\t\t\t(const struct level_clickregion_edge[]){\n") + for a,b in points_to_edges(points): + P,Q,R = get_edge_equation(a,b) + out.write(f"\t\t\t\t{{{P},{Q},{R}}},\n") + out.write("\t\t\t},\n") + out.write("\t\t},\n"); +out.write("\t\t{0}\n") +out.write("\t},\n") # clickregions end +out.write("};\n") diff --git a/compiled_structures.h b/compiled_structures.h index 14d0e55..a3d3f01 100644 --- a/compiled_structures.h +++ b/compiled_structures.h @@ -6,8 +6,8 @@ struct navmesh_point { int x, y; }; struct navmesh_tri_edge { - float a,b,c; // line equation a*x + b*y + c > 0 if point is in triangle, and value gives distance from line. - int other_tri; // -1 if this edge is a border of navmesh, else triangle it connects to + float a,b,c; // line equation a*x + b*y + c > 0 if point is in polygon, and value gives distance from line. + int other_tri; // -1 if this edge is a border of navmesh, else polygon it connects to struct navmesh_point center; // intermediate point for use in routing. could be improved later. }; struct navmesh_tri { @@ -25,5 +25,17 @@ struct navmesh { const unsigned char *pathfindgrid; // [dest*num_tris + source] gives index of next tri. Placeholder value is used when dest==source. }; +struct level_clickregion_edge { + float a,b,c; // line equation a*x + b*y + c > 0 if point is in polygon +}; +struct level_clickregion { + int id; + int num_edges; + const struct level_clickregion_edge *edges; +}; +struct level_predef_data { + const struct level_clickregion *clickregions; // terminated by null entry +}; + #endif /* COMPILED_STRUCTURES_H_ */ diff --git a/engine.h b/engine.h index 62d2459..6942887 100644 --- a/engine.h +++ b/engine.h @@ -9,6 +9,7 @@ struct object { int width; int height; const char *pixels; + const struct level_clickregion *clickregion; // if not null, overrides click bounds check }; typedef void (*script_wake_fn)(struct script *scr, int wakeupMode, int arg1, int arg2, int arg3, int arg4); @@ -54,7 +55,8 @@ void push_scene(int scene); void replace_scene(int scene); void pop_scene(); void scene_add_clickrect(int id, int x, int y, int width, int height); -void scene_add_object(int id, int x, int y, int width, int height, const char *pixels); +struct object *scene_add_object(int id, int x, int y, int width, int height, const char *pixels); +void scene_load_predef(const struct level_predef_data *predef); struct object *find_object_by_id(int id); struct script *scene_add_script(int id, bool interrupt_existing); struct script *scene_get_script(int id); @@ -67,10 +69,6 @@ void start_player_walk_to_point(int x, int y); // x and y are not corrected to l #define SCENE_MANAGERS_OFFICE_SAFE 3 #define SCENE_BASEMENT 4 -// The player ID and walk script are globally relevant -#define OBJID_PLAYER 4 -#define OBJID_PLAYER_WALK_SCRIPT 5 - // game.cpp void scene_setup(int scene, int fromscene); void onclick(int curscene, int objid); diff --git a/game.cpp b/game.cpp index 68979e3..e4c2511 100644 --- a/game.cpp +++ b/game.cpp @@ -1,6 +1,7 @@ #include #include #include "engine.h" +#include "objids.h" #define BGWIDTH 1280 #define BGHEIGHT 800 @@ -15,53 +16,41 @@ extern const char _binary_sprite_stickman_raw_start[]; extern struct navmesh navmesh_lobby; extern struct navmesh navmesh_managers_office; extern struct navmesh navmesh_basement; +extern struct level_predef_data predef_basement, predef_lobby, predef_managers_office; -#define OBJID_BACKGROUND 1 -#define OBJID_DOOR_TO_MANAGERS_OFFICE_FROM_LOBBY 2 -#define OBJID_DOOR_TO_LOBBY_FROM_MANAGERS_OFFICE 3 -// #define OBJID_PLAYER 4 -// #define SCRIPTID_PLAYER_WALK 5 -#define OBJID_PLAYER_WALK_TO_DOOR_SCRIPT 6 -#define OBJID_MANAGERS_OFFICE_SAFE 7 -#define OBJID_MANAGERS_OFFICE_TRAPDOOR 8 -#define OBJID_BASEMENT_POPCORN 9 -#define OBJID_BASEMENT_ELECTRICAL_BOX 10 -#define OBJID_BASEMENT_LADDER 11 -#define OBJID_CLOSE_MODAL 12 +static void create_player(int x, int y) { + const int WIDTH=51, HEIGHT=111; + scene_add_object(OBJID_PLAYER, x-WIDTH/2, y-HEIGHT, WIDTH, HEIGHT, _binary_sprite_stickman_raw_start); +} void scene_setup(int scene, int fromscene) { top_scene.render_fn = standard_scene_render; switch(scene) { case SCENE_LOBBY: scene_add_object(OBJID_BACKGROUND, 0, 0, BGWIDTH, BGHEIGHT, _binary_sprite_lobby_raw_start); - scene_add_object(OBJID_DOOR_TO_MANAGERS_OFFICE_FROM_LOBBY, 273, 313, 76, 128, nullptr); + scene_load_predef(&predef_lobby); switch(fromscene) { case SCENE_MANAGERS_OFFICE: - scene_add_object(OBJID_PLAYER, 308-51/2, 445-111, 51, 111, _binary_sprite_stickman_raw_start); + create_player(308, 445); break; default: - scene_add_object(OBJID_PLAYER, 424, 575, 51, 111, _binary_sprite_stickman_raw_start); + create_player(424, 675); break; } top_scene.navmesh = &navmesh_lobby; break; case SCENE_MANAGERS_OFFICE: scene_add_object(OBJID_BACKGROUND, 0, 0, BGWIDTH, BGHEIGHT, _binary_sprite_managers_office_raw_start); - scene_add_object(OBJID_DOOR_TO_LOBBY_FROM_MANAGERS_OFFICE, 740, 440, 151, 276, nullptr); - scene_add_object(OBJID_MANAGERS_OFFICE_TRAPDOOR, 332, 565, 139, 87, nullptr); - scene_add_object(OBJID_MANAGERS_OFFICE_SAFE, 784, 297, 191, 188, nullptr); + scene_load_predef(&predef_managers_office); switch(fromscene) { case SCENE_LOBBY: - scene_add_object(OBJID_PLAYER, 804-51/2, 708-111, 51, 111, _binary_sprite_stickman_raw_start); + create_player(804, 708); break; case SCENE_BASEMENT: - scene_add_object(OBJID_PLAYER, 408-51/2, 559-111, 51, 111, _binary_sprite_stickman_raw_start); - break; - case SCENE_MANAGERS_OFFICE_SAFE: - scene_add_object(OBJID_PLAYER, 895-51/2, 497-111, 51, 111, _binary_sprite_stickman_raw_start); + create_player(408, 559); break; default: - scene_add_object(OBJID_PLAYER, 424, 575, 51, 111, _binary_sprite_stickman_raw_start); + create_player(424, 675); break; } top_scene.navmesh = &navmesh_managers_office; @@ -73,13 +62,13 @@ void scene_setup(int scene, int fromscene) { break; case SCENE_BASEMENT: scene_add_object(OBJID_BACKGROUND, 0, 0, BGWIDTH, BGHEIGHT, _binary_sprite_basement_raw_start); - scene_add_object(OBJID_BASEMENT_LADDER, 396, 86, 85, 312, nullptr); + scene_load_predef(&predef_basement); switch(fromscene) { case SCENE_MANAGERS_OFFICE: - scene_add_object(OBJID_PLAYER, 435-51/2, 404-111, 51, 111, _binary_sprite_stickman_raw_start); + create_player(435, 404); break; default: - scene_add_object(OBJID_PLAYER, 424, 575, 51, 111, _binary_sprite_stickman_raw_start); + create_player(424, 675); break; } top_scene.navmesh = &navmesh_basement; diff --git a/navmesh/basement.tmx b/navmesh/basement.tmx index 347309e..8f05873 100644 --- a/navmesh/basement.tmx +++ b/navmesh/basement.tmx @@ -1,34 +1,5 @@ - - -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - - @@ -40,7 +11,7 @@ - - + + diff --git a/navmesh/lobby.tmx b/navmesh/lobby.tmx index 8e70227..f810e96 100644 --- a/navmesh/lobby.tmx +++ b/navmesh/lobby.tmx @@ -1,40 +1,10 @@ - - -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - - - - - + + diff --git a/navmesh/managers_office.tmx b/navmesh/managers_office.tmx index d6f2b2d..0436a0d 100644 --- a/navmesh/managers_office.tmx +++ b/navmesh/managers_office.tmx @@ -1,29 +1,5 @@ - - - -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - - + @@ -62,9 +38,13 @@ - - - - + + + + + + + + diff --git a/objids.h b/objids.h new file mode 100644 index 0000000..9042a43 --- /dev/null +++ b/objids.h @@ -0,0 +1,12 @@ +#define OBJID_BACKGROUND 1 +#define OBJID_DOOR_TO_MANAGERS_OFFICE_FROM_LOBBY 2 +#define OBJID_DOOR_TO_LOBBY_FROM_MANAGERS_OFFICE 3 +#define OBJID_PLAYER 4 +#define OBJID_PLAYER_WALK_SCRIPT 5 +#define OBJID_PLAYER_WALK_TO_DOOR_SCRIPT 6 +#define OBJID_MANAGERS_OFFICE_SAFE 7 +#define OBJID_MANAGERS_OFFICE_TRAPDOOR 8 +#define OBJID_BASEMENT_POPCORN 9 +#define OBJID_BASEMENT_ELECTRICAL_BOX 10 +#define OBJID_BASEMENT_LADDER 11 +#define OBJID_CLOSE_MODAL 12 diff --git a/pinetab2_framework.cpp b/pinetab2_framework.cpp index 1217f9b..bd7d94e 100644 --- a/pinetab2_framework.cpp +++ b/pinetab2_framework.cpp @@ -18,6 +18,7 @@ #include #include "engine.h" #include "compiled_structures.h" +#include "objids.h" #define PLAYFIELD_WIDTH 1280 #define PLAYFIELD_HEIGHT 800 @@ -182,7 +183,7 @@ void pop_scene() { // any cleanup? } -void scene_add_object(int id, int x, int y, int width, int height, const char *pixels) { +struct object *scene_add_object(int id, int x, int y, int width, int height, const char *pixels) { if(id == 0) error(1, 0, "scene_add_object: id 0 is invalid"); struct object *objects = top_scene.objects; @@ -194,12 +195,19 @@ void scene_add_object(int id, int x, int y, int width, int height, const char *p objects[i].width = width; objects[i].height = height; objects[i].pixels = pixels; - return; + return &objects[i]; } } error(1, 0, "too many game objects"); } +void scene_load_predef(const struct level_predef_data *predef) { + for(const struct level_clickregion *cr = predef->clickregions; cr->num_edges; cr++) { + struct object *obj = scene_add_object(cr->id, 0, 0, 0, 0, nullptr); + obj->clickregion = cr; + } +} + struct object *find_object_by_id(int id) { struct object *objects = top_scene.objects; for(int i = 0; i < MAX_OBJECTS_PER_SCENE; i++) { @@ -360,10 +368,23 @@ void handle_tap(int x, int y) { struct navmesh *cur_navmesh = top_scene.navmesh; struct object *objects = top_scene.objects; for(int i = 0; i < MAX_OBJECTS_PER_SCENE; i++) { - if(objects[i].id && (unsigned int)(x - objects[i].x) < objects[i].width && (unsigned int)(y - objects[i].y) < objects[i].height) { - onclick(sceneid, objects[i].id); - if(top_scene.id != sceneid) return; // early exit if scene changed, and don't walk the player either + if(!objects[i].id) continue; + if(objects[i].clickregion) { + const struct level_clickregion *cr = objects[i].clickregion; + for(int i = 0; i < cr->num_edges; i++) { + if(cr->edges[i].a*x + cr->edges[i].b*y + cr->edges[i].c < 0) + goto click_not_on_object; + } + } else { + if((unsigned int)(x - objects[i].x) >= objects[i].width || (unsigned int)(y - objects[i].y) >= objects[i].height) + goto click_not_on_object; } + + // clicked on the object + onclick(sceneid, objects[i].id); + if(top_scene.id != sceneid) return; // early exit if scene changed, and don't walk the player either + + click_not_on_object:; } if(walkgen == player_walk_generation) { // no other handler moved the player