#include "scene_map.hpp" extern Game game; extern Windmill windmill; // import des map extern Map map_village; extern Map map_interieur_forgeron; // import des objets extern Object chaumiere1; extern Object panneau1; extern Object forgeron1; //---------------------------------------------------------------------------------------------------- // CONSTRUCTOR //---------------------------------------------------------------------------------------------------- Scene_Map::Scene_Map() { // debug show_repere = false; show_coordinates = false; // histoire vue_horloge = false; vue_panneau_moulin = false; parle_avec_forgeron = false; } //---------------------------------------------------------------------------------------------------- // LAUNCH //---------------------------------------------------------------------------------------------------- void Scene_Map::launch() { time_scene = 0; load_map(); windmill.set_camera(&camera); // histoire // ... } void Scene_Map::load_map() { // mise a jour de la map pour la scene windmill.load_map(game.map); // creation des bouding box 3D //delete bbox; free(bbox); //bbox = new Bbox3D[game.map->list_object_length]; bbox = (Bbox3D*) malloc(game.map->list_object_length * sizeof(Bbox3D)); //if (bbox == NULL) debug_pop("ERROR ptr bbox NULL"); memset(bbox, 0, game.map->list_object_length * sizeof(Bbox3D)); for (int i=0; ilist_object_length; i++) { Object* current_object = game.map->object[i]; Bbox3D* current_bbox = &bbox[i]; int nb_poly = (current_object->collision < 0) ? current_object->modele_size : current_object->collision; if (nb_poly > current_object->modele_size) nb_poly = current_object->modele_size; for (int j=0; jmodele[j]; for (int k=0; ktype; k++) { Point point = windmill.get_point(current_modele, k); current_bbox->x1 = min(current_bbox->x1, point.x); current_bbox->y1 = min(current_bbox->y1, point.y); current_bbox->z1 = min(current_bbox->z1, point.z); current_bbox->x2 = max(current_bbox->x2, point.x); current_bbox->y2 = max(current_bbox->y2, point.y); current_bbox->z2 = max(current_bbox->z2, point.z); } } if (current_object->axe == Z_BILLBOARD) { current_bbox->radius = max(current_bbox->y1, current_bbox->y2); } } // mise a zero du temps sur la map time_scene = 0; } //---------------------------------------------------------------------------------------------------- // DRAW //---------------------------------------------------------------------------------------------------- void Scene_Map::draw() { //ML_clear_vram(); dclear(C_WHITE); windmill.draw(); // MAP VILLAGE if (game.map == &map_village) { if (vue_panneau_moulin) { //ML_rectangle(34, 15, 95, 50, 0, ML_WHITE, ML_WHITE); //PrintXY(34, 20, "MOULIN DES", 0); //PrintXY(52, 30, "RIBES", 0); //PrintMini(45, 45, "NineStars", 0); } } // MAP INTERIEUR FORGERON if (game.map == &map_interieur_forgeron) { if (parle_avec_forgeron) { //Point point_ancrage = windmill.get_point(&forgeron1.modele, 0); //ML_rectangle(50, 10, 118, 54, 1, ML_BLACK, ML_WHITE); } } if (show_repere) windmill.show_repere(); if (show_coordinates) windmill.show_coordinates(); //ML_display_vram(); dupdate(); } //---------------------------------------------------------------------------------------------------- // UPDATE //---------------------------------------------------------------------------------------------------- void Scene_Map::update() { time_scene += 0.02; // gestion des touches /*if (input_trigger(K_EXIT)) { scene = EXIT; return; } if (input_trigger(K_MENU)) { scene = SCENE_TITLE; return; } if (input_trigger(K_F1)) { scene = SCENE_MAP_DEBUG; return; } if (input_trigger(K_F2)) { show_repere = !show_repere; } if (input_trigger(K_F3)) { show_coordinates = !show_coordinates; }*/ // action du joueur sur la map player_action(); // animation des objets sur la map animation(); // mouvements du joueur if (game.player.can_move) { player_move(); player_turn(); } if (game.player.dissociate_camera == false) { camera.set(game.player.x, game.player.y, game.player.z + game.player.height, game.player.yaw, game.player.pitch); } //debug_display(id(windmill.object_cursor), 3); //debug_display(windmill.poly_cursor, 4); } void Scene_Map::player_action() { // MAP VILLAGE if (game.map == &map_village) { /*if (input_trigger(K_EXE)) { if (action_object(object(20))) { if (vue_panneau_moulin) { game.player.can_move = true; game.player.dissociate_camera = false; windmill.set_camera(&camera); } else { game.player.can_move = false; game.player.dissociate_camera = true; look(&panneau1, 0, 8, 17, 270, -10); windmill.set_camera(&camera_look); } vue_panneau_moulin = not vue_panneau_moulin; } }*/ } // MAP INTERIEUR FORGERON if (game.map == &map_interieur_forgeron) { /*if (input_trigger(K_EXE)) { // interaction avec le forgeron if (parle_avec_forgeron) { parle_avec_forgeron = false; game.player.can_move = true; game.player.dissociate_camera = false; } else { if (action_object(&forgeron1)) { parle_avec_forgeron = true; game.player.can_move = false; game.player.dissociate_camera = true; camera.set(-23, 4, game.player.height, 198, 0); } } }*/ } } void Scene_Map::animation() { // MAP VILLAGE if (game.map == &map_village) { object(6)->angle -= 1; } } void Scene_Map::player_move() { /*///////////// METTRE DANS PLAYER ET RETURN LE FLAG float new_x = game.player.x; float new_y = game.player.y; float new_z = game.player.z; // deplacement float front, side; input_move(&front, &side); // si des touches sont pressees if (side != 0 or front != 0) { game.player.moving = true; //game.player.translation_speed = min(game.player.translation_speed + 0.25, game.player.translation_speed_max); if (game.player.translation_speed < game.player.translation_speed_max) { game.player.translation_speed += game.player.translation_acceleration; // acceleration } else { game.player.translation_speed = game.player.translation_speed_max; } // conversion dans le repere monde float angle_rad = game.player.yaw * 3.1415 / 180.0; float x = (front * cosf(angle_rad) - side * sinf(angle_rad)) * game.player.translation_speed; float y = (front * sinf(angle_rad) + side * cosf(angle_rad)) * game.player.translation_speed; new_x += x; new_y += y; } else { game.player.moving = false; game.player.translation_speed = 0; } // saut if (input_press(K_8) and not game.player.jumping) { game.player.jump_speed = game.player.jump_speed_max; game.player.jumping = true; } else { game.player.jump_speed -= 0.981; // gravite } new_z += game.player.jump_speed; // collision flag = collision(&new_x, &new_y, &new_z); // contact avec le sol ou un objet if (flag.type == COLLISION_GROUND or flag.type == COLLISION_ON) { game.player.jumping = false; game.player.jump_speed = 0; } // hors terrain if (flag.type == COLLISION_BOUND) { debug_display("trop loin", 2); } game.player.x = new_x; game.player.y = new_y; game.player.z = new_z; */ } void Scene_Map::player_turn() {/* float yaw = 0; float pitch = 0; if (input_press(K_RIGHT)) yaw = -1; if (input_press(K_LEFT)) yaw = 1; if (input_press(K_DOWN)) pitch = -0.5; if (input_press(K_UP)) pitch = 0.5; if (yaw != 0 or pitch != 0) { game.player.turning = true; if (game.player.rotation_speed < game.player.rotation_speed_max) { game.player.rotation_speed += float(game.player.rotation_speed_max / 10.0); } } else { game.player.turning = false; game.player.rotation_speed = 0; } yaw = game.player.yaw + yaw * game.player.rotation_speed; pitch = game.player.pitch + pitch * game.player.rotation_speed; if (yaw < 0) yaw += 360; if (yaw >= 360) yaw -= 360; if (pitch > 90) pitch = 90; if (pitch < -90) pitch = -90; game.player.yaw = yaw; game.player.pitch = pitch; */ } //----------------------------------------------------------------------------- // COLLISION // renvoie le type de la derniere collision detectee // 0 rien // 1 sol // 2 cote objet // 3 dessus objet // 4 z_billboard // 5 hors terrain //----------------------------------------------------------------------------- Collision_flag Scene_Map::collision(float* new_x, float* new_y, float* new_z) { Collision_flag flag; float belly = game.player.belly; float total_height = game.player.total_height; flag.type = COLLISION_NONE; flag.object = NULL; if (*new_z <= 0) { *new_z = 0; flag.type = COLLISION_GROUND; } for (int i = 0; ilist_object_length; i++) { Object* current_object = game.map->object[i]; // si une bbox a ete cree pour l objet if (current_object->collision != 0) { Bbox3D* current_bbox = &bbox[i]; float cosinus, sinus; float player_x, player_y, player_z; float temp_new_x, temp_new_y, temp_new_z; // si objet.axe != N if (current_object->axe == Z) { float angle = 3.1415 * current_object->angle / 180.0; cosinus = cosf(angle); sinus = sinf(angle); player_x = cosinus * (game.player.x-current_object->x) + sinus * (game.player.y-current_object->y); player_y = - sinus * (game.player.x-current_object->x) + cosinus * (game.player.y-current_object->y); player_z = game.player.z - current_object->z; temp_new_x = cosinus * (*new_x-current_object->x) + sinus * (*new_y-current_object->y); temp_new_y = - sinus * (*new_x-current_object->x) + cosinus * (*new_y-current_object->y); temp_new_z = *new_z - current_object->z; } else { cosinus = 1; sinus = 0; player_x = game.player.x - current_object->x; player_y = game.player.y - current_object->y; player_z = game.player.z - current_object->z; temp_new_x = *new_x - current_object->x; temp_new_y = *new_y - current_object->y; temp_new_z = *new_z - current_object->z; } if (temp_new_z > current_bbox->z2) { // player au dessus // si je mets rien ici, on pourra pas sauter sur une caisse... } else if (temp_new_z + total_height < current_bbox->z1) { // player en dessous } else { // détermine si INT ou EXT //if (game.player.x > current_bbox->x1 and game.player.x < current_bbox->x2 and // game.player.y > current_bbox->y1 and game.player.y < current_bbox->y2) if (current_object->collision < 0) { // si player a l interieur de l objet if (temp_new_x - belly < current_bbox->x1) { temp_new_x = current_bbox->x1 + belly; } if (temp_new_x + belly > current_bbox->x2) { temp_new_x = current_bbox->x2 - belly; } if (temp_new_y - belly < current_bbox->y1) { temp_new_y = current_bbox->y1 + belly; } if (temp_new_y + belly > current_bbox->y2) { temp_new_y = current_bbox->y2 - belly; } *new_x = cosinus * temp_new_x - sinus * temp_new_y + current_object->x; *new_y = sinus * temp_new_x + cosinus * temp_new_y + current_object->y; if (flag.type <= COLLISION_WALL) { flag.type = COLLISION_WALL; flag.object = current_object; } } else { if (current_object->axe == Z_BILLBOARD) { bool inside_after = belly < current_bbox->radius; if (inside_after) { //debug_pop("collsiosn"); if (flag.type <= COLLISION_CARA) { flag.type = COLLISION_CARA; flag.object = current_object; } } } else { bool inside_after = (temp_new_x + belly > current_bbox->x1 and temp_new_x - belly < current_bbox->x2 and temp_new_y + belly > current_bbox->y1 and temp_new_y - belly < current_bbox->y2); // si player a l exterieur de l objet if (inside_after) { // player rentre dans objet par le haut if (player_z >= current_bbox->z2 and temp_new_z < current_bbox->z2) { temp_new_z = current_object->z + current_bbox->z2; *new_z = temp_new_z; if (flag.type <= COLLISION_ON) { flag.type = COLLISION_ON; flag.object = current_object; } } else { // si on rentre dans l'objet if (player_x < current_bbox->x1) { temp_new_x = current_bbox->x1 - belly; } if (player_x > current_bbox->x2) // modifier par un else ? { temp_new_x = current_bbox->x2 + belly; } if (player_y < current_bbox->y1) { temp_new_y = current_bbox->y1 - belly; } if (player_y > current_bbox->y2) { temp_new_y = current_bbox->y2 + belly; } // transformation inverse *new_x = cosinus * temp_new_x - sinus * temp_new_y + current_object->x; *new_y = sinus * temp_new_x + cosinus * temp_new_y + current_object->y; if (flag.type <= COLLISION_WALL) { flag.type = COLLISION_WALL; flag.object = current_object; } } } } } } } } if (*new_x * *new_x + *new_y * *new_y > MAP_EXTERIOR_LIMIT * MAP_EXTERIOR_LIMIT) { flag.type = COLLISION_BOUND; *new_x = game.player.x; *new_y = game.player.y; } return flag; } /*Collision_flag Scene_Map::collision(float* new_x, float* new_y, float* new_z) { Collision_flag flag; float belly = game.player.belly; float total_height = game.player.total_height; flag.type = COLLISION_NONE; flag.object = NULL; if (*new_z <= 0) { *new_z = 0; flag.type = COLLISION_GROUND; } for (int i = 0; ilist_object_length; i++) { Object* current_object = game.map->object[i]; // si une bbox a ete cree pour l objet if (current_object->for_collision != 0) { Bbox3D* current_bbox = &bbox[i]; float cosinus, sinus; float player_x, player_y, player_z; float temp_new_x, temp_new_y, temp_new_z; // si objet.axe != N if (current_object->axe == Z) { float angle = 3.1415 * current_object->angle / 180.0; cosinus = cosf(angle); sinus = sinf(angle); player_x = cosinus * (game.player.x-current_object->x) + sinus * (game.player.y-current_object->y); player_y = - sinus * (game.player.x-current_object->x) + cosinus * (game.player.y-current_object->y); player_z = game.player.z - current_object->z; temp_new_x = cosinus * (*new_x-current_object->x) + sinus * (*new_y-current_object->y); temp_new_y = - sinus * (*new_x-current_object->x) + cosinus * (*new_y-current_object->y); temp_new_z = *new_z - current_object->z; } else { cosinus = 1; sinus = 0; player_x = game.player.x - current_object->x; player_y = game.player.y - current_object->y; player_z = game.player.z - current_object->z; temp_new_x = *new_x - current_object->x; temp_new_y = *new_y - current_object->y; temp_new_z = *new_z - current_object->z; } if (temp_new_z > current_bbox->z2) { // player au dessus // si je mets rien ici, on pourra pas sauter sur une caisse... } else if (temp_new_z + total_height < current_bbox->z1) { // player en dessous } else { // détermine si INT ou EXT //if (game.player.x > current_bbox->x1 and game.player.x < current_bbox->x2 and // game.player.y > current_bbox->y1 and game.player.y < current_bbox->y2) if (current_object->type_collision == OUT) { // si player a l interieur de l objet if (temp_new_x - belly < current_bbox->x1) { temp_new_x = current_bbox->x1 + belly; } if (temp_new_x + belly > current_bbox->x2) { temp_new_x = current_bbox->x2 - belly; } if (temp_new_y - belly < current_bbox->y1) { temp_new_y = current_bbox->y1 + belly; } if (temp_new_y + belly > current_bbox->y2) { temp_new_y = current_bbox->y2 - belly; } *new_x = cosinus * temp_new_x - sinus * temp_new_y + current_object->x; *new_y = sinus * temp_new_x + cosinus * temp_new_y + current_object->y; if (flag.type <= COLLISION_WALL) { flag.type = COLLISION_WALL; flag.object = current_object; } } if (current_object->type_collision == IN) { if (current_object->axe == Z_BILLBOARD) { bool inside_after = belly < current_bbox->radius; if (inside_after) { //debug_pop("collsiosn"); if (flag.type <= COLLISION_CARA) { flag.type = COLLISION_CARA; flag.object = current_object; } } } else { bool inside_after = (temp_new_x + belly > current_bbox->x1 and temp_new_x - belly < current_bbox->x2 and temp_new_y + belly > current_bbox->y1 and temp_new_y - belly < current_bbox->y2); // si player a l exterieur de l objet if (inside_after) { // player rentre dans objet par le haut if (player_z >= current_bbox->z2 and temp_new_z < current_bbox->z2) { temp_new_z = current_object->z + current_bbox->z2; *new_z = temp_new_z; if (flag.type <= COLLISION_ON) { flag.type = COLLISION_ON; flag.object = current_object; } } else { // si on rentre dans l'objet if (player_x < current_bbox->x1) { temp_new_x = current_bbox->x1 - belly; } if (player_x > current_bbox->x2) // modifier par un else ? { temp_new_x = current_bbox->x2 + belly; } if (player_y < current_bbox->y1) { temp_new_y = current_bbox->y1 - belly; } if (player_y > current_bbox->y2) { temp_new_y = current_bbox->y2 + belly; } // transformation inverse *new_x = cosinus * temp_new_x - sinus * temp_new_y + current_object->x; *new_y = sinus * temp_new_x + cosinus * temp_new_y + current_object->y; if (flag.type <= COLLISION_WALL) { flag.type = COLLISION_WALL; flag.object = current_object; } } } } } } } } if (*new_x * *new_x + *new_y * *new_y > MAP_EXTERIOR_LIMIT * MAP_EXTERIOR_LIMIT) { flag.type = COLLISION_BOUND; *new_x = game.player.x; *new_y = game.player.y; } return flag; }*/ void Scene_Map::look(Object* object, float x, float y, float z, float yaw, float pitch) { Vertex vertex; int cosinus, sinus; vertex.set_xyz(x, y, z); windmill.compute_object_angle(object, &cosinus, &sinus); windmill.transform_model_to_world(&vertex, 1, object, cosinus, sinus); camera_look.x = vertex.x; camera_look.y = vertex.y; camera_look.z = vertex.z; camera_look.yaw = PI * (object->angle + yaw) / DEG; camera_look.pitch = to_rad(pitch); } void Scene_Map::lerp_camera(Camera camera_start, Camera camera_end, float t) { camera_temp.x = (1-t) * camera_start.x + t * camera_end.x; camera_temp.y = (1-t) * camera_start.y + t * camera_end.y; camera_temp.z = (1-t) * camera_start.z + t * camera_end.z; camera_temp.yaw = (1-t) * camera_start.yaw + t * camera_end.yaw; camera_temp.pitch = (1-t) * camera_start.pitch + t * camera_end.pitch; } Object* Scene_Map::object(int id) { if (id < 0 or id >= game.map->list_object_length) { //debug_pop("ERROR id out of range"); return NULL; } return game.map->object[id]; } int Scene_Map::id(Object* object) { if (object == NULL) return -1; for (int i = 0; ilist_object_length; i++) { if (game.map->object[i] == object) { return i; } } //debug_pop("ERROR object not found"); return -1; } bool Scene_Map::action_object(Object* object, int poly_id) { if (look_object(object, poly_id) == false) return false; Point center_poly = windmill.get_center_poly(&object->modele[poly_id]); return action_object(object, center_poly.x, center_poly.y, center_poly.z); } bool Scene_Map::action_object(Object* object, float x, float y, float z) { Vertex vertex; int cosinus, sinus; vertex.set_xyz(x, y, z); windmill.compute_object_angle(object, &cosinus, &sinus); windmill.transform_model_to_world(&vertex, 1, object, cosinus, sinus); float dx = vertex.x - game.player.x; float dy = vertex.y - game.player.y; float dz = vertex.z - game.player.z; if (dx < 0) dx = -dx; if (dy < 0) dy = -dy; if (dz < 0) dz = -dz; return (dx <= game.player.action_distance and dy <= game.player.action_distance); } bool Scene_Map::look_object(Object* object, int poly_id) { if (poly_id == -1) { return (object == windmill.object_cursor); } else { return (object == windmill.object_cursor and poly_id == windmill.poly_cursor); } } //---------------------------------------------------------------------------------------------------- // TERMINATE //---------------------------------------------------------------------------------------------------- void Scene_Map::terminate() { } //---------------------------------------------------------------------------------------------------- // DESTRUCTOR //---------------------------------------------------------------------------------------------------- Scene_Map::~Scene_Map() { // rien }