Last active
August 29, 2015 14:15
-
-
Save rdavisau/96e9dba98fc0e2484fc5 to your computer and use it in GitHub Desktop.
CocosSharp Extension Methods - Helpers for actions, layout, sizing, drawing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Snippet Name: CocosSharp Extension Methods | |
Platform: All | |
Function: CocosSharp helpers for actions, layout, sizing, drawing | |
Includes: | |
- Awaitable CCNode.RunActionsWithTask - allows you to await the running of a set of actions (for example, in order to not proceed with subsequent code till an animation completes), without having to explicitly calculate the duration of the actions or use a callback. | |
- Easy relative positioning with CCNode.PlaceAt - allows you to position a CCNode relative to the boundaries of a parent CCNode. Fluent style, so can be used at initialisation time. | |
- Easy filled colours with CCDrawNode.FillWith and quick sprite initialisation with CCNode.WithSprite, also fluent. | |
- Quick insetting or outsetting with CCSize.MultiplyBy. | |
- A few others - just take a look - they are all documented :) | |
You can paste this whole gist into LINQPad with the CocosSharp package installed and it will run the sample. | |
Snippet: | |
*/ | |
public static class CocosExtensions | |
{ | |
/// <summary> | |
/// Returns a task that will complete after the provided actions complete. | |
/// Will not complete if the action list contains a CCRepeatForever. | |
/// </summary> | |
/// <param name="node"></param> | |
/// <param name="actions">The actions to perform</param> | |
/// <returns></returns> | |
public static Task<bool> RunActionsWithTask(this CCNode node, params CCFiniteTimeAction[] actions) | |
{ | |
var t = new TaskCompletionSource<bool>(); | |
node.RunAction(new CCSequence(actions.Concat(new[] { new CCCallFunc(() => t.SetResult(true)) }).ToArray())); | |
return t.Task; | |
} | |
/// <summary> | |
/// Centers label text vertically and horizontally | |
/// </summary> | |
/// <typeparam name="TLabel"></typeparam> | |
/// <param name="label"></param> | |
/// <returns></returns> | |
public static TLabel WithTextCentered<TLabel>(this TLabel label) where TLabel : CCLabel | |
{ | |
label.HorizontalAlignment = CCTextAlignment.Center; | |
label.VerticalAlignment = CCVerticalTextAlignment.Center; | |
return label; | |
} | |
/// <summary> | |
/// Applies the specified horizontal text aligment | |
/// </summary> | |
/// <typeparam name="TLabel"></typeparam> | |
/// <param name="label"></param> | |
/// <param name="alignment"></param> | |
/// <returns></returns> | |
public static TLabel WithTextAlignment<TLabel>(this TLabel label, CCTextAlignment alignment) where TLabel : CCLabel | |
{ | |
label.HorizontalAlignment = alignment; | |
return label; | |
} | |
/// <summary> | |
/// Draws a rectangle the size of the provided node's BoundingBox in the provided colour | |
/// </summary> | |
/// <typeparam name="TNode"></typeparam> | |
/// <param name="node"></param> | |
/// <param name="colour"></param> | |
/// <returns></returns> | |
public static TNode FillWith<TNode>(this TNode node, CCColor3B colour) where TNode : CCDrawNode | |
{ | |
node.Color = colour; | |
node.DrawRect(node.BoundingBox); | |
return node; | |
} | |
/// <summary> | |
/// Loads a sprite into the provided CCnode | |
/// </summary> | |
/// <typeparam name="TNode"></typeparam> | |
/// <param name="node"></param> | |
/// <param name="fileName"></param> | |
/// <returns></returns> | |
public static TNode WithSprite<TNode>(this TNode node, string fileName) | |
where TNode : CCNode | |
{ | |
node.AddChild(new CCSprite(new CCTexture2D(fileName))); | |
return node; | |
} | |
/// <summary> | |
/// Places the target node within the provided parent node (or its existing node) according to the xPct and yPct factors | |
/// </summary> | |
/// <typeparam name="T"></typeparam> | |
/// <param name="node"></param> | |
/// <param name="xPct">A value from 0f to 1f (left to right) indicating how far along the x-axis the node should sit within the parent.</param> | |
/// <param name="yPct">A value from 0f to 1f (top to bottom) indicating how far along the y-axis the node should sit within the parent.</param> | |
/// <param name="parent">The parent node within which the target should sit. If null, the target must already have a parent.</param> | |
/// <returns></returns> | |
public static T PlaceAt<T>(this T node, double xPct, double yPct, CCNode parent = null) where T : CCNode | |
{ | |
if (parent == null) | |
parent = node.Parent.AssertNotNull("No parent container for node requiring PlaceAt"); | |
else | |
{ | |
// check whether target already has a parent, if it does we need to remove it before placing in new parent | |
if (node.Parent != null) | |
node.RemoveFromParent(false); | |
parent.AddChild(node); | |
} | |
var parentSize = parent.BoundingBox.Size; | |
var targetX = (float)(parentSize.Width * xPct); | |
var targetY = (float)(parentSize.Height - (parentSize.Height * yPct)); | |
node.AnchorPoint = CCPoint.AnchorMiddle; | |
node.Position = new CCPoint(targetX, targetY); | |
return node; | |
} | |
/// <summary> | |
/// Returns the target node with the provided actions set to repeat indefinitely | |
/// </summary> | |
/// <typeparam name="TNode"></typeparam> | |
/// <param name="node"></param> | |
/// <param name="actions"></param> | |
/// <returns></returns> | |
public static TNode WithOngoingActions<TNode>(this TNode node, params CCFiniteTimeAction[] actions) where TNode : CCNode | |
{ | |
var repeat = new CCRepeatForever (actions); | |
node.RunAction (repeat); | |
return node; | |
} | |
/// <summary> | |
/// Return a new CCSize with the dimensions of factor * the target CCSize | |
/// </summary> | |
/// <param name="size"></param> | |
/// <param name="factor"></param> | |
/// <returns></returns> | |
public static CCSize MultiplyBy(this CCSize size, float factor) | |
{ | |
return new CCSize(size.Width * factor, size.Height * factor); | |
} | |
/// <summary> | |
/// Return a new CCSize with the dimensions of xFactor * the target CCSize width, yFactor * the target CCSize height | |
/// </summary> | |
/// <param name="size"></param> | |
/// <param name="factor"></param> | |
/// <returns></returns> | |
public static CCSize MultiplyBy(this CCSize size, float xFactor = 1, float yFactor = 1) | |
{ | |
return new CCSize(size.Width * xFactor, size.Height * yFactor); | |
} | |
/// <summary> | |
/// Returns target after asserting not null | |
/// </summary> | |
/// <typeparam name="T"></typeparam> | |
/// <param name="obj"></param> | |
/// <param name="msg"></param> | |
/// <returns></returns> | |
public static T AssertNotNull<T>(this T obj, string msg = null) | |
{ | |
Debug.Assert(obj != null, msg ?? "AssertNotNull failed"); | |
return obj; | |
} | |
/// <summary> | |
/// Clamps the provided value to within the provided range | |
/// </summary> | |
/// <param name="f"></param> | |
/// <param name="min"></param> | |
/// <param name="max"></param> | |
/// <returns></returns> | |
public static float Between(this float f, float min, float max) | |
{ | |
return Math.Max(Math.Min(max, f), min); | |
} | |
/// <summary> | |
/// Returns true if the provided value is positive | |
/// </summary> | |
/// <param name="f"></param> | |
/// <returns></returns> | |
public static bool IsPositive(this float f) | |
{ | |
return f >= 0; | |
} | |
/// <summary> | |
/// Returns true if the provided value is negative | |
/// </summary> | |
/// <param name="f"></param> | |
/// <returns></returns> | |
public static bool IsNegative(this float f) | |
{ | |
return !IsPositive(f); | |
} | |
/// <summary> | |
/// Returns true if the provided values have different signs | |
/// </summary> | |
/// <param name="f1"></param> | |
/// <param name="f2"></param> | |
/// <returns></returns> | |
public static bool HasDifferentSignTo(this float f1, float f2) | |
{ | |
return !f1.HasSameSignAs(f2); | |
} | |
/// <summary> | |
/// Returns true if the provided values have the same sign (both positive, both negative) | |
/// </summary> | |
/// <param name="f1"></param> | |
/// <param name="f2"></param> | |
/// <returns></returns> | |
public static bool HasSameSignAs(this float f1, float f2) | |
{ | |
return (f1.IsPositive() && f2.IsPositive()) || (f1.IsNegative() && f2.IsNegative()); | |
} | |
} | |
/* | |
Example Use - Label Utils, PlaceAt, FillWith, RunActionsWithTask: | |
*/ | |
public static class Example | |
{ | |
public static async void DoExample(this CCLayer @this) | |
{ | |
var container = new CCNode() | |
{ | |
ContentSize = new CCSize(@this.VisibleBoundsWorldspace.MaxX*.75f, @this.VisibleBoundsWorldspace.MaxY*.1f), | |
Scale = 5f, | |
Rotation = -22.5f, | |
}.PlaceAt(.5f, .35f, @this); | |
var filledBanner = new CCDrawNode() {ContentSize = container.ContentSize} | |
.FillWith(CCColor3B.Red) | |
.PlaceAt(.5f, .5f, container); | |
var newLabel = new CCLabel("LABEL!", "consolas", 48f) | |
.WithTextCentered() | |
.PlaceAt(.5f, .5f, container); | |
await container.RunActionsWithTask(new CCEaseBounceOut(new CCScaleTo(1f, 1f))); | |
filledBanner.FillWith(CCColor3B.Green); | |
newLabel.Text = "The animation is done!!"; | |
} | |
} | |
/* below is just scaffolding */ | |
void Main() | |
{ | |
var app = new CCApplication { ApplicationDelegate = new AppDelegate() }; | |
app.StartGame(); | |
} | |
public class AppDelegate : CCApplicationDelegate | |
{ | |
public override void ApplicationDidFinishLaunching(CCApplication app, CCWindow window) | |
{ | |
var scene = new CCScene(window); | |
var layer = new MyLayer(); | |
scene.AddChild(layer); | |
window.RunWithScene(scene); | |
} | |
} | |
public class MyLayer : CCLayer | |
{ | |
protected override void AddedToScene() | |
{ | |
base.AddedToScene(); | |
this.DoExample(); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment