I moved to a new URL! Check it out!

posts tagged with: csharp

Behavior Tree Experiments

Behavior Tree Experiments
As I dig back into my main project one of the upcoming things on my to do list that has been bugging me has been getting the enemies working in a fun and compelling way. Something where they feel smart enough to be challenging to take on.

Usually the way I've always done enemies is through finite state machines which is a pretty fancy term that you shouldn't look up on Wikipedia unless you're going to become incredibly confused. Basically a finite state machine can be used to separate an enemy's behaviors into a bunch of different distinct states. A state can then link itself to other states. So an enemy might have attack, confused, hurt, or defeated states, and depending on what's happening in the game it will switch between them to act on things.

A behavior tree is way more fancy than that and apparently is more powerful in a lot of ways. Ways that I'm not sure that I understand yet, and ways that I've been trying to figure out over the past however long I've actually been working on this game.

Image


I've started putting together a quick behavior tree library that covers the basics that I learned from this article here. For now I'm calling it Kodo and you can check out the full source on BitBucket. I'm not sure how well it works at all, so be warned. Currently I'm using it for some tests using Otter, and so far it seems like things are working but I haven't stepped into the realm of incredibly complicated trees yet.

One of the toughest things for me right now is understand how exactly I'm supposed to be building behavior trees. Finite state machines have always been easier for me to implement, and understand, and going from that to behavior trees has left me completely clueless for the most part, but everywhere I go on the internet assures me that behavior trees are ultimately worth it in the end!

Quick Otter Camera Example

Quick Otter Camera Example
A question about the camera in Otter came up on the forums, and I whipped up a small example that could be useful to take a look at for getting started with Otter in general. The whole program is just this little chunk of code:

using Otter;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CameraTestThing {
class Program {
static void Main(string[] args) {

var game = new Game("Camera Test", 320, 180);
game.SetWindowScale(4);
game.Start(new TestScene());
}
}

class TestScene : Scene {

public TestScene() {
var grid = new Grid(1000, 1000, 20, 20, Color.Grey);
AddGraphic(grid);
Add(new Player());
}
}

class Player : Entity {

Vector2 speed = new Vector2();
Vector2 targetSpeed = new Vector2();
Vector2 maxSpeed = new Vector2(2, 2);
float accel = 0.01f;

Axis movementAxis = Axis.CreateArrowKeys();

public Player() {
SetGraphic(Image.CreateRectangle(10, Color.Red));
AddComponent(movementAxis);
}

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

targetSpeed.X = movementAxis.X * maxSpeed.X;
targetSpeed.Y = movementAxis.Y * maxSpeed.Y;

speed.X = Util.Approach(speed.X, targetSpeed.X, accel);
speed.Y = Util.Approach(speed.Y, targetSpeed.Y, accel);

X += speed.X;
Y += speed.Y;

Scene.CenterCamera(X, Y);
}
}
}

Compiling that with the latest dev version of Otter gives you a simple player object that can move around a scene. The background is a grid so that you can actually see scrolling happening. This quickly shows how to set up a movement Axis, how to apply speed to an object while getting input from the Axis, and how to center the camera on the object.

Otter Updates 0.9.6

Otter Updates 0.9.6
Otter is slowly approaching the big 1.0.0 moment, and I've been tinkering with it little by little trying to fix bugs that pop up. I've also been using the dev branch so you can see my updates as I make them. Otherwise the default branch is supposed to be the "stable" one, and every once in awhile I merge the dev branch in with the default one.

Here's some of the recent changes and fixes!

* Text now has CenterTextOrigin() in an attempt to find the center of the actual text, and not the full bounding box.

* RichText also now has CenterTextOrigin()

* Fixed Text bug that would cause text to jitter when the height of the tallest character was changed.

* Fixed the same issue in RichText.

* Tilemaps have had some improvements in their performance for looking up tiles.

* Tilemaps can now use Enums for their layers.

* Fixed bugs with accessing tiles out of range in a Tilemap. Tiles are now automatically clamped inside of the limits of the Tilemap.

* Tilemap GetTiles() will return a list of TileInfo objects for every tile on a specific layer.

* GridCollider now has a Clear() function

* GridColliders can now load collision data from a Tilemap, using a specific layer on the Tilemap.

* Fixed a bug with not updating Graphics when their alpha was changed.

* Game's "SmoothAll" value should now actually affect Textures. Considering changing this to a static value on Texture.

* Fixed crash bug with Surface's SaveToFile() function.

* Updated the Glide Tween Library to the latest revision.

* Updated the documentation.

That's all for now. If you have any issues you can post on the forums and that'll be the easiest way to get help. Hope everyone out there is having fun with the engine!

Dev Log: Shader Experiments

Dev Log: Shader Experiments
Since my break to work on the remaining bits of Otter I haven't really fallen back into the groove on working on my big game project yet. Yesterday I dedicated the day to playing around with shaders since I'm really interested in using them for all kinds of cool visual effects.

Image


This is what I ended up coming up with at the end of the day. First I was playing around with gradient maps for recoloring an image, and then I started to mess with displacement to make cool waves in the image. Finally I wanted to experiment with having a render texture that could be passed to the shader for dynamic effects.

Basically how this little program works is that there is the static image with a shader loaded. Then there's a Surface object that can be painted on with the mouse. The shader uses the texture from that Surface to affect the image in different ways.

Here's the full C# source:
using Otter;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ShaderTesting {
class Program {
static void Main(string[] args) {
var image = new Image("pic.jpg");
var game = new Game("ShaderZ", image.Width, image.Height);

game.FirstScene = new TestScene();

game.Start();
}
}

class TestScene : Scene {

Image image = new Image("pic.jpg");
Image circle = new Image("circle.png");
Surface distortion;

public TestScene() {
AddGraphic(image);
distortion = new Surface(image.Width, image.Height);
circle.CenterOrigin();
circle.Blend = BlendMode.Add;
AddGraphic(distortion);
circle.Alpha = 0.1f;
distortion.Visible = false;
distortion.AutoClear = false;
}

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

if (Timer % 30 == 0) {
try {
image.Shader = new Shader("../../shader.frag");
}
catch(Exception e) {
Console.WriteLine("Shader error:");
Console.WriteLine(e.Message);
}
image.Shader.SetParameter("gradient", new Texture("gradient.png"));
}
if (Input.MouseButtonPressed(MouseButton.Right)) {
distortion.Clear();
}
image.Shader.SetParameter("time", Timer);
image.Shader.SetParameter("distortion", distortion.Texture);
image.Shader.SetParameter("offset", Util.SinScale(Timer, 0, 1));

if (Input.MouseButtonDown(MouseButton.Left)) {
Draw.SetTarget(distortion);
Draw.Graphic(circle, MouseX, image.Height - MouseY);
Draw.ResetTarget();
}
}

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

Draw.Circle(MouseX - 15, MouseY - 15, 30, Color.None, Color.Red, 2);
}
}
}

And the GLSL shader source:
sampler2D texture;
sampler2D gradient;
sampler2D distortion;
uniform float offset;
uniform float time;
uniform float mixfactor;

void main() {
vec2 pos = gl_TexCoord[0];
vec2 distortColor = texture2D(distortion, pos);
pos.x += distortColor.r * (sin(time * 0.1 + pos.x * 10) * 0.05);
pos.y -= distortColor.g * (cos(time * 0.1 + pos.y * 10) * 0.05);
vec4 color = texture2D(texture, pos);

float gray = (color.r + color.g + color.b) / 3;

vec4 gradientColor = texture2D(gradient, vec2(gray, offset));

gl_FragColor = mix(color, gradientColor, distortColor.r + distortColor.g);
}

You can download everything here. Note that you'll have to give it a reference to Otter to compile and run it yourself.

More Otter Updates

More Otter Updates
I've gotten myself into the bad habit of procrastinating on my game project by working on Otter some more!

I just pushed another wave of updates on the journey to the big 1.0.0.

* Text and RichText's rendering positions have been changed. The default origin will now be the top left most position of any text, instead of allowing for "bleed." This should make it simpler to deal with.

* The Tilemap class got a few updates including a performance boost for clearing tiles, and a final pass on tile layers. Everything in the Tilemap class should now be usable as intended.

* Documentation fixes and updates across the board.

* Debugger has been updated to adjust for the Text updates.

So at this point I think the only thing that's left is fixing whatever bugs come up. So if you hit any bugs in any point in Otter then please let me know on the forums!

Otter Updates

Otter Updates
Things are moving along for Otter, my SFML.Net based game making framework!

I pushed a lot of changes this week that is bringing it closer to the big version 1.0. I overhauled a lot of the code in the Graphics classes, fixed some bugs, and updated all of the documentation for mostly everything. I also went through and cleaned up a lot of the code and organized it into nifty regions.

Right now my plan is to just keep testing things for awhile yet to make sure there's no crazy show-stopping bugs before I publicly announce to the world that it's officially version 1.0. Some of my recent changes have not been tested that thoroughly yet, and there have been a few bug reports popping up that I've been fixing up, so I can only imagine there are more bugs lurking in the shadows.

As far as sprite batching goes, I decided that I'm holding off on official sprite batching support until after version 1.0. There is some stuff set up in the back end of things to turn on sprite batching, but there are a handful of bugs that need to be resolved first and I don't think I'm going to be able to get them squished quickly enough. Aside from that, my performance tests seem to indicate that sprite batching isn't really that helpful anyway.

If you're using Otter and encounter any bugs, you can let me know on the forums or directly on the BitBucket issue tracker.