Exemple #1
0
void moveBulldozer(int dist){
	
	for(int n=0; n<dist;n++){
		//	d.game->sim->getRailPen()->move(1, d.game->sim);
		Point p = d.game->sim.railPen.getPos();
		if(d.game->sim.railPen.getMode() == RailPen::PAINTING){
			Rail * newRail = d.game->sim.railPen.makeNewRail(d.game->sim.railMap.getRailAt(p.row, p.col));
			d.game->sim.railMap.setRail(p.row, p.col, newRail);

			ForkRail *rf = dynamic_cast<ForkRail *>(newRail);
			if(rf){
				d.game->sim.addFork(rf);
			}

			Point lastPoint = d.game->sim.railPen.getPos();
			Dir lastDir = d.game->sim.railPen.getLastDir();
			Dir backDir = -lastDir; 
			lastPoint.move(backDir);
			Rail * lastRail = d.game->sim.railMap.getRailAt(lastPoint.row, lastPoint.col);
			if(lastRail){
				newRail->linkRailAt(backDir, lastRail);
			}
		}
		d.game->sim.railPen.forward();
	}
}
Exemple #2
0
Rail * RailPen::makeNewRail(Rail * rail){
	DirEnv env;
	if(rail){
		env = rail->getEnv();
	}
	env.addPath(-lastDir, dir);
	Rail * newRail = env.makeNewRail();
	if(rail){
		for(int n(Dir::E) ;n<(Dir::NUM_DIRS); n++){
			Dir dir (n);
			Rail * linked = rail->getLinkedRailAt(dir);
			if(linked){
				newRail->linkRailAt(dir, linked);
			}
		}
	}
	return newRail;	
}
Exemple #3
0
// ojo, no pinta cuando distance es mayor que 1. Testear esto!!!!!!!!!!!!!!
bool RailPen::move(int distance, Sim * sim){
	Point p = getPos();
	if(getMode() == PAINTING){
		if(distance>0){
			for(int n= 0; n<distance;n++){
				Rail * newRail = makeNewRail(sim->railMap.getRailAt(p.row, p.col));
				sim->railMap.setRail(p.row, p.col, newRail);

				ForkRail *rf = dynamic_cast<ForkRail *>(newRail);
				if(rf){
					sim->addFork(rf);
				}

				Point lastPoint = getPos();
				Dir lastDir = getLastDir();
				Dir backDir = -lastDir; 
				lastPoint.move(backDir);
				Rail * lastRail = sim->railMap.getRailAt(lastPoint.row, lastPoint.col);
				if(lastRail){
					newRail->linkRailAt(backDir, lastRail);
				}
			 	forward();	
			}
		}else{
			for(int n=0; n>distance;n--){
				Point p = getPos();
				sim->railMap.setRail(p.row, p.col, 0);
				backwards();
			}
		}
	}else{
		pos.move(dir, distance);
		lastDir=dir;
	}
	return true;
}
Exemple #4
0
void World::Update(const float time_delta) {
	mCurrentLevelTime += time_delta;
	// INPUT!
	const sf::Input& in = GameApp::get_mutable_instance().GetInput();
	sf::View& view = GameApp::get_mutable_instance().GetView();
	if(GameApp::get_mutable_instance().IsEditorMode()) {
		float px = 10;
		if(in.IsKeyDown(sf::Key::LShift) || in.IsKeyDown(sf::Key::RShift)) {
			px *= 5;
		}
		if(in.IsKeyDown(sf::Key::Up)) {
			view.SetCenter(view.GetCenter().x, view.GetCenter().y - px);
		}
		if(in.IsKeyDown(sf::Key::Down)) {
			view.SetCenter(view.GetCenter().x, view.GetCenter().y + px);
		}
		if(in.IsKeyDown(sf::Key::Left)) {
			view.SetCenter(view.GetCenter().x - px, view.GetCenter().y);
		}
		if(in.IsKeyDown(sf::Key::Right)) {
			view.SetCenter(view.GetCenter().x + px, view.GetCenter().y);
		}

		Coordinates mp;
		mp.SetScreenPixel(GameApp::get_mutable_instance().GetMousePosition());
		if(mEditorMouseAction == EMA_GRAB) {
			mEditorMouseActionEntity->SetPosition( mEditorMouseActionStartEntityPosition.GetWorldFloat() +
												   mp.GetWorldFloat() -
												   mEditorMouseActionStartMousePosition.GetWorldFloat() );
		} else if(mEditorMouseAction == EMA_ALPHA) {
			float mpf = mp.GetScreenFloat().y;
			float mspf = mEditorMouseActionStartMousePosition.GetScreenFloat().y;
			float d = (mspf - mpf) * 5.f;
			float a = mEditorMouseActionStartEntityAlpha + d;
			if (a > 1) a = 1;
			if (a < 0) a = 0;
			mEditorMouseActionEntity->SetAlpha( a );
		} else if(mEditorMouseAction == EMA_SCALE) {
			Vector2D md = mEditorMouseActionStartEntityPosition.GetScreenPixel() - mp.GetScreenPixel();
			Vector2D sd = mEditorMouseActionStartEntityPosition.GetScreenPixel() - mEditorMouseActionStartMousePosition.GetScreenPixel();
			float f =  md.Magnitude() / sd.Magnitude();
			mEditorMouseActionEntity->SetScale( mEditorMouseActionStartEntityScale * f );
		} else if(mEditorMouseAction == EMA_ROTATE) {
			Coordinates ep;
			ep.SetWorldFloat(mEditorMouseActionEntity->GetPosition());
			mEditorMouseActionEntity->SetRotation(
					(mEditorMouseActionStartMousePosition.GetWorldFloat()-ep.GetWorldFloat()).Rotation()
					-(mp.GetWorldFloat()-ep.GetWorldFloat()).Rotation()
					+ mEditorMouseActionStartEntityRotation );
		}
	} else if(GameApp::get_mutable_instance().GetAppMode() == AM_PUZZLE) {
		// draw point on closest rail
		Rail* r = GetClosestRail();
		if(r != NULL) {
			Coordinates tmp;
			tmp.SetScreenPixel(GameApp::get_mutable_instance().GetMousePosition());
			float d = r->ClosestPositionOnLine(tmp.GetWorldFloat());
			mClosestRailPoint = r->GetPointFromFloat(d);
		}
		mClosestRail = r;

	}
	if(GetBoxEntity() != NULL && GetBoxEntity()->UsesPhysics() && !GameApp::get_mutable_instance().GetInput().IsMouseButtonDown(sf::Mouse::Left)) {
		mCurrentRail = GetClosestRail(true, GetBoxEntity()->GetBody()->getWorldTransform().getOrigin());
	}

	//mDynamicsWorld->stepSimulation(time_delta, 10);
	if(GameApp::get_mutable_instance().GetAppMode() == AM_PLAY) {
		mDynamicsWorld->stepSimulation(1 / 60.f, 10);
		mDynamicsWorld->clearForces();
	}

	Entity* c = GetClosestEntityOnLayer(GameApp::get_mutable_instance().GetMousePosition(), mEditorLayer);
	BOOST_FOREACH(Entity& entity, mEntities) {
		int h = 0;
		if (mEditorSelectedEntity == &entity) h = 2;
		else if (c == &entity) h = 1;
		entity.SetHighlightMode(h);
		entity.Update(time_delta);
		/*if(entity.GetLifeTime() >= entity.GetTimeToLive()) {
			mDynamicsWorld->removeRigidBody(entity.GetBody().get());
			mEntities.erase_if(boost::bind(&Entity::GetUID, _1) == entity.GetEntityUniqueId());
		}*/
	}
Exemple #5
0
	// draw the rails
	BOOST_FOREACH(Rail& r, mRails) {
		r.Update(time_delta);
	}
Exemple #6
0
// Generates the actual mesh for the river, and adds it to this entitiy's
// rendermesh component.
void RiverComponent::CreateRiverMesh(corgi::EntityRef& entity) {
  static const fplbase::Attribute kMeshFormat[] = {
      fplbase::kPosition3f, fplbase::kTexCoord2f, fplbase::kNormal3f,
      fplbase::kTangent4f, fplbase::kEND};
  static const fplbase::Attribute kBankMeshFormat[] = {
      fplbase::kPosition3f, fplbase::kTexCoord2f, fplbase::kNormal3f,
      fplbase::kTangent4f,  fplbase::kColor4ub,   fplbase::kEND};
  std::vector<vec3_packed> track;
  const RiverConfig* river = entity_manager_->GetComponent<ServicesComponent>()
                                 ->config()
                                 ->river_config();

  RiverData* river_data = Data<RiverData>(entity);
  river_data->render_mesh_needs_update_ = false;

  // Initialize the static mesh that will be made around the river banks.
  auto* physics_component = entity_manager_->GetComponent<PhysicsComponent>();
  physics_component->InitStaticMesh(entity);

  Rail* rail = entity_manager_->GetComponent<ServicesComponent>()
                   ->rail_manager()
                   ->GetRailFromComponents(river_data->rail_name.c_str(),
                                           entity_manager_);

  // Generate the spline data and store it in our track vector:
  rail->Positions(river->spline_stepsize(), &track);

  fplbase::AssetManager* asset_manager =
      entity_manager_->GetComponent<ServicesComponent>()->asset_manager();

  const size_t num_bank_contours = river->default_banks()->Length();
  const size_t num_bank_quads = num_bank_contours - 2;
  const size_t river_idx = river->river_index();
  const size_t segment_count = track.size();
  const size_t river_vert_max = segment_count * 2;
  const size_t river_index_max = (segment_count - 1) * kNumIndicesPerQuad;
  const size_t bank_vert_max = segment_count * num_bank_contours;
  const size_t bank_index_max =
      (segment_count - 1) * kNumIndicesPerQuad * num_bank_quads;
  assert(num_bank_contours >= 2 && river_idx < num_bank_contours - 1);
  const unsigned int num_zones = river->zones()->Length();

  // Need to allocate some space to plan out our mesh in:
  std::vector<NormalMappedVertex> river_verts(river_vert_max);
  river_verts.clear();
  std::vector<unsigned short> river_indices(river_index_max);
  river_indices.clear();

  std::vector<NormalMappedColorVertex> bank_verts(bank_vert_max);
  bank_verts.clear();
  std::vector<unsigned short> bank_indices(bank_index_max);
  bank_indices.clear();
  // Use one set of bank vertices for the entire riverbank, but separate out
  // the zones via indices, so we can use different materials (and possibly
  // shaders) per zone. We still keep bank_indices for the normal calculation,
  // though.
  std::vector<std::vector<unsigned short>> bank_indices_by_zone;
  bank_indices_by_zone.resize(num_zones);

  std::vector<unsigned int> bank_zones;  // indexed by segment
  bank_zones.resize(segment_count, 0);   // default of 0
  unsigned int zone_id = 0;

  // TODO: Use a local random number generator. Resetting the global random
  //       number generator is not a nice. Also, there's no guarantee that
  //       mathfu::Random will continue to use rand().
  srand(river_data->random_seed);

  std::vector<float> actual_zone_end;
  actual_zone_end.resize(segment_count, 1);
  // Precalculate the actual zone end locations.
  for (size_t i = 0; i < segment_count; i++) {
    const float fraction =
        static_cast<float>(i) / static_cast<float>(segment_count);
    if (zone_id + 1 < river->zones()->Length() &&
        fraction > river->zones()->Get(zone_id + 1)->zone_start()) {
      actual_zone_end[zone_id] = fraction;
      zone_id = zone_id + 1;
    }
  }
  // Start over from zone 0.
  zone_id = 0;

  const RiverZone* current_zone = river->zones()->Get(zone_id);
  Material* current_bank_material =
      asset_manager->LoadMaterial(current_zone->material()->c_str());
  float river_width = current_zone->width() != 0 ? current_zone->width()
                                                 : river->default_width();

  // Construct the actual mesh data for the river:
  std::vector<vec2> offsets(num_bank_contours);
  for (size_t i = 0; i < segment_count; i++) {
    // River track is circular.
    const size_t prev_i = i == 0 ? segment_count - 1 : i - 1;

    // Get the current position on the track, and the normal (to the side).
    const vec3 track_delta = vec3(track[i]) - vec3(track[prev_i]);
    const vec3 track_normal =
        vec3::CrossProduct(track_delta, kAxisZ3f).Normalized();
    const vec3 track_position =
        vec3(track[i]) + river->track_height() * kAxisZ3f;

    // The river texture is tiled several times along the course of the river.
    // TODO: Change this from tile count to actual physical size for a tile.
    //       Requires that we know the total path distance.
    const float texture_v = river->texture_tile_size() * static_cast<float>(i) /
                            static_cast<float>(segment_count);

    // Fraction of the river we have gone through, approximately.
    const float fraction =
        static_cast<float>(i) / static_cast<float>(segment_count);

    if (fraction >= actual_zone_end[zone_id]) {
      zone_id = zone_id + 1;
      current_zone = river->zones()->Get(zone_id);
      // Each zone has its own texture.
      current_bank_material =
          asset_manager->LoadMaterial(current_zone->material()->c_str());
      // Each zone has its own river width.
      river_width = current_zone->width() != 0 ? current_zone->width()
                                               : river->default_width();
      current_bank_material = asset_manager->LoadMaterial(
          river->zones()->Get(zone_id)->material()->c_str());
    }
    bank_zones[i] = zone_id;
    float zone_start = zone_id == 0 ? 0 : actual_zone_end[zone_id - 1];
    float zone_end = actual_zone_end[zone_id];
    float within_fraction = (fraction - zone_start) / (zone_end - zone_start);
    if (current_bank_material->textures().size() == 1) {
      // Ensure we stay continuous with transitional zones.
      within_fraction = within_fraction < 0.5f ? 1.0f : 0.0f;
    }

    int within_color = static_cast<int>(255.0 * within_fraction);
    // Cap the color to 0..255 byte.
    unsigned char within_color_byte = static_cast<unsigned char>(
        within_color < 0 ? 0 : (within_color > 255 ? 255 : within_color));

    // Get the (side, up) offsets of the bank vertices.
    // The offsets are relative to `track_position`.
    // side == distance along `track_normal`
    // up == distance along kAxisZ3f
    for (size_t j = 0; j < num_bank_contours; ++j) {
      const RiverBankContour* b = (current_zone->banks() != nullptr)
                                      ? current_zone->banks()->Get(j)
                                      : river->default_banks()->Get(j);
      offsets[j] =
          vec2(mathfu::Lerp(b->x_min(), b->x_max(), mathfu::Random<float>()),
               mathfu::Lerp(b->z_min(), b->z_max(), mathfu::Random<float>()));
    }

    // Create the bank vertices for this segment.
    for (size_t j = 0; j < num_bank_contours; ++j) {
      const bool left_bank = j <= river_idx;
      const vec2 off = offsets[j];
      const vec3 vertex =
          track_position +
          (off.x() + river_width * (left_bank ? -1 : 1)) * track_normal +
          off.y() * kAxisZ3f;
      // The texture is stretched from the side of the river to the far end
      // of the bank. There are two banks, however, separated by the river.
      // We need to know the width of the bank to caluate the `texture_u`
      // coordinate.
      const size_t bank_start = left_bank ? 0 : num_bank_contours - 1;
      const size_t bank_end = left_bank ? river_idx : river_idx + 1;
      const float bank_width = offsets[bank_start].x() - offsets[bank_end].x();
      const float texture_u = (off.x() - offsets[bank_end].x()) / bank_width;

      bank_verts.push_back(NormalMappedColorVertex());
      bank_verts.back().pos = vec3_packed(vertex);
      bank_verts.back().tc = vec2_packed(vec2(texture_u, texture_v));
      bank_verts.back().norm = vec3_packed(vec3(0, 1, 0));
      bank_verts.back().tangent = vec4_packed(vec4(1, 0, 0, 1));
      unsigned char color_bytes[4] = {255, 255, 255, within_color_byte};
      memcpy(bank_verts.back().color, color_bytes, sizeof(color_bytes));
    }

    // Ensure vertices don't go behind previous vertices on the inside of
    // a tight corner.
    if (i > 0) {
      const NormalMappedColorVertex* prev_verts =
          &bank_verts[bank_verts.size() - 2 * num_bank_contours];
      NormalMappedColorVertex* cur_verts =
          &bank_verts[bank_verts.size() - num_bank_contours];
      for (size_t j = 0; j < num_bank_contours; j++) {
        const vec3 vert_delta =
            vec3(cur_verts[j].pos) - vec3(prev_verts[j].pos);
        const float dot = vec3::DotProduct(vert_delta, track_delta);
        const bool cur_vert_goes_backwards_along_track = dot <= 0.0f;
        if (cur_vert_goes_backwards_along_track) {
          cur_verts[j].pos = vec3(prev_verts[j].pos) + 0.000001f * track_delta;
        }
      }
    }

    // Force the beginning and end to line up in their geometry:
    if (i == segment_count - 1) {
      for (size_t j = 0; j < num_bank_contours; j++)
        bank_verts[bank_verts.size() - (8 - j)].pos = bank_verts[j].pos;
    }

    // The river has two of the middle vertices of the bank.
    // The texture coordinates are different, however.
    const size_t river_vert = bank_verts.size() - num_bank_contours + river_idx;
    float normalized_texture_v = i / static_cast<float>(segment_count);
    river_verts.push_back(NormalMappedVertex());
    river_verts.back().pos = bank_verts[river_vert].pos;
    river_verts.back().tc = vec2(0.0f, normalized_texture_v);
    river_verts.back().norm = bank_verts[river_vert].norm;
    river_verts.back().tangent = bank_verts[river_vert].tangent;

    river_verts.push_back(NormalMappedVertex());
    river_verts.back().pos = bank_verts[river_vert + 1].pos;
    river_verts.back().tc = vec2(1.0f, normalized_texture_v);
    river_verts.back().norm = bank_verts[river_vert + 1].norm;
    river_verts.back().tangent = bank_verts[river_vert + 1].tangent;
  }

  // Not counting the first segment, create triangles in our index
  // list to represent this segment.
  //
  for (size_t i = 0; i < segment_count - 1; i++) {
    auto make_quad = [&](std::vector<unsigned short>& indices, int base_index,
                         int off1, int off2) {
      indices.push_back(static_cast<unsigned short>(base_index + off1));
      indices.push_back(static_cast<unsigned short>(base_index + off1 + 1));
      indices.push_back(static_cast<unsigned short>(base_index + off2));

      indices.push_back(static_cast<unsigned short>(base_index + off2));
      indices.push_back(static_cast<unsigned short>(base_index + off1 + 1));
      indices.push_back(static_cast<unsigned short>(base_index + off2 + 1));
    };

    // River only has one quad per segment.
    make_quad(river_indices, 2 * i, 0, 2);

    // Case when kNumBankCountours = 8, and river_idx = 3;
    //
    //  0___1___2___3   4___5___6___7
    //  | _/| _/| _/|   | _/| _/| _/|
    //  |/__|/__|/__|   |/__|/__|/__|
    //  8   9  10  11  12  13  14  15
    for (size_t j = 0; j <= num_bank_quads; ++j) {
      // Do not create bank geo for the river.
      if (j == river_idx) continue;
      unsigned int zone = bank_zones[i];
      int base_index = i * num_bank_contours;
      int offset1 = j;
      int offset2 = num_bank_contours + j;
      make_quad(bank_indices, base_index, offset1, offset2);
      make_quad(bank_indices_by_zone[zone], base_index, offset1, offset2);

      // Add the same triangles to the static mesh associated with the entity.
      physics_component->AddStaticMeshTriangle(
          entity, vec3(bank_verts[base_index + offset1].pos),
          vec3(bank_verts[base_index + offset1 + 1].pos),
          vec3(bank_verts[base_index + offset2].pos));

      physics_component->AddStaticMeshTriangle(
          entity, vec3(bank_verts[base_index + offset2].pos),
          vec3(bank_verts[base_index + offset1 + 1].pos),
          vec3(bank_verts[base_index + offset2 + 1].pos));
    }
  }

  // Make sure we used as much data as expected, and no more.
  assert(river_indices.size() == river_index_max);
  assert(river_verts.size() == river_vert_max);
  assert(bank_indices.size() == bank_index_max);
  assert(bank_verts.size() == bank_vert_max);

  Mesh::ComputeNormalsTangents(bank_verts.data(), bank_indices.data(),
                               bank_verts.size(), bank_indices.size());

  // Load the material from files.
  Material* river_material =
      asset_manager->LoadMaterial(river->material()->c_str());
  // Create the actual mesh objects, and stuff all the data we just
  // generated into it.
  Mesh* river_mesh = new Mesh(river_verts.data(), river_verts.size(),
                              sizeof(NormalMappedVertex), kMeshFormat);

  river_mesh->AddIndices(river_indices.data(), river_indices.size(),
                         river_material);

  // Add the river mesh to the river entity.
  RenderMeshData* mesh_data = Data<RenderMeshData>(entity);
  mesh_data->shader = asset_manager->LoadShader(river->shader()->c_str());
  if (mesh_data->mesh != nullptr) {
    // Mesh's destructor handles cleaning up its GL buffers
    delete mesh_data->mesh;
    mesh_data->mesh = nullptr;
  }
  mesh_data->mesh = river_mesh;
  mesh_data->culling_mask = 0;  // Never cull the river.
  mesh_data->pass_mask = 1 << corgi::RenderPass_Opaque;

  river_data->banks.resize(num_zones, corgi::EntityRef());
  for (unsigned int zone = 0; zone < num_zones; zone++) {
    Material* bank_material = asset_manager->LoadMaterial(
        river->zones()->Get(zone)->material()->c_str());

    Mesh* bank_mesh =
        new Mesh(bank_verts.data(), bank_verts.size(),
                 sizeof(NormalMappedColorVertex), kBankMeshFormat);

    bank_mesh->AddIndices(bank_indices_by_zone[zone].data(),
                          bank_indices_by_zone[zone].size(), bank_material);
    if (!river_data->banks[zone]) {
      // Now we make a new entity to hold the bank mesh.
      river_data->banks[zone] = entity_manager_->AllocateNewEntity();
      entity_manager_->AddEntityToComponent<RenderMeshComponent>(
          river_data->banks[zone]);

      // Then we stick it as a child of the river entity, so it always moves
      // with it and stays aligned:
      auto transform_component =
          GetComponent<corgi::component_library::TransformComponent>();
      transform_component->AddChild(river_data->banks[zone], entity);
    }

    RenderMeshData* child_render_data =
        Data<RenderMeshData>(river_data->banks[zone]);
    if (bank_material->textures().size() == 1) {
      child_render_data->shader =
          asset_manager->LoadShader("shaders/textured_lit");
    } else {
      child_render_data->shader =
          asset_manager->LoadShader("shaders/textured_lit_bank");
    }
    if (child_render_data->mesh != nullptr) {
      // Mesh's destructor handles cleaning up its GL buffers
      delete child_render_data->mesh;
      child_render_data->mesh = nullptr;
    }
    child_render_data->mesh = bank_mesh;
    child_render_data->culling_mask = 0;  // Don't cull the banks for now.
    child_render_data->pass_mask = 1 << corgi::RenderPass_Opaque;
  }

  // Finalize the static physics mesh created on the river bank.
  short collision_type = static_cast<short>(river->collision_type());
  short collides_with = 0;
  if (river->collides_with()) {
    for (auto collides = river->collides_with()->begin();
         collides != river->collides_with()->end(); ++collides) {
      collides_with |= static_cast<short>(*collides);
    }
  }
  std::string user_tag = river->user_tag() ? river->user_tag()->c_str() : "";
  physics_component->FinalizeStaticMesh(entity, collision_type, collides_with,
                                        river->mass(), river->restitution(),
                                        user_tag);
}