Quick look at the wolf catching up on the day’s news.
Aqua Utopia|海の底で記憶を紡ぐ

@theartofmadeline
almost home

ellievsbear
icyghini twinkie
cherry valley forever
I'd rather be in outer space 🛸

pixel skylines

bliss lane
RMH
Misplaced Lens Cap
Keni
Fai_Ryy
h
Cosimo Galluzzi

#extradirty
sheepfilms

KIROKAZE

seen from Türkiye

seen from Türkiye
seen from United States

seen from United States

seen from Singapore
seen from Bangladesh

seen from Türkiye

seen from Germany
seen from United States
seen from United States
seen from Spain
seen from United States

seen from United States
seen from Colombia

seen from Italy
seen from Serbia
seen from Bangladesh

seen from Türkiye

seen from Malaysia
seen from Germany
@ericmbernier
Quick look at the wolf catching up on the day’s news.

Anya is live and ready to show you everything. Watch her strip, dance, and perform exclusive shows just for you. Interact in real-time and make your fantasies come true.
Free to watch • No registration required • HD streaming
A few logo mockups.
Welcome to The Wolf’s Bite
The Wolf’s Bite is a one-versus-one, choose-your-own-adventure game, inspired by the classic fairytale, “The Three Little Pigs”. It also draws inspiration from the likes of “Shrek”, and “The Stinky Cheeseman and Other Fairly Stupid Tales”. As far as mechanics go, The Wolf’s Bite is influenced by “The Yawhg”, with an emphasis on thwarting the other player.
Here is a brief synopsis of the game’s main story:
After failing to thrive in the highly competitive residential demolition industry, mostly due to difficulties dealing with brick construction, The Big Bad Wolf decided it was time for a career change. Unable to resist the lure of entrepreneurship, he decided to enter the restaurant business. The Three Little Pigs, dissatisfied with their free sample demolitions, are conspiring against The Big Bad Wolf and his new restaurant, The Wolf’s Bite. The grand opening is next week. Will The Big Bad Wolf finally launch a successful enterprise or will the Three Little Pigs throw up a metaphorical brick wall and stop him?
We hope you enjoy a glimpse into our development process! Here, have a cookie!
A Look Back at 2014
It's been awhile since I've posted to this Tumblr, which I mostly started to host my Otter Tutorials. I've been busy working on A Wicked Curse with Izzy, and figured it would be fun to write a summary of my past year.
First, 2014 started off pretty weird. I was still in a lull following Comic Book Cody's success on FGL, and wasn't motivated to work on anything. I updated my website to its current look, and continued to tinker with Otter in my spare time. I was feeling unproductive, and wanted to release something, whether it be a game, an article, or whatever. This is when I decided to write a high-level tutorial series on Otter. The series has been pretty popular, given the small size of Otter's community. I occasionally receive emails thanking me for the series, and/or asking for help which I am always glad to give. Unfortunately, Otter's API is still very volatile and I don't have the bandwidth to support and update all of my tutorials through Otter's many iterations. However, all of the source code for the tutorials is hosted on my website, and will hopefully help introduce more people to the framework.
Fueled by the kind words from the Otter community, I was eager to pump out a small game or two. Doing so would mean I'd have to put my intentions to work on a bigger, desktop/PC game on hold for a few months. Inspired by a tweet, I took to the FGL community to collaborate with an artist. With a little luck, I stumbled across Iskander Aminov's portfolio, and shot him a message. We agreed to work together, and in a few weeks time Rampage Rex was born. Rex was successfully sponsored by Not Doppler, who was an absolute pleasure to work with!
Around the same time Rex was sponsored I attended PAX East in Boston. I met a few fellow indie developers, played some games, and had an absolute blast. I've even purchased passes to Friday and Saturday's PAX East in 2015. I'm really looking forward to going back! :D
Though Rex was sponsored, it was not scheduled to be released until mid-Fall. My urge to release something new was not quite satisfied yet. So, I did what any sane person would do: I started tinkering with Haxe, OpenFL, and the two libraries HaxePunk and HaxeFlixel. I've written here in the past that I had a fun time using FlashPunk, but wanted to move onto more powerful technology. Haxe seemed to be the perfect fit, but I was afraid to take the plunge. I also noticed that the HaxeFlixel community was much stronger than HaxePunk's, and quite frankly I didn't want to learn a new API. Despite this, I started tinkering with HaxeFlixel, and the humble beginnings of a project, featuring this cool witch, were born. More on this later...
Given Rex's success in finding a decent sponsorship, and having fun working together, Izzy and I decided to make another game. The next game was inspired by a random children's book that I stumbled upon on Amazon. Within a few more weeks, part-time of course, Vegan Vampire was up for sponsorship on FGL. We nabbed a moderate sponsorship, slightly smaller than Rex's, and sold a couple of site-locks as well. This game released the first week of September, and coincidently, Rex released later in the same month. Needless to say, September was a pretty exciting month!
Up to this point, the year was about three-quarters finished. I had released a tutorial series, a couple of games, tinkered with some new technology, and had few abandoned prototypes that aren't worth detailing here. I was still feeling pretty unproductive with myself. :(
Upon releasing Comic Book Cody in 2013 I told myself I wanted to move on from the Flash games market. There is nothing wrong with making web-based browser games in Flash, but after the development of Cody I had grown fatigued of making small games, while seeking sponsorships from web portals. However, FlashPunk is so awesome, I went ahead and made Rampage Rex and Vegan Vampire regardless of what I told myself in 2013! With those two games out of my system, I started to focus more on that witch game posted above.
This witch game's art was ugly, I had no artist on board with the project, and the game's design was still pretty rough. I didn't let this stop me though. I pitched the overall idea to Izzy, and he was pretty into it. I let him know that we were going to target the PC/Mac/Linux platforms at first, with the intention to distribute on Steam. After much debate, we settled on naming the game "A Wicked Curse", and plan to work on it for most of 2015. You can follow along with the game's development on its Tumblr, or TIGSource Devlog. If you have a minute, please like us on Facebook too!
That about sums up my 2014. It was a pretty weird year. I feel I stagnated at times, but after looking back on the entire year, progress was made. This isn't something I should be ashamed of. Here's to 2015 being even better, for both you and me!
Paralysis by Analysis - A Glimpse at a few 2D Frameworks
I was recently browsing Reddit, and came across this post. The post really resonated with me, as I feel I have recently been going through similar struggles. Hence, it inspired this blog entry.
When I finished "Comic Book Cody" last summer I told myself I was going to steer away from Flash and focus on developing a larger game, targeting the PC/Mac/Linux platforms. I enjoy making quick Flash games, but I really want to challenge myself with a bigger project, while learning a new technology. I also hit a point where I didn't enjoy working in Flash anymore, and I felt that the time was right to move on.
I researched numerous options available to me, multiple times. Unity seems great, but I don't really prefer its workflow. I even gave the Unity-based, code-centric framework, Futile, a shot. While awesome in its own ways, I still didn't feel it was what I was looking for. I've used FlashPunk for over three years now, so I definitely want a framework that is more code-centric than an engine's approach, such as Unity. I compiled a small list of interesting, 2D-based frameworks, and provided a brief description of each:
Otter
Otter is a 2D game development framework using SFML and its .NET bindings. This means you develop in my preferred language, C#, and get to target PC/Mac/Linux, and possibly iOS and Android in the future. It's also inspired by FlashPunk, as its creator, Kyle Pulver, used FlashPunk for years. Well, case closed; I guess Otter is my framework of choice. Well, yes, and no. Otter is great, but it is still very new. Due to this, the community is miniscule. Besides the basic Pong example on the site, the only other tutorial currently available online, as far as I know, is the tutorial series that I wrote. I'm not pointing any fingers, by any means. Kyle is just one person, and he has his own games to develop. What he's managed to accomplish up to this point as one person is extremely impressive. However, the lack of a community is probably its biggest con, and is the reason why I am going to list a few other options to consider.
Haxe, OpenFL, HaxeFlixel, HaxePunk
Haxe, and its various frameworks all deserved to be mentioned in the same section. First, according to the Haxe website, Haxe is a programming language that can be compiled to all popular programming platforms with its fast compiler – JavaScript, Flash, NekoVM, PHP, C++, C# and Java – which means your apps will support all popular mobile devices, such as iOS, Android, BlackBerry and more.
Basically, Haxe is an open-source language, similar, but better in many ways than AS3, that can be compiled to numerous platforms. This all sounds very nice.
Add OpenFL into the mix, which is an open-source implementation of the Flash API, written in Haxe. Basically, if Flash was your go to technology of choice prior to using Haxe, you should feel right at home using OpenFL. OpenFL also has a pretty active community, and founder Joshua Granick is very active on Twitter, often offering his time to help others through their issues. But wait, there's more!
Many Flash game developers utilize one of the two popular frameworks, Flixel or FlashPunk. Considering Haxe's similarity to AS3, it's not a big surprise that there exist a Haxe port of both frameworks, HaxeFlixel and HaxePunk. Feel free to learn more about these frameworks via their respective websites. I can't say that I have worked very closely with either of them yet, as I have merely compiled a few simple test projects and prototypes in both. However, in the limited time that I have spent with each, I have noticed that the HaxeFlixel community seems to be more active, and also larger in size. Similar to my discussion regarding Otter, if community activity is important to you, I'd sway towards HaxeFlixel, even despite my years of experience with FlashPunk. HaxeFlixel also has a robust website, offering numerous examples and demos to help you get started.
Phaser
I don't talk about HTML5 often, but I have had mentions about Phaser pop into my timeline on Twitter for a few months now. It is developed by Richard Davey, the developer of Flixel Power Tools. Phaser is iterated on rapidly, and was recently upgraded from version 1.x to version 2.0 in just a matter of months. Talk about productivity! Phaser also has a pretty established community over on its forums. In fact, the community is so active, that it took me a few minutes just to find the 2.0 release announcement thread. If you're looking to get your HTML5 apps onto PC/Mac/Linux as a native application then you're going to have to utilize a tool such as node-webkit. Mobile porting has a few options available, with one of the more popular being CocoonJS. I can't speak much about Phaser's performance, as I haven't worked with it at all. It is just another framework worth looking into, with a very active and supportive community. Feel free to check out its many examples here.
That concludes my quick glimpse into a few 2D frameworks that have caught my eye. Perhaps one will fit your needs, and you will feel right at home working with it! Ironically, all of this tinkering with technology not named FlashPunk gave me the itch to jam out a new game, developed in FlashPunk. Thus, "Rampage Rex" was born :)

Anya is live and ready to show you everything. Watch her strip, dance, and perform exclusive shows just for you. Interact in real-time and make your fantasies come true.
Free to watch • No registration required • HD streaming
Tyrannosaurus Wrecks
I haven't released anything new dating back to last summer, unless you count my Otter Tutorial series. I've been slowly developing a larger project, that isn't ready for public feedback just yet. I hopped on the FGL forums, and reached out to a new artist for a collaboration. After a few messages exchanged back and forth, I'm happy to announce I'm working on a new FlashPunk project, temporarily named "Tyrannosaurus Wrecks".
I have an official DevLog over on TIGSource, here. I'd love to hear your feedback, as we rapidly develop this game. This is going to be a small project, so we intend to work quickly, and release before the start of Spring.
Also, be sure to check out my artist's website. He's pretty talented!
Note: Since writing this entry the game's title has been changed to "Rampage Rex".
Otter 2D Top-Down Adventure Tutorial (Part 10) - Polish and Final Thoughts
Well, they say all good things must come to an end and it appears that we've reached the final entry in this tutorial series :( Last time we added a Boss, and a dynamic EndScene, which pretty much gave our game a beginning, middle, and end. We could call it quits now, but our game is lacking some much needed polish. This entry isn't going to scrutinize every little detail, but instead just add minimal polish to the TitleScene-->GameScene transition. We'll conclude with some helpful links, and general discussion about game development.
First, let's polish up that title screen! Open your TitleScene.cs class, and add the following line towards the top of the class, above the constructor:
// We will tween this image in when the Scene switches public Image darkScreen = Image.CreateRectangle(Global.GAME_WIDTH, Global.GAME_HEIGHT, new Otter.Color("000000"));
Next, modify the constructor, so that our image from above is not visible, but has been added to the Scene:
darkScreen.Alpha = 0; this.AddGraphic(darkScreen);
Now, modify the Update method, changing the if-statement that checks if the start button has been pressed so that it tweens our new image in, as opposed to jumping right to the GameScene:
// Before we jumped right to the GameScene. Now we fade the TitleScene out if (Global.PlayerSession.Controller.Start.Pressed) { // If using Otter v0.9.7 or newer simply omit 'Glide.GlideManagerImpl' Glide.GlideManagerImpl.Tweener.Tween(darkScreen, new { Alpha = 1 }, 30f, 0).OnComplete(PlayGame); }
Lastly, move the logic that was once in the above if-statement to the new, required 'PlayGame' callback method that gets called upon completion of the above tween:
private void PlayGame() { titleSong.Stop();
Global.TUTORIAL.RemoveScene(); Global.TUTORIAL.AddScene(new GameScene()); }
Launch your game, and hit enter to advance past the TitleScene and you should see something similar to this:
As I stated in Part 9, we don't have much of a game on our hands. I made this 'game' just big enough to teach a few basics, and hopefully you have the knowledge to now build small games in Otter. Iterate on our little game here if you want. You can use the code however you desire! Make a top-down shooter with randomly spawning enemies, with a high score counter. Make a top-down stealth game where you can only move forward when an enemy's back is towards you. Or, just make a Flappy Bird clone, because that's what everybody else is doing!
While, this is a tutorial series on the Otter framework, there are many other awesome frameworks out there. If C# isn't your thing, or if you just like to tinker with new technology, then I suggest checking out any of the following, in no particular order:
FlashPunk
Futile
HaxeFlixel / HaxePunk
LibGDX
Those are just a few of the Frameworks that I have given a try. Of course, I'm most familiar with FlashPunk, so if you go that route please feel free to contact me for help via Twitter!
So, you got your framework picked out, but you're going to need solid tools as well in order to be productive. I could write a long, elaborate list, recommending many different tools, but others have already done this for me :D Check out the nice list of game dev tools over on the HaxeFlixel website.
There are thousands, upon thousands of game development related articles on the web. Just keeping up with all of them, never mind reading each one could take hours per week. Luckily, I have a handful of solid articles bookmarked, and want to share them here. In random order, here are a few of my favorites:
Finishing a Game
Learning through Failure
Don't quit your day job
A mini-rant by Rami Ismail of Vlambeer
I could easily post a dozen more that I've collected over the years, but stop reading articles and go make some games already! Besides, the Pixel Prospector already has the ultimate list of indie resources up.
Lastly, if you're looking for any game-dev communities to join, there are many, with these being the two that I frequent often:
TIGSource Forums (the devlogs are pretty inspirational)
Reddit /r/gamedev
That about brings us to the end of this tutorial series. It's been fun, and to the two (one can only hope there's at least two) of you who made it to the end, I thank you for sticking it out with me. I hope you learned a thing or two and now have the knowledge to make some small, fun games in Otter! Just make sure you tweet me about your games so I can play them!
Well, since this is the end, I just can't resist...
Get the code on GitHub!
Download the entire project instead, here!
Otter 2D Top-Down Adventure Tutorial (Part 9) - Adding a Boss and an EndScene
We're nearing the end of the tutorials! Last time, we implemented the camera, making it follow our Player around in a fashion similar to the traditional 2D Zelda games. It's time to add a vile boss, and an EndScene which will either congratulate the player for winning, or bring the bad news of game over.
There are a lot of new assets to introduce for this tutorial. First, download all of the following graphics, saving each to your 'Assets/Graphics' folder, and add a reference to each once afterwards:
Note, the graphics' file names are as follows: boss.png, bossBullet.png, bossParticle.png, otterEnd.png, and otterGameOver.png.
Fresh graphics aren't the only new assets for this entry. Download the sound for the when the boss shoots here, saving it to the 'Assets/Sound' folder, and the ending music here, saving it to the 'Assets/Music' folder. Add a reference to each in your project.
Let's get the easy stuff out of the way first. Open your 'Assets.cs' class and add the following:
public const string BOSS_SPRITE = "../../Assets/Graphics/boss.png"; public const string BOSS_BULLET = "../../Assets/Graphics/bossBullet.png"; public const string BOSS_PARTICLE = "../../Assets/Graphics/bossParticle.png"; public const string END_IMG = "../../Assets/Graphics/otterEnd.png"; public const string END_GAME_OVER = "../../Assets/Graphics/otterGameover.png"; public const string SND_BOSS_SHOOT = "../../Assets/Sound/bossShoot.ogg"; public const string MUSIC_END = "../../Assets/Music/end.ogg";
Next, open your 'Global.cs' class and add one line, while modifying the line that instantiates your CameraShaker:
public static CameraShaker camShaker; public static Boss boss;
A new boss object! Did we even implement it yet? Nope, but I had to get you excited somehow, or at least try. Add a new C# class to the 'Entities' folder, named 'Boss.cs'. Our Boss isn't going to be too flashy, and doesn't really introduce any new concepts. It will stand in place, firing bullets in all four cardinal directions, once every 100 frames. The Boss class looks as follows:
using Otter;
using OtterTutorial;
using System;
namespace OtterTutorial.Entities { public class Boss : Entity { // Shoot once every 100 frames public const int SHOOT_DURATION = 100; // Default health points the boss starts with public const int DEFAULT_HEALTH = 15;
public int health = 1; public int shootTimer = 0; public Spritemap<string> sprite; public Sound hurt = new Sound(Assets.SND_ENEMY_HURT);
public Boss(float x, float y) : base(x, y) { health = DEFAULT_HEALTH;
// Set up the Spritemap in the same manner we did for the player sprite = new Spritemap<string>(Assets.BOSS_SPRITE, 32, 40); sprite.Add("standLeft", new int[] { 0, 1 }, new int[] { 10f, 10f }); sprite.Add("standRight", new int[] { 0, 1 }, new float[] { 10f, 10f }); sprite.Add("standDown", new int[] { 3, 4 }, new float[] { 10f, 10f }); sprite.Add("standUp", new int[] { 6, 7 }, new float[] { 10f, 10f }); sprite.Add("walkLeft", new int[] { 0, 1 }, new float[] { 10f, 10f }); sprite.Add("walkRight", new int[] { 0, 1 }, new float[] { 10f, 10f }); sprite.Add("walkDown", new int[] { 3, 4 }, new float[] { 10f, 10f }); sprite.Add("walkUp", new int[] { 6, 7 }, new float[] { 10f, 10f }); sprite.Play("standLeft"); sprite.Scale = 2; // Our sprite is rather small, so scale it up in size
Graphic = sprite;
// Since we scaled up 2x we must make the hitbox 2x big as well SetHitbox(64, 80, (int)Global.Type.ENEMY); }
public override void Update() { base.Update();
shootTimer++; if (shootTimer >= SHOOT_DURATION) { shootTimer = 0;
Scene.Add(new BossBullet(X + 16, Y + 20, Global.DIR_UP)); Scene.Add(new BossBullet(X + 16, Y + 20, Global.DIR_DOWN)); Scene.Add(new BossBullet(X + 16, Y + 20, Global.DIR_LEFT)); Scene.Add(new BossBullet(X + 16, Y + 20, Global.DIR_RIGHT)); }
// Check if a Player fired Bullet hits us var collb = Collider.Collide(X, Y, (int)Global.Type.BULLET); if (collb != null) { Bullet b = (Bullet)collb.Entity; b.Destroy();
Global.camShaker.ShakeCamera();
// 9999 value is meaningless, and just for fun DamageText dt = new DamageText(X, Y, "9999"); Global.TUTORIAL.Scene.Add(dt);
hurt.Play();
health--;
// If dead add a new explosion if (health <= 0) { Global.TUTORIAL.Scene.Add(new Explosion(X, Y, true)); RemoveSelf(); } } } } }
The Boss class introduces one new object, a BossBullet. We will need to implement this as well. Add another new class to your 'Entities' folder, named 'BossBullet.cs'. This class is very similar to our 'Bullet.cs' class, only containing a few subtle differences, mainly the graphic that is displayed, particles emitted, and sound played. This class looks as follows:
using Otter; using OtterTutorial; using OtterTutorial.Effects; using System; namespace OtterTutorial.Entities { public class BossBullet : Entity { public float bulletSpeed = 10.0f; public int direction = 0; public float distanceTraveled = 0f; public float maxDistance = 350f; public Image image; public Sound shootSnd = new Sound(Assets.SND_BOSS_SHOOT); public BossBullet(float x, float y, int dir) { X = x; Y = y; direction = dir; image = new Image(Assets.BOSS_BULLET); Graphic = image; Global.TUTORIAL.Scene.Add(new BossTrail(X, Y)); SetHitbox(16, 14, (int)Global.Type.BOSS_BULLET); shootSnd.Play(); } public override void Update() { switch (direction) { case Global.DIR_UP: { Y -= bulletSpeed; break; } case Global.DIR_DOWN: { Y += bulletSpeed; break; } case Global.DIR_LEFT: { X -= bulletSpeed; break; } case Global.DIR_RIGHT: { X += bulletSpeed; break; } } if (distanceTraveled % 60 == 0) { Global.TUTORIAL.Scene.Add(new BossTrail(X, Y)); } distanceTraveled += bulletSpeed; if (distanceTraveled >= maxDistance) { RemoveSelf(); } } } }
Now, I know duplicating code is a big no-no, and under normal circumstances I would have created a more generic Bullet class, and have the BossBullet and Player's Bullet extend this parent class. However, for simplicity's sake, I have created this additional class, as opposed to going back and reworking the structure of classes from past tutorials. Feel free to edit the BossBullet.cs class in anyway you see fit, though! Moving on, let's implement the BossTrail class.
Right-click the 'Effect's folder, adding a new C# class named 'BossTrail.cs'. This class is very similar to the BulletTrail class, and is implemented as so:
using Otter; using OtterTutorial; using OtterTutorial.Effects; using System; namespace OtterTutorial.Effects { public class BossTrail : BulletParticle { public const int DESTROY_FRAME = 3; public BossTrail(float x, float y) : base(x, y) { destroyFrame = DESTROY_FRAME; sprite = new Spritemap<string>(Assets.BOSS_PARTICLE, 32, 40); sprite.Add("Emit", new int[] { 0, 1, 2, 3 }, new float[] { 10f, 10f, 10f, 10f }); sprite.Play("Emit"); Graphic = sprite; } } }
The Explosion class has been modified a bit. It now contains a boolean, determining if the explosion was due to a Boss or not. Such explosions will eventually cause our game's current Scene to change. Add the following variable to the 'Explosion.cs' class, above its constructor:
public bool bossExplode = false;
Modify the Explosion constructor, so that it takes in the following parameters:
public Explosion(float x, float y, bool boss = false, int width = 32, int height = 40, Color expColor = null, int radius = 20)
Next, add a reference to the Scenes namespace at the top of our class:
using OtterTutorial.Scenes;
Additionally, add this line to the Explosion constructor:
bossExplode = boss;
Lastly, within the Update method, directly below the call to RemoveSelf, add the following code:
if (bossExplode) { Global.gameMusic.Stop(); Global.TUTORIAL.Scene.RemoveAll(); Global.TUTORIAL.SwitchScene(new EndScene()); }
This code changes the current Scene to the EndScene, as the Boss is clearly dead. Before we go ahead and implement the new EndScene class, we should make the Player check for any collisions with bullets fired by the Boss. If such a collision occurs, the Player should now die :(, and we should see a game over screen, which will be added in a few steps below. Open the 'Player.cs' class, adding the following code towards the very bottom of the Update method:
var collb = Collider.Collide(X, Y, (int)Global.Type.BOSS_BULLET); if (collb != null) { BossBullet b = (BossBullet) collb.Entity; b.RemoveSelf(); dead = true; Global.TUTORIAL.Scene.Add(new Explosion(X, Y, true)); RemoveSelf(); }
The Player hasn't had its Hitbox set just yet, so let's go ahead and do that in its constructor via the following line:
SetHitbox(WIDTH, HEIGHT, (int)Global.Type.PLAYER);
Before the Player.cs class can compile we must add a boolean variable towards the top of the class, above the constructor, tracking if the player is dead or not:
public bool dead = false;
The Player can now die, the map contains a big Boss that fires bullets, and all that is left to add is a new Scene displaying either a game over message upon the Player's death, or an indication of victory upon defeat of the Boss. To this point, we've referenced our new EndScene class but haven't actually created it. Add a new C# class to the 'Scenes' folder, named 'EndScene.cs'. This class is very similar to our TitleScene.cs class, with a few subtle differences. The class is as follows:
using Otter; using OtterTutorial; using OtterTutorial.Entities; using System; namespace OtterTutorial.Scenes { public class EndScene : Scene { public Image endImage = new Image(Assets.END_IMG); public Text endText = new Text("You win! You rock! \\:D/", Assets.FONT_PANIC, 64); public Text enterText = new Text("Press Enter to go back to title screen!", Assets.FONT_PANIC, 24); public const float TIMER_BLINK = 25f; public float blinkTimer = 0; public Music endMusic = new Music(Assets.MUSIC_END, true); public EndScene() { // If the Player is dead then display Game Over // Otherwise, display that they won if (Global.player.dead) { endImage = new Image(Assets.END_GAME_OVER); endText = new Text("Oh no! You died! :(", Assets.FONT_PANIC, 60); endText.OutlineColor = new Otter.Color("FF0000"); } else { // Our victory image is a bit big, so scale it down endImage.Scale = 0.75f; endText.OutlineColor = new Otter.Color("7FA8D2"); } endImage.CenterOrigin(); endImage.X = Global.TUTORIAL.HalfWidth; endImage.Y = 1000; this.AddGraphic(endImage); Glide.GlideManagerImpl.Tweener.Tween(endImage, new { Y = 245 }, 30f, 0f).Ease(Ease.BackOut); endText.OutlineThickness = 3; endText.CenterOrigin(); endText.X = Global.TUTORIAL.HalfWidth; endText.Y = 55; this.AddGraphic(endText); enterText.OutlineColor = new Otter.Color("7FA8D2"); enterText.OutlineThickness = 2; enterText.CenterOrigin(); enterText.X = Global.TUTORIAL.HalfWidth; enterText.Y = 450; this.AddGraphic(enterText); endMusic.Play(); // Clean up some Global variable Global.player = null; Global.boss = new Boss(900, 600); Global.camShaker = null; Global.gameMusic = null; } public override void Update() { base.Update(); blinkTimer++; if (blinkTimer >= TIMER_BLINK) { enterText.Visible = !enterText.Visible; blinkTimer = 0; } if (Global.PlayerSession.Controller.Start.Pressed) { endMusic.Stop(); // Go back to the TitleScene if the player hits Enter Global.TUTORIAL.RemoveScene(); Global.TUTORIAL.AddScene(new TitleScene()); } } } }
To wrap things up, open the GameScene.cs class and add the following line at the end of the Begin method:
Add(Global.boss);
Now add the following towards the top of the class:
using OtterTutorial.Util;
Finally, add the following lines to the GameScene constructor, and we should be done:
if (Global.boss == null) { Global.boss = new Boss(900, 600); }
if (Global.camShaker == null) { Global.camShaker = new CameraShaker(); }
There's one last step to go in order to get everything to compile. Modify the Type enum in our Global.cs class by adding two new values of 'BOSS_BULLET' and 'PLAYER'.
Hopefully everything went smoothly, and when you play your game you have something similar to this:
Our game might not be much to play, nor is it very fun, but we have a game on our hands with a beginning, middle, and end! Yes, it is very small, but a foundation is in place to expand upon. There's just one entry to go in this series. This entry should cover adding a bit more polish and examine expanding the game on your own time. I'll also discuss more game dev related tools and resources, as well as cool sites and articles to check out. Until next time, pat yourself on the back for making it this far, and then throw yourself a well deserved pizza party :D
Take me to Part 10 of the tutorial!
Download the source code to this tutorial!
Otter 2D Top-Down Adventure Tutorial (Part 8) - Creating a "Zeldalike" Camera
Previously, in the seventh tutorial we learned about tile maps, got one rendering in our game, and implemented basic collision with solid, non-walkable tiles. Unfortunately, we cannot walk around the entire map at this time, which makes the world that we created seem pretty pointless. The goal of this entry is to implement a camera that snaps around, from screen to screen in a similar fashion to the camera seen in many of the traditional 2D Zelda games:
Our implementation is going to treat each new screen that we transition to as a new Scene, replacing our previous Scene's tiles with the next screen'stiles. To get things started, declare a global Scene variable towards the top of our GameScene.cs class:
public Scene nextScene;
This variable is going to hold the next Scene that we are moving to, while we transition out of the prior Scene. I provided a map in the last tutorial that is 3 screens wide, and two screens tall, for a total of six screens. We are going to need to keep track of which screen the player is currently on, and render these screens accordingly. Pretending that our screens are on a typical J,I coordinate system, the coordinates of our map's screens would look something like this:
We want to move the Player around one screen at a time when they reach the edge of the current screen. This is accomplished with some modifications and enhancements to our GameScene.cs class. But first, we need to add a few variables to our Global.cs class. Modify said class, and add the following:
public static bool paused = false; public static Music gameMusic = null;
Time to get that camera moving! Open the GameScene.cs class and add the following variables towards the top of the class, above the constructor:
// Scene object that will hold the next scene that we transition to public Scene nextScene;
// Use a J,I coordinate system for our map's screens to avoid // confusion with our already existing X,Y coordinate systems public int screenJ; public int screenI;
The nextScene variable is going to be used to instantiate the next Scene that the Player is moving to. The screenJ and screenI variables are used to determine if we still have any map left to navigate, or if we have reached an edge.
Our constructor needs a handful of changes, and instead of going over each one line by line, it will just be easier to replace your current constructor with the new one:
// Our new constructor takes in the new J,I coordinates, and a Player object public GameScene(int nextJ = 0, int nextI = 0, Player player = null) : base() { screenJ = nextJ; screenI = nextI;
// If a Player object isn't passed in, start at the default x,y position of 100,100 if (player == null) { Global.player = new Player(100, 100); } else { Global.player = player; }
// Create and load our Tilemap and GridCollider tilemap = new Tilemap(Assets.TILESET, WIDTH, HEIGHT, Global.GRID_WIDTH, Global.GRID_HEIGHT); grid = new GridCollider(WIDTH, HEIGHT, Global.GRID_WIDTH, Global.GRID_HEIGHT); string mapToLoad = Assets.MAP_WORLD; string solidsToLoad = Assets.MAP_SOLID; LoadWorld(mapToLoad, solidsToLoad);
// Since we are constantly switching Scenes we need to do some checking, // ensuring that the music doesn't get restarted. // We should probably add an isPlaying boolean to the Music class. I will do this soon. if (Global.gameMusic == null) { Global.gameMusic = new Music(Assets.MUSIC_GAME); Global.gameMusic.Play(); Global.gameMusic.Volume = 0.40f; } }
Considering that we are working with multiple Scenes at once, I have decided to move all of the calls that add Graphics and Entities to the Scene to the Scene's Begin method. We also check if the gameMusic is null or not, ensuring that we invoke its Play method just once, avoiding any ugly, duplicate music loops. Here's the overridden Begin method that we now need:
// We now add our Entities and Graphics once the Scene has been switched to public override void Begin() { Entity gridEntity = new Entity(0, 0, null, grid); Add(gridEntity); AddGraphic(tilemap);
// Ensure that the player is not null if (Global.player != null) { Add(Global.player);
// Never should be paused once transitioning is complete Global.paused = false; }
Add(Global.camShaker);
// This is rather crude, as we re-add the Enemy every time we switch screens // A good task beyond these tutorials would be ensuring that non-player // Entities retain their state upon switching screens Add(new Enemy(500, 400)); }
Previously, our Update method was pretty barren, if there at all. Now, our Update method needs to continuously check the Player's position, determining if a Scene change is necessary. Alter or add your Update method, so that it reads as follows:
public override void Update() { if (Global.paused) { return; }
// Check the Player's X,Y position, and determine if we need to move a // Scene up, down, left, or right. We also check the current J and I values, // ensuring that we don't move past our actual tileset, into a plain grey screen const float HALF_TILE = Global.GRID_WIDTH / 2; if (Global.player.X - CameraX < HALF_TILE) { if (screenJ > 0) { if (Global.player.X > 50) { screenJ--; this.Scroll(-1, 0); } } }
if (Global.player.Y - CameraY < HALF_TILE) { if (screenI > 0) { if (Global.player.Y > 32) { screenI--; this.Scroll(0, -1); } } }
if (Global.player.X - CameraX - Global.GAME_WIDTH > -HALF_TILE) { if (screenJ < 2) { screenJ++; this.Scroll(1, 0); } }
if (Global.player.Y - CameraY - Global.GAME_HEIGHT > -HALF_TILE) { if (screenI < 1) { screenI++; this.Scroll(0, 1); } } }
As you can see from the new code in the Update method, and the fact that our project no longer compiles, we need to implement a Scroll method. This new method will move the CameraX and CameraY values to their new position:
// Scroll method that moves the CameraX, CameraY // coordinates by the multiple dx, dy values public void Scroll(int dx, int dy) { // Pause the game when we start scrolling Global.paused = true;
// Set the nextScene and call UpdateLists to // ensure all Entities are cleaned up properly nextScene = new GameScene(screenJ, screenI, Global.player); nextScene.UpdateLists();
// Push the player over with the screen via a Tween float pushPlayerX = dx * 30; float pushPlayerY = dy * 30;
// If using Otter v0.9.7 or newer simply omit 'Glide.GlideManagerImpl' Glide.GlideManagerImpl.Tweener.Tween(Global.player, new { X = Global.player.X + pushPlayerX, Y = Global.player.Y + pushPlayerY }, 30f, 0);
// Finally, push the Camera over by a multiple of the // Game's width and height, and set the call back method // to our new ScrollDone method // If using Otter v0.9.7 or newer simply omit 'Glide.GlideManagerImpl' Glide.GlideManagerImpl.Tweener.Tween(this, new { CameraX = CameraX + Global.GAME_WIDTH * dx, CameraY = CameraY + Global.GAME_HEIGHT * dy }, 30f, 0).OnComplete(ScrollDone); }
There is one last step to go before we can launch our game and start zipping around our lush, immersive world that this guy would be proud of:
The tween that moves the CameraX, and CameraY values has a callback method that we haven yet to implement. As you can see, if you want to add a callback method to a tween in Glide.cs, it is accomplished via a call to OnComplete. Here is the ScrollDone method that must be added to our GameScene.cs class:
// Method called once the screen scrolling is all done public void ScrollDone() { // Once the scroll is done remove all added graphics // and call UpdateLists to clean everything up and // then switch to the nextScene RemoveAll(); UpdateLists();
// Set the nextScene's Camera values to the current Scene's // freshly tweened camera values, otherwise we snap back to screen 0,0 nextScene.CameraX = CameraX; nextScene.CameraY = CameraY; Global.TUTORIAL.SwitchScene(nextScene); }
Launch our game, and start walking around. Go ahead, I'll wait for you. Back? Well, hopefully your Player walks around, snapping from screen to screen in typical old-school Zelda fashion. Hopefully, it looks similar to my game in action:
Before concluding, I should point out a couple of enhancements that make for great side tasks to tackle until I release the next tutorial. First, we are not currently keeping track of the Enemy's X,Y coordinates when a Scene switches. We merely reload the Enemy back to its original starting position. It would be pretty cool to modify our game to keep tabs on the Enemy, and reload it back at its last seen position. Second, the camera doesn't move over enough when walking to any screen besides screen 1. This can be seen in the GIF above. If you look closely you will notice that a small portion of screen 1's tiles can be seen in screen 2.
That sums it up for this entry. We still don't have a 'real' game on our hands, but the next entry will get us one step closer. We will be adding an EndScene, and of course a dreaded boss fight!
Take me to part 9 of the tutorial!
Download the source code to this tutorial!
Otter 2D Top-Down Adventure Tutorial (Part 7) - Introduction to Tilemaps
In Part 6 we added an Enemy, and introduced collisions. In this entry we are going to go over Tilemaps, and GridColliders. By the end of the tutorial you should have a basic Tilemap loading, and displaying. Additionally, our Player Entity should collide with certain tiles, and freely walk over any others. The end goal is something like this ugly thing:
Before we get started, if you're unfamiliar with 2D tile maps then I suggest that you read this well written blog post explaining tile maps, as opposed to having me attempt to explain them. If you are already familiar with tile maps, but aren't sure how to construct levels with them, then I suggest you look into using either Ogmo Editor, or DAME Editor. Each site has a page dedicated to tutorials, and both tools are very easy to pick up and learn.
I've made my fair share of platformers, each utilizing Ogmo, but for this tutorial we are going to be working with levels that I created in DAME. I chose DAME for this tutorial because I prefer working with CSV files when dealing with large worlds, and DAME has the ability to export our levels in CSV (comma-separated-values) format. I realize the latest version of Ogmo exports CSV data as well, but I built these levels with Dame, before realizing so. Sure, our world won't be large just yet, but if you go on and make your very own Zelda-sized adventure, it will become very large, very quickly. Onto the actual tutorial!
First, let's download our graphics. Download the awesome tile set that I spent all night on, saving it to the 'Assets/Graphics' folder:
Once you have downloaded the graphic, add a reference to it within your OtterTutorial project by right-clicking the 'Graphics' folder, selecting Add-->Exiting Item, and adding our new tile map graphic.
Now, create a new folder in your 'Assets' folder named 'Levels'. I have gone and created two maps in DAME. The first map is our world map, and the second is the map of our solid tiles that the player cannot walk over. Download the first map here, and the second map here, saving each to your 'Assets/Levels' folder. Don't forget to add a project reference to each. If you want to play around with my DAME Project files, feel free to download my project files here. Our actual map is three screens wide, two screens tall, and looks like this:
It is a rather crude map, with each of its 640x480 screens numbered. The tiles that make up the actual numbers are solid tiles.
With all of our assets in place we can now start writing some code. Add the following lines to your 'Assets.cs' class:
public const string TILESET = "../../Assets/Graphics/tileset.png"; public const string MAP_WORLD = "../../Assets/Levels/tiles.csv"; public const string MAP_SOLID = "../../Assets/Levels/solids.csv";
We also need to add a few variables to our Global.cs class. Open said class, and add the following:
// These variables will be used when creating our Tilemap related objects public const int GAME_WIDTH = 640; public const int GAME_HEIGHT = 480; public const int GRID_WIDTH = 32; public const int GRID_HEIGHT = 32;
Other than these two classes, all that we need to do now is modify our GameScene.cs class. We are going to be opening and reading CSV files, hence we must include the System.IO package towards the top of our class, with our other import statements:
using System.IO;
A few global class variables will be necessary. Add them above our GameScene constructor:
// Our Tilemap's calculated width and height public const int WIDTH = Global.GAME_WIDTH * 3; public const int HEIGHT = Global.GAME_HEIGHT * 2;
public Tilemap tilemap = null; public GridCollider grid = null;
Our constructor needs to instantiate these new Tilemap and GridCollider objects, while also adding them to our Scene. Since Otter renders any new Graphics on top of any Graphics already existing in our Scene, we must add our Tilemap first, and our Player and Enemy Entities afterwards. This ensures that the Player and Enemy always appear above the Tilemap, and not behind it. Add the following code to the beginning of your GameScene constructor:
tilemap = new Tilemap(Assets.TILESET, WIDTH, HEIGHT, Global.GRID_WIDTH, Global.GRID_HEIGHT); grid = new GridCollider(WIDTH, HEIGHT, Global.GRID_WIDTH, Global.GRID_HEIGHT); Entity gridEntity = new Entity(0, 0, null, grid); Add(gridEntity); string mapToLoad = Assets.MAP_WORLD; string solidsToLoad = Assets.MAP_SOLID; LoadWorld(mapToLoad, solidsToLoad); AddGraphic(tilemap);
Unfortunately, the above code will break our project, making it no longer compile. In order to fix our issues, we must first implement the LoadWorld method:
private void LoadWorld(string map, string solids) { // Get our CSV map in string format and load it via our tilemap string newMap = CSVToString(map); tilemap.LoadCSV(newMap); // Get our csv solid map and load it into our GridCollider string newSolids = CSVToString(solids); grid.LoadCSV(newSolids); }
We're close to getting tiles onto the screen, but we're not quite there yet. Let's implement the CSVToString method next. This method takes in a CSV as a string, and turns it into something the LoadCSV methods can digest:
// Add this method to your GameScene.cs class private static string CSVToString(string csvMap) { string ourMap = "";
using (var reader = new StreamReader(csvMap)) { // Read each line, adding a line-break to the end of each string line; while ((line = reader.ReadLine()) != null) { ourMap += line; ourMap += "\n"; } } return ourMap; }
Before the above will compile you also need to add the following line towards the very top of the GameScene class:
using System.IO;
Prior to the updates I made to these tutorials this particular portion of the tutorial actually went into the Otter code base and made some additions. This is no longer necessary, as Kyle has added my LoadCSV method to both the Tilemap and GridCollider classes. This saves us some work!
Before we change the Player's Update method to account for collision with our solid tiles, feel free to launch our game. If everything went accordingly, the tiles should now appear, and our GameScene should look similar to this screen shot:
As you can see in the picture above, our Player can walk all over any tiles, including the yellow tiles that are designated as solid tiles in our solids map. Our GridCollider is already instantiated and added to our GameScene, but we are not actually invoking it to check for collisions. We need to do this in our Player's Update method. Open the Player.cs class, scroll down to the Update method, and add the following variables, directly below the line 'bool verticalMovement = true;':
float xSpeed = 0; float ySpeed = 0; float newX; float newY; GameScene checkScene = (GameScene)Scene;
Also, add the following towards the top of the Player class:
using OtterTutorial.Scenes;
The Update method contains two if statements that check for horizontal and vertical movement. We need to adjust these statements, making them check for any possible collisions with solid tiles and negate any possible movement upon collision. Replace these two if statements, with our new, and improved if statements:
// Check horizontal movement if (Global.PlayerSession.Controller.Left.Down) { newX = X - moveSpeed;
// Check if we are colliding with a solid rectangle or not. // Ensure the GridCollider snaps our values to a grid, by passing // in a false boolean for the usingGrid parameter if (!checkScene.grid.GetRect(newX, Y, newX + WIDTH, Y + HEIGHT, false)) { xSpeed = -moveSpeed; } direction = Global.DIR_LEFT; sprite.FlippedX = true; } else if (Global.PlayerSession.Controller.Right.Down) { newX = X + moveSpeed; if (!checkScene.grid.GetRect(newX, Y, newX + WIDTH, Y + HEIGHT, false)) { xSpeed = moveSpeed; } direction = Global.DIR_RIGHT; sprite.FlippedX = false; } else { horizontalMovement = false; }
// Check vertical movement if (Global.PlayerSession.Controller.Up.Down) { newY = Y - moveSpeed; if (!checkScene.grid.GetRect(X, newY, X + WIDTH, newY + HEIGHT, false)) { ySpeed = -moveSpeed; } direction = Global.DIR_UP; sprite.FlippedX = false; } else if (Global.PlayerSession.Controller.Down.Down) { newY = Y + moveSpeed; if (!checkScene.grid.GetRect(X, newY, X + WIDTH, newY + HEIGHT, false)) { ySpeed = moveSpeed; } direction = Global.DIR_DOWN; sprite.FlippedX = false; } else { verticalMovement = false; }
Next, we never actually added those global WIDTH and HEIGHT variables. Add those now, above the constructor in the Player class:
public const int WIDTH = 32; public const int HEIGHT = 40;
The last thing left to do is to adjust our Player's X,Y values by our xSpeed and ySpeeds, respectively. At the very bottom of the Update method, write the following:
if (verticalMovement && horizontalMovement) { X += xSpeed / DIAGONAL_SPEED; Y += ySpeed / DIAGONAL_SPEED; } else { X += xSpeed; Y += ySpeed; }
It appears that I lied, and we have one more step to go. Notice above, that our code slows our movement down a bit if we are moving diagonally. Without this slow down we will appear to be moving too fast when both horizontal and vertical movement exist. Add the const float value 'DIAGONAL_SPEED' towards the top of the Player.cs class, above the constructor:
public const float DIAGONAL_SPEED = 1.4f;
Play our game, and try to walk into the bright, yellow '1' in the middle of the screen. Hopefully, the Player can no longer walk across, nor on these yellow tiles. If so, good job! By now, I'm sure you have something that looks like this:
If it bothers you, I went ahead and moved the Enemy down to Y-position 400, so it avoids the yellow tiles as well.
We've added a very important part to our game in this entry. We introduced Tilemaps, the key to building lush, robust worlds in a Zelda-like game, and can handle basic collision with unwalkable tiles. In one of the photos above, I displayed the entire map that was made for this tutorial. However, if you move around in our game the entire map is not accessible. In the next entry, we will get the camera moving in a manner typically seen in the older, 2D, Zelda games. Until then...
Take me to Part 8 of the tutorial.
Download the source code to this tutorial.
Please note, I wanted to cover loading Ogmo levels in this tutorial as well, but felt it became too large. I am not neglecting Ogmo, and will be saving this topic for a later entry.

Anya is live and ready to show you everything. Watch her strip, dance, and perform exclusive shows just for you. Interact in real-time and make your fantasies come true.
Free to watch • No registration required • HD streaming
Otter 2D Top-Down Adventure Tutorial (Part 6) - Enemies and Collisions
In part 5 we added sound effects, particles, and screen shake. Things are starting to look good, and now we will add some enemies and handle their collision with any bullets fired by the player.
First, let's get an enemy onto the screen. I've gone and altered our player sprite sheet a bit, making it red while changing the face a bit. Download the image below to your 'Assets/Graphics' folder and add it to your project by right-clicking this folder, Add-->Existing Item and selecting the new enemy image.
Next, let's create the Enemy class and get our new graphic rendering. Right-click your OtterTutorial project, and select Add-->New Item, and add a new C# class named 'Enemy.cs'. Before we start implementing our Enemy class we're going to add a few global variables to the Global.cs class that will be needed for this tutorial. Open your Global.cs class, and add the following lines:
public enum Type
{ BULLET, ENEMY }
With our new global enum in place, let's open the Enemy.cs class and replace it with the following class:
using Otter;
using OtterTutorial;
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;
namespace OtterTutorial.Entities { public class Enemy : Entity { // Default speed an enemy will move in public const float DEFAULT_SPEED = 3.4f; // Default health points our enemy starts with public const int DEFAULT_HEALTH = 4; public int health = 1; public float speed = 1f; public Spritemap<string> sprite; public Enemy(float x, float y): base(x,y) { health = DEFAULT_HEALTH; speed = DEFAULT_SPEED; // Set up the Spritemap in the same manner we did for the player sprite = new Spritemap<string>(Assets.ENEMY_SPRITE, 32, 40); sprite.Add("standLeft", new int[] { 0, 1 }, new float[] { 10f, 10f }); sprite.Add("standRight", new int[] { 0, 1 }, new float[] { 10f, 10f }); sprite.Add("standDown", new int[] { 3, 4 }, new float[] { 10f, 10f }); sprite.Add("standUp", new int[] { 6, 7 }, new float[] { 10f, 10f }); sprite.Add("walkLeft", new int[] { 0, 1 }, new float[] { 10f, 10f }); sprite.Add("walkRight", new int[] { 0, 1 }, new float[] { 10f, 10f }); sprite.Add("walkDown", new int[] { 3, 4 }, new float[] { 10f, 10f }); sprite.Add("walkUp", new int[] { 6, 7 }, new float[] { 10f, 10f }); sprite.Play("standLeft"); Graphic = sprite; } public override void Update() { base.Update(); } } }
Before we launch the game just yet, we need to add an Enemy to our GameScene. This is easily accomplished by adding the following line to the constructor in the GameScene.cs class:
Add(new Enemy(500, 350)); // Add at x,y coords 500, 350
Lastly, your probably noticed nothing compiles just yet. Add the following line to Assets.cs:
public const string ENEMY_SPRITE = "../../Assets/Graphics/enemy.png";
Launch our game, advance past the TitleScene, and hopefully you have something that looks like this:
With our enemy now rendering on the screen, let's now make any bullets that the player fires collide with the enemy, and disappear. Otter gives a few options for handling collision between Entities. We are going to use the most basic option provided, and what I consider the most common. The method of collision handling that we will be using utilizes rectangles for all collisions between Entity objects. We will define a rectangular collision area for an Entity, otherwise known as its hitbox, and then use the various methods that Otter provides to test if one Entity's hitbox intersects with another. For example, in our current instance, we will be checking if a Bullet's hitbox intersects with an Enemy's hitbox, and will then handle the situation accordingly.
In one of the first steps above we defined a global enum, named 'Type' that is going to be used to keep track of our various Entity types and aid with collision. If you need to brush up on enums in C#, please read this. Each time we define a hitbox we need to supply an integer that represents the Entity's type, with our call to SetHitbox. This type can be looked up when colliding with another Entity, and we can then determine if we need to take action due to the collision or not. Let's now set the Hitboxes for our Enemy.cs class and Bullet.cs class by adding the following lines to each constructor, respectively:
// Set our Enemy hitbox to be 32 x 40. This goes in our Enemy class SetHitbox(32, 40, (int)Global.Type.ENEMY);
// Add this line to the Bullet.cs constructor SetHitbox(16, 14, (int) Global.Type.BULLET);
After defining our hitboxes, we can now check for and handle any collision between Enemies and Bullets. Let's do so by modifying the Update method in the Enemy.cs class to look like such:
public override void Update() { base.Update(); // Access the Enemy's Collider to check collision var collb = Collider.Collide(X, Y, (int)Global.Type.BULLET);
if (collb != null) { Bullet b = (Bullet) collb.Entity; b.Destroy(); } }
As you can see, Entities have access to a Collider object that we utilize to check for any collisions. We invoke the Collider's Collide method, checking if we have collided at the passed in X, Y coordinates with any Entities that are of the Bullet type. If we determine that we have collided with any Bullets, we then call the offending Bullets' Destroy method. In our custom destroy method we can do many things, such as add some particles to the screen, cause explosions, or simply remove the Bullet from the screen. We haven't actually implemented the Destroy method in our Bullet.cs class, so let's do that now:
// Add this to your Bullet class, below your Update method public void Destroy() { RemoveSelf(); }
Now, if we play our game, any Bullets that are fired into the Enemy should collide with the Enemy and vanish. Way to go! Let's not stop here though. We're now going to make the Enemy walk back and forth in a straight line, take damage, and explode upon running out of health.
First, add the following global class variables to the Enemy.cs class:
public const float MOVE_DISTANCE = 300; // left = true, right = false public bool direction = true;
// Used to keep track of the enemy distance moved public float distMoved = 0f;
These new variables will be used to make our Enemy move back-and-forth, in a straight line, left-to-right. We now need to modify the Enemy's Update method, making the player move across the screen. Add the following code to this method:
// If going left, flip the spritesheet sprite.FlippedX = direction; // if moving left then go left, otherwise go right if (direction) { X -= speed; } else { X += speed; }
// Update distance moved, and check if we should flip directions distMoved += speed; if (distMoved >= MOVE_DISTANCE) { direction = !direction; distMoved = 0f; }
If we play our game now the Enemy should walk back and forth in a straight line. Before we make our Enemies explode into a blaze of glory, let's add some red damage text that floats upwards each time an Enemy takes damage. This is a cool feature typically seen in RPG games, ranging from the older Final Fantasy games to the modern day game, "Borderlands 2". Create a new C# class named 'DamageText.cs' in your 'Effects' folder. We are going to implement this class as so:
using Otter; using OtterTutorial; using System; namespace OtterTutorial.Entities { public class DamageText : Entity { // Random jitter so that each DamageText object // doesn't appear in the exact same spot private const int MIN_X_JITTER = 0; private const int MAX_X_JITTER = 30; // Our Text object that displays on screen private Text text; public DamageText(float x, float y, string dmgText, int fontSize = 16) { text = new Text(dmgText, fontSize); text.Color = Color.Red; // Move the X value a bit for each new DamageText so they // all don't appear in the same spot if the Enemy is idle X = x + Otter.Rand.Int(MIN_X_JITTER, MAX_X_JITTER); Y = y - 20; Graphic = text; } public override void Update() { base.Update(); // Slowly subtract from our alpha value text.Alpha -= 0.02f; Y -= 1.25f; // Drift upwards // Remove once invisible if (text.Alpha <= 0) { RemoveSelf(); } } } }
The class above is rather simple. Our graphic is a simple Text object, which we set via a passed in string value. Once on screen, our DamageText objects drift upwards, and slowly disappear.
Let's add some DamageText Entities to the code in which we determined if a Bullet collided with an Enemy or not. Add the following in the 'if (collb != null)' if-statement, underneath our b.Destroy() call:
// Shake the camera when a Bullet hits an Enemy // and then add a new DamageText object with the // abritary string "1234". Lastly add it to our Scene Global.camShaker.ShakeCamera(); DamageText dt = new DamageText(X, Y, "1234"); Global.TUTORIAL.Scene.Add(dt);
Run the game, shoot the Enemy a few times, and hopefully you have some red text popping up on screen whenever a Bullet makes contact with the Enemy. Here is a pic of my game in action for comparison:
It isn't very satisfying to shoot this enemy infinitely, especially without ever seeing it succumb to our barrage of bullets. One would expect a big explosion, and even more screen shake, no? Well hopefully you do, because we're adding that next!
Right-click your 'Effects' folder, and add a new C# class named 'Explosion.cs'. An Explosion is going to extend the Entity object, contain a simple image, and gradually fade off screen. My Explosion.cs class looks like this:
using Otter; using OtterTutorial; using System; namespace OtterTutorial.Entities { public class Explosion : Entity { public Image img; // Default color is white public Color color = new Color("FFFFFF"); public Sound explode = new Sound(Assets.SND_BULLET_EXPLODE); public Explosion(float x, float y, int width = 32, int height = 40, Color expColor = null, int radius = 20) { X = x + width / 2; Y = y; // You can pass in a custom color, if desired if (expColor != null) { color = expColor; } // Center ourselves and set the graphic img = Image.CreateCircle(radius, color); img.CenterOrigin(); Graphic = img; Global.camShaker.ShakeCamera(40f); explode.Play(); } public override void Update() { base.Update(); // Gradually grow, in the fashion of an explosion // If you want to get fancy, perhaps you could make this // a decaying growth, or even Tween it so it grows faster // at the beginning img.ScaleX += 0.10f; img.ScaleY += 0.10f; img.CenterOrigin(); // Gradually phase to invisible img.Alpha -= 0.04f; if (img.Alpha <= 0) { RemoveSelf(); } } } }
The Enemy object needs to decrement its health every time a Bullet hits it, check if its health is at or below zero, and if so, add a new Explosion in its place while removing itself from the current Scene. Add the following code to your Enemy.cs class, right below the code where we add our DamageText objects, in the Update method:
health--; // Decrement the health by 1 for each Bullet that hits if (health <= 0) { // Add a new Explosion and remove self from the Scene if out of health Global.TUTORIAL.Scene.Add(new Explosion(X, Y)); RemoveSelf(); }
We have one last addition to make for this entry. It's pretty lame that we don't play a sound when a Bullet hits an Enemy. We should change that. First, download our new sound file from here. Save this file to your 'Assets/Sound' folder. Once saved, add a reference to it inside your project by right-clicking the OtterTutorial project and selecting Add-->Existing Item. After doing so, update the Assets.cs class with a reference to our new sound:
public const string SND_ENEMY_HURT = "../../Assets/Sound/enemyHurt.ogg";
All that is left to do is to play our new sound when a Bullet hits an Enemy. Instantiate a new Sound object above the constructor in the Enemy.cs class:
public Sound hurt = new Sound(Assets.SND_ENEMY_HURT);
Play the sound by adding the following directly above the line 'health--;' in the Enemy's Update method:
hurt.Play();
Finally, the in-game music is playing at too high of a volume and draining out our sound effects. Add the following line to our GameScene.cs class, right below the line 'gameMusic.Play();':
// Lower the volume to 40% of its original volume gameMusic.Volume = 0.40f;
Play the game, shoot the enemy, listen to our new sounds, watch the damage text float upwards, and celebrate when the enemy explodes into screen-shaking bliss. Way to save the day! That Enemy looked up to no good, and probably would have gotten away with it, too, if it wasn't for us meddling game developers!
Take me to Part 7 of the tutorial!
Download the source code to this tutorial here.
Otter 2D Top-Down Adventure Tutorial (Part 5) - Sound Effects, Particles and Screen Shake
With our player moving and shooting thanks to the last tutorial, it is time to add some sound effects, particles, and of course, screen shake! If you've followed the entire series of tutorials so far, you should have a GameScene that looks like this:
We should already have the particle and explosion graphics from the last tutorial. However, you still need to download the sound effects, one for the bullet shooting, and the other for when the bullet explodes. Download each sound effect, saving them to your 'Assets/Sound' folder. Once the sound files have been saved, right-click the 'Sound' folder, select 'Add-->Existing Item', and add each sound to your project.
If you are looking to create your own, similar sound effects then look no further than the free app, Bfxr. This tool is capable of producing a wide variety of 8-bit inspired sound effects, and is great for when you need quick, and simple sound effects in a hurry.
If you hadn't already guessed, we are first going to get some sound effects playing. Add the following lines to your Assets.cs class:
public const string SND_BULLET_SHOOT = "../../Assets/Sound/bulletShoot.ogg"; public const string SND_BULLET_EXPLODE = "../../Assets/Sound/bulletExplode.ogg";
Next, let's create a sound object in our Bullet.cs class, above our constructor:
public Sound shootSnd = new Sound(Assets.SND_BULLET_SHOOT);
Now, we want to play the shoot sound effect every time a new bullet is added to the Scene. Add the following line to the constructor in the Bullet.cs class.
// This line goes in our constructor shootSnd.Play();
If you play the game now, you should hear a sound every time a bullet fires. Good job!
Currently, bullets are fired and just disappear, which isn't much fun. It'd be a lot cooler if they left a bright trail and exploded instead! It is time to add a new folder to our project that will be the home for our classes related to effects, such as particles, explosions, etc. Right-click your OtterTutorial project, select Add-->New Folder, and name the folder 'Effects'. The first class that we will add to this folder is our 'BulletParticle.cs' class. This class is going to be the parent class to our 'BulletTrail.cs' and 'BulletExplosion.cs' particle classes. Go ahead and create these two classes as well, also in the 'Effects' folder.
Let's first implement the 'BulletParticle.cs' class.
using Otter; using OtterTutorial; using System; namespace OtterTutorial.Effects { // BulletParticle extends the Entity class public class BulletParticle : Entity { // Our bullet particle graphics contain multiple frames. Spritemap makes sense here. public Spritemap<string> sprite; // Once the animation hits this frame, remove ourself from the Scene public int destroyFrame = 1; public BulletParticle(float x, float y) : base(x, y) { } public override void Update() { base.Update(); // Have our particle drift up a bit as it dissolves Y -= (float)(1.5 / Otter.Rand.Float(1, 3)); // Check if we have finished playing. If so, remove self if (sprite.CurrentFrame == destroyFrame) { RemoveSelf(); } } } }
As you can see above, our BulletParticle class extends the Entity class, contains a single Spritemap, floats upward in its Update method, and is removed upon entering its final frame of animation. Time to code the BulletExplosion.cs class:
using Otter; using OtterTutorial; using OtterTutorial.Effects; using System; namespace OtterTutorial.Effects { // BulletExplosion will extend ParticleEffect public class BulletExplosion : BulletParticle { // Used to keep track of when to remove explosion from the scene public const int DESTROY_FRAME = 3; // Sound that is played when to remove explosion from the scene private Sound bulletExplodeSnd = new Sound(Assets.SND_BULLET_EXPLODE); public BulletExplosion(float x, float y) : base(x, y) { destroyFrame = DESTROY_FRAME; // Set up our explosion animation, and play it. Lastly, set our graphic. sprite = new Spritemap<string>(Assets.BULLET_EXPLOSION, 32, 40); sprite.Add("Emit", new int[] { 0, 1, 2, 3 }, new float[] { 10f, 10f, 10f, 10f}); sprite.Play("Emit"); Graphic = sprite; bulletExplodeSnd.Play(); } } }
Our project won't compile just yet, and even if it did no explosions would appear! Add the following to your Assets.cs class, so that our Spritemap above knows where to find the explosion image. Also, add a reference to the BULLET_PARTICLE, for later:
public const string BULLET_EXPLOSION = "../../Assets/Graphics/explosion.png"; public const string BULLET_PARTICLE = "../../Assets/Graphics/particle.png
Next, we need to actually add some explosions to our Scene. Presently, our bullets fire and just disappear after traveling their designated max distance. Before a bullet removes itself from the current Scene we should have it add a new BulletExplosion in its place! Within your Bullet.cs's update method, add the following line, above the call to RemoveSelf:
Global.TUTORIAL.Scene.Add(new BulletExplosion(X, Y));
Lastly, we need to add a reference to our new OtterTutorial.Entities namespace in our Bullet.cs class. This is done by merely adding the following line at the top of the class, preferably below the 'using OtterTutorial;' line:
using OtterTutorial.Effects;
Hit start/run, advance to our GameScene, and fire a few bullets. You should see something similar to this:
This looks better, but it is still pretty lacking. I suggest you read, and perhaps check out the video by Jan Willem Nijman, one half of Vlambeer, detailing how to make your action games feel better. We will be adding screen shake to our game next!
I am a big fan of screen shake. So much so, I usually create a handy utility class that handles all of our shaking for us. We are going to do this here. First, right-click your project, and add a new folder named 'Util'. Right-click this new folder, select Add-->New Item and add a new C# class named 'CameraShaker.cs'.
using Otter; using OtterTutorial; using System; namespace OtterTutorial.Util { public class CameraShaker : Entity { // Variables that will store our camera X,Y coordinates before shaking private float priorCameraX = 0f; private float priorCameraY = 0f; // Variable used to keep track of how long we have been shaking for private float shakeTimer = 0f; // Number of frames to shake the camera for. Gets set in constructor private float shakeFrames = 0f; // Bool used to determine if the camera needs shaking or not private bool shakeCamera = false; // Default constructor public CameraShaker() { } public void ShakeCamera(float shakeDur = 20f) { // If camera isn't already shaking if (!shakeCamera) { // Save our original X,Y values priorCameraX = this.Scene.CameraX; priorCameraY = this.Scene.CameraY; // Set shakeCamera to true, and our shake duration shakeCamera = true; shakeFrames = shakeDur; } } public override void Update() { if (shakeCamera) { // Move the Camera X,Y values a random, but controlled amount this.Scene.CameraX = priorCameraX + (10 - 6 * 2 * Rand.Float(0, 1)); this.Scene.CameraY = priorCameraY + (10 - 6 * 2 * Rand.Float(0, 1)); // Increase the shake timer by one frame // and check if we have been shaking long enough shakeTimer++; if (shakeTimer >= shakeFrames) { shakeCamera = false; shakeTimer = 0; shakeFrames = 0; this.Scene.CameraX = priorCameraX; this.Scene.CameraY = priorCameraY; } } } } }
With our freshly implemented CameraShaker.cs class in place, we should next instantiate one in our Global.cs class (while not forgetting to add 'using OtterTutorial.Util;' towards the top of the class):
public static CameraShaker camShaker = new CameraShaker();
We now need to add the CameraShaker to our GameScene (or any scene that wants to use it) otherwise it cannot be invoked. Put the following line in your GameScene.cs constructor:
Add(Global.camShaker);
Last, we need to actually invoke our CameraShaker's ShakeCamera method when a bullet explodes. Add the following to the constructor of your 'BulletExplosion.cs' class:
// Shake the camera each time we explode Global.camShaker.ShakeCamera();
Hit start/run again, advance to the GameScene and fire a few more bullets. Upon explosion you should see our new CameraShaker class in action!
Even with screen shake, our game hasn't started to 'pop' yet, even with my amazing, top-notch art work ;). We should add some trailing particles to the bullet as it flies across the screen, as well as some trailing partcles behind the player as it moves around the screen. First, we will add the bullet trail. We've already added the 'BulletTrail.cs' class, which is intended to be a child of the 'BulletParticle.cs'. Time to code it:
using Otter;
using OtterTutorial; using OtterTutorial.Effects;
using System;
namespace OtterTutorial.Effects { public class BulletTrail : BulletParticle { public const int DESTROY_FRAME = 3;
public BulletTrail(float x, float y) : base(x, y) { destroyFrame = DESTROY_FRAME;
sprite = new Spritemap<string>(Assets.BULLET_PARTICLE, 32, 40); sprite.Add("Emit", new int[] { 0, 1, 2, 3 }, new float[] { 10f, 10f, 10f, 10f }); sprite.Play("Emit"); Graphic = sprite; } } }
If you compare the BulletTrail and BulletExplosion classes you will notice that they are pretty similar; almost to the point where two different classes might not be necessary. I took this route in case you want to extend the functionality of these two objects. You could make explosions eventually do damage, the green particles poison enemies; the possibilities are truly limitless. These classes also show a decent example of inheritance, and how it works, as well as a few benefits that it provides.
We are going to make our Bullet class add BulletTrail objects as it flies across the screen. Add the following to the Bullet constructor:
// Add a BulletTrail particle as soon as the Bullet enters the Scene Global.TUTORIAL.Scene.Add(new BulletTrail(X, Y));
Lastly, add the following to the Update method in the Bullet class:
// Add a new BulletTrail particle every 60 pixels traveled if (distanceTraveled % 60 == 0) { Global.TUTORIAL.Scene.Add(new BulletTrail(X, Y)); }
The last portion to add is a trailing particle when the player is walking. This particle effect will be a simple entity that trails the player, floats up a bit, and then disappears. Right-click the Effects folder, and add a new C# class named 'WalkParticle.cs'. This class looks as follows:
using Otter; using OtterTutorial; using OtterTutorial.Effects; using System; namespace OtterTutorial.Effects { public class WalkParticle : Entity { // Number of frames to remain on screen for public const int PARTICLE_FRAMES = 5; // Our graphic will be a simple image public Image image; public int direction = 0; public int particleTimer = 0; public WalkParticle(float x, float y) : base(x, y) { // Our graphic will be a purple circle, with a 4 pixel radius Color col = new Color("9612C2"); image = Image.CreateCircle(4, col); Graphic = image; } public override void Update() { // Float upward Y -= (float)(1.5 / Otter.Rand.Float(1, 3)); // Gradually become transparent before disappearing image.Alpha -= 0.10f; particleTimer++; if (particleTimer >= PARTICLE_FRAMES) { RemoveSelf(); } } } }
All that's left is to add some of these new particles while the player walks. Modify the Update method in your Player.cs class by adding the following towards the bottom of the class:
// Add particles if the player is moving in any direction if (verticalMovement || horizontalMovement) { // Add walking particles float particleXBuffer = 0; float particleYBuffer = 0; switch (direction) { case Global.DIR_UP: { particleXBuffer = Otter.Rand.Float(8, 24); particleYBuffer = Otter.Rand.Float(0, 5); Global.TUTORIAL.Scene.Add(new WalkParticle(X + particleXBuffer, Y + 40)); break; } case Global.DIR_DOWN: { particleXBuffer = Otter.Rand.Float(8, 24); Global.TUTORIAL.Scene.Add(new WalkParticle(X + particleXBuffer, Y)); break; } case Global.DIR_LEFT: { particleYBuffer = Otter.Rand.Float(-2, 2); Global.TUTORIAL.Scene.Add(new WalkParticle(X + 32 - 3, Y + 40 + particleYBuffer)); break; } case Global.DIR_RIGHT: { particleYBuffer = Otter.Rand.Float(-2, 2); Global.TUTORIAL.Scene.Add(new WalkParticle(X + 3, Y + 40 + particleYBuffer)); break; } } }
Lastly, if things don't compile, ensure that the following line is added towards top of the Player class:
using OtterTutorial.Effects;
Launch our game, and we should see all of our new effects in action. The player will create an ugly, but purple trail in each direction it walks, and all of the bullets will leave a green trail behind, before exploding into a pink, screen-shaking cloud of awesomeness. Hopefully, you have something that looks like this in action:
All of the polish added in this entry was influenced by the discussion in the feel good repository thread, on the braingale public forums.
We've covered enough for now. Next time we will add some evil enemies, introduce collision amongst entities, and make said enemies explode upon death. Unless of course the enemies get to your first...
Take me to Part 6 of the tutorial!
Download the source code to this tutorial here.
Otter 2D Top-Down Adventure Tutorial (Part 4) - Adding the Player Entity
Last time, we finished up our title screen, and loaded an empty Scene intended for our gameplay. In this entry, we will create an Entity for the player, implementing its walking and shooting abilities. Time to get started!
First, we should download the required graphics for this tutorial. Save the player, bullet, particle, and explosion images displayed below. Either right-click and save each image below, or download this zip file containing all of our images. Make sure you save each graphic to your ‘Assets/Graphics’ folder. Next, add the images to your project by right-clicking your ‘Graphics’ folder and selecting Add—>Existing Image. Within the popup, navigate to your ‘Assets/Graphics’ folder, select all of the new images, and click ‘Add’.
If you are looking to create your own pixel art and don't know where to begin I suggest you take a look at this awesome tutorial. As far as tools go, I suggest Pixen for Mac users, and Pickle for Windows. That is about all I have to say about art, as I usually hire artists for my games :).
Shall we write some code?
Keeping to our code organization from prior tutorials, right-click your ‘OtterTutorial’ project, select ‘Add New Folder’ and create a folder named ‘Entities’. Then, right-click this folder and select ‘Add—>New Item’, and create a new C# class named ‘Player.cs’. Include Otter, and extend the Entity class like so:
using Otter; using System; namespace OtterTutorial.Entities { public class Player : Entity { } }
So, we have a Player class that extends the Entity class, but what exactly is an Entity? Well, the Entity class is probably the class that you will be working with the most in Otter. Entities are capable of:
Updating, which includes movement, shooting bullets, and other various forms of game logic.
Rendering, or drawing graphics to the screen.
Colliding and interacting with other entities.
By the end of this tutorial our player entity should be able to move around, shoot bullets, and render a spritemap graphic onto the screen. We will save collision for a later entry.
Alright, time to start coding the player. First, add the following above your Player constructor:
// Our entity's graphic will be a Spritemap private Spritemap<string> sprite; public float moveSpeed = 4.0f; public int direction = 0;
Second, add the following lines to your Assets.cs class:
public const string PLAYER = "../../Assets/Graphics/player.png"; public const string PLAYER_EXPLOSION = "../../Assets/Graphics/explosion.png"; public const string PLAYER_PARTICLE = "../../Assets/Graphics/particle.png"; public const string BULLET = "../../Assets/Graphics/bullet.png";
Third, update your Player’s constructor to match this one:
public Player(float x = 0, float y = 0) { // When creating a new player, the desired X,Y coordinates are passed in. If excluded, we start at 0,0 X = x; Y = y; // Create a new spritemap, with the player.png image as our source, 32 pixels wide, and 40 pixels tall sprite = new Spritemap<string>(Assets.PLAYER, 32, 40); // We must define each animation for our spritemap. // An animation is made up of a group of frames, ranging from 1 frame to many frames. // Each 32x40 box is a single frame in our particular sprite map. // The frames start counting from 0, and count from left-to-right, top-to-bottom sprite.Add("standLeft", new int[] { 0, 1 }, new float[] { 10f, 10f }); sprite.Add("standRight", new int[] { 0, 1 }, new float[] { 10f, 10f }); sprite.Add("standDown", new int[] { 3, 4 }, new float[] { 10f, 10f }); sprite.Add("standUp", new int[] { 6, 7 }, new float[] { 10f, 10f }); sprite.Add("walkLeft", new int[] { 0, 1 }, new float[] { 10f, 10f }); sprite.Add("walkRight", new int[] { 0, 1 }, new float[] { 10f, 10f }); sprite.Add("walkDown", new int[] { 3, 4 }, new float[] { 10f, 10f }); sprite.Add("walkUp", new int[] { 6, 7 }, new float[] { 10f, 10f }); // Tell the spritemap which animation to play when the scene starts sprite.Play("standDown"); // Lastly, we must set our Entity's graphic, otherwise it will not display Graphic = sprite; ; }
I realize that the constructor above contains a lot of new things to throw at you at once. Let’s break down some of the stuff you might not understand. First, we must set our entity’s X,Y coordinates, via the passed in x,y parameters. Next, we create our spritemap, and define each animation. As I explain above in the code’s comments, each animation is made up of frames. Our particular spritemap contains frames that are 32x40 pixels in size. The spritemap takes our player.png image, and slices it into 32x40 frames from left-to-right, and top-to-bottom. The top-left frame, also our first frame, is frame 0. I’ve gone and altered our player image from earlier, overlaying each frame index, to help understand things better:
Next, add the following line to your Global.cs class:
public static Player player = null;
Also, make sure you add the line 'using OtterTutorial.Entities;' at the top of your Global.cs class, if it is not already there.
A very basic version of our Player class is all set to go, but has not been added to our GameScene yet. Let's modify the GameScene.cs class to look like the following:
using Otter; using OtterTutorial.Entities; using System; namespace OtterTutorial.Scenes { public class GameScene : Scene { public GameScene() { // Instantiate the global player that we will be using often // The player will start at X,Y coordinates 75,75 Global.player = new Player(75, 75); // Add the player entity to our GameScene Add(Global.player); } } }
Starting the game and advancing past the title screen should display our player, bouncing up and down in place. We will add some music for him to dance to later. However, next, we will give him the ability to walk around the screen.
First, let's add the appropriate buttons to our Session object. I am going to tie the player's movement to the arrow keys on the keyboard, and the shoot button to the 'X' key. The following lines should be added to your Program.cs class, right below the line in which we set our start button:
Global.PlayerSession.Controller.Up.AddKey(Key.Up); Global.PlayerSession.Controller.Left.AddKey(Key.Left); Global.PlayerSession.Controller.Down.AddKey(Key.Down); Global.PlayerSession.Controller.Right.AddKey(Key.Right); Global.PlayerSession.Controller.X.AddKey(Key.X);
Next, we must check if these keys are being pressed in the Player.cs class, and handle the input accordingly. We must also play the proper animation in our spritesheet, that corresponds with the current input. This is all done in our Update method, which you should modify to look like so:
public override void Update() { base.Update(); // Used to determine which directions we are moving in bool horizontalMovement = true; bool verticalMovement = true; // Check horizontal movement if (Global.PlayerSession.Controller.Left.Down) { X -= moveSpeed; sprite.Play("walkLeft"); sprite.FlippedX = true; } else if (Global.PlayerSession.Controller.Right.Down) { X += moveSpeed; sprite.Play("walkRight"); sprite.FlippedX = false; } else { horizontalMovement = false; } // Check vertical movement if (Global.PlayerSession.Controller.Up.Down) { Y -= moveSpeed; sprite.Play("walkUp"); sprite.FlippedX = false; } else if (Global.PlayerSession.Controller.Down.Down) { Y += moveSpeed; sprite.Play("walkDown"); sprite.FlippedX = false; } else { verticalMovement = false; } // If we are not moving play our idle animations // Currently our spritesheet lacks true idle // animations, but this helps get the idea across if (!horizontalMovement && !verticalMovement) { if (sprite.CurrentAnim.Equals("walkLeft")) { sprite.Play("standLeft"); } else if (sprite.CurrentAnim.Equals("walkRight")) { sprite.Play("standRight"); } else if (sprite.CurrentAnim.Equals("walkDown")) { sprite.Play("standDown"); } else if (sprite.CurrentAnim.Equals("walkUp")) { sprite.Play("standUp"); } } }
Our player should now respond to input from the arrow keys, moving in eight possible directions. Unfortunately, we haven't modified the camera to move with the player yet. This will come in a future tutorial. To finish up this entry, we are going to give the player the ability to shoot bullets in the direction in which they are facing.
Let's make that Bullet.cs class. Right-click your 'Entities' folder, Add-->New Item and create a new C# class titled 'Bullet.cs'. Before we implement the Bullet class, we should add a few constant integer values to our Global.cs class. Copy and paste the following lines into said class:
public const int DIR_UP = 0; public const int DIR_DOWN = 1; public const int DIR_LEFT = 2; public const int DIR_RIGHT = 3;
These integers are going to be utilized for tracking which direction to shoot our bullets in. Time to code that Bullet.cs class:
using Otter; using OtterTutorial; using System; namespace OtterTutorial.Entities { public class Bullet : Entity { // Default bullet speed public float bulletSpeed = 10.0f; // Direction the bullet is going to travel in public int direction = 0; // Distance the bullet has traveled public float distanceTraveled = 0f; // Max distance a bullet can travel public float maxDistance = 350f; // The image object that is our bullet's graphic public Image image; public Bullet(float x, float y, int dir) { // Set the Bullet's X,Y coordinates, and its direction X = x; Y = y; direction = dir; // Set the graphic to our bullet image image = new Image(Assets.BULLET); Graphic = image; } public override void Update() { base.Update(); // Move in the correct direction that the bullet was fired in switch (direction) { case Global.DIR_UP: { Y -= bulletSpeed; break; } case Global.DIR_DOWN: { Y += bulletSpeed; break; } case Global.DIR_LEFT: { X -= bulletSpeed; break; } case Global.DIR_RIGHT: { X += bulletSpeed; break; } } // If we have traveled the max distance or more, then // the bullet will remove itself from the current Scene distanceTraveled += bulletSpeed; if (distanceTraveled >= maxDistance) { RemoveSelf(); } } } }
Before the player can actually shoot we must check for input from the shoot button. Add the following to the Update method in the Player class:
if (Global.PlayerSession.Controller.X.Pressed) { Global.TUTORIAL.Scene.Add(new Bullet(X, Y, direction)); }
Unfortunately, we still don't know which direction the player is shooting in yet. Update the two if/else blocks in the Player's update method, so that they update our direction variable:
// Check horizontal movement if (Global.PlayerSession.Controller.Left.Down) { X -= moveSpeed; sprite.Play("walkLeft"); sprite.FlippedX = true; direction = Global.DIR_LEFT; } else if (Global.PlayerSession.Controller.Right.Down) { X += moveSpeed; sprite.Play("walkRight"); sprite.FlippedX = false; direction = Global.DIR_RIGHT; } else { horizontalMovement = false; } // Check vertical movement if (Global.PlayerSession.Controller.Up.Down) { Y -= moveSpeed; sprite.Play("walkUp"); sprite.FlippedX = false; direction = Global.DIR_UP; } else if (Global.PlayerSession.Controller.Down.Down) { Y += moveSpeed; sprite.Play("walkDown"); sprite.FlippedX = false; direction = Global.DIR_DOWN; } else { verticalMovement = false; }
Now, if we play our game, our GameScene should now allow the player to move in multiple directions via the arrow keys, and shoot bullets by hitting the 'X' key. Lastly, we are going to add some music to the GameScene to conclude this tutorial. You can download the song that we will use from my site, here. This is not a song that I created. Here are its credits:
"There It Is" Kevin MacLeod (incompetech.com) Licensed under Creative Commons: By Attribution 3.0 http://creativecommons.org/licenses/by/3.0/
Next, we need to get that new song playing in the GameScene. First, add this line to your Assets.cs class:
public const string MUSIC_GAME = "../../Assets/Music/game.ogg";
Second, add the following line to your GameScene.cs class, above the constructor:
public Music gameMusic = new Music(Assets.MUSIC_GAME);
Third, tell the new Music object to play when the GameScene is loaded, by adding the following line to the constructor:
gameMusic.Play();
Run the game, get past the title screen, and we should now have a funky loop playing on repeat!
We've covered a lot in this entry. As a result, I think it is time for a well deserved break! Next time we will be polishing up our shooting mechanic, introducing particles, sound effects, and screen shake! At this pace, we should have something looking like this soon ;)
Take me to Part 5 of the tutorial!
Download the source code to this tutorial here.
Otter 2D Top-Down Adventure Tutorial (Part 3) - Polishing our TitleScene
In the last entry we started creating our game's title screen. We left off with just an image of an otter on the screen. Today, we will add some text, a bit of polish, and handle user input that will allow the player to advance to the actual game. Let's cut to the chase!
Currently, the image of the otter is rendering at the X, Y position of 0,0. It is in the upper-left of the screen, and honestly, it looks pretty bad there. Let us center the image, and tween it in with a nice transition by changing our TitleScene constructor to look like so:
// Center the title picture titleImage.CenterOrigin(); titleImage.X = Global.TUTORIAL.HalfWidth; titleImage.Y = 1000; // When tweening something in, make sure it is actually off the screen first this.AddGraphic(titleImage); // Otter utilizes the C# Tweening library called Glide // More info can be found here: http://www.reddit.com/r/gamedev/comments/1fabdh/ // Below, we tween the titleImage to its new Y position, in .30 seconds. Our Easing function utilized is Ease.BackOut // If using Otter v0.9.7 or newer please omit 'Glide.GlideManagerImpl' from your code. Tweener.Tween is all that is needed. Glide.GlideManagerImpl.Tweener.Tween(titleImage, new { Y = 250 }, 30f, 0f).Ease(Ease.BackOut);
The comments in the above code should do a decent job of documenting what is occurring. Basically, we center the image, set its X, Y coordinates accordingly, and then tell the Glide tweening library to Tween it in once the Scene starts. Pretty simple!
Next, we are going to put some text on the screen. Add the following line to your Assets.cs class:
public const string FONT_PANIC = "../../Assets/Fonts/PanicStricken.ttf";
Now, we want to instantiate an Otter Text object, that will utilize the font that we downloaded in our last tutorial. Add the following lines in your TitleScene.cs class, above the constructor:
public Text titleText = new Text("Otter Tutorial", Assets.FONT_PANIC, 84); public Text enterText = new Text("Press Enter", Assets.FONT_PANIC, 40);
We have created two new text objects. One will read 'Otter Tutorial' and the other 'Press Enter'. However, we haven't added them to our Scene, so don't expect them to show up just yet. Within the TitleScene constructor, underneath the code that Tweens our title image in, add these lines:
// Set the text's outline color to the // hex color #7FA8D2 (Otter2d.com Blue) titleText.OutlineColor = new Otter.Color("7FA8D2"); titleText.OutlineThickness = 3; // Set the outline thickness to 3 pixels titleText.CenterOrigin(); titleText.X = Global.TUTORIAL.HalfWidth; titleText.Y = 25; this.AddGraphic(titleText);
As you can see above, we give the text an outline color, center it, and add it to the scene. If you now hit Start/Run you should have a title screen that tweens in the image of the otter, and displays the text 'Otter Tutorial', right above the image. We can't stop there though. Let's add that 'Press Enter' text, and make it blink so that it grabs the player's attention. First, to add the text itself, let's mimic the way in which we added the prior text. Add these lines to our constructor:
enterText.OutlineColor = new Otter.Color("7FA8D2"); enterText.OutlineThickness = 2; enterText.CenterOrigin(); enterText.X = Global.TUTORIAL.HalfWidth; enterText.Y = 450; this.AddGraphic(enterText);
The enter text will now appear on our screen, but unfortunately, it will not blink yet. No worries, there's nothing a few lines of code can't handle. Add the following above your constructor, with your other variable declarations:
public const float TIMER_BLINK = 25f; public float blinkTimer = 0;
With these new declarations in place, add the following code to TitleScene.cs's update method:
blinkTimer++; if (blinkTimer >= TIMER_BLINK) { enterText.Visible = !enterText.Visible; blinkTimer = 0; }
Now, hit start/run and the 'Press Enter' text should be blinking. There are other ways to do this, that utlize the built-in timers provided with .NET, but I chose my crude, ugly method instead. Up to this point, you should have something that looks like this:
So, we have some tweens, some blinking text, why not add some music? As usual, we will need to add a new string to our Assets.cs class, referencing the location of our song. Add this line to the Assets.cs class:
public const string MUSIC_TITLE = "../../Assets/Music/menu.ogg";
We need to add just two lines to the TitleScene.cs class to get the song playing. First, the following line should go above your constructor, with your other global class variables:
// Create a new, looping sound object, with our MUSIC_TITLE as its source public Music titleSong = new Music(Assets.MUSIC_TITLE, true);
All that is left is to tell our TitleScene to play the song. This is accomplished via the following line:
titleSong.Play();
Hit start/run, and our awesome polka (why I chose a polka song, I have no idea) song will be playing! Go dance around a bit, I'll wait.
Our title scene is pretty cool and all, but as fun as it is, we don't want to stare at it forever. We want to transition to the actual game upon pressing enter. We will need to create an empty Scene class that we will implement in a later tutorial. Additionally, we will also have to add input handling to our TitleScene class, allowing the player to advance to this new Scene. We're going to manage player input via a Session. From the Otter documentation, the Session class is a class that represents a player session. Use a Session for maintaining and using information about a player. For example a two player game might have two sessions, one for each player, each with their own controls configured and save data.
First, add a new Session to our Global.cs class:
public static Session PlayerSession;
Then, instantiate this session in our Program.cs class, after the call to the SetWindow method, before the call to the Start method:
Global.PlayerSession = Global.TUTORIAL.AddSession("Player");
Next, we need to bind input buttons to our session. For this tutorial, we will just set the 'start' button to the return key on our keyboard. Add the following below the line you added in our previous step:
Global.PlayerSession.Controller.Start.AddKey(Key.Return);
Lastly, our TitleScene class needs to check if the player hits start. Add the following code to the Update method in TitleScene.cs:
if (Global.PlayerSession.Controller.Start.Pressed) { titleSong.Stop(); Global.TUTORIAL.RemoveScene(); Global.TUTORIAL.AddScene(new GameScene()); }
Ah, but wait, this won't compile. We need to add a new GameScene class to our project. Right click your 'Scenes' folder, Add->-New Item and add a new class titled GameScene.cs. Replace the created class with the following:
using Otter; using System; using System.Text; namespace OtterTutorial.Scenes { public class GameScene : Scene { } }
If you have followed along with each step, then feel free to hit start/run. Once the title screen has loaded, hitting enter should cause the screen to go black. We have entered our new GameScene! \:D/ That should be enough for this tutorial. Next time we will add a cool, purple alien-looking player to our scene that can walk around, and shoot bullets. For now, enjoy that awesome polka music!
Lastly, if you want to get an idea of what I consider to be a superb title screen, take a look at the title screen from "Spelunky". Unfortunately, a static image doesn't do it justice, and I couldn't find any videos of just the title screen.
Take me to part 4 of the tutorial!
Download the source code to this tutorial here.
Otter 2D Top-Down Adventure Tutorial (Part 2) - Creating Your First Scene
Previously, I introduced Otter2D by Kyle Pulver, a 2D game framework developed in C#, built on top of SFML.NET. If you need to go over the basics that get a blank canvas up and running, feel free to check out my last post. In this entry, we will get a simple title screen rendering. Please note that we are still working with our 'OtterTutorial' project, in case you chose to name your project differently during the last tutorial.
First, we should do a little house keeping. We are going to start working with assets, including images, sounds, music, etc. We will need to create a folder that will house all of our assets. To do so, right-click the 'OtterTutorial' project within Visual Studio Express, select Add-->New Folder. Name this folder 'Assets'. Once done, right-click the new Assets folder, select Add-->New Folder again and name this new folder 'Graphics'. Repeat this step three more times, naming each successive folder 'Fonts', 'Music', and 'Sound'.
Now that we have our folder structure in place for all of our assets, let's add some assets to those empty folders! I've gone and selected a few assets for us to play with. First, download this random image of an otter, and save it in your 'Assets/Graphics' folder.
Second, the title screen music is from opengameart.org, courtesy of Bruno Belotti. All of its relative info can be found here. Considering that SFML does not support MP3 files, I have gone and created an Ogg file for you to use. You can download it from my website here. Make sure you save it to your 'Assets/Music' folder.
Third, I have gone and selected a random, free, font from the Internet. It is titled "Panic Stricken", and it can be downloaded from the following URL: http://www.1001freefonts.com/panic_stricken.font. The font should be downloaded to your 'Assets/Fonts' folder.
With all of our new assets in their appropriate folders, we must add a reference to each asset in our Visual Studio project. Right-click each respective folder (Fonts, Graphics, Music), and select Add-->Existing Item. Next, select the current asset that you're adding to the project and click 'Add'. Repeat these steps until you have added the otter image, title song, and font. Things our progressing right along, and we now have all of our assets for this tutorial in place, and ready for use. Your solution should look similar to this:
Next, before I explain scenes and how they work, I am going to quickly cover some code organization that I do. I am not the world's best programmer (in fact, I don't even think that I'm a good programmer), but I do know that game projects can grow rather large, very quickly. Due to this, when I create a new game project, whether it is a small prototype, or long-term project, I usually create both an Assets class and Global class. The Assets class contains string references for all of my various assets, and the Global class is where I put all of my global variables that the game will use. Right-click your game project, select Add-->New Item, and add a new class named 'Assets.cs'. Repeat these steps again, this time creating the 'Global.cs' class.
Time to create that title screen!
When Otter starts going, the game loop updates the currently loaded Scene. Scenes serve as a container for your entities, graphics and other on-screen items. Your game can have any number of Scene classes, but only one Scene is active at once. While active, a scene will update and render each Entity object that has been added to it. So, basically, while your game is running you will have your Game object that oversees everything, including the current Scene, and a Scene that contains a bunch of Entities, graphics, text, etc. that it is in charge of. If you're familiar with the Worlds paradigm seen in FlashPunk, this will be right up your alley. If not, don't worry, it will come to you with some practice. Our simple game is going to have a scene that will server as our Title Screen, and another Scene where the gameplay will take place.
Normally, I organize my classes into sub-folders. For example, all of my Scenes will go in my Scenes folder, Entities in the Entities folder, so on and so forth. Create a new folder in our OtterTutorial project, and name it 'Scenes'. Right-click the new Scenes folder, select Add-->New Item, and create a new C# class named 'TitleScene.cs'. Include Otter at the top, and extend the Scene class like so:
using Otter; using System; using System.Collections.Generic; using System.Text; namespace OtterTutorial.Scenes { public class TitleScene : Scene { } }
Save your work. Create the default constructor, and override Scene's Update method by adding the following:
using Otter; using System; using System.Collections.Generic; using System.Text; namespace OtterTutorial.Scenes { public class TitleScene : Scene { public TitleScene() { } public override void Update() { base.Update(); } } }
Time to start utilzing our Assets.cs and Global.cs classes from above. Instantiate a new const string that will reference our title image's location like so:
// I've pasted the entire class this one time so you can see where the strings we will add in the future should go using Otter; using System; using System.Text; namespace OtterTutorial { public class Assets { public const string TITLE_IMG = "../../Assets/Graphics/otter.jpg"; } }
Following that, add a null game object to the Global.cs class:
// Again, I've pasted the entire class this one time so you can see where future code will go using Otter; using System; using System.Collections.Generic; using System.Text; namespace OtterTutorial { public class Global { public static Game TUTORIAL = null; } }
So, when do we actually put something cool on our screen? Well, add the line
using OtterTutorial;
to the top of your TitleScene.cs class and then add the following above the class' constructor:
// Create a new Image object, referencing the Otter image in our Assets folder public Image titleImage = new Image(Assets.TITLE_IMG);
We have just created an Image object, that will use the cute picture of the otter from earlier in this tutorial. However, before it will show up in our TitleScene, we must add the image to the Scene itself. This can be done within our TitleScene constructor, like so:
// Before we can see any graphics, they must be added to the active scene via code AddGraphic(titleImage);
This might seem like a lot of work to get a mere image on the screen, but all of these organizational steps will pay off in future tutorials, and perhaps even in all of the awesome games you make! Finally, all that remains is a few changes to our Program.cs class:
using Otter; using OtterTutorial; using OtterTutorial.Scenes; using System; using System.Collections.Generic; using System.Text; namespace OtterTutorial { public class Program {
static void Main(string[] args) {
Global.TUTORIAL = new Game("OtterTutorial", 640, 480); Global.TUTORIAL.SetWindow(640, 480); Global.TUTORIAL.FirstScene = new TitleScene(); Global.TUTORIAL.Start(); } } }
Save all of your work, hit the Start/Run button and VOILA! We have our Otter picture rendering on the screen. The next step is to submit to Steam Greenlight and party like rock stars!
While our title screen is rather vanilla at the moment, I feel we have covered enough for this tutorial. Next time we will polish the title screen up a bit, add a tween or two, implement the handling of user input, and get us to the Game Scene where the real fun begins.
Take me to part 3 of the tutorial!
Download the source code to this tutorial here.

Anya is live and ready to show you everything. Watch her strip, dance, and perform exclusive shows just for you. Interact in real-time and make your fantasies come true.
Free to watch • No registration required • HD streaming
Otter2D Top-Down Adventure Tutorial (Part 1) - An Intro to Otter2D, a 2D Framework Using SFML.NET
I recently started poking around a new 2D framework that uses SFML.NET, named Otter2D, by Kyle Pulver. I don't know Kyle personally, but I do know that he was an avid FlashPunk user, like myself. It seems he was looking to move on from Flash, and thus, Otter2D was born. Don't get me wrong, I still love FlashPunk, and give it my highest recommendation, especially if you're just getting into Flash/AS3. However, I prefer to code in C#, and Otter2D came around at just the right time for me to fiddle around with some new technology. I intend to write a series of small tutorials introducing you to Otter2D, teaching you how to get some entities up on the screen, animating, shooting projectiles with particle effects, and more!
Otter2D is completely free, and the source code can be found hosted on BitBucket. Kyle has already provided a couple of videos that demonstrate how to get a basic pong clone up and running. The source code for this pong clone can also be downloaded via the web, and is a good starting point for learning some Otter2D basics. However, for this tutorial I will still be starting from the very beginning with installing Visual Studio 2012.
Before I go on, I'd like to note that I won't be teaching C# in these tutorials. If you are looking to learn C#, or just brush up on a few things I suggest checking out these tutorials.
Ok, let's get to the fun stuff.
First, I assume you are starting from scratch and using Windows (I actually code on a Mac running Parallels). Head on over to the Microsoft website and download Visual Studio Express 2012. You don't have to use Visual Studio Express 2012. Personally, I've worked in both VSE 2010 and VSE 2012, and I prefer the look and feel of VSE 2012. If you truly are starting from scratch, then I believe the Visual Studio install should install everything you need, including the .NET framework. Lastly, you don't have to use an Express version of Visual Studio. If you prefer a premium version, they too work just as well, if not better.
Once the install has finished, start up Visual Studio Express if it does not do so automatically. From the welcome screen, select New Project-->Visual C#-->Windows-->Console Application. You can name your project whatever you choose. I have gone and named mine 'OtterTutorial'. Click 'OK' once everything looks good, and Visual Studio will go ahead and create your project's template. Woohoo, progress!
Now that your project's skeleton has been created, you should go ahead and download Otter2D if you haven't already. Unzip Otter2D into a convenient location, as it is going to be referenced in our OtterTutorial solution. Next, right-click your solution, go to Add-->Existing Project, and navigate to your Otter.csproj file. Select the csproj file, and click OK to add Otter to your solution.
Unfortunately, there is still another step to go before you can start coding like a rock star. Currently, you have your OtterTutorial project, and the Otter project in your solution. Our OtterTutorial project must be made aware of the Otter project in order to use it. This is accomplished by adding a reference to Otter in the OtterTutorial project. To do so, right-click the OtterTutorial project within the solution, select ‘References’, and then click ‘Add Reference’. From here, expand ‘Solution’, and highlight ‘Project’. Check the box next to Otter and click OK.
You should now have a basic solution, containing both Otter, and your OtterTutorial project (or whatever you chose to name it). Time to write some code! \:D/
I want to keep each entry in this series as short as possible. Hence, I am only going to cover getting a blank screen up and running. This is already documented in the Getting Started guide on Otter's website. If you feel you already have these steps down, then please feel free to skip ahead to the next tutorial.
Open the Program.cs class in Visual Studio. Replace your Program.cs with the following:
// Must include Otter in your project, so we add this line using Otter; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace OtterTutorial // This can be anything you choose, I opted for my project's name { public class Program { static void Main(string[] args) { // Create a new Game object, 640x480 pixels in size // The window will run with the title "OtterTutorial" Game tutorial = new Game("OtterTutorial", 640, 480);
// You can set the actual window size to something different than the Game's resolution. tutorial.SetWindow(640, 480); // Start the game \:D/ tutorial.Start(); } } }
I have gone and added comments in the code above that should thoroughly explain things. Save your work, and hit the Start/Run button. You should now have an awesome, yet boring (we will get to the fun stuff soon!) black box on your screen, like this one:
Well, that should do it for part one. I feel like we have covered enough for a basic intro. Next time we will learn about scenes, create our game's title screen, and try to take over the world.
Cheers!
Take me to part 2 of the tutorial!
Download the source code to this tutorial here.
My Top 10 Games of 2013
I tried to spend more time playing games in 2013 than 2012. Unfortunately, I didn't have the time to get to every game I had my eyes on this year, including "Fire Emblem", "Risk of Rain" and a few others. Regardless, I got my hands on a lot of great titles in 2013, and here are my ten favorite, in numerical order with a small blurb explaining each:
Games with a good story really captivate me. "The Last of Us" has arguable the best story in any game I've played, and I've played my fair share of RPGs.
Sure it came out for XBox 360 in 2012, but I didn't actually spend significant time with it until 2013. It also released for PC this year, hence I feel it can make the list.
"Rogue Legacy" takes a bit of "Spelunky", "Dark Souls", and "Metroid", and mashes them all together. Once you get past the necessary grinding it is a lot of fun.
Look at all these platformers. The unique crosslink mechanic is what makes "Gunpoint" so much fun. The music is pretty awesome too.
I love everything Zelda, and "A Link Between Worlds" does not disappoint as far as delivering a solid Zelda experience goes.
"Year Walk" is my favorite iOS game I've played to date. It has a unique atmosphere, solid puzzles, and a few jump scares along the way.
"Bioshock Infinite" has its flaws, but it still makes my list. Having not played a Bioshock game until Infinite, I enjoyed the Vigor system and seeing the city of Columbia. The voice acting and music are excellent as well.
A huge Zelda fan such as myself couldn't ignore "Ittle Dew". It oozes charm, fun puzzles, and is pretty to look at.
"Brothers" is pretty amazing to look at, and uses the PS3 controller in a way I had never seen before. The story is well done as well, making it worth your time.
"Ridiculous Fishing" is just a very well designed game from top to bottom. If you have to buy just one iOS game in your lifetime I would say this is the one.
There you have it. Hopefully 2014 provides as many fun games for me to play, as a break from game development is always needed from time to time.
Here's to the new year!