void CreateDecor(Vector3 position, Vector3 leftVector) { // We discard a few calls _discard++; if (_discard % 3 != 0) { return; } // We use the simplex noise to evaluate chances with smooth transition double chance = _noise.Evaluate(position.X * 0.2f, 0) + 1; Node node = null; bool isTree = false; // Common decorations (grasses) if (chance < 1.2f) { // We discard a few of these too if (_rng.Next(6) < 4) { node = AtomicMain.CreateSpriteNode(_decorationLib.GetRandomFromGroup(0), 3, false); } } else if (chance < 1.3f) { node = AtomicMain.CreateSpriteNode(_decorationLib.GetRandomFromGroup(1), 4, false); } else if (chance < 1.7f) { // We only spawn trees if the surface isn't too steep if (Math.Abs(leftVector.Y) < 0.1f) { node = AtomicMain.CreateSpriteNode(_decorationLib.GetRandomFromGroup(2), 4, false); node.Scale2D = node.Scale2D *= 1 + _rng.Next(30) / 100f; isTree = true; } } if (node != null) { // We position the node on the surface, if the node is a tree we don't rotate it AND offset it a bit node.SetPosition(position + Vector3.Forward * 15); if (!isTree) { Quaternion transformation = Quaternion.FromRotationTo(Vector3.Left, leftVector); node.SetRotation(transformation); } else { node.Translate(-node.Up * 0.1f); } } }
public Terrain(Scene scene) { _scene = scene; // We load the materials, the ones in this example only use built in techniques, we use diffuse for the ground for performance _surfaceMaterial = Cache.Get <Material>("Materials/UnlitAlpha.xml"); _surfaceMaterial.SetTexture(0, Cache.Get <Texture2D>("Scenarios/grasslands/surface.png")); _chunkMaterial = Cache.Get <Material>("Materials/Unlit.xml"); _chunkMaterial.SetTexture(0, Cache.Get <Texture2D>("Scenarios/grasslands/ground.png")); // We create and populate a library with the decorations Func <string, Sprite2D> GetSprite = file => Cache.Get <Sprite2D>($"Scenarios/grasslands/Object/{file}"); _decorationLib = new DecorationLibrary <Sprite2D>( new [] { GetSprite("Bush (1).png"), GetSprite("Bush (2).png"), GetSprite("Bush (3).png"), GetSprite("Bush (4).png") }, new [] { GetSprite("Mushroom_1.png"), GetSprite("Mushroom_2.png"), GetSprite("Stone.png"), GetSprite("Sign_2.png") }, new [] { GetSprite("Tree_1.png"), GetSprite("Tree_2.png"), GetSprite("Tree_3.png") } ); // We setup the hotstop/origin of each sprite to be next to its bottom foreach (Sprite2D sprite in _decorationLib.GetAllResources()) { sprite.SetHotSpot(new Vector2(0.5f, 0.1f)); } // We generate the chunks and add some boxes randomly Sprite2D crateSprite = Cache.Get <Sprite2D>("Scenarios/grasslands/Object/Crate.png"); for (int i = 0; i < Chunksize * chunksToGenerate; i += Chunksize) { GenerateChunk(i); // Crates if (_rng.Next(100) < PercentageOfChunksWithCrates) { Node crateNode = AtomicMain.CreateSpriteNode(crateSprite, 3); crateNode.SetPosition(new Vector3(i + _rng.Next(8), 20, -5)); CollisionBox2D crateCollider = crateNode.CreateComponent <CollisionBox2D>(); crateCollider.SetSize(0.76f, 0.76f); crateCollider.SetDensity(1.0f); crateCollider.SetRestitution(0.6f); crateCollider.SetFriction(0.4f); } } }
public Clouds(float startX, int minY, int deviation, int amount, int range) { _minY = minY; _deviation = deviation; _range = range; Sprite2D[] cloudSprites = { Cache.Get <Sprite2D>("Scenarios/cloud1.png"), Cache.Get <Sprite2D>("Scenarios/cloud2.png"), Cache.Get <Sprite2D>("Scenarios/cloud3.png") }; // We pre-fill the screen with clouds float cloudSpacing = range * 2 / amount; _clouds = new Node[amount]; for (int i = 0; i < amount; i++) { _clouds[i] = AtomicMain.CreateSpriteNode(cloudSprites[rng.Next(cloudSprites.Length)], 4, false); RecycleCloud(startX -= cloudSpacing, _clouds[i]); } }
public Node CreateWheel(Sprite2D sprite, Vector2 relativePosition, float radius, int suspensionFrequency, float suspensionDamping, ParticleEffect2D particles, float distanceToEmitParticles) { Node wheelNode = AtomicMain.CreateSpriteNode(sprite); wheelNode.SetPosition2D(relativePosition); // CreateSpriteNode adds a RigidBody for us, so we get it here RigidBody2D wheelRigidBody = wheelNode.GetComponent <RigidBody2D>(); // We activate CCD wheelRigidBody.SetBullet(true); AtomicMain.AddCollider <CollisionCircle2D>(wheelNode).SetRadius(radius); // The Box2D wheel joint provides spring for simulating suspension ConstraintWheel2D wheelJoint = Node.CreateComponent <ConstraintWheel2D>(); wheelJoint.SetOtherBody(wheelRigidBody); wheelJoint.SetAnchor(relativePosition); wheelJoint.SetAxis(Vector2.UnitY); wheelJoint.SetFrequencyHz(suspensionFrequency); wheelJoint.SetDampingRatio(suspensionDamping); // Each wheel has a particle emitter to emit particles when it's in contact with the surface Node particlesNode = Node.Scene.CreateChild(); particlesNode.SetPosition(new Vector3(relativePosition.X, relativePosition.Y, 14)); ParticleEmitter2D particleEmitter = particlesNode.CreateComponent <ParticleEmitter2D>(); particleEmitter.SetEffect(particles); // We create a new Wheel struct and add to the _wheels list _wheels.Add(new Wheel(wheelRigidBody, wheelJoint, particleEmitter, distanceToEmitParticles)); return(wheelNode); }
public Node CreateHead(Sprite2D sprite, Vector3 relativePosition, float colliderRadius, Vector2 neckAnchor) { Node head = AtomicMain.CreateSpriteNode(sprite); head.SetPosition(relativePosition); AtomicMain.AddCollider <CollisionCircle2D>(head).SetRadius(colliderRadius); // This is the actual neck joint ConstraintRevolute2D joint = head.CreateComponent <ConstraintRevolute2D>(); joint.SetOtherBody(_rigidBody); joint.SetAnchor(neckAnchor); // This is the spring, it's attached to the body with an offset ConstraintDistance2D spring = head.CreateComponent <ConstraintDistance2D>(); spring.SetOtherBody(_rigidBody); spring.SetOwnerBodyAnchor(-Vector2.UnitY * 2); spring.SetOtherBodyAnchor(Node.WorldToLocal2D(head.WorldPosition2D - Vector2.UnitY * 2)); spring.SetFrequencyHz(3); spring.SetDampingRatio(0.4f); return(head); }