bool AiLocation::validate ( void ) const { NAN_CHECK(m_position_p); NAN_CHECK(m_radius); NAN_CHECK(m_offset_p); TerrainObject * terrain = TerrainObject::getInstance(); if(terrain == NULL) return true; float w = terrain->getMapWidthInMeters() / 2.0f; bool valid = true; valid &= (m_position_p.x <= w); valid &= (m_position_p.x >= -w); valid &= (m_position_p.z <= w); valid &= (m_position_p.z >= -w); float dist2 = getPosition_w().magnitudeSquared(); valid &= (dist2 >= 9.0f); if(!valid) { DEBUG_WARNING(ConfigServerGame::getReportAiWarnings(),("AiLocation::validate - Location (%f,%f,%f) is OOW or too near the origin - terrain size %fx%f\n",m_position_p.x,m_position_p.y,m_position_p.z,w*2.0f,w*2.0f)); } return valid; }
// 新建场景 void TerrainEditorPlugin::onNewScene(IScene *scene) { // 找到所有地形,激活之 IScene::SceneObjectIterator iter = scene->getSceneObjectIterator(); while(iter.hasMoreElements()) { ISceneObject *obj = iter.getNext(); if(obj->getType() == TerrainObjectFactory::FACTORY_TYPE) { TerrainObject *terrain = static_cast<TerrainObject*>(obj); activateTerrain(terrain->getOgreTerrain()); } } }
bool Ned3DObjectManager::interactEnemyTerrain(EnemyObject &enemy, TerrainObject &terrain) { Terrain *terr = terrain.getTerrain(); if(terr == NULL) return false; //test for enemy collision with terrain Vector3 enemyPos = enemy.getPosition(); float terrainHeight = terr->getHeight(enemyPos.x,enemyPos.z); if (enemyPos.y < terrainHeight) { enemyPos.y = terrainHeight; //enemy.setPPosition(enemyPos); int tmpHndl = gParticle.createSystem("enemyfeatherssplat"); gParticle.setSystemPos(tmpHndl, enemyPos); int thumpSound = gSoundManager.requestSoundHandle("Thump.wav"); int instance = gSoundManager.requestInstance(thumpSound); if(thumpSound != SoundManager::NOINSTANCE) { gSoundManager.setPosition(thumpSound,instance,enemyPos); gSoundManager.play(thumpSound,instance); gSoundManager.releaseInstance(thumpSound,instance); } enemy.killObject(); return true; } return false; }
bool Ned3DObjectManager::interactCrowTerrain(CrowObject &crow, TerrainObject &terrain) { Terrain *terr = terrain.getTerrain(); if(terr == NULL) return false; //test for crow collision with terrain Vector3 crowPos = crow.getPosition(); float terrainHeight = terr->getHeight(crowPos.x,crowPos.z); if (crowPos.y < terrainHeight) { crowPos.y = terrainHeight; crow.setPosition(crowPos); int tmpHndl = gParticle.createSystem("crowfeatherssplat"); gParticle.setSystemPos(tmpHndl, crowPos); int thumpSound = gSoundManager.requestSoundHandle("Thump.wav"); int instance = gSoundManager.requestInstance(thumpSound); if(thumpSound != SoundManager::NOINSTANCE) { gSoundManager.setPosition(thumpSound,instance,crowPos); gSoundManager.play(thumpSound,instance); gSoundManager.releaseInstance(thumpSound,instance); } crow.killObject(); return true; } return false; }
TerrainObject *Terrain::obj_at_point(const coord::phys3 &point) { coord::tile t = point.to_tile3().to_tile(); TileContent *tc = this->get_data(t); if (!tc) { return nullptr; } // prioritise selecting the smallest object TerrainObject *smallest = nullptr; for (auto obj_ptr : tc->obj) { if (obj_ptr->contains(point) && (!smallest || obj_ptr->min_axis() < smallest->min_axis())) { smallest = obj_ptr; } } return smallest; }
// 保存场景 void TerrainEditorPlugin::onPreSaveScene(const String &fileName ,IScene *scene) { // 找到所有地形,保存之 IScene::SceneObjectIterator iter = scene->getSceneObjectIterator(); while(iter.hasMoreElements()) { ISceneObject *obj = iter.getNext(); if(obj->getType() == TerrainObjectFactory::FACTORY_TYPE) { TerrainObject *terrain = static_cast<TerrainObject*>(obj); String outBasename; String outExtention; String outPath; StringUtil::splitFullFilename(fileName , outBasename , outExtention , outPath); removeTerrainBlockerPass(terrain->getOgreTerrain()); terrain->save(outBasename); addTerrainBlockerPass(terrain->getOgreTerrain()); } } }
void QuadtreeNode::ComputeBoundingBox(const vec3* vertices) { assert(vertices); m_BBox.min.y = 100000.0f; m_BBox.max.y = -100000.0f; if(m_pTerrainChunk) { std::vector<GLuint>& tIndices = m_pTerrainChunk->getIndiceArray(0); for(GLuint i=0; i<tIndices.size(); i++) { vec3 vertex = vertices[ tIndices[i] ]; if(vertex.y > m_BBox.max.y) m_BBox.max.y = vertex.y; if(vertex.y < m_BBox.min.y) m_BBox.min.y = vertex.y; } for(GLuint i=0; i<m_pTerrainChunk->getObjectsArray().size(); i++) { TerrainObject* obj = m_pTerrainChunk->getObjectsArray()[ i ]; Mesh* mesh = obj->getMesh(0); BoundingBox bbox = mesh->getBoundingBox(); bbox.Translate( obj->getPosition() ); m_BBox.Add( bbox ); } } // De la même facon, on traite les fils if(m_pChildren) { for(int i=0; i<4; i++) { m_pChildren[i].ComputeBoundingBox(vertices); if(m_BBox.min.y > m_pChildren[i].m_BBox.min.y) m_BBox.min.y = m_pChildren[i].m_BBox.min.y; if(m_BBox.max.y < m_pChildren[i].m_BBox.max.y) m_BBox.max.y = m_pChildren[i].m_BBox.max.y; } } }
bool Ned3DObjectManager::interactPlaneTerrain(PlaneObject &plane, TerrainObject &terrain) { Terrain *terr = terrain.getTerrain(); if(terr == NULL) return false; //test for plane collision with terrain Vector3 planePos = plane.getPosition(); EulerAngles planeOrient = plane.getOrientation(); Vector3 disp = planePos - disp; RotationMatrix planeMatrix; planeMatrix.setup(plane.getOrientation()); // get plane's orientation float planeBottom = plane.getBoundingBox().min.y; float terrainHeight = terr->getHeight(planePos.x,planePos.z); if(plane.isPlaneAlive() && planeBottom < terrainHeight) { //collision Vector3 viewVector = planeMatrix.objectToInertial(Vector3(0,0,1)); if(viewVector * terr->getNormal(planePos.x,planePos.z) < -0.5f // dot product || plane.isCrashing()) { plane.killPlane(); int partHndl = gParticle.createSystem("planeexplosion"); gParticle.setSystemPos(partHndl, plane.getPosition()); int boomHndl = gSoundManager.requestSoundHandle("Boom.wav"); int boomInst = gSoundManager.requestInstance(boomHndl); if(boomInst != SoundManager::NOINSTANCE) { gSoundManager.setPosition(boomHndl,boomInst,plane.getPosition()); gSoundManager.play(boomHndl,boomInst); gSoundManager.releaseInstance(boomHndl,boomInst); } plane.setSpeed(0.0f); planePos += 2.0f * viewVector; planeOrient.pitch = kPi / 4.0f; planeOrient.bank = kPi / 4.0f; plane.setOrientation(planeOrient); } else planePos.y = terrainHeight + planePos.y - planeBottom; //plane.setPPosition(planePos); return true; } return false; }
bool GameMain::on_input(SDL_Event *e) { Engine &engine = Engine::get(); switch (e->type) { case SDL_QUIT: engine.stop(); break; case SDL_MOUSEBUTTONDOWN: { //thanks C++! we need a separate scope because of new variables... // a mouse button was pressed... // subtract value from window height to get position relative to lower right (0,0). coord::window mousepos_window {(coord::pixel_t) e->button.x, (coord::pixel_t) e->button.y}; coord::camgame mousepos_camgame = mousepos_window.to_camgame(); // TODO once the terrain elevation milestone is implemented, use a method // more suitable for converting camgame to phys3 coord::phys3 mousepos_phys3 = mousepos_camgame.to_phys3(); coord::tile mousepos_tile = mousepos_phys3.to_tile3().to_tile(); if (clicking_active and e->button.button == SDL_BUTTON_LEFT) { log::dbg("LMB [window]: x %9hd y %9hd", mousepos_window.x, mousepos_window.y); log::dbg("LMB [camgame]: x %9hd y %9hd", mousepos_camgame.x, mousepos_camgame.y); auto phys_per_tile = openage::coord::settings::phys_per_tile; log::dbg("LMB [phys3]: NE %8.3f SE %8.3f UP %8.3f", ((float) mousepos_phys3.ne) / phys_per_tile, ((float) mousepos_phys3.se) / phys_per_tile, ((float) mousepos_phys3.up) / phys_per_tile); log::dbg("LMB [tile]: NE %8ld SE %8ld", mousepos_tile.ne, mousepos_tile.se); TerrainChunk *chunk = terrain->get_create_chunk(mousepos_tile); chunk->get_data(mousepos_tile)->terrain_id = editor_current_terrain; } else if (clicking_active and e->button.button == SDL_BUTTON_RIGHT) { // get chunk clicked on, don't create it if it's not there already // -> placing buildings in void is forbidden that way TerrainChunk *chunk = terrain->get_chunk(mousepos_tile); if (chunk == nullptr) { break; } // get object currently standing at the clicked position TerrainObject *obj = chunk->get_data(mousepos_tile)->obj; if (obj != nullptr) { obj->remove(); this->placed_buildings.erase(obj); this->available_sounds[obj->sound_id_destruction].play(); delete obj; } else { TestBuilding *newbuilding = this->available_buildings[this->editor_current_building]; int coloring = util::random_range(1, 8 + 1); TerrainObject *newobj = new TerrainObject( newbuilding->texture, newbuilding->foundation_size, coloring, newbuilding->sound_id_destruction ); // try to place the obj, it knows best whether it will fit. bool obj_placed = newobj->place(terrain, mousepos_tile); if (obj_placed) { this->available_sounds[newbuilding->sound_id_creation].play(); this->placed_buildings.insert(newobj); if (newbuilding->foundation_terrain > 0) { // TODO: use the gamedata terrain lookup! newobj->set_ground(newbuilding->foundation_terrain, 0); } } else { delete newobj; } } break; } else if (not scrolling_active and e->button.button == SDL_BUTTON_MIDDLE) { // activate scrolling SDL_SetRelativeMouseMode(SDL_TRUE); scrolling_active = true; // deactivate clicking as long as mousescrolling is active clicking_active = false; } break; } case SDL_MOUSEBUTTONUP: if (scrolling_active and e->button.button == SDL_BUTTON_MIDDLE) { // stop scrolling SDL_SetRelativeMouseMode(SDL_FALSE); scrolling_active = false; // reactivate mouse clicks as scrolling is over clicking_active = true; } break; case SDL_MOUSEMOTION: // scroll, if middle mouse is being pressed // SDL_GetRelativeMouseMode() queries sdl for that. if (scrolling_active) { // move the cam coord::vec2f cam_movement {0.0, 0.0}; cam_movement.x = e->motion.xrel; cam_movement.y = e->motion.yrel; // this factor controls the scroll speed // cam_movement *= 1; // calculate camera position delta from velocity and frame duration coord::camgame_delta cam_delta; cam_delta.x = cam_movement.x; cam_delta.y = - cam_movement.y; //update camera phys position engine.camgame_phys += cam_delta.to_phys3(); } break; case SDL_MOUSEWHEEL: if (this->ctrl_active) { editor_current_building = util::mod<ssize_t>(editor_current_building + e->wheel.y, this->available_buildings.size()); } else { editor_current_terrain = util::mod<ssize_t>(editor_current_terrain + e->wheel.y, this->terrain->terrain_id_count); } break; case SDL_KEYUP: switch (((SDL_KeyboardEvent *) e)->keysym.sym) { case SDLK_ESCAPE: //stop the game engine.stop(); break; case SDLK_F1: engine.drawing_huds = !engine.drawing_huds; break; case SDLK_F3: engine.drawing_debug_overlay = !engine.drawing_debug_overlay; break; case SDLK_LCTRL: this->ctrl_active = false; break; } break; case SDL_KEYDOWN: switch (((SDL_KeyboardEvent *) e)->keysym.sym) { case SDLK_SPACE: this->terrain->blending_enabled = !terrain->blending_enabled; break; case SDLK_F2: engine.get_screenshot_manager().save_screenshot(); break; case SDLK_LCTRL: this->ctrl_active = true; break; } break; } return true; }