Duckbridge

Just a couple of kids with some dreams

Category: Luckslinger

Luckslinger tech #2 – A simple, yet effective Event system in Unity

Hey again, this is entry 2 in the ‘Luckslinger tech’ series  and this one will be about the ‘event system’ that we use in our games. We use this in MANY places in Luckslinger and it makes the development of the game(and other games) a lot easier and more flexible.

This system is used for dispatching in-game events and is similar to the publish-subscribe pattern.

The system is quite simple, there is object A which listens to object B and then when object B wants to send a message to object A, it just dispatches, that message. An example:

GameManager {
     Player player = new Player();
     player.AddEventListener(this.gameObject);  
     public void OnPlayerDied() {
          RestartGame();
       }
} 
Player {
   Public void OnHit() {
        health--;
        if(health < 1) {
           DispatchMessage(“OnPlayerDied”, null);
         }
     }
}

It’s an example of an event that we actually use in Luckslinger (but ofcourse it’s not that simple in-game).

When ‘DispatchMessage’ is called, it sends a message to all the objects that are listening to the Player object, in this case it’s only the GameManager, so in the GameManger, the ‘OnPlayerDied’ function is called through the event (and no parameter is passed, you could do that if you want)

So how do you get a system like this to work? Well we’re in Luck, because in Unity this is relatively easy to do (We can also do this in Java, but I’ll do a separate post on this if people want to know how to do it).

Unity has this thing called ‘SendMessage’, which allows you to call a function on an object by it’s name (a string). And you guessed it, we will basically be using this function, but we’ll be building something around it to make it work easy!

 

The code looks like this:

public abstract class DispatchBehaviour : MonoBehaviour {
     
     private List<GameObject> listeninggameObjects = new List<GameObject>();
     protected bool isEnabled = true;
 
     public void DispatchMessage(string message, object parameter) {
         if(listeninggameObjects != null) {
             for(int i = 0 ; i < listeninggameObjects.Count ; i++) {
                 if(listeninggameObjects[i]) {
                     listeninggameObjects[i].SendMessage(message, parameter, SendMessageOptions.DontRequireReceiver);
                 }
             }
         }    
     }
     
     public void AddEventListener(GameObject go) {
         if(go != null && !listeninggameObjects.Contains(go)) {
             listeninggameObjects.Add(go);
         }
     }
 
     public void RemoveEventListener(GameObject go) {
         listeninggameObjects.Remove (go);
     }    public virtual void Disable() {
         this.isEnabled = false;
     }
 }

 

So it is a class that is a child of MonoBehaviour (so you can extend the DispatchBehaviour class in your own classes). Which means that you could make a Player class which is able to dispatch messages to other objects by doing the following:
 
 public class Player : DispatchBehaviour  {
             //player code stuff
} 

Basically what the DispatchBehaviour class does is that you can add objects into the list of Listeners with the ‘AddEventListener’ function and then you can send a message to all of them in the ‘DispatchMessage(‘message’,parameter)’ function. And because you extend the DispatchBehaviour class, you can always access the functions.

The way this would work in Unity is quite simple, almost the same as what I’ve done before.
I’ll give some pseudo/example code:

 public class GameManager : MonoBehaviour {
public void Awake() {
Player player = this.transform.Find(“Player”).GetComponent<Player>();
player.AddEventListener(this.gameObject);
}

public void OnPlayerDied() {
Debug.Log(“Ah, you died, restart”);
}

public void OnPlayerDied(Player player) {
Debug.Log(“Ah, player with “ + player.name +” died, restart”);
}

}

public class Player : DispatchBehaviour {

public void Awake() {
Invoke(“OnFakeDied”, 2f);
}

public void OnFakeDied() {
DispatchMessage(“OnPlayerDied”, null);
}

public void OnFakeDiedWithParameter () {
DispatchMessage(“OnPlayerDiedWithName”, this);
}

}

You could probably just copy-paste this into Unity in an empty Scene with two gameObjects and just attach the correct scripts to the game Objects and it should work.

That’s it! Pretty easy right :).
My name is Marciano Viereck and I’m the programmer at Duckbridge and we’ve recently released Luckslinger on Steam with a 2 man team.

Luckslinger tech – #1 How to make 2D Sprite animations in Unity

So we’ve just released Luckslinger on Steam and some people were curious about the ‘system’ that we use for doing all the sprite-animations in the game. Actually the basics are quite simple, but after that it gets a bit more complicated. For this post I’ll just go over the basics and explain how we use Unity’s Sprites to make simple(and later complex) 2D sprite animations.

Basically how it works is that, we make the animations in Graphicsgale and then export it as a full png. So that the whole animation is in one image. Then we import it in Unity as a Sprite with ‘Multiple’ sprite mode, we then cut all the frames of the spritesheet correctly and filter as point and set the Format to Truecolor.

We then create an ‘SpriteAnimation’ in Unity and then add the ‘Animation2D’ component to it, we then add all the cut sprites in the array, do the settings, press Play in Unity and voila!

 

So how does this ‘Animation2D’ component work? We’ll make it right now!

So I’d say, create a new C# Class in your Unity project and call it Animation2D.

First of all, we’ll need to add some settings to the Class.

public float FPS;
public bool isLooping;
public Sprite[] frames;
public bool playOnStartup = false;
private SpriteRenderer outputRenderer;
private float secondsToWait;

private int currentFrame;
private bool stopped = false;

Most of these variables are quite self-explanatory, you can set the FPS in the editor, set if it’s looping or not, set drag the correct frames for the animation and choose wether the animation will play when the scene loads. And the private variables are more for internal stuff.

So where do we go from here? Create an Awake function for your class (void Awake()) and it should look like this.

public void Awake () {
         outputRenderer = this.GetComponent<SpriteRenderer>();
             
         currentFrame = 0;
         if(FPS > 0) 
             secondsToWait = 1/FPS;
         else 
             secondsToWait = 0f;

         if(playOnStartup) {
             Play(true);
         }
     }

What happens here is that firstly we grab the SpriteRenderer which should also be added to the GameObject which contains this script, then we just reset the frame and set the secondstoWait. If the ‘playOnStartup’ is set to true, then the animation will start playing instantly. (otherwise you can make it play from somewhere else by calling the ‘Play’ function which we’ll make in a second.

 

public void Play(bool reset = false) {

         if(reset) {
             currentFrame = 0;
         }

         stopped = false;
         outputRenderer.enabled = true;

         if(frames.Length > 1) {
             Animate();
         } else if(frames.Length > 0) {
             outputRenderer.sprite = frames[0];
         }
     }

I guess most of this function also explains itself, I just reset some variables and check if there are more than 1 sprites into the array of animation sprites. If so, then start playing the animation, if not, then just set the sprite to the outputRenderer so it’s a still animation.

So next up if the final part, and the ‘core’ part of the Animation2D class, and can be used to add more functionality to the Animation2D class (as we have!)

public virtual void Animate() {
         CancelInvoke("Animate");
         if(currentFrame >= frames.Length) {
             if(!isLooping) {
                 stopped = true;
             } else {
                 currentFrame = 0;
             }
         }
     
         outputRenderer.sprite = frames[currentFrame];

         if(!stopped) {
             currentFrame++;
         }

         if(!stopped && secondsToWait > 0) {
             Invoke("Animate", secondsToWait);
         }
     }

So this function is called by ‘Invoke’ and first of all Cancels any Invoke that might have been called (so that the animation doesn’t mess up by accident). Basically what it does is increment the ‘currentFrame’ counter by 1 and then takes the sprite in the animation’s array at that index and applies it to the output.

And it checks if you want it to loop. If you want it to loop and the counter is longer or equal to the size of the animation array, then it will reset. If not, it will just stop.

And then if the animation hasn’t stopped yet it will use Invoke to re-call the Animation function.

I guess you could easily make a ‘Stop’ function which Cancels any Invoke of ‘Animate’ and sets ‘stopped’ to true.

Horse running animation in Luckslinger made with this system

That’s all for now, if you have any question or so feel free to email (duckbridge.dev[at]gmail.com) or comment. This animation class is quite simple, but we built our whole animation system based on this little class here!

I guess I could do more of these posts about more code-stuff of our game, like the loading system, saving system, some minigames, Ui stuff, some AI stuff, whatever.

My name is Marciano Viereck and I’m the programmer at Duckbridge and we’ve recently released Luckslinger on Steam. (with a 2 man team)

Luckslinger got greenlit!

Hey people,

It’s been a rough road, but Luckslinger got greenlit today! We’re so excited about it and happy and tired and many things at the same time. At some point we didn’t think that Luckslinger would still get greenlit. It’s so crazy, just a few hours ago I was thinking that I wouldn’t mind waiting a few more weeks to get greenlit, but then it just happened!

GREENLIT

 

Continue reading

New old post: ‘Bullets & Beats’ (Luckslinger)

Hey all,

I was going through my documents and I actually found an old article that I (probably) wanted to post a loooong time ago (around october 2014) but never did… for some reason.
So here it is, the ‘new old post’, enjoy

About a month ago we decided to upload a demo of ‘Bullets & Beats’ (or as it’s now called ‘Luckslinger’) to Newgrounds and GameJolt, to see it people would like it and if our mechanic would work at all.

bulletsbeats

 

Continue reading

Luckslinger showcase at Hell o’ bullets event

Last friday we attended our first bigger event called Hell o’ Bullets which is a collaborative shoot’em up showcase by Amulware, bitHuffel, Critical Bit, Two Tribes and 2Awesome Studio with the support of Indietopia. Eventhough Luckslinger isn’t a ‘shoot’em up’ we were still allowed to showcase our game at the event, which was super cool!

lEuhu85Because Donald and I both don’t live near Groningen, we decided to take the train early to be on time. When we arrived at the event we found out that we actually arrived way too early, so we decided to just get some coffee and hot chocolate milk<3 in the centre of Groningen…
Continue reading

Hell o’ bullets

Good news! we will be showcasing Luckslinger at the ‘Hell o Bullets‘ event in Groningen at the 21st and 22nd of November! We’re really excited about it, but we still have quite some stuff left to fix for the event.

Last Wednesday we also did a showcase at the ‘Connected Lunch’ event at the Dutch Game Garden. The Connected Lunch is a monthly event where developers can showcase their game and people can play it. It’s very good for some small play-test sessions.

The event was really fun and cool and most of the feedback that we received was quite positive and people seemed to enjoy the game. We hope to upload some pictures of the event soon though!

Luckslinger screenshots

We’re currently busy with working on Luckslinger. Luckslinger a hip hop infused spaghetti western action platformer with a lucky twist. It is a 2D action platformer in which luck is measurable, changeable and has an impact on the game world.

We have made quite some content for the game already, but there is a still a long road ahead of us!
Some screenshots can be seen here
gnXjWvK

KhB89uR

kXBRjXW

lEuhu85

SS-Shootout

Copyright © 2017 Duckbridge

Theme by Anders NorenUp ↑