CocosSharp is a library for building 2D games using C# and F#. It is a .NET port of the popular Cocos2D engine. I wanted to play around with this library for a while and came up with a very simple demo to get a basic understanding of it.
This demo shows how to create a Particle follower. Simply drag your finger across the screen and a particle explosion will occur! You can view the source on Github if you directly want to dive into the code. Otherwise, read on and learn how to build a particle follower using the CocosSharp 2D Game Engine and Xamarin.Forms to build a beautiful cross-platform app.
The goal
The goal is to create a neat particle follower that follows your fingers around on the phone when you touch it. Although it’s not very useful, it’s beautiful to look at and will help you get your first steps into development with CocosSharp.
Play around with the source to change colors, speed and more!
Getting started
I’ll use Xamarin.Forms as starting point. Simply add the CocosSharp.Forms NuGet package to all Projects (iOS, Android and .NET Standard).
Once we got that in place, let’s move on!
Device specific variables
First, we’ll need to determine the size of the screen so we’ll be able to use it later. Since that differs for each device, we’ll need to request the OS to pass along that value to Xamarin.Forms. Add the following to the App.cs
-file.
public partial class App : Application {
public static int Height { get; set; }
public static int Width { get; set; }
public static int Density { get; set; }
}
To fill these values, we’ll need to add them in the OS specific solutions. For iOS, this means changing the AppDelegate.cs
.
public override bool FinishedLaunching(UIApplication app, NSDictionary options) {
App.Height = (int)UIScreen.MainScreen.Bounds.Height;
App.Width = (int)UIScreen.MainScreen.Bounds.Width;
App.Density = (int)UIScreen.MainScreen.Scale;
}
And for Android, we’ll need to update the MainActivity.cs
.
protected override void OnCreate(Bundle bundle) {
var metrics = Resources.DisplayMetrics;
App.Width = (int) metrics.WidthPixels / metrics.Density;
App.Height = (int) metrics.HeightPixels / metrics.Density;
App.Density = (int) metrics.Density;
}
Now that we got these values inside of Xamarin.Forms, we can move on!
The view
CocosSharp uses a CCGameView
in order to work. We’ll wrap that inside of a Xamarin.Forms ContentView
. I called this the ParticlesView
.
public class ParticlesView : ContentView {
ParticlesScene _scene;
public ParticlesView() {
var sharpView = new CocosSharpView {
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand,
ViewCreated = HandleViewCreated
};
Content = sharpView;
}
void HandleViewCreated(object sender, EventArgs e) {
var ccGView = sender as CCGameView;
if (ccGView != null) {
ccGView.DesignResolution = new CCSizeI(App.Width, App.Height);
_scene = new ParticlesScene(ccGView);
ccGView.RunWithScene(_scene);
}
}
}
A couple of things that I’d like to point out:
ViewCreated
– This is the event when the element is placed which we’ll use to draw theCCGameView
DesignResolution
– Here you see why we need theApp.Width
andApp.Height
to determine the dimensions to draw onRunWithScene
– CocosSharp uses aCCScene
to run the application, which we’ll create in the next step
Add a scene with particles
The scene is the piece of code that’ll actually draw the different particles on a CCLayer
. Let’s see how the ParticlesScene
looks like!
public class ParticlesScene : CCScene {
CCLayer _layer;
public ParticlesScene(CCGameView gameView) : base(gameView) {
_layer = new CCLayer();
this.AddLayer(_layer);
}
public void DrawParticle(CCPoint point) {
var explosion = new CCParticleExplosion(CCPoint.Zero) {
TotalParticles = 10,
StartColor = new CCColor4F(CCColor3B.White),
EndColor = new CCColor4F(CCColor3B.Black),
Position = new CCPoint(point.X / App.Density, App.Height - point.Y / App.Density)
};
_layer.AddChild(explosion);
}
}
The DrawParticle
-method will be called later on to draw the particles. CocosSharp comes with a couple of built-in Particles, like CCParticleFire
and CCParticleSmoke
. In this demo, we’ll be using the CCParticleExplosion
but you can play around with these values as well. Just play around with these variables do have more fun!
Enable touch
Update the HandleViewCreated
-method of the ParticlesView
and add an CCEventListenerTouchOneByOne
to enable listening to touch events. From here, we’ll call the DrawParticle
-method.
_scene = new ParticlesScene(ccGView);
var touchEvent = new CCEventListenerTouchOneByOne();
touchEvent.OnTouchBegan = (touch, _event) => {
_scene.DrawParticle(touch.LocationOnScreen);
return true;
};
touchEvent.OnTouchMoved = (touch, _event) => {
_scene.DrawParticle(touch.LocationOnScreen);
};
_scene.AddEventListener(touchEvent);
Finally, update the MainPage.xaml
to use the new view and you’re ready to go!
<ContentPage xmlns:local="clr-namespace:Particles" x:Class="Particles.MainPage">
<StackLayout>
<local:ParticlesView HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />
</StackLayout>
</ContentPage>
Conclusion & Download
Although the sample is pretty simple, it gives me a basic understanding of CocosSharp. The outcome looks pretty good and is fun to play around with! Since the Android Emulator supports multi-touch, we can even check how amazing that looks.
Take note there’s a discussion on where the future of CocosSharp as well as Cocos2d is going. What do you think? Let me know in the comments or on Twitter and feel free to improve the code.
Further reading:
4 comments On Particle follower with CocosSharp and Xamarin.Forms
Is there someway we could implement this functionality in a pre-existing Xamarin Forms app, so if the consumer tapped on a button/field there would be an explosion of particles (implementing it at the content page level)?
Absolutely! The ParticlesView is just a Xamarin.Forms ContentView, so if the Scene is already created you can easily pass along any action from the ContentPage downwards. Good luck!
Congratulations, I really liked it!,
I use CocosSharp, I’m sad about your abandonment. 🙁
Marco, i am having problems with texturecache, have you used this recently successfully?
I don’t know what you’re exactly bumping into, so feel free to contact me or hit me up on Twitter with a sample so I’ll be able to help you out. Looking forward!