void CreateScene() { scene_ = new Scene(context_); scene_->CreateComponent<Octree>(); scene_->CreateComponent<DebugRenderer>(); // Компонент PhysicsWorld можно и не создавать, // так как он создается автоматически при необходимости. scene_->CreateComponent<PhysicsWorld>(); // Создаем ноду и прикрепляем к ней камеру и управляющий логический компонент. auto cameraNode = scene_->CreateChild("Camera"); auto camera = cameraNode->CreateComponent<Camera>(); cameraNode->SetPosition(CAMERA_DEFAULT_POS); cameraNode->CreateComponent<CameraLogic>(); // Создаем ноду и прикрепляем к ней источник света (солнечный свет). auto lightNode = scene_->CreateChild(); auto light = lightNode->CreateComponent<Light>(); light->SetLightType(LIGHT_DIRECTIONAL); light->SetCastShadows(true); lightNode->SetDirection(Vector3(-0.5f, -1.0f, 1.0f)); // Создаем ноду и прикрепляем к ней скайбокс и управляющий логический компонент. auto envNode = scene_->CreateChild(); auto skybox = envNode->CreateComponent<Skybox>(); skybox->SetModel(CACHE->GetResource<Model>("Models/Box.mdl")); skybox->SetMaterial(CACHE->GetResource<Material>("Materials/Env.xml")); envNode->CreateComponent<EnvironmentLogic>(); }
// Добавляем в сцену НЛО. void CreateUfo() { auto ufoNode = scene_->CreateChild("Ufo"); auto ufoObject = ufoNode->CreateComponent<AnimatedModel>(); ufoObject->SetModel(CACHE->GetResource<Model>("Models/Ufo.mdl")); ufoObject->SetCastShadows(true); ufoNode->SetRotation(UFO_DEFAULT_ROTATION); ufoNode->CreateComponent<UfoLogic>(); // Так как модель состоит из нескольких материалов, // то список материалов удобно загружать из файла (Models/Ufo.txt). ufoObject->ApplyMaterialList(); // Запускаем циклическое проигрывание анимации (покачивание НЛО). auto animCtrl = ufoNode->CreateComponent<AnimationController>(); animCtrl->PlayExclusive("Models/Fly.ani", 0, true); auto body = ufoNode->CreateComponent<RigidBody>(); // Два статических тела не будут генерировать события о столкновениях, // поэтому хотя бы одно тело должно быть динамическим. // Задаем для НЛО массу больше нуля, чтобы сделать его динамическим. body->SetMass(1.0f); // Но нам не нужна симуляция физики, нас интересует только факт касания объектов. body->SetKinematic(true); // Нода с НЛО содержит несколько компонентов CollisionShape для более точного описания формы. // Размеры шейпов были подобраны в редакторе Urho3D. // Корпус. auto shape1 = ufoNode->CreateComponent<CollisionShape>(); shape1->SetShapeType(SHAPE_CAPSULE); shape1->SetSize(Vector3(1.9f, 6.4f, 0.0f)); shape1->SetPosition(Vector3(0.0f, -0.3f, 0.0f)); shape1->SetRotation(Quaternion(90.f, 0.0f, 0.0f)); // Кабина. auto shape2 = ufoNode->CreateComponent<CollisionShape>(); shape2->SetShapeType(SHAPE_CAPSULE); shape2->SetSize(Vector3(1.6f, 3.3f, 0.0f)); shape2->SetPosition(Vector3(0.0f, 0.8f, 0.0f)); shape2->SetRotation(Quaternion(90.f, 0.0f, 0.0f)); // Прикрепляем к НЛО источник голубого света. auto lightNode = ufoNode->CreateChild(); lightNode->SetPosition(Vector3(0.0f, -3.0f, 0.0f)); auto light = lightNode->CreateComponent<Light>(); light->SetColor(Color(0.0f, 1.0f, 1.0f)); light->SetSpecularIntensity(0.0f); light->SetRange(5.0f); }
// Создание барьеров. // Барьер имеет две дочернии ноды - верхнюю и нижнюю трубы. // Зазор между трубами является физическим телом, чтобы можно было легко определить, // что НЛО успешно преодолел барьер и следует увеличить счетчик очков. void CreateBarriers() { for (int i = 0; i < NUM_BARRIERS; i++) { auto barrierNode = scene_->CreateChild("Barrier"); barrierNode->CreateComponent<BarrierLogic>(); // Барьеры размещаются за пределами экрана со случайным смещением по высоте. barrierNode->SetPosition(Vector3(BAR_OUTSIDE_X + i * BAR_INTERVAL, BAR_RANDOM_Y, 0.0f)); // Создаём статическое физическое тело для зазора (размер формы столкновений // подбирался в редакторе Urho3D). barrierNode->CreateComponent<RigidBody>(); auto shape = barrierNode->CreateComponent<CollisionShape>(); shape->SetShapeType(SHAPE_BOX); shape->SetSize(Vector3(7.8f, BAR_GAP, 7.8f)); // Создаем верхнюю и нижнюю трубы. CreatePipe(barrierNode, true); CreatePipe(barrierNode, false); } }
void on_tick(const interface::TickEvent &event) { log_d(MODULE, "entitytest::on_tick"); static uint a = 0; if(((a++) % 100) == 0){ main_context::access(m_server, [&](main_context::Interface *imc){ Scene *scene = imc->check_scene(m_main_scene); Node *n = scene->GetChild("Box"); n->SetPosition(Vector3(0.0f, 6.0f, 0.0f)); n->SetRotation(Quaternion(30, 60, 90)); Node *n2 = scene->GetChild("Box2"); n2->SetPosition(Vector3(-0.4f, 8.0f, 0.0f)); n2->SetRotation(Quaternion(30, 60, 90)); m_slow_count++; if(m_slow_count == 2){ Node *n = scene->CreateChild("Box"); n->SetPosition(Vector3(0.0f, 10.0f, 0.0f)); n->SetScale(Vector3(1.0f, 1.0f, 1.0f)); RigidBody *body = n->CreateComponent<RigidBody>(); CollisionShape *shape = n->CreateComponent<CollisionShape>(); shape->SetBox(Vector3::ONE); body->SetMass(1.0); body->SetFriction(0.75f); // Model and material is set on client } }); return; } main_context::access(m_server, [&](main_context::Interface *imc){ Scene *scene = imc->check_scene(m_main_scene); Node *n = scene->GetChild("Box"); //n->Translate(Vector3(0.1f, 0, 0)); Vector3 p = n->GetPosition(); log_v(MODULE, "Position: %s", p.ToString().CString()); }); }