public bool canSpawnObject(float distance, ObjectType thisObjectType, int targetObjectIndex, ObjectType targetObjectType) { // return true if the parameters do not apply to the current distance if (!probability.withinDistance(distance)) { return(true); } // The target object doesn't matter if we are using objects of the same object type float totalDistance = infiniteObjectHistory.getTotalDistance(thisObjectType == ObjectType.Scene); if (minDistanceSameObjectType) { // lastSpawnDistance: the distance of the last object spawned of the inputted object type float lastSpawnDistance = infiniteObjectHistory.getLastObjectTypeSpawnDistance(thisObjectType); if (totalDistance - lastSpawnDistance <= minDistance) { return(false); } } // The rest of the tests need the target object, so if there is no target object then we are done early if (targetObjectIndex == -1) { return(true); } // objectSpawnIndex: spawn index of the last object of the same type (for example, the last duck obstacle spawn index) int objectSpawnIndex = infiniteObjectHistory.getObjectSpawnIndex(targetObjectIndex); // can always spawn if the object hasn't been spawned before and it is within the probabilities if (objectSpawnIndex == -1) { return(true); } // latestSpawnIndex: spawn index of the latest object type int latestSpawnIndex = infiniteObjectHistory.getObjectTypeSpawnIndex(targetObjectType); // can't spawn if there isn't enough object separation if (latestSpawnIndex - objectSpawnIndex <= minObjectSeparation) { return(false); } // objectLastDistance: distance of the last spawned object of the same type float objectLastDistance = infiniteObjectHistory.getSpawnDistance(targetObjectIndex); // can't spawn if we are too close to another object if (totalDistance - objectLastDistance <= minDistance) { return(false); } // looks like we can spawn return(true); }
// spawn the platforms, obstacles, power ups, and coins private PlatformObject spawnObjects(ObjectLocation location, Vector3 position, Vector3 direction, bool activateImmediately) { setupSection(location, false); int localIndex = infiniteObjectManager.getNextObjectIndex(ObjectType.Platform, spawnData); if (localIndex == -1) { print("Unable to spawn platform. No platforms can be spawned based on the probability rules"); return(null); } PlatformObject platform = spawnPlatform(localIndex, location, position, direction, activateImmediately); if (platform.canSpawnCollidable() && Random.value >= noCollidableProbability.getValue(infiniteObjectHistory.getTotalDistance(false))) { // First try to spawn an obstacle. If there is any space remaining on the platform, then try to spawn a coin. // If there is still some space remaing, try to spawn a powerup. // An extension of this would be to randomize the order of ObjectType, but this way works if the probabilities // are setup fairly spawnCollidable(ObjectType.Obstacle, position, direction, location, platform, localIndex, activateImmediately); if (platform.canSpawnCollidable()) { spawnCollidable(ObjectType.Coin, position, direction, location, platform, localIndex, activateImmediately); if (platform.canSpawnCollidable()) { spawnCollidable(ObjectType.PowerUp, position, direction, location, platform, localIndex, activateImmediately); } } } return(platform); }
// The probability of this object occuring can be based on the previous objects spawned. public bool probabilityAdjustment(InfiniteObjectHistory infiniteObjectHistory, float distance, ref float localDistance, ref float probability) { for (int i = 0; i < rules.Count; ++i) { if ((probability = rules[i].probabilityAdjustment(distance, targetObjectIndex, targetObject.getObjectType())) != -1) { localDistance = infiniteObjectHistory.getTotalDistance(targetObjectIsScene) - infiniteObjectHistory.getSpawnDistance(targetObjectIndex); return(true); } } return(false); }
// The probability of this object occuring can be based on the previous objects spawned. public bool probabilityAdjustment(InfiniteObjectHistory infiniteObjectHistory, float distance, ref float localDistance, ref float probability) { if (targetObjectIndex == -1) { Debug.LogError("ObjectRuleMap:probabilityAdjustment error: target object doesn't exist. Ensure the target object has been added to the Infinite Object Manager."); return false; } for (int i = 0; i < rules.Count; ++i) { if ((probability = rules[i].probabilityAdjustment(distance, targetObjectIndex, targetObject.getObjectType())) != -1) { localDistance = infiniteObjectHistory.getTotalDistance(targetObjectIsScene) - infiniteObjectHistory.getSpawnDistance(targetObjectIndex); return true; } } return false; }
/** * The next platform is determined by probabilities as well as object rules. * spawnData contains any extra data that is needed to make a decision if the object can be spawned */ public int getNextObjectIndex(ObjectType objectType, ObjectSpawnData spawnData) { InfiniteObject[] objects = null; switch (objectType) { case ObjectType.Platform: objects = platforms; break; case ObjectType.Scene: objects = scenes; break; case ObjectType.Obstacle: objects = obstacles; break; case ObjectType.Coin: objects = coins; break; case ObjectType.PowerUp: objects = powerUps; break; } float totalProbability = 0; float distance = infiniteObjectHistory.getTotalDistance(objectType == ObjectType.Scene); int objectIndex; for (int localIndex = 0; localIndex < objects.Length; ++localIndex) { objectIndex = localIndexToObjectIndex(localIndex, objectType); // cache the result objectCanSpawnCache[objectIndex] = appearanceRules[objectIndex].canSpawnObject(distance, spawnData); if (!objectCanSpawnCache[objectIndex]) { continue; } probabilityCache[objectIndex] = appearanceProbability[objectIndex].getProbability(distance) * appearanceRules[objectIndex].probabilityAdjustment(distance); totalProbability += probabilityCache[objectIndex]; } // chance of spawning nothing (especially in the case of collidable objects) if (totalProbability == 0) { return(-1); } float randomValue = Random.value; float prevObjProbability = 0; float objProbability = 0; // with the total probability we can determine a platform // minor optimization: don't check the last platform. If we get that far into the loop then regardless we are selecting that platform for (int localIndex = 0; localIndex < objects.Length - 1; ++localIndex) { objectIndex = localIndexToObjectIndex(localIndex, objectType); if (!objectCanSpawnCache[objectIndex]) { continue; } objProbability = probabilityCache[objectIndex]; if (randomValue <= (prevObjProbability + objProbability) / totalProbability) { return(localIndex); } prevObjProbability += objProbability; } return(objects.Length - 1); }