Tutorials Tutorials




Note: These tutorials explain how to code apps with the Delta Engine and quickly go through the most important topics. There is much more to explore in the sample games code, help and by looking through the source code. Things advance every release, these tutorials just cover the most basic features. You can also achieve most things here just as easily via the Editor visually.

To get started please install the Editor and copy+paste the code presented here into the Continuous Updater or try it directly in your browser. Alternatively you can also open each of the Tutorials presented here in your installer or cloned source code folder (under Tutorials there is one solution per category).


Basic Tutorial 1: Create Window


Start by deriving your Program class from the App class:
1
2
3
4
5
6
7
8
9
10
11
12
public class Program : App
{
  public Program()
  {
    // Initialization code goes here
  }
 
  public static void Main()
  {
    new Program().Run();
  }
}
Unit tests can derive from TestWithMocksOrVisually<App> instead, which allows testing easily via ReSharper, NCrunch, TestDriven.Net, Visual Studio, manually or any other testing framework. When trying out code in the Editor (Continuous Updater) or your browser (like all the examples here) you just need the initialization code.

The Window is created automatically, but if you want to change it use the App.Resolve method, which you can also use to get any engine or game class.
1
Resolve<Window>().BackgroundColor = Color.CornflowerBlue;
1
resolver->Resolve<Window>()->SetBackgroundColor(Color::CornflowerBlue);
1
Resolve<Window>().BackgroundColor = Color.CornflowerBlue;
1
Resolve<Window>().BackgroundColor = Color.CornflowerBlue
Download Windows Download Android Play Play in Browser

External Link: OpenGL Tutorial how to open a window


Basic Tutorial 2: Draw Line


To draw a line create a Line2D object with the start and end position plus a color.
1
2
3
4
5
var line = new Line2D(-Vector2D.Half, Vector2D.Half, Color.Red);
line.Rotation = 0;
line.Entity.AddComponent(new Rotate2D());
Scene.Current.AttachGestureAndMessages(line, Gesture.Click,
  new SetRenderDataMessage<Color> { NewValue = Color.Yellow });
1
auto line = std::make_shared<Line2D>(Point::Zero, Point::One, Color::Red);
1
Resolve<Window>().BackgroundColor = Color.CornflowerBlue;
1
Resolve<Window>().BackgroundColor = Color.CornflowerBlue
As you will see in later tutorials we can change or remove it and any other renderable entity at any time. Line2D is just a simple EntityBuilder class adding the Line2DData (relative Start & End positions), Vector2D (to make it a 2D entity) and Color RenderData components for the line. Here we also add a Rotation RenderData component, any other component (there are hundreds) can be added to and will change how the entity is rendered or behaves. All of the Delta Engine logic works this way, which makes the Editor extremely powerful and anything written with components is reusable.

All entities are persistent and will stay on the screen until deactivated via Dispose. The third code line rotates the line around, which is explained further in tutorial 5 below. The last line attaches a gesture with a message to the entity and changes the color of it when clicking (or tapping) on the screen. Details on triggers and gestures can be found in our wiki, they are not just used for input, but for event or app logic executing something when the trigger is invoked (think of it like a global if statement or state machine).

Download Windows Download Android Play Play in Browser

External Link: OpenGL low level line drawing

Basic Tutorial 3: Draw Ellipse


The Rendering namespace provides a ton of shapes you can use or extend. Line2D and FilledRectangle2D are useful for debugging, others like Ellipse2D are also useful:
1
new Ellipse(Vector2D.Half, 0.4f, 0.2f, Color.Red);
1
std::make_shared<Ellipse>(Point::Half, 0.4f, 0.2f, Color::Red);
1
new Ellipse(Point.Half, 0.4f, 0.2f, Color.Red);
1
new Ellipse(Point.Half, 0.4f, 0.2f, Color.Red)
This looks very simple, but you can already do a lot with simple shapse like these by combining them. Check out the How to compose entities - Build a smiley out of Ellipse2D componentswiki entry.
Download Windows Download Android Play Play in Browser

External Link: OpenGL Tutorial how to draw a triangle


Basic Tutorial 4: Draw Image


To load and draw images in 2D use the Sprite class:
1
new Sprite("DeltaEngineLogo", Vector2D.Zero);
1
std::make_shared<Sprite>("DeltaEngineLogo", Vector2D::Zero);
1
new Sprite("DeltaEngineLogo", Vector2D.Zero);
1
new Sprite("DeltaEngineLogo", Vector2D.Zero)
Any position or size value is specified in Quadratic Screen Space, which helps supporting any resolution or aspect ratio on any device. Use alignment to align elements on the screen or to parent entities.

Download Windows Download Android Play Play in Browser


External Link: OpenGL Texturing

Basic Tutorial 5: Draw Rotating Sprite


Attach any component to change the behavior of an entity. In this example we are just using the Rotate2D component to rotate the sprite by 90 degrees each second (can be adjusted):
1
2
3
4
5
6
var sprite = new Sprite("DeltaEngineLogo", Vector2D.Zero)
{
  Size = new Size(0.5f),
  Rotation = 0
};
sprite.Entity.AddComponent(new Rotate2D());
1
std::make_shared<Ellipse>(Point::Half, 0.4f, 0.2f, Color::Red);
1
2
3
new Sprite(ContentLoader.Load<Material>("Logo"),
  Rectangle.HalfCentered).
  StartRotating(Randomizer.Current.Get(-50, 50));
1
2
3
new Sprite(ContentLoader.Load<Material>("Logo"),
  Rectangle.HalfCentered).
  StartRotating(Randomizer.Current.Get(-50, 50))
This works with any entity class, it could be the line or ellipse from the previous tutorials or any other 2D entity there is. Attaching Rotate2D to a 3D entity or any entity that does not have a Rotation RenderData component has no effect, the Editor will show you a warning if an entity is incomplete. All values are in degrees and per second. In this example the sprite will rotate 90 degrees every second (45 in 0.5s).

Download Windows Download Android Play Play in Browser


External Link: OpenGL Tutorial about rotations



Basic Tutorial 6: Draw Scrollable Background


Another example is the MoveUV component, which allows changing the UV rectangle used for rendering over time. Check the Entity tutorials for player and enemy classes on top of this moving background.
1
2
3
4
var sprite = new Sprite("Road", Vector2D.Zero);
sprite.Size = Size.One;
sprite.UV = UVRectangle.One;
sprite.Entity.AddComponent(new MoveUV { Speed = Vector2D.Down });
1
std::make_shared<Ellipse>(Point::Half, 0.4f, 0.2f, Color::Red);
1
2
3
new Sprite(ContentLoader.Load<Material>("Logo"),
  Rectangle.HalfCentered).
  StartRotating(Randomizer.Current.Get(-50, 50));
1
2
3
new Sprite(ContentLoader.Load<Material>("Logo"),
  Rectangle.HalfCentered).
  StartRotating(Randomizer.Current.Get(-50, 50))
MoveUV works with any Entity2D that has a tile-able texture (make sure you set the AllowTiling property of an image to True in the Editor). You cannot use it with a line or ellipse because it does not have any UV texture coordinates. You might also have noticed that we have to add the UV component via the Sprite.UV property, like we had to do with Sprite.Rotation before when using the Rotate2D component. When using the Editor these required components are added automatically for you, but in code you have to do this yourself. If an entity does not do what you want, either check yourself if all requirements are met in code (the Rotate2DProcessor clearly states it needs both a Rotation component and a Rotate2D component) or use the Editor to see if an entity is incomplete (a red warning will appear in the properties).

Download Windows Download Android Play Play in Browser



Basic Tutorial 7: Draw Font


Simply speaking FontText is just like all the other entities we met before, it just has different constructor parameters. Normally the same font content is used many times (e.g. text on lots of buttons), like Sprites can be created from Image objects, FontText can be created from Font content objects (Font.Default just points to the Verdana12 DefaultContent font).
1
new FontText(Font.Default, "Hi there", Vector2D.Zero);
1
std::make_shared<FontText>(Font::Default, "Hi there", Vector2D::Zero);
1
new FontText(Font.Default, "Hi there", Vector2D.Zero);
1
new FontText(Font.Default, "Hi there", Vector2D.Zero)
Feel free to play around using the classes you learned about till now. For example recolor the font and make it rotate.

Download Windows Download Android Play Play in Browser


External Link: OpenGL Tutorial how to draw 2D text



Basic Tutorial 8: Play Sound


Creating Sounds works like the examples above. To play them attach the PlayMessage, which is usually triggered through some trigger or gesture. Often sounds are part of a more complex entity like a particle effect or a sub entity like the attack or death animation.
1
2
3
4
var sound = new Sound("DefaultSound");
new FontText(Font.Default, "Click to play sound", Vector2D.Zero);
Scene.Current.AttachGestureAndMessages(sound, Gesture.Click,
  new PlayMessage());
1
std::make_shared<Sound>("DefaultSound");
1
2
var sound = ContentLoader.Load<Sound>("DefaultSound");
new Command("Click", () => sound.Play());
1
2
var sound = ContentLoader.Load<Sound>("DefaultSound")
new Command("Click", () => sound.Play())
Download Windows Download Android Play Play in Browser



Basic Tutorial 9: Play Music

Music content is also loaded like any other content and is used identically to all other multimedia content. As mentioned before playback is triggered through the PlayMessage component. In addition music can be managed by adding the MusicList template entity into a scene to play all musics found in it (and its parent scenes).
1
2
3
4
var music = new Music("DefaultMusic");
new FontText(Font.Default, "Click to play music", Vector2D.Zero);
Scene.Current.AttachGestureAndMessages(music, Gesture.Click,
  new PlayMessage());
1
std::make_shared<Music>("DefaultMusic");
1
2
var music = ContentLoader.Load<Music>("DefaultMusic");
new Command("Click", () => music.Play());
1
2
var music = ContentLoader.Load<Music>("DefaultMusic")
new Command("Click", () => music.Play())
Download Windows Download Android Play Play in Browser



Basic Tutorial 10: Play Video

Video content is also handled in the same manner as Sound or Music, but usually will block the whole screen with the video to be played (especially on mobile platforms). Playback can be stopped by the user (click gesture) or in code (timeout trigger, other triggers). When the video ends a trigger is also invoked, e.g. to go to the next scene.
1
2
3
4
var video = new Video("DefaultVideo");
new FontText(Font.Default, "Click to play video", Vector2D.Zero);
Scene.Current.AttachGestureAndMessages(video, Gesture.Click,
  new PlayMessage());
1
std::make_shared<Music>("DefaultMusic");
1
2
var music = ContentLoader.Load<Music>("DefaultMusic");
new Command("Click", () => music.Play());
1
2
var music = ContentLoader.Load<Music>("DefaultMusic")
new Command("Click", () => music.Play())
Download Windows Download Android Play Play in Browser



Back to top

Entities


Entities are the motor of all things you can interact with or render on screen in your game or application. Pretty much all high level classes are derived from Entity and you can mix and match functionality easily as you have seen in the Basic Tutorials already. In the following 10 tutorials we will write a very simple 2D racing game while explaining the basics of entities.


Entities Tutorial 1: Creating Your Own Entity


To create an Entity you can either derive from an existing EntityBuilder (like Sprite, Button, shapes, etc.) or just build your own. You do not actually need a EntityBuilder, it is just used in code, all it does it add components to a new entity. The same can be done manually and this is how all entities loaded from content work and how the Editor works.

For new rendering features implement a Renderer, for new logic add a Processor. Renderers and Processors are defined and executed automatically for the component combinations they use (called nodes). E.g. SpriteRenderer requires Vector2D and an Image component, which is what the Sprite class add to a new entity created with it. In this example we will extend the Sprite class to load the Earth animation material. In later tutorials this Earth class is extended more.
1
2
3
4
5
6
public class Earth : Sprite
{
  public Earth(Vector2D position)
    : base(Scene.Current.GetEntity("EarthImagesAnimation"),
      position) {}
}
To use the new Earth class we just need to instantiate it. Let's do it ten times and attach a click event to the original EarthImagesAnimation content entity, so each new instantiated earth pauses if it is clicked on.
1
2
3
4
5
Scene.Current.AttachGestureAndMessages(
  Scene.Current.GetEntity("EarthImagesAnimation"),
  Gesture.Click, new TogglePauseMessage());
for (int num = 0; num < 10; num++)
  new Earth(new Vector2D(-0.45f + num / 10.0f, 0));
For this kind of code the Continuous Updater of the Editor is very useful and fun to use. You could quickly change the 10 earths to 100, have them rotate or animate with different speeds, give them colors, adjust how they are spaced, etc. All while seeing what you doing right then and there without switching context from your IDE to your app back and forth. Once you start coding this way you will never want to go back to the typical code-compile-run-see result on screen-exit loop for these kind of visual tasks.

Download Windows Download Android Play Play in Browser



Entities Tutorial 2: Attaching Behavior


Entities have any number of components, which controls what behavior and data they have. Renderers and Processors are executed based on which components are present. Let's extend the Earth Entity by simply adding a few more components:
1
2
3
4
5
6
7
8
9
10
11
public class Earth : Sprite
{
  public Earth(Vector2D position)
    : base(Scene.Current.GetEntity("EarthImagesAnimation"),
      position)
  {
    Entity.AddComponent(Gravity2D.Shared);
    Entity.AddComponent(new Velocity2D());
    Entity.AddComponent(new BounceIfAtScreenEdge());
  }
}
Components by themselves just hold some adjustable data like scale, position or rotation values, which are easily adjustable with sliders in the Editor via the Entity Properties. Renderers bring things on screen, but there are far more Processors that modify the entity data each tick based on the component values. In this example Gravity2D specifies that the Entity should be pulled down (Gravity2D.Shared is global and all entities using it will be forced to the same direction). Velocity2D holds the current velocity of the entity, which is important because an entity does not have anything by default, everything needs to be added as needed (position, color, rotation, velocity, etc.). Finally the BounceIfAtScreenEdge provides collision support so the entity does not fall out of the screen, but instead bounces off and stays visible. Once a Earth reaches the screen border it bounces and move back to the middle of the screen again until gravity pushes it down again.

Download Windows Download Android Play Play in Browser



Entities Tutorial 3: Adding more components


An Entity can have multiple data components like a color, position, points for polygons, images or anything else you might need for each of your entities. Components can be added by calling the Add method of the Entity class.

In the previous tutorial we already added a component to give our Earth gravity. Let's add a red outline to our earth sprite.
1
2
3
4
5
6
7
8
9
10
11
12
public class Earth : Sprite
{
  public Earth(Vector2D position)
    : base(Scene.Current.GetEntity("EarthImagesAnimation"),
      position)
  {
    Entity.AddComponent(new OutlineColor { Color = Color.Red });
    Entity.AddComponent(Gravity2D.Shared);
    Entity.AddComponent(new Velocity2D());
    Entity.AddComponent(new BounceIfAtScreenEdge());
  }
}
Download Windows Download Android Play Play in Browser



Entities Tutorial 4: Changing Default Behavior of Components


Components have a default behavior described via their default constructor (they cannot have any other constructor or method btw). Often you want to change the behavior (via the Editor), which means you just set some different values via the properties. This is either done at initialization time or later via messages.

RenderData is automatically interpolated in between frames (which includes all low level datatypes like Color, Rotation, Vector2D, Vector3D, Quaternion, etc. and all other classes using the Lerp interface). The BounceIfAtScreenEdge component from before is also a CollisionHappened component, which can be used for the CollisionTrigger in attached entities to do extra things when a bouncing happened. In this example we are going to use it to change the color of the Earth, using the Logo again here to see the new random color a bit easier:
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Earth : Sprite
{
  public Earth(Vector2D position)
    : base("DeltaEngineLogo", position)
  {
    Entity.AddComponent(new Velocity2D
      { Speed = new Vector2D(0.2f, 0.5f)});
    Entity.AddComponent(new BounceIfAtScreenEdge
      { ReflectionStrength = 1 });
    Scene.Current.AttachTriggerAndMessages(Entity,
      new CollisionTrigger(), new RandomColorMessage());
  }
}
Download Windows Download Android Play Play in Browser



Entities Tutorial 5: Tags


Every entity can have a custom tag attached to it. This allows to quickly query through the list of entities as well and can be used for other specific user needs. An entity can have multiple tags. You can freely add and remove tags with AddTag and RemoveTag or clear them all with the ClearTags method.:
1
2
3
new Earth(new Vector2D(0.3f, 0.5f)).AddTag("EarthToggle");
new Earth(new Vector2D(0.5f, 0.5f)).AddTag("EarthToggle");
new Earth(new Vector2D(0.7f, 0.5f)).AddTag("EarthNormal");
We now have 2 earths with the "EarthToggle" tag and one with "EarthNormal". In this example we are going to use an input command to toggle the animation playback for all entities with the tag "EarthToggle" on each click. To grab all entities with a specific tag you can ask the EntitiesRunner like this:
1
2
3
4
5
6
new Command(Command.Click, () =>
{
  foreach (Earth entity in
    EntitiesRunner.Current.GetEntitiesWithTag("EarthToggle"))
    entity.IsPlaying = !entity.IsPlaying;
});
Download Windows Download Android Play Play in Browser



Entities Tutorial 6: Triggers


An Trigger is a behavior which does a fixed predetermined task. Currently most triggers in the Delta Engine are used in combination with input commands to control when they should be invoked (e.g. MouseMovementTrigger will cause any input command to fire that has this trigger attached to it whenever the mouse is moved). In later more advanced tutorials a more complex trigger system for use in levels will be explained (LevelStartedTrigger, CollisionTrigger, TimeTrigger, etc.). For now we can just simply extend our Earth class to do something whenever we detect a collision.
1
2
3
4
5
6
7
public Program()
{
  var random = Randomizer.Current;
  for (int num = 0; num < 3; num++)
    new Earth(new Vector2D(random.Get(0.2f, 0.8f), random.Get(0.3f, 0.7f)),
      new Vector2D(random.Get(-0.4f, 0.4f), random.Get(-0.3f, 0.3f)));
}
We now have 3 Earths moving around on the screen and overlapping from time to time when they should collide. Let's change the Color of any Earth colliding with any other earth in an Update method, which is available once we derive from Updateable. Like before we could use GetEntitiesWithTag to find our Earth entities, but we can also get all entities of a type via EntitiesRunner.Current.GetEntitiesOfType.
1
2
3
4
5
6
7
public void Update()
{
  var allEarths = EntitiesRunner.Current.GetEntitiesOfType<Earth>();
  Set(allEarths.Any(other => this != other &&
    Center.DistanceTo(other.Center) < Size.Width)
    ? Color.Yellow : Color.White);
}
If you are not that used to Linq in C# yet, this is the same code using a simple foreach loop:
1
2
3
4
5
6
7
8
9
10
11
12
13
public void Update()
{
  var allEarths = EntitiesRunner.Current.GetEntitiesOfType<Earth>();
  bool isCollidingWithAnotherEarth = false;
  foreach (Earth otherEarth in allEarths)
    if (this != otherEarth &&
      Center.DistanceTo(otherEarth.Center) < Size.Width)
    {
      isCollidingWithAnotherEarth = true;
      break;
    }
  Set(isCollidingWithAnotherEarth ? Color.Yellow : Color.White);
}
Download Windows Download Android Play Play in Browser



Entities Tutorial 7: Deactivating Entities


All the entities in the game can be activated and deactivated at will. If an entity is deactivated then it is not handled by the behaviors anymore and hence is non-existent (neither rendered nor updated). When an entity is created, it is active by default. To pause just updating you can also pause an entity or temporarily remove an update behavior.
1
2
var earth = new Earth(Vector2D.Half);
new Command(Command.Click, () => earth.IsActive = !earth.IsActive);

Entities are also deactivated when they are disposed, which by default just sets IsActive to false thus detaching all behaviors.
1
entity.Dispose();
As long as you restore all your data in the virtual IsActive property you can always activate and deactivate entities (even disposed ones, which just call IsActive = false by default as described above). Inactive entities have just data and no connections to any behaviors anymore, if they run out of scope they will be cleaned up (as opposed to active entities, which will stay alive until you dispose them like in all previous tutorials).
1
entity.IsActive = true;
If your entity contains other entities as children (for example a screen or panel might contain other controls like buttons or labels) all of them will be activated or deactivated when you change IsActive of the owner. This feature is really useful for UI or other complex entities. Pausing works the same way, you can just pause any entity, which will stop its Update execution if the IsPausable flag is true (e.g. when opening an option screen to stop the application from doing its normal work).
1
Time.IsPaused = true;
Download Windows Download Android Play Play in Browser



Entities Tutorial 8: Input Commands


Input Commands make it really easy to control your application. All of the interactable build-in types like UI controls, Cameras or Actors use commands to control them. All you need to know is the name of the command and you can connect it to any method or action.
1
new Command(Command.Exit, Resolve<Window>().CloseAfterFrame);
This means whenever the Exit command is triggered the Window.CloseAfterFrame method is executed and will close the whole application. The Exit command is triggered for any device that supports it (e.g. Escape key on a keyboard), but any input trigger can be connected to any command via the Input Command Editor (which stores all commands and triggers into the DefaultCommands.xml content file).

For our little tutorial game we want to control a Player entity with the keyboard cursor keys or using a GamePad on a console, PC or mobile device. Or using touch triggers if the user clicks on the left or right portion of the screen. All this is done for us by just using the MoveLeft and MoveRight commands.
1
2
3
4
5
6
7
8
9
10
11
12
public class Player : Sprite
{
  public Player()
    : base(ContentLoader.Load<Material>("Logo"),
    new Vector2D(0.5f, 0.7f))
  {
    new Command(Command.MoveLeft,
      () => Center -= new Vector2D(Time.Delta * 0.5f, 0));
    new Command(Command.MoveRight,
      () => Center += new Vector2D(Time.Delta * 0.5f, 0));
  }
}
Download Windows Download Android Play Play in Browser



Entities Tutorial 9: Enemies


To make our game a bit more dynamic and exciting we should create new Enemies as the time goes along. There can be events or command triggers like in the previous tutorials to create new entities or change them, but in order to create new entities all the time we need a little helper construct to spawn our little Enemies (which are just Earth entities from before, we just rename the class to Enemy).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class EnemySpawner : Entity, Updateable
{
  public void Update()
  {
    if (Time.CheckEvery(2.5f))
      new Enemy();
  }
  public bool IsPauseable { get { return true; } }
}
 
public class Enemy : Sprite
{
  public Enemy()
    : base(ContentLoader.Load<Material>("Earth"),
      Rectangle.FromCenter(new Vector2D(Randomizer.Current.Get(),
      0.1f), new Size(0.1f * 1.35f, 0.1f)))
  {
    Add(new SimplePhysics.Data
    { Gravity = new Vector2D(0.0f, 0.1f), Duration = 10 });
    Start<SimplePhysics.Move>();
  }
}
Download Windows Download Android Play Play in Browser



Entities Tutorial 10: Putting it all together in the LogoRacer game


The final entities tutorial brings it all together in a little sample game called LogoRacer. You have to avoid the spinning earths as long as possible to get more points.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
public Program()
{
  new Sprite(ContentLoader.Load<Material>("Road"), Rectangle.One).
    StartMovingUV(new Vector2D(0, -0.8f));
  new ScoreDisplay(new Player(), new EnemySpawner());
  new Command("Exit", Resolve<Window>().CloseAfterFrame);
}
 
public class ScoreDisplay : FontText, Updateable
{
  public ScoreDisplay(Player player, EnemySpawner spawner)
    : base(Font.Default, "Score: ",
      Rectangle.FromCenter(0.5f, 0.25f, 0.2f, 0.1f))
  {
    this.player = player;
    this.spawner = spawner;
    RenderLayer = 1;
  }
 
  private readonly Player player;
  private readonly EnemySpawner spawner;
 
  public void Update()
  {
    if (Text.StartsWith("Game Over"))
      return;
    if (player.Color == Color.White)
      Text = "Score: " + spawner.EnemiesSpawned;
    else
      Text = "Game Over! " + Text;
  }
  public bool IsPauseable { get { return false; } }
}
 
public class EnemySpawner : Entity, Updateable
{
  public void Update()
  {
    if (!Time.CheckEvery(spawnTime))
      return;
    EnemiesSpawned++;
    if (spawnTime > 0.5f)
      spawnTime -= 0.15f;
    new Enemy();
  }
 
  private float spawnTime = 2.5f;
  public int EnemiesSpawned { get; private set; }
  public bool IsPauseable { get { return true; } }
}
 
public class Enemy : Sprite
{
  public Enemy()
    : base(ContentLoader.Load<Material>("Earth"),
      Rectangle.FromCenter(new Point(Randomizer.Current.Get(),
      0.1f), new Size(0.1f * 1.35f, 0.1f)))
  {
    Add(new SimplePhysics.Data
    { Gravity = new Point(0.0f, 0.1f), Duration = 10 });
    Start<SimplePhysics.Fall>();
  }
}
 
public class Player : Sprite, Updateable
{
  public Player()
    : base(ContentLoader.Load<Material>("Logo"),
      new Point(0.5f, 0.7f))
  {
    new Command("MoveLeft",
      () => Center -= new Point(Time.Delta * 0.5f, 0));
    new Command("MoveRight",
      () => Center += new Point(Time.Delta * 0.5f, 0));
  }
 
  public void Update()
  {
    var earths = EntitiesRunner.Current.GetEntitiesOfType<Enemy>();
    if (!earths.Any(e =>
      Center.DistanceTo(e.Center) < Size.Width/3 + e.Size.Width/2))
      return;
    Set(Color.Red);
    foreach (var command in commands)
      command.IsActive = false;
  }
  public bool IsPauseable { get { return true; } }
}
Download Windows Download Android Play Play in Browser

External Links

Open GL Tutorials: http://www.opengl-tutorial.org/
XNA Tutorials: http://nehe.gamedev.net/