I moved to a new URL! Check it out!

Dev Log: Coroutine Example

Image


Thanks to knowledge passed down from Chevy Ray I was able to get Coroutines working in Otter recently! Coroutines are magical chunks of code that are able to yield their execution and remember their state. It's bonkers what you can do with them using this power.

I added an example to Otter to hopefully help out any folks that are looking into using them:
using Otter;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CoroutineExample {
class CoroutineScene : Scene {

public Image ImageBox = Image.CreateRectangle(50);

public Color NextColor = Color.White;
public Color CurrentColor = Color.White;

public CoroutineScene() : base() {
// Center that box.
ImageBox.CenterOrigin();

// Gotta draw the box.
AddGraphic(ImageBox);

// Set the box position.
ImageBox.X = 100;
ImageBox.Y = 100;
}

public override void Begin() {
base.Begin();

// Start the coroutine, yo.
Game.Coroutine.Start(MainRoutine());
}

/// <summary>
/// The main coroutine to execute. This will move the box around and change its color.
/// </summary>
/// <returns>Whatever a coroutine thing returns. Sometimes 0 I guess.</returns>
IEnumerator MainRoutine() {
// Wait for 30 frames.
yield return Coroutine.Instance.WaitForFrames(30);
// Set the next color.
NextColor = Color.Red;
// Move the box to the top right.
yield return MoveBoxTo(540, 100);

// Wait for 30 frames.
yield return Coroutine.Instance.WaitForFrames(30);
// Set the next color.
NextColor = Color.Yellow;
// Move the box to the bottom right.
yield return MoveBoxTo(540, 380);

// Wait for 30 frames.
yield return Coroutine.Instance.WaitForFrames(30);
// Set the next color.
NextColor = Color.Green;
// Move the box to the bottom left.
yield return MoveBoxTo(100, 380);

// Wait for 30 frames.
yield return Coroutine.Instance.WaitForFrames(30);
// Set the next color.
NextColor = Color.Cyan;
// Move the box to the top left.
yield return MoveBoxTo(100, 100);

// Start a new coroutine.
Game.Coroutine.Start(MainRoutine());
}

IEnumerator MoveBoxTo(float x, float y) {
// Used to determine the completion.
var initialDistance = Util.Distance(ImageBox.X, ImageBox.Y, x, y);

float currentDistance = float.MaxValue;
while (currentDistance > 1) {
currentDistance = Util.Distance(ImageBox.X, ImageBox.Y, x, y);

// Determine the completion of the movement from 0 to 1.
var completion = Util.ScaleClamp(currentDistance, 0, initialDistance, 1, 0);

// Lerp the color of the box.
ImageBox.Color = Util.LerpColor(CurrentColor, NextColor, completion);

// Spin the box along with its movement.
ImageBox.Angle = Util.ScaleClamp(completion, 0, 1, 0, 360);

// Actually move the box.
ImageBox.X = Util.Approach(ImageBox.X, x, 5);
ImageBox.Y = Util.Approach(ImageBox.Y, y, 5);

// Wait until next frame.
yield return 0;
}

// Done moving. Update the color.
CurrentColor = NextColor;
}
}
}
I'm actually totally not sure if I'm doing it correctly in the example, but it seems to be working out well so far. Going to try using them for various things now in my current projects!

Comments

Toth
Toth
Yeah, Coroutines are great =D

A good implementation would be create a state machine with Coroutines, saves a lot of work.
Posted March 31st 2014 6:39 AM
Gary the Llama
Gary the Llama
Perfect timing. This will solve something I was working on just last night.
Posted March 31st 2014 8:14 AM
new comment!

Post your comment!

Name
Email
Comment