Object bounding boxes are defined in the tiled map editor, alongside navmeshes.
parent
6cf3dbd607
commit
b7f31cdeaf
5
Makefile
5
Makefile
|
@ -58,7 +58,10 @@ sprite_%.o: $(PROJECT_ROOT)sprites/%.xcf
|
||||||
@# symbols are _binary_sprite_%_raw_start / _end / _size
|
@# symbols are _binary_sprite_%_raw_start / _end / _size
|
||||||
|
|
||||||
navmesh_%.c: $(PROJECT_ROOT)navmesh/%.tmx $(PROJECT_ROOT)compile_navmesh.py
|
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
|
%.png: $(PROJECT_ROOT)sprites/%.xcf
|
||||||
gimp -in -b '(let ((image (car (gimp-xcf-load 0 "$<" "$(notdir $<)")))) ;\
|
gimp -in -b '(let ((image (car (gimp-xcf-load 0 "$<" "$(notdir $<)")))) ;\
|
||||||
|
|
|
@ -14,16 +14,21 @@ def points_to_edges(points):
|
||||||
points = points + [points[0]]
|
points = points + [points[0]]
|
||||||
return zip(points[:-1], points[1:])
|
return zip(points[:-1], points[1:])
|
||||||
|
|
||||||
for polygon in tree.findall("objectgroup[@name='navmesh']/object/polygon"):
|
def parse_object_polygon_points(object):
|
||||||
basex = int(polygon.getparent().attrib["x"])
|
polygon_data = object.find("polygon")
|
||||||
basey = int(polygon.getparent().attrib["y"])
|
basex = int(object.attrib["x"])
|
||||||
points=[]
|
basey = int(object.attrib["y"])
|
||||||
for point in polygon.attrib["points"].split(" "):
|
if polygon_data is None:
|
||||||
x,y=point.split(",")
|
# It's a rectangle by default
|
||||||
x,y=int(x)+basex,int(y)+basey
|
width = float(object.attrib["width"])
|
||||||
points.append((x,y))
|
height = float(object.attrib["height"])
|
||||||
#print(points)
|
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]
|
ax,ay=points[0]
|
||||||
bx,by=points[1]
|
bx,by=points[1]
|
||||||
cx,cy=points[2]
|
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)
|
# positive for clockwise winding order. Example clockwise winding order: (0,0), (1,0), (0,1)
|
||||||
if cross < 0:
|
if cross < 0:
|
||||||
points = points[::-1]
|
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)
|
poly_id = len(polys)
|
||||||
polys.append(points)
|
polys.append(points)
|
||||||
|
@ -69,23 +91,14 @@ for dest in range(len(polys)):
|
||||||
out = open(outpath,"w")
|
out = open(outpath,"w")
|
||||||
|
|
||||||
out.write("#include \"compiled_structures.h\"\n")
|
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");
|
out.write(f"static const struct navmesh_tri {basename}_triangles[{len(polys)}] = {{\n");
|
||||||
for poly_id,points in enumerate(polys):
|
for poly_id,points in enumerate(polys):
|
||||||
out.write("\t{\n")
|
out.write("\t{\n")
|
||||||
out.write("\t\t"+str(len(points))+",\n")
|
out.write("\t\t"+str(len(points))+",\n")
|
||||||
out.write("\t\t(const struct navmesh_tri_edge[]){\n")
|
out.write("\t\t(const struct navmesh_tri_edge[]){\n")
|
||||||
for a,b in points_to_edges(points):
|
for a,b in points_to_edges(points):
|
||||||
(ax,ay),(bx,by) = a,b
|
P,Q,R = get_edge_equation(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
|
|
||||||
|
|
||||||
edge_id = tuple(sorted((a,b)))
|
edge_id = tuple(sorted((a,b)))
|
||||||
polys_on_edge = edge2poly[edge_id]
|
polys_on_edge = edge2poly[edge_id]
|
||||||
assert len(polys_on_edge) in (1,2)
|
assert len(polys_on_edge) in (1,2)
|
||||||
|
@ -95,12 +108,10 @@ for poly_id,points in enumerate(polys):
|
||||||
else:
|
else:
|
||||||
other_poly_id = -1
|
other_poly_id = -1
|
||||||
|
|
||||||
|
(ax,ay),(bx,by)=a,b
|
||||||
centx, centy = (ax+bx)/2, (ay+by)/2
|
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(f"\t\t\t{{{P},{Q},{R},{other_poly_id},{{{int(centx)},{int(centy)}}}}},\n")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
out.write("\t\t},\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\t(const struct navmesh_point[]){" + ",".join(f"{{{x},{y}}}" for x,y in points) + "},\n")
|
||||||
out.write("\t},\n");
|
out.write("\t},\n");
|
||||||
|
@ -112,4 +123,21 @@ for dest in range(len(polys)):
|
||||||
out.write(str(pathfind_matrix[source][dest])+",")
|
out.write(str(pathfind_matrix[source][dest])+",")
|
||||||
out.write("\n")
|
out.write("\n")
|
||||||
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")
|
||||||
|
|
|
@ -6,8 +6,8 @@ struct navmesh_point {
|
||||||
int x, y;
|
int x, y;
|
||||||
};
|
};
|
||||||
struct navmesh_tri_edge {
|
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.
|
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 triangle it connects to
|
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_point center; // intermediate point for use in routing. could be improved later.
|
||||||
};
|
};
|
||||||
struct navmesh_tri {
|
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.
|
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_ */
|
#endif /* COMPILED_STRUCTURES_H_ */
|
||||||
|
|
8
engine.h
8
engine.h
|
@ -9,6 +9,7 @@ struct object {
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
const char *pixels;
|
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);
|
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 replace_scene(int scene);
|
||||||
void pop_scene();
|
void pop_scene();
|
||||||
void scene_add_clickrect(int id, int x, int y, int width, int height);
|
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 object *find_object_by_id(int id);
|
||||||
struct script *scene_add_script(int id, bool interrupt_existing);
|
struct script *scene_add_script(int id, bool interrupt_existing);
|
||||||
struct script *scene_get_script(int id);
|
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_MANAGERS_OFFICE_SAFE 3
|
||||||
#define SCENE_BASEMENT 4
|
#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
|
// game.cpp
|
||||||
void scene_setup(int scene, int fromscene);
|
void scene_setup(int scene, int fromscene);
|
||||||
void onclick(int curscene, int objid);
|
void onclick(int curscene, int objid);
|
||||||
|
|
43
game.cpp
43
game.cpp
|
@ -1,6 +1,7 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
|
#include "objids.h"
|
||||||
|
|
||||||
#define BGWIDTH 1280
|
#define BGWIDTH 1280
|
||||||
#define BGHEIGHT 800
|
#define BGHEIGHT 800
|
||||||
|
@ -15,53 +16,41 @@ extern const char _binary_sprite_stickman_raw_start[];
|
||||||
extern struct navmesh navmesh_lobby;
|
extern struct navmesh navmesh_lobby;
|
||||||
extern struct navmesh navmesh_managers_office;
|
extern struct navmesh navmesh_managers_office;
|
||||||
extern struct navmesh navmesh_basement;
|
extern struct navmesh navmesh_basement;
|
||||||
|
extern struct level_predef_data predef_basement, predef_lobby, predef_managers_office;
|
||||||
|
|
||||||
#define OBJID_BACKGROUND 1
|
static void create_player(int x, int y) {
|
||||||
#define OBJID_DOOR_TO_MANAGERS_OFFICE_FROM_LOBBY 2
|
const int WIDTH=51, HEIGHT=111;
|
||||||
#define OBJID_DOOR_TO_LOBBY_FROM_MANAGERS_OFFICE 3
|
scene_add_object(OBJID_PLAYER, x-WIDTH/2, y-HEIGHT, WIDTH, HEIGHT, _binary_sprite_stickman_raw_start);
|
||||||
// #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
|
|
||||||
|
|
||||||
void scene_setup(int scene, int fromscene) {
|
void scene_setup(int scene, int fromscene) {
|
||||||
top_scene.render_fn = standard_scene_render;
|
top_scene.render_fn = standard_scene_render;
|
||||||
switch(scene) {
|
switch(scene) {
|
||||||
case SCENE_LOBBY:
|
case SCENE_LOBBY:
|
||||||
scene_add_object(OBJID_BACKGROUND, 0, 0, BGWIDTH, BGHEIGHT, _binary_sprite_lobby_raw_start);
|
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) {
|
switch(fromscene) {
|
||||||
case SCENE_MANAGERS_OFFICE:
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
scene_add_object(OBJID_PLAYER, 424, 575, 51, 111, _binary_sprite_stickman_raw_start);
|
create_player(424, 675);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
top_scene.navmesh = &navmesh_lobby;
|
top_scene.navmesh = &navmesh_lobby;
|
||||||
break;
|
break;
|
||||||
case SCENE_MANAGERS_OFFICE:
|
case SCENE_MANAGERS_OFFICE:
|
||||||
scene_add_object(OBJID_BACKGROUND, 0, 0, BGWIDTH, BGHEIGHT, _binary_sprite_managers_office_raw_start);
|
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_load_predef(&predef_managers_office);
|
||||||
scene_add_object(OBJID_MANAGERS_OFFICE_TRAPDOOR, 332, 565, 139, 87, nullptr);
|
|
||||||
scene_add_object(OBJID_MANAGERS_OFFICE_SAFE, 784, 297, 191, 188, nullptr);
|
|
||||||
switch(fromscene) {
|
switch(fromscene) {
|
||||||
case SCENE_LOBBY:
|
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;
|
break;
|
||||||
case SCENE_BASEMENT:
|
case SCENE_BASEMENT:
|
||||||
scene_add_object(OBJID_PLAYER, 408-51/2, 559-111, 51, 111, _binary_sprite_stickman_raw_start);
|
create_player(408, 559);
|
||||||
break;
|
|
||||||
case SCENE_MANAGERS_OFFICE_SAFE:
|
|
||||||
scene_add_object(OBJID_PLAYER, 895-51/2, 497-111, 51, 111, _binary_sprite_stickman_raw_start);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
scene_add_object(OBJID_PLAYER, 424, 575, 51, 111, _binary_sprite_stickman_raw_start);
|
create_player(424, 675);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
top_scene.navmesh = &navmesh_managers_office;
|
top_scene.navmesh = &navmesh_managers_office;
|
||||||
|
@ -73,13 +62,13 @@ void scene_setup(int scene, int fromscene) {
|
||||||
break;
|
break;
|
||||||
case SCENE_BASEMENT:
|
case SCENE_BASEMENT:
|
||||||
scene_add_object(OBJID_BACKGROUND, 0, 0, BGWIDTH, BGHEIGHT, _binary_sprite_basement_raw_start);
|
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) {
|
switch(fromscene) {
|
||||||
case SCENE_MANAGERS_OFFICE:
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
scene_add_object(OBJID_PLAYER, 424, 575, 51, 111, _binary_sprite_stickman_raw_start);
|
create_player(424, 675);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
top_scene.navmesh = &navmesh_basement;
|
top_scene.navmesh = &navmesh_basement;
|
||||||
|
|
|
@ -1,34 +1,5 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<map version="1.9" tiledversion="1.9.2" orientation="orthogonal" renderorder="right-down" width="40" height="25" tilewidth="32" tileheight="32" infinite="0" nextlayerid="5" nextobjectid="4">
|
<map version="1.9" tiledversion="1.9.2" orientation="orthogonal" renderorder="right-down" width="40" height="25" tilewidth="32" tileheight="32" infinite="0" nextlayerid="5" nextobjectid="4">
|
||||||
<layer id="1" name="Tile Layer 1" width="40" height="25">
|
|
||||||
<data encoding="csv">
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
||||||
</data>
|
|
||||||
</layer>
|
|
||||||
<imagelayer id="2" name="Image Layer 1">
|
<imagelayer id="2" name="Image Layer 1">
|
||||||
<image source="../build/default/basement.png" width="1280" height="800"/>
|
<image source="../build/default/basement.png" width="1280" height="800"/>
|
||||||
</imagelayer>
|
</imagelayer>
|
||||||
|
@ -40,7 +11,7 @@
|
||||||
<polygon points="0,0 -101,174 821,174 679,-74 248,-76"/>
|
<polygon points="0,0 -101,174 821,174 679,-74 248,-76"/>
|
||||||
</object>
|
</object>
|
||||||
</objectgroup>
|
</objectgroup>
|
||||||
<objectgroup id="4" name="Object Layer 2">
|
<objectgroup id="4" name="clickable">
|
||||||
<object id="3" x="396" y="86" width="85" height="312"/>
|
<object id="3" name="OBJID_BASEMENT_LADDER" x="396" y="86" width="85" height="312"/>
|
||||||
</objectgroup>
|
</objectgroup>
|
||||||
</map>
|
</map>
|
||||||
|
|
|
@ -1,40 +1,10 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<map version="1.9" tiledversion="1.9.2" orientation="orthogonal" renderorder="right-down" width="40" height="25" tilewidth="32" tileheight="32" infinite="0" nextlayerid="5" nextobjectid="19">
|
<map version="1.9" tiledversion="1.9.2" orientation="orthogonal" renderorder="right-down" width="40" height="25" tilewidth="32" tileheight="32" infinite="0" nextlayerid="5" nextobjectid="19">
|
||||||
<layer id="1" name="Tile Layer 1" width="40" height="25">
|
|
||||||
<data encoding="csv">
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
||||||
</data>
|
|
||||||
</layer>
|
|
||||||
<imagelayer id="2" name="Image Layer 1">
|
<imagelayer id="2" name="Image Layer 1">
|
||||||
<image source="../build/default/lobby.png" width="1280" height="800"/>
|
<image source="../build/default/lobby.png" width="1280" height="800"/>
|
||||||
</imagelayer>
|
</imagelayer>
|
||||||
<objectgroup id="3" name="Object Layer 1">
|
<objectgroup id="3" name="clickable">
|
||||||
<object id="1" x="273" y="313" width="76" height="128"/>
|
<object id="1" name="OBJID_DOOR_TO_MANAGERS_OFFICE_FROM_LOBBY" x="273" y="313" width="76" height="128"/>
|
||||||
<object id="3" x="908" y="322" width="53" height="117"/>
|
|
||||||
</objectgroup>
|
</objectgroup>
|
||||||
<objectgroup id="4" name="navmesh">
|
<objectgroup id="4" name="navmesh">
|
||||||
<object id="10" x="213" y="441">
|
<object id="10" x="213" y="441">
|
||||||
|
|
|
@ -1,29 +1,5 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<map version="1.9" tiledversion="1.9.2" orientation="orthogonal" renderorder="right-down" width="30" height="20" tilewidth="32" tileheight="32" infinite="0" nextlayerid="5" nextobjectid="22">
|
<map version="1.9" tiledversion="1.9.2" orientation="orthogonal" renderorder="right-down" width="30" height="20" tilewidth="32" tileheight="32" infinite="0" nextlayerid="5" nextobjectid="24">
|
||||||
<layer id="1" name="Tile Layer 1" width="30" height="20">
|
|
||||||
<data encoding="csv">
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
||||||
</data>
|
|
||||||
</layer>
|
|
||||||
<imagelayer id="2" name="Image Layer 1">
|
<imagelayer id="2" name="Image Layer 1">
|
||||||
<image source="../build/default/managers_office.png" width="1280" height="800"/>
|
<image source="../build/default/managers_office.png" width="1280" height="800"/>
|
||||||
</imagelayer>
|
</imagelayer>
|
||||||
|
@ -62,9 +38,13 @@
|
||||||
<polygon points="0,0 0,60 135,60"/>
|
<polygon points="0,0 0,60 135,60"/>
|
||||||
</object>
|
</object>
|
||||||
</objectgroup>
|
</objectgroup>
|
||||||
<objectgroup id="4" name="Object Layer 2">
|
<objectgroup id="4" name="clickable">
|
||||||
<object id="19" x="740" y="440" width="151" height="276"/>
|
<object id="19" name="OBJID_DOOR_TO_LOBBY_FROM_MANAGERS_OFFICE" x="740" y="440" width="151" height="276"/>
|
||||||
<object id="20" x="332" y="565" width="139" height="87"/>
|
<object id="22" name="OBJID_MANAGERS_OFFICE_TRAPDOOR" x="347" y="563">
|
||||||
<object id="21" x="784" y="297" width="191" height="188"/>
|
<polygon points="0,0 -37,91 113,91 127,-1"/>
|
||||||
|
</object>
|
||||||
|
<object id="23" name="OBJID_MANAGERS_OFFICE_SAFE" x="784" y="417">
|
||||||
|
<polygon points="0,0 1,-122 150,-122 193,-79 192,75 40,75"/>
|
||||||
|
</object>
|
||||||
</objectgroup>
|
</objectgroup>
|
||||||
</map>
|
</map>
|
||||||
|
|
|
@ -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
|
|
@ -18,6 +18,7 @@
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
#include "compiled_structures.h"
|
#include "compiled_structures.h"
|
||||||
|
#include "objids.h"
|
||||||
|
|
||||||
#define PLAYFIELD_WIDTH 1280
|
#define PLAYFIELD_WIDTH 1280
|
||||||
#define PLAYFIELD_HEIGHT 800
|
#define PLAYFIELD_HEIGHT 800
|
||||||
|
@ -182,7 +183,7 @@ void pop_scene() {
|
||||||
// any cleanup?
|
// 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");
|
if(id == 0) error(1, 0, "scene_add_object: id 0 is invalid");
|
||||||
|
|
||||||
struct object *objects = top_scene.objects;
|
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].width = width;
|
||||||
objects[i].height = height;
|
objects[i].height = height;
|
||||||
objects[i].pixels = pixels;
|
objects[i].pixels = pixels;
|
||||||
return;
|
return &objects[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
error(1, 0, "too many game objects");
|
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 *find_object_by_id(int id) {
|
||||||
struct object *objects = top_scene.objects;
|
struct object *objects = top_scene.objects;
|
||||||
for(int i = 0; i < MAX_OBJECTS_PER_SCENE; i++) {
|
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 navmesh *cur_navmesh = top_scene.navmesh;
|
||||||
struct object *objects = top_scene.objects;
|
struct object *objects = top_scene.objects;
|
||||||
for(int i = 0; i < MAX_OBJECTS_PER_SCENE; i++) {
|
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) {
|
if(!objects[i].id) continue;
|
||||||
onclick(sceneid, objects[i].id);
|
if(objects[i].clickregion) {
|
||||||
if(top_scene.id != sceneid) return; // early exit if scene changed, and don't walk the player either
|
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
|
if(walkgen == player_walk_generation) { // no other handler moved the player
|
||||||
|
|
Loading…
Reference in New Issue