public AnimalPreset(AnimalBehaviourComponent.AnimalSex sex, PackedScene scene, AnimalBehaviourComponent.AnimalDiet diet, int foodChainLevel, int breedability, string presetName, int foodDrop = 1, float birthDrop = 20.0f, float oxygenConsumption = 0.0001f, float co2Production = 0.0001f) { this.sex = sex; this.scene = scene; this.diet = diet; this.foodChainLevel = foodChainLevel; this.breedability = breedability; this.presetName = presetName; this.oxygenConsumption = oxygenConsumption; this.co2Production = co2Production; this.foodDrop = foodDrop; this.birthDrop = birthDrop; }
public void SpawnAnimal(string presetName, AnimalBehaviourComponent.AnimalSex sex, Vector3 position) { // Choose preset AnimalPreset preset = null; foreach (AnimalPreset p in presets) { if (p.presetName.Equals(presetName) && p.sex == sex) { preset = p; break; } } // Use preset to generate animal PackedScene chosenScene = preset.scene; KinematicBody kb = (KinematicBody)chosenScene.Instance(); Entity entity = new Entity(); kb.AddChild(entity); entity.SetName("Entity"); AnimalBehaviourComponent behaviourComponent = new AnimalBehaviourComponent(entity, preset.sex, preset.diet, preset.foodChainLevel, preset.breedability, preset.presetName, preset.oxygenConsumption, preset.co2Production, preset.foodDrop, preset.birthDrop); PhysicsComponent physicsComponent = new PhysicsComponent(entity); entity.AddComponent(behaviourComponent); entity.AddComponent(physicsComponent); kb.SetTranslation(position); AddChild(kb); }
//Creates a chunk at specified index, note that the chunk's position will be chunkIndex * chunkSize private void CreateChunk(IntVector2 chunkIndex, bool buildMesh) { if (loadedChunks.TryGetValue(chunkIndex, out Tuple <Chunk, bool, bool> tuple)) //Chunk already created { if (buildMesh && !tuple.Item2) //But maybe we need to build a mesh for it? { loadedChunks[chunkIndex] = new Tuple <Chunk, bool, bool>(tuple.Item1, true, tuple.Item3); chunksToUpdate.AddLast(chunkIndex); } if (!tuple.Item3) // If node not created, but it is in memory { tuple.Item1.Visible = true; } } else { byte[,,] blocks = worldGenerator.GetChunk(chunkIndex, Chunk.SIZE); Chunk chunk = new Chunk(this, chunkIndex, blocks); this.AddChild(chunk); loadedChunks[chunkIndex] = new Tuple <Chunk, bool, bool>(chunk, buildMesh, true); if (buildMesh) { chunksToUpdate.AddLast(chunkIndex); } chunkNo++; //We take data from ANIMAL_CHUNK_RANGE closest chunks to player, throw it in a normal distribution, and generate animals from the dist. if (chunkNo == (int)ANIMAL_CHUNK_RANGE) { chunkNo = 0; // Spawn animals Vector3 playerPos = player.GetTranslation(); IntVector2 playerChunk = new IntVector2((int)(playerPos.x / (Chunk.SIZE.x * Block.SIZE)), (int)(playerPos.z / (Chunk.SIZE.z * Block.SIZE))); Dictionary <string, int> animalCount = CountAnimalsInChunk(playerChunk); Random rand = new Random(); foreach (KeyValuePair <string, int> pair in animalCount) { //number to spawn double u1 = 1.0 - rand.NextDouble(); //uniform(0,1] random doubles double u2 = 1.0 - rand.NextDouble(); double randStdNormal = Math.Sqrt(-2.0 * Math.Log(u1)) * Math.Sin(2.0 * Math.PI * u2); //random normal(0,1) double randNormal = (pair.Value + (pair.Value / 4.0f) * randStdNormal); int number = (int)(Math.Max(0, Math.Round(randNormal / ANIMAL_CHUNK_RANGE))); for (int i = 0; i < number; i++) { double sexNum = rand.NextDouble(); AnimalBehaviourComponent.AnimalSex sex = (sexNum > 0.5 ? AnimalBehaviourComponent.AnimalSex.Male : AnimalBehaviourComponent.AnimalSex.Female); Vector3 chunkOrigin = (new Vector3(chunkIndex.x * Chunk.SIZE.x, Chunk.SIZE.y / 2.0f, chunkIndex.y * Chunk.SIZE.z) * Block.SIZE); Vector3 chunkSize = Chunk.SIZE * Block.SIZE; Vector3 randomPosition = new Vector3(rand.Next(0, (int)chunkSize.x), 100.0f, rand.Next(0, (int)chunkSize.z)); // ugly, TODO: fix GetNode(Game.GAME_PATH).GetNode("AnimalSpawner").Call("SpawnAnimal", pair.Key, sex, chunkOrigin + randomPosition); } } } } }