diff --git a/echo_character.cpp b/echo_character.cpp index 8a8c1f2..f4b47e4 100644 --- a/echo_character.cpp +++ b/echo_character.cpp @@ -305,177 +305,71 @@ void echo_char::next_grid() grid1per = 1; } -/** Utility method that finds the point that is the intersection between the - * ray that starts at "prev_pos" and is in the direction of unit vector "vec", - * and the plane with y-coordinate "level_y". - * @param prev_pos The position the ray starts from. - * @param vec UNIT vector that the ray points in. - * @param level_y The y_coordinate of the - */ -static vector3f* end_pt(vector3f* prev_pos, vector3f* vec, float level_y) -{ - if(vec->y != 0) - { - float delta_y = level_y - prev_pos->y; - if((delta_y > 0 && vec->y < 0) || (delta_y < 0 && vec->y > 0)) - return(NULL); - vec = (*vec) * (delta_y / vec->y); - } - else - return(NULL); - vector3f* ret = *prev_pos + vec; - delete vec; - CHKPTR(ret); - return(ret); -} - -static grid* check_level(GRID_PTR_SET* level, vector3f* pos, vector3f* my_end_pt, vector3f angle) -{ - GRID_PTR_SET::iterator it = level->begin(), end = level->end(); - grid* g = NULL; - while(it != end) - { - g = *it; - if(g->is_pt_on(angle, my_end_pt)) - { - return(g); - } - it++; - } - return(NULL); -} - -static grid* check_levels_above(LEVEL_MAP* levels_above, vector3f* pos, vector3f* vec, vector3f angle) -{ - if(levels_above->size() < 1) - return(NULL); - LEVEL_MAP::iterator it = levels_above->begin(), end = levels_above->end(); - vector3f* pt = NULL; - grid* g = NULL; - while(it != end) - { - pt = end_pt(pos, vec, it->first); - if(pt == NULL) - { - pt = new vector3f(); - CHKPTR(pt); - pt->set(pos); - } - g = check_level(it->second, pos, pt, angle); - delete pt; - if(g != NULL) - return(g); - it++; - } - return(NULL); -} - -static grid* check_levels_below(LEVEL_MAP* levels_below, vector3f* pos, vector3f* vec, vector3f angle) -{ - if(levels_below->size() < 1) - return(NULL); - LEVEL_MAP::iterator it = levels_below->end(), end = levels_below->begin(); - vector3f* pt = NULL; - grid* g = NULL; - do - { - it--; - pt = end_pt(pos, vec, it->first); - if(pt == NULL) - { - pt = new vector3f(); - CHKPTR(pt); - pt->set(pos); - } - if(g != NULL) - return(g); - } - while(it != end); - return(NULL); -} - void echo_char::step() { gfx_color3f(0.5f, 0.5f, 0.5f); if(speed == SPEED_FALL_FROM_SKY) { draw(fall_position); - if(fall_position->y < target_y) + if(!paused) { - if(typeid(*grid1) == typeid(hole)) - initialize_falling(fall_position); + if(fall_position->y < target_y) + { + if(typeid(*grid1) == typeid(hole)) + initialize_falling(fall_position); + else + land(grid1, true); + } else - land(grid1, true); - } - else - { - if(!paused) + { /// Do the falling... fall_position->y -= actual_speed * WAIT / 1000; - } - if(!paused) + } actual_speed += ACCEL * WAIT / 1000; + } } else if(speed == SPEED_FALL) { - vector3f* relative_pos = fall_position->rotate_xy(echo_ns::angle); - draw(relative_pos); - if(relative_pos->y < echo_ns::get_lowest_level() - 5) - { - reset(); - } - else + vector3f* absolute_pos = fall_position->rotate_xy(echo_ns::angle); + draw(absolute_pos); + if(!paused) { - //check for available places to fall onto - grid* cam_grid = NULL; - vector3f* cam_real = echo_ns::angle.angle_to_real(); - vector3f* cam_vec = (*relative_pos) - cam_real; - vector3f* neg_cam_vec = cam_vec->negate(); - if(cam_real->y > 0) //viewing downwards + if(absolute_pos->y < echo_ns::get_lowest_level() - 5) { - LEVEL_MAP* levels_below = echo_ns::current_stage->get_levels_lower_than(relative_pos->y); - cam_grid = check_levels_below(levels_below, relative_pos, cam_vec, echo_ns::angle); - delete levels_below; - if(cam_grid == NULL || typeid(*cam_grid) == typeid(hole)) - { - LEVEL_MAP* levels_above = echo_ns::current_stage->get_levels_higher_than(relative_pos->y); - cam_grid = check_levels_above(levels_above, relative_pos, neg_cam_vec, echo_ns::angle); - delete levels_above; - } + reset(); } - else //viewing up + else { - LEVEL_MAP* levels_above = echo_ns::current_stage->get_levels_higher_than(relative_pos->y); - cam_grid = check_levels_above(levels_above, relative_pos, cam_vec, echo_ns::angle); - delete levels_above; - if(cam_grid == NULL || typeid(*cam_grid) == typeid(hole)) + //check for available places to fall onto + grid* cam_grid = NULL; + vector3f* next_absolute_pos = new vector3f(); + CHKPTR(next_absolute_pos); + next_absolute_pos->set(absolute_pos); + next_absolute_pos->y -= actual_speed * WAIT / 1000; + + vector3f* p1 = absolute_pos->neg_rotate_xy(echo_ns::angle); + vector3f* p2 = next_absolute_pos->neg_rotate_xy(echo_ns::angle); + cam_grid = echo_ns::current_stage->get_grid_intersection(p1, p2, echo_ns::angle); + + if(cam_grid != NULL && typeid(*cam_grid) != typeid(hole)) { - LEVEL_MAP* levels_below = echo_ns::current_stage->get_levels_lower_than(relative_pos->y); - cam_grid = check_levels_below(levels_below, relative_pos, neg_cam_vec, echo_ns::angle); - delete levels_below; + delete fall_position; + fall_position = NULL; + land(cam_grid, true); } - } - delete cam_real; - delete neg_cam_vec; - delete cam_vec; - if(cam_grid != NULL && typeid(*cam_grid) != typeid(hole)) - { - delete fall_position; - fall_position = NULL; - land(cam_grid, true); - } - else if(!paused) - { - //do the falling... - relative_pos->y -= actual_speed * WAIT / 1000; - actual_speed += ACCEL * WAIT / 1000; - //renew the fall_position - delete fall_position; - fall_position = relative_pos->neg_rotate_yx(echo_ns::angle); + else + { + //do the falling... + actual_speed += ACCEL * WAIT / 1000; + //renew the fall_position + delete fall_position; + fall_position = next_absolute_pos->neg_rotate_yx(echo_ns::angle); + } + delete next_absolute_pos; } } //delete the vector - delete relative_pos; + delete absolute_pos; } else if(grid1 != NULL) { diff --git a/echo_ingame_loader.cpp b/echo_ingame_loader.cpp index cf08e04..15f7dcc 100644 --- a/echo_ingame_loader.cpp +++ b/echo_ingame_loader.cpp @@ -43,6 +43,7 @@ #include #endif #include +#include #include #include #include @@ -71,7 +72,27 @@ STATUS echo_execdir(char** save) GetModuleFileName(NULL, exe, MAX_PATH); return(echo_parentdir(exe, save)); #elif ECHO_OSX + /// Just use cwd + *save = NULL; + int size = 0; + char* result = 0; + do + { + size += PATH_MAX; + if(*save != NULL) + delete *save; + *save = new char[size]; + CHKPTR(*save); + result = getcwd(*save, size * sizeof(char)); + } + while(result == NULL && errno == ERANGE); + if(result == NULL) + return(FAIL); + else + return(WIN); #else + + //* //copied from l-portable //step 1: get the directory of this binary @@ -120,6 +141,7 @@ STATUS echo_execdir(char** save) strcpy(*save, pwd); return(WIN); } + // */ #endif } return(FAIL); diff --git a/echo_loader.cpp b/echo_loader.cpp index 89b0043..9f2c24b 100644 --- a/echo_loader.cpp +++ b/echo_loader.cpp @@ -1204,7 +1204,10 @@ static grid* parse_grid(echo_xml_element* txe, stage* st, DEPENDENCY_MAP* map, e if(echo_xml_get_int_attribute(txe, "noland", &noland) == WIN) { if(noland) + { + new_grid->set_land(0); LD_PRINT("it's not land-able!\n"); + } } if(!escroot) { diff --git a/echo_math.cpp b/echo_math.cpp index 59ceb66..1c16aef 100644 --- a/echo_math.cpp +++ b/echo_math.cpp @@ -176,13 +176,47 @@ vector3f* vector3f::rotate_xy(vector3f rot) return(ret); } +vector3f* vector3f::neg_rotate_xy(vector3f rot) +{ + if(rot.x == 0 && rot.y == 0 && rot.z == 0) + { + vector3f* ret = new vector3f(x, y, z); + CHKPTR(ret); + return(ret); + } + vector3f* ret = new vector3f(x + , y * ECHO_COSF(-rot.x) - z * ECHO_SINF(-rot.x) + , y * ECHO_SINF(-rot.x) + z * ECHO_COSF(-rot.x)); + CHKPTR(ret); + float z_save = ret->z; + ret->z = ret->z * ECHO_COSF(-rot.y) - ret->x * ECHO_SINF(-rot.y); + ret->x = z_save * ECHO_SINF(-rot.y) + ret->x * ECHO_COSF(-rot.y); + return(ret); +} + void vector3f::set(float my_x, float my_y, float my_z) { x = my_x; y = my_y; z = my_z; } - +vector3f* vector3f::rotate_yx(vector3f rot) +{ + //float rad_x = -TO_RAD(rot.x), rad_y = -TO_RAD(rot.y); + if(rot.x == 0 && rot.y == 0 && rot.z == 0) + { + vector3f* ret = new vector3f(x, y, z); + CHKPTR(ret); + return(ret); + } + vector3f* ret = new vector3f(z * ECHO_SINF(rot.y) + x * ECHO_COSF(rot.y), y + , z * ECHO_COSF(rot.y) - x * ECHO_SINF(rot.y)); + CHKPTR(ret); + float y_save = ret->y; + ret->y = ret->y * ECHO_COSF(rot.x) - ret->z * ECHO_SINF(rot.x); + ret->z = y_save * ECHO_SINF(rot.x) + ret->z * ECHO_COSF(rot.x); + return(ret); +} vector3f* vector3f::neg_rotate_yx(vector3f rot) { //float rad_x = -TO_RAD(rot.x), rad_y = -TO_RAD(rot.y); @@ -299,6 +333,37 @@ STATUS IK_angle(float length1, float length2, float distance, float* angle) return(WIN); } +/// Adapted from http://www.idevgames.com/forum/showthread.php?t=7458 +int lineSeg_intersect(vector3f* a1, vector3f* a2, vector3f* b1, vector3f* b2) +{ + float a1yb1y = a1->y - b1->y; + float a1xb1x = a1->x - b1->x; + float a2xa1x = a2->x - a1->x; + float a2ya1y = a2->y - a1->y; + + //---------------------------------------------------------------------- + + float crossa = a1yb1y * (b2->x - b1->x) - a1xb1x * (b2->y - b1->y); + float crossb = a2xa1x * (b2->y - b1->y) - a2ya1y * (b2->x - b1->x); + + //---------------------------------------------------------------------- + + if(crossb == 0) + return(false); + else if(fabs(crossa) > fabs(crossb) || crossa * crossb < 0) + return(false); + else + { + crossa = a1yb1y * a2xa1x - a1xb1x * a2ya1y; + if(fabs(crossa) > fabs(crossb) || crossa * crossb < 0) + return(false); + } + + //---------------------------------------------------------------------- + + return(true); +} + //-----------ANGLE_RANGE---------- angle_range::angle_range(vector3f* my_v1, vector3f* my_v2) diff --git a/echo_math.h b/echo_math.h index a63e4f4..5c9db4c 100644 --- a/echo_math.h +++ b/echo_math.h @@ -55,8 +55,10 @@ class vector3f vector3f* angle_xy(); //rotate from the screen to the world via the camera angle vector3f* rotate_xy(vector3f rot); + vector3f* neg_rotate_xy(vector3f rot); //rotate from the world to the screen via the camera angle vector3f* neg_rotate_yx(vector3f rot); + vector3f* rotate_yx(vector3f rot); //rotate around y axis, putting it in a new vector vector3f* rotate_about_y(float angle); //rotate around y axis, putting answers bak in myself @@ -105,6 +107,8 @@ class angle_range #define VECPTR_TO_RANGE(v) (new angle_range(v, v)) STATUS IK_angle(float length1, float length2, float distance, float* angle); +int lineSeg_intersect(vector3f* a1, vector3f* a2, vector3f* b1, vector3f* b2); + float echo_sin(int deg); float echo_cos(int deg); float echo_sin(float deg); diff --git a/echo_stage.cpp b/echo_stage.cpp index 3625797..9220060 100644 --- a/echo_stage.cpp +++ b/echo_stage.cpp @@ -209,6 +209,34 @@ int stage::get_num_goals() return(num_goals); } +grid* stage::get_grid_intersection(vector3f* p1, vector3f* p2, vector3f angle) +{ + grid* ret = NULL; + float shortest_dist = FLT_MAX; + STAGE_MAP::iterator it = grids->begin(); + STAGE_MAP::iterator end = grids->end(); + while(it != end) + { + if(it->second->should_land(angle) && it->second->projected_line_intersect(p1, p2, angle)) + { + grid_info_t* info = it->second->get_info(angle); + if(info != NULL) + { + vector3f* rot = info->pos->rotate_xy(angle); + float dist = p1->dist(rot); + if(dist < shortest_dist) + { + ret = it->second; + shortest_dist = dist; + } + delete rot; + } + } + it++; + } + return(ret); +} + LEVEL_MAP* stage::get_levels_lower_than(float y) { LEVEL_MAP::iterator it = levels->begin(), end = levels->end(); diff --git a/echo_stage.h b/echo_stage.h index 7583370..d3ab2dc 100644 --- a/echo_stage.h +++ b/echo_stage.h @@ -63,6 +63,8 @@ class stage void set_name(std::string* name); void set_num_goals(int num_goals); + grid* get_grid_intersection(vector3f* p1, vector3f* p2, vector3f angle); + grid* get_start(); std::string* get_name(); int get_num_goals(); diff --git a/escgrid.cpp b/escgrid.cpp index 5105c18..b041208 100644 --- a/escgrid.cpp +++ b/escgrid.cpp @@ -266,3 +266,14 @@ int escgrid::is_goal(vector3f angle) grid* esc = get_esc(angle); return(esc ? esc->is_goal(angle) : grid::is_goal(angle)); } +int escgrid::should_land(vector3f angle) +{ + grid* esc = get_esc(angle); + return(esc ? esc->should_land(angle) : grid::should_land(angle)); +} + +int escgrid::projected_line_intersect(vector3f* p1, vector3f* p2, vector3f angle) +{ + grid* esc = get_esc(angle); + return(esc ? esc->projected_line_intersect(p1, p2, angle) : grid::projected_line_intersect(p1, p2, angle)); +} diff --git a/escgrid.h b/escgrid.h index c09ad6e..8d76cbd 100644 --- a/escgrid.h +++ b/escgrid.h @@ -49,9 +49,13 @@ class escgrid : public grid //virtual line3f* get_lines(vector3f angle); virtual void draw(vector3f angle); virtual int equals(grid* g, vector3f angle); - + + virtual int should_land(vector3f angle); + virtual void set_as_goal(); + virtual int projected_line_intersect(vector3f* p1, vector3f* p2, vector3f angle); + virtual void toggle_goal(vector3f angle); virtual int is_goal(vector3f angle); virtual void init_to_null(); diff --git a/grid.cpp b/grid.cpp index 9c90074..fc6ddd7 100644 --- a/grid.cpp +++ b/grid.cpp @@ -87,6 +87,7 @@ void grid::init_to_null() polyID = 0; #endif already_init = 1; + landable = 1; } void grid::init(grid_info_t* my_info, grid* my_prev, grid* my_next, int my_num_neighbors) @@ -327,6 +328,51 @@ float grid::vert_shift(float percent_in) //return(-0.05f); return(0.05f * echo_cos(360 * percent_in) - 0.05f); } + +int grid::projected_line_intersect(vector3f* p1, vector3f* p2, vector3f angle) +{ + vector3f* proj_pt0 = points[0]->neg_rotate_xy(angle); + vector3f* proj_pt1 = points[1]->neg_rotate_xy(angle); + vector3f* proj_pt2 = points[2]->neg_rotate_xy(angle); + vector3f* proj_pt3 = points[3]->neg_rotate_xy(angle); + + /* + ECHO_PRINT("points of grid: "); + ginfo->pos->dump(); + ECHO_PRINT("\n"); + points[0]->dump(); + proj_pt0->dump(); + ECHO_PRINT("\n"); + proj_pt1->dump(); + ECHO_PRINT("\n"); + proj_pt2->dump(); + ECHO_PRINT("\n"); + proj_pt3->dump(); + ECHO_PRINT("\n"); + ECHO_PRINT("\npoints: "); + p1->dump(); + ECHO_PRINT("\n"); + p2->dump(); + ECHO_PRINT("\n"); + ECHO_PRINT("\n"); + // */ + int ret = lineSeg_intersect(p1, p2, proj_pt0, proj_pt1) + || lineSeg_intersect(p1, p2, proj_pt1, proj_pt2) + || lineSeg_intersect(p1, p2, proj_pt2, proj_pt3) + || lineSeg_intersect(p1, p2, proj_pt3, proj_pt0); + delete proj_pt0, proj_pt1, proj_pt2, proj_pt3; + return(ret); +} + +void grid::set_land(int land) +{ + landable = land; +} +int grid::should_land(vector3f angle) +{ + return(landable); +} + #ifdef ECHO_NDS unsigned int grid::get_polyID(vector3f angle) { diff --git a/grid.h b/grid.h index 8a37355..6544627 100644 --- a/grid.h +++ b/grid.h @@ -57,6 +57,7 @@ class grid int am_goal; //int goal_angle; int draw_me; + int landable; int already_init; TRIGGER_SET* triggers; @@ -105,9 +106,14 @@ class grid virtual int should_draw(); virtual void set_draw(int draw); virtual void draw(vector3f angle); + + virtual void set_land(int land); + virtual int should_land(vector3f angle); virtual int is_pt_on(vector3f angle, vector3f* pt); + virtual int projected_line_intersect(vector3f* p1, vector3f* p2, vector3f angle); + virtual float vert_shift(float percent_in); void draw_goal(vector3f angle); diff --git a/perspective_fall.xml b/perspective_fall.xml index e336473..8f17ada 100644 --- a/perspective_fall.xml +++ b/perspective_fall.xml @@ -8,8 +8,8 @@ - - + +