Posted By: 3run
Ellipsoid collisions - 01/08/18 14:26
Hi!
Here is my simplified version of Helgast's ellipsoid collision between entities from RPG Toolkit!
Code:
Could be used for pushing NPCs etc. Credit goes to Helghast!
Greets!
Here is my simplified version of Helgast's ellipsoid collision between entities from RPG Toolkit!
Code:
Code:
#define PRAGMA_POINTER #define TRACE_FLAGS (IGNORE_ME | IGNORE_PASSABLE | IGNORE_PASSENTS | IGNORE_MAPS | IGNORE_SPRITES | IGNORE_CONTENT) #define MOVE_FLAGS (IGNORE_ME | IGNORE_PASSABLE | IGNORE_PASSENTS | IGNORE_MAPS | IGNORE_SPRITES | IGNORE_CONTENT) #define obj_radius skill60 #define obj_type skill61 #define NONE 0 #define NPC 1 void draw_collider(ENTITY *ent, COLOR *c, var radius){ // do elipsoid drawing for debug here VECTOR temp_pos, temp_next_pos; vec_fill(&temp_pos, 0); vec_fill(&temp_next_pos, 0); int i = 0; for(i = 0; i < 360; i += 30){ // get current rotational piece vec_set(&temp_pos, vector(radius, 0, 0)); vec_rotate(&temp_pos, vector(i, 0, 0)); vec_add(&temp_pos, &ent->x); // get next rotational position vec_set(&temp_next_pos, vector(radius, 0, 0)); vec_rotate(&temp_next_pos, vector(i + 30, 0, 0)); vec_add(&temp_next_pos, &ent->x); // draw a "quad" to show the collision shape draw_line3d(vector(temp_pos.x, temp_pos.y, temp_pos.z - ent->max_z), c, 0); draw_line3d(vector(temp_pos.x, temp_pos.y, temp_pos.z - ent->max_z), c, 100); draw_line3d(vector(temp_pos.x, temp_pos.y, temp_pos.z + ent->max_z), c, 100); draw_line3d(vector(temp_next_pos.x, temp_next_pos.y, temp_next_pos.z + ent->max_z), c, 100); draw_line3d(vector(temp_next_pos.x, temp_next_pos.y, temp_next_pos.z + ent->max_z), c, 0); draw_line3d(vector(temp_pos.x, temp_pos.y, temp_pos.z - ent->max_z), c, 0); draw_line3d(vector(temp_pos.x, temp_pos.y, temp_pos.z - ent->max_z), c, 100); draw_line3d(vector(temp_next_pos.x, temp_next_pos.y, temp_next_pos.z - ent->max_z), c, 100); draw_line3d(vector(temp_next_pos.x, temp_next_pos.y, temp_next_pos.z - ent->max_z), c, 0); } } ENTITY *find_closest_collider(ENTITY *ent){ ENTITY *pointer = NULL; ENTITY *closest = NULL; var closest_distance = 999999; for(pointer = ent_next(NULL); pointer; pointer = ent_next(pointer)){ // push only NPCs if(pointer->obj_type != NPC){ continue; } // if the next entity is not the same as the looking entity if(pointer != ent){ // if the distance is closer then the previous closest entity if(vec_dist(&ent->x, &pointer->x) < closest_distance){ // set new closest distance closest_distance = vec_dist(&ent->x, &pointer->x); // you are the closest entity to look at now closest = pointer; } } } if(closest != NULL){ return(closest); } return(NULL); } void elipsoid_collision(ENTITY *ent){ ENTITY *collider = NULL; ent->obj_radius = ent->max_x * 4; while(ent){ collider = find_closest_collider(ent); if(collider != NULL){ // distance check on collider and push away of too close (faked elipsoid collision) if(vec_dist(&ent->x, &collider->x) < ent->obj_radius){ VECTOR temp; vec_diff(&temp, &collider->x, &ent->x); ANGLE temp_ang; vec_to_angle(&temp_ang, &temp); // angle to the player vec_set(&temp, vector(ent->x + ent->obj_radius * cos(temp_ang.pan), ent->y + ent->obj_radius * sin(temp_ang.pan), 0)); vec_diff(&temp, &temp, &collider->x); temp.z = 0; vec_scale(&temp, time_step); c_move(collider, nullvector, &temp, MOVE_FLAGS | GLIDE); } } wait(1); } } void npc(){ set(my, TRANSLUCENT | LIGHT | UNLIT | POLYGON); vec_set(&my->scale_x, vector(1, 1, 1)); c_setminmax(my); my->obj_type = NPC; } void main(){ warn_level = 6; fps_max = 60; level_load(""); wait(3); mouse_mode = 4; sun_light = 0; camera->arc = 15; set(camera, ISOMETRIC); vec_set(&camera->x, vector(0, 0, 128)); vec_set(&camera->pan, vector(0, -90, 0)); ENTITY *hero = ent_create(CUBE_MDL, vector(0, 0, 0), NULL); set(hero, TRANSLUCENT | LIGHT | UNLIT); vec_set(&hero->scale_x, vector(1, 1, 1)); c_setminmax(hero); hero->obj_type = NPC; elipsoid_collision(hero); ent_create(CUBE_MDL, vector(0, 32, 0), npc); ent_create(CUBE_MDL, vector(0, -32, 0), npc); while(hero){ VECTOR temp; vec_set(&temp, vector(mouse_pos.x, mouse_pos.y, 128)); vec_for_screen(&temp, camera); vec_set(&hero->x, &temp); draw_collider(hero, COLOR_RED, hero->obj_radius); if(key_space){ fps_max = 20; } else{ fps_max = 60; } wait(1); } }
Greets!