A Simple Generic Timer System for Unity ECS

Timers are used in different ways in video games such as to allow the players to fast forward in strategy games, or to be used by systems for computations like damage per minute type of effect, and much more. In my experiment project using Unity’s pure ECS, I needed a timer for setting how long an NPC will be on idle.

In this quick tutorial I’ll show you how I implemented this timer system. As usual, there are references at the end of the blog for further reading. Enjoy!

The Timer Component Tag

Let’s start with the Timer tag that we will add to the entities that we want the timer system to affect. Keep in mind that we will be implementing a generic system later that will take this timer tag as the system’s data type. The tag will look like this:

public struct Timer<T> : IComponentData where T : struct {
    // Note that we don't reset the values here since
    // we will remove this component when we're done anyways

    public float ElapsedTime;
    public float TargetDuration;

    public Timer(float targetDuration) : this() {
        SetDuration(targetDuration);
    }

    public bool IsDone {
        get {
            return this.ElapsedTime >= this.TargetDuration;
        }
    }

    private void SetDuration(float targetDuration) {
        this.ElapsedTime = 0;
        this.TargetDuration = targetDuration;
    }
}

I admit that this code looks weird because we introduce a type T, but never use it anywhere in the struct. But, this will help us differentiate the different timer systems later. This is done this way as a workaround to the fact that we can’t inherit structs and structs can’t derive from classes.

The Generic Timer System

For the system, we’ll implement a generic timer system. This will allow us to extend the timer system and have different timers for different parts of the game (such as animations, idle, game speed, etc.). This is what it looks like in code:

public class TimerBaseSystem<T> : SystemBase where T : struct, IComponentData {
    private EntityQuery timerQuery;
    private EntityCommandBufferSystem entityCommandBufferSystem;

    private const float TIME_SCALE = 1f;

    /// <summary>
    /// We set the TimeScale as virtual so that subclasses can have their own timescales if needed.
    /// A use case for this is for faster speeds or faster enemies in strategy games.
    /// </summary>
    protected virtual float TimeScale {
        get {
            return TIME_SCALE;
        }
    }

    /// <summary>
    /// This is the scaled time - applying the Timescale to the delta time.
    /// </summary>
    private float ScaledTime {
        get {
            return this.Time.DeltaTime * this.TimeScale;
        }
    }

    protected override void OnCreate() {
        base.OnCreate();

        this.entityCommandBufferSystem = this.World.GetOrCreateSystem<EntityCommandBufferSystem>();

        // The main idea here is that everything that has the Timer tag of type T will only be processed
        this.timerQuery = this.EntityManager.CreateEntityQuery(
            ComponentType.ReadWrite<Timer<T>>()
        );
    }

    protected override void OnUpdate() {
        UpdateTimerJob job = new UpdateTimerJob {
            EntityTypeHandle = GetEntityTypeHandle(),
            TimerTypeHandle = GetComponentTypeHandle<Timer<T>>(),
            CurrentTimeInterval = this.ScaledTime,
            CommandBuffer = this.entityCommandBufferSystem.CreateCommandBuffer().AsParallelWriter()
        };

        this.Dependency = job.ScheduleParallel(this.timerQuery, this.Dependency);
        this.entityCommandBufferSystem.AddJobHandleForProducer(this.Dependency);
    }

    // BURST IT!!! YAAS!
    [BurstCompile]
    private struct UpdateTimerJob : IJobChunk {
        [ReadOnly]
        public EntityTypeHandle EntityTypeHandle;

        [ReadOnly]
        public float CurrentTimeInterval;

        public ComponentTypeHandle<Timer<T>> TimerTypeHandle;

        public EntityCommandBuffer.ParallelWriter CommandBuffer;

        public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex) {
            NativeArray<Entity> entities = chunk.GetNativeArray(this.EntityTypeHandle);
            NativeArray<Timer<T>> timers = chunk.GetNativeArray(this.TimerTypeHandle);

            for (int i = 0; i < entities.Length; ++i) {
                Timer<T> timer = timers[i];

                timer.ElapsedTime += this.CurrentTimeInterval;

                if (timer.IsDone) {
                    int sortKey = firstEntityIndex + i;
                    this.CommandBuffer.RemoveComponent<Timer<T>>(sortKey, entities[i]);
                }

                timers[i] = timer;
            }
        }
    }
}

Now, if you want to extend the timer system – say, you want another one with a faster timescale, it will look like this:

public struct FastTimeScaleTag : IComponentData {
}

public class FastTimeScaleTimerSystem : TimerBaseSystem<FastTimeScaleTag> {
    protected override float TimeScale {
        get {
            return 2f;
        }
    }
}

We first create a new tag that we will then use as the type for the new timer system. Then inside the timer system, we override the TimeScale and set it higher (faster) than the default 1 inside the base class.

A caveat however, if you run this now, you will get an ArgumentException error. This is because in ECS, all ComponentTypes should be known during compile time. To remedy this you can create a separate file, say AssemblyInfo.cs and add the following:

[assembly: RegisterGenericComponentType(typeof(Timer<NormalTimeScaleTag>))]
[assembly: RegisterGenericComponentType(typeof(Timer<FastTimeScaleTag>))]

You can also add this in the TimerBaseSystem class right after declaring your using directives if that is more convenient for you.

To further make it easier to track all the timer systems, we can make a separate system group for all the timers. Then update our timer systems inside that group.

// Depending on your use case, you can choose when your timers should update
[UpdateBefore(typeof(EndSimulationEntityCommandBufferSystem))]
public class TimerSystemsGroup : ComponentSystemGroup {
}

[UpdateInGroup(typeof(TimerSystemsGroup))]
public class TimerBaseSystem<T> : SystemBase where T : struct, IComponentData {
// Rest of the timer system code
}

Now, we are almost set. We just need to add the timer tags to our entities. My use case for this timer is for how long an NPC should wait (be idle) before moving. That said adding the components for me would look something like:

// This will make the NPC wait for 3 seconds at a normal time scale.
// More or less 3 seconds in real life.
this.CommandBuffer.AddComponent(firstEntityIndex, npcEntity,
    new Timer<NormalTimeScaleTag>(3f)
);

// This will make the NPC move earlier than the one above with a
// faster timescale which is twice of the normal time scale
// which is about 1.5 seconds in real life.
this.CommandBuffer.AddComponent(firstEntityIndex, npcEntity,
    new Timer<FastTimeScaleTag>(3f)
);

To demonstrate this I made the following setup:

  • Two NPCs with different time scales (1f and 2f), but the same idle wait time of 3 seconds; and,
  • A MovementSystem that would move the two NPCs after waiting

And it looks something like this (note that timing might differ since I just captured this with a screen to gif tool):

Unity Pure ECS Generic Timer System Example
Don’t worry, they still met in the end and lived happily ever after. *wink*

And there you have it. For further improvement, I’m thinking of adding a query in the base system that the subclasses can override, so that other parts of the game can get the scaled time from any respective timer systems. I already got it working and if you want to read more about query systems, Marnel from Squeaky Wheel wrote a simple query system. He made a better version of that system that doesn’t involve boxing but I can’t seem to find a reference about it online, maybe soon.

If you have questions you can reach me via Twitter or Instagram – That’s all for now and see you in the next one!

References:

P.S. It took a lot longer for me to release this blog because of something great happening soon – Academia: School Simulator is releasing in just a couple of weeks and boy are we nervous in Squeaky Wheel. Please check it out on Steam and let us know what you think. Thank you again, have a good one, and stay safe!

Neil Creates: Dice Hunter

Master tactical dice battles! Enjoy the clever combination of skill and luck. Dice Hunter is a turn-based role playing game with collectible dice. Play now for FREE!
Become the Dicemancer and assume the incredible ability to capture creatures into dice. Hunt dice and wield them to save the Land of Chance from the marauding minions and evil allies of the wicked Snake Eyes. – Greener Grass, Dice Hunter: Quest of the Dicemancer Google Play Store Page

Start To Finish Video:

Part 1: Making the Dice

First off, I made the dices using Blender (which you can get on Steam now). I used the default cube that’s already on the scene upon startup. Then, I added a cylinder and duplicated it (in edit mode).

NC2_Blender_MakingCylinders

After that, I applied a Boolean modifier to the cube and set the object parameter to the cylinder that I’ve created in the previous step; Finally, I set the operation parameter to Difference. This way, Blender will ‘subtract’ the area of the cylinder that intersects with the cube and close the inside of the ‘holes’ made.

NC2_Blender_BooleanOperation
Before the operation

NC2_Blender_AfterOperation
After the operation

After that, you’ll notice that there were some ugly faces on the cube (in edit mode). This is because the boolean operation doesn’t take any consideration about triangles or quads. It’ll just perform the operation and connect the vertices of the main object and the ‘holes’ made during the operation.

NC2_Blender_Solved!

In order to fix this, I applied another modifier to the cube – Remesh. This modifier re-solves the mesh and figure out another way of distributing the vertices of that mesh. You can see it here, after applying the remesh modifier, I came up with a cube with these vertices:

NC2_Blender_RemeshedCube
Neat!

After that, in order to get rid of the sharp edges (real life dices doesn’t have those sharp edges. Well, not that I know of.), I applied another modifier – Yes, I love modifiers – to the mesh, a Subsurf modifier.

NC2_Blender_Subsurf

After that, you can add another modifier, a Decimate modifier, in order to reduce the number of vertices. Or, you can just reduce the number of subsurf steps. After making the cube, I exported it to a FBX file and imported it in Unity.

Part 2: Unity Setup

In Unity, I made a simple scene with a plane (for the ground) and six dices, just like in Dice Hunter.

NC2_Unity_Setup

Part 3: PROGRAMMING!!!

To start off, I added a RigidBody component to each of the die. This is because I want to make the dices react or have a realistic motion/physics. After that I made a variable referencing the RigidBody component and applied a force to the dices every time the left mouse button is pressed.


using UnityEngine;
public class DiceTossScript : MonoBehaviour {
private static float force = 150f;

private Rigidbody rb;

private void Start() {
 rb = GetComponent<Rigidbody>();
}

private void FixedUpdate() {
 if (Input.GetMouseButtonDown(0)) {
   rb.AddForce(Vector3.up * force);
 }
}
}

The reason why I used Vector3.up instead of transform.up is because, the latter one will change when the object rotates while the former is constantly pointing to the ‘up of the world’, the global up, whatever you call it, the up of everything.

After that I added another piece of code in the FixedUpdate function which will add a torque (or rotation force, if you will) to the cube which will make it rotate randomly.

private void FixedUpdate() {
if (Input.GetMouseButtonDown(0)) {
//This generates a random point to apply the torque
//This way, the dices will rotate randomly
var temp = new Vector3(Random.Range(-1f, 1f), 0f, Random.Range(-1f, 1f));

rb.AddForce(Vector3.up * force);
rb.AddTorque(temp * 1000f);
}
}

I also added a physics material that has a bounciness in it. Then, I set the friction to minimum in order to prevent the dices from ‘standing’ on their edges. This happens because of the friction between the edges and the ground which makes the dice fall super slowly, which does not happen in real life (well, maybe…).

Then for determining which face is up, I added triggers on each side of the die. The main logic I thought of is that, the trigger will check if it’s hitting the ground; if it does, the die will return the number of the opposite side.

NC2_Unity_

After that, I wrote a script that will be applied on each of these triggers with will perform the logic stated above.

using UnityEngine;

public class SideIndicator : MonoBehaviour {
private void OnTriggerStay(Collider other) {
if (other.transform.name == "Ground") {
var parent = transform.parent.GetComponent<DiceTossScript>();
var temp = int.Parse(transform.name);
DiceTossScript.combination[parent.diceIndex] = temp;
}
}
}

I also added a static array of integers in the DiceTossScript in order to hold the combination of the faces up. Just like in Dice Hunter, this can be used in order to determine how many ‘attack’ faces are up for combos and other power ups.

After that, I also added a diceIndex on each die which corresponds to an index in the array of integers. That is, die 1 is mapped to array[0], die 2 is mapped to array[1], and so on.

//Declaration of the int array and the diceIndex variables
public static int[] combination;
public int diceIndex = 0;

private void Start() {
rb = GetComponent<Rigidbody>();

//Initialization of the array that has six elements
//Each element corresponds to each dice
combination = new int[6];
}

Then, I noticed that there was unnecessary rotation in the y-axis when the dices land, which does not happen in Dice Hunter. This is fixed by multiplying the angularVelocity of the RigidBody to 0, which basically stops it, when the dices are already close to their initial y-position. I did this in the update function, you can also perform this checking in the LateUpdate function, if you want to.

private void Update() {
 if(transform.position.y &lt; 0.35f)
 rb.angularVelocity *= 0f;
}

And that’s it. Moving on from here, you can use the combination array in order to build more on a game mechanics.

Here are the final codes:

For the DiceTossScript.cs:

using UnityEngine;

public class DiceTossScript : MonoBehaviour {
private static float force = 150f;
public static int[] combination;

public int diceIndex = 0;
private Rigidbody rb;

private void Start() {
rb = GetComponent<Rigidbody>();
combination = new int[6];
}

private void Update() {
if(transform.position.y < 0.35f)
rb.angularVelocity *= 0f;
}

private void FixedUpdate() {
if (Input.GetMouseButtonDown(0)) {
var temp = new Vector3(Random.Range(-1f, 1f), 0f, Random.Range(-1f, 1f));rb.AddForce(Vector3.up * force);
rb.AddTorque(temp * 1000f);
}
}
}

 

And for the SideIndicator.cs:

using UnityEngine;

public class SideIndicator : MonoBehaviour {
  private void OnTriggerStay(Collider other) {
   if (other.transform.name == "Ground") {
    var parent = transform.parent.GetComponent<dicetossscript>();
    var temp = int.Parse(transform.name);
    DiceTossScript.combination[parent.diceIndex] = temp;
   }
  }
}

There you have it, I hope you enjoyed the tutorial. There were errors here and there and that is the beauty of learning – we make mistakes and we learn from them.

If you have comments, suggestions, recommendations, and questions, comment them down below and let’s have a healthy discussion.

Thank you and see you in the next one!

Neil Creates: Don’t Starve

Don’t Starve is an uncompromising wilderness survival game full of science and magic. Enter a strange and unexplored world full of strange creatures, dangers, and surprises. Gather resources to craft items and structures that match your survival style. – Klei EntertainmentDon’t Starve Steam Page

Part 1: Set Up

First off, I made the sprite sheet for the game first in order to have something to work with, using Photoshop.

Capture.PNG

As you might notice, I only used one sheet for both the player and the environment assets. I did this only for the sake of the tutorial. If you’re going to make a game, it’s a great practice to separate the static (mostly environment and props) sprites from those with animations (characters, effects, etc.).

Capture

After finishing up with the sheet on Photoshop. I made a separate PNG file which I will then manipulate in Unity. Now, Unity can actually read .psd files right off the bat. But, I kept the .psd file of my sheet separate from what I actually used in Unity (I also do this with FBX and .blend files when doing 3D). This may add another step in the pipeline and I can’t really say any benefits from doing this, but for me, it’s another great practice to backup and keep all ‘raw’ or original files separate from the one being used in the engine.

Capture.PNG

As for slicing the sheet, you can use Unity’s built-in sprite editor or use a 3rd party application, whichever you feel more comfortable working with (I used Unity’s built-in sprite editor). Then, you can automate this process and you can also slice manually, especially if you have a specific requirement with the sprites. Also, I kept the pivot points of the sprites in the middle – this is not usually the case, especially with characters that have different sprites for different parts of their body.

For example, you have a character which is composed of separate sprites (shoulder, arms, hands, etc.) and you will be applying inverse kinematics where the hand is the target from the shoulder. In a character’s arm, you don’t want the pivot of the shoulder to be in the middle of the sprite ‘cut’; this will make it difficult to manipulate, because the rotation of the shoulder will be relative to where the pivot is, in this case, the shoulder will rotate weirdly. Instead, you want the pivot to be where the shoulder joint is; this way, the shoulder will ‘naturally’ move. It’s important to keep requirements like this in mind when slicing up sprite sheets in order to avoid going back and making changes which will be a pain, especially if you’re already in the middle of production.

Capture

I then added an Animator component to the character; this will hold the parameters (that we will be accessing via code) which will determine which animation will be played (idle, walking, and attacking). For producing the animations, I used Unity’s animation tab to cycle through my sprites.

You can say that, Unity pretty much has it all *wink*.

Capture

In order to control the animations, I set up the parameters and the transition logic of the animations in Unity’s Animator tab. I used a float as a parameter to transition between the ‘idle’ and the ‘walk’ animations, which may not be the best option since you can use a boolean to determine if the character is moving or not. But, I suggest that you get used to using floats because you can have a walking animation and a running animation, which will be determined via the speed/velocity – which is mostly a float – of your character. Then for the attack, I used a boolean because the player can be ‘attacking’ or ‘not attacking’.

Part 2: Programming

As mentioned in the video, there are multiple ways of moving objects in Unity:

  • transform.Translate()
  • RigidBody (Forces, VelocityChange, and MovePosition mostly)
  • Character Controller
  • Unity’s NavMesh (I don’t think this is a good idea, in main characters, but GREAT WITH AI)
  • Changing the object’s Transform component via code (works sometimes, but not advisable)

For our player, I added a rigidBody component and moved the sprite around in 3D space via VelocityChange.

Here are the codes:

For the player,


using UnityEngine;
public class PlayerScript : MonoBehaviour {

[SerializeField] //These are used to make the variables show up in the inspector
private float moveSpeed;
[SerializeField]
private float hitDistance;
private float currentSpeed;
private Animator anim;
private Rigidbody rb;

private int woodCount = 0;

private float maxAttackSpeed = 1.2f, attackTimer = 0;

void Start () {
   anim = GetComponent<Animator>();
   rb = GetComponent<Rigidbody>();
}

private void Update() {
 if (Input.GetMouseButton(0)) {
  interact();
  anim.SetBool("isAttacking", true);
 } else {
  anim.SetBool("isAttacking", false);
 }
}

void FixedUpdate () {
 if (Input.GetButton("Horizontal")) {
  currentSpeed = Input.GetAxis("Horizontal") * moveSpeed * Time.deltaTime;

  if(currentSpeed < 0) {
   GetComponent<SpriteRenderer>().flipX = true;
  } else {
   GetComponent<SpriteRenderer>().flipX = false;
  }

  rb.AddForce(currentSpeed * transform.right, ForceMode.VelocityChange);
 }else if (Input.GetButton("Vertical")) {
  currentSpeed = Input.GetAxis("Vertical") * moveSpeed * Time.deltaTime;
  rb.AddForce(currentSpeed * transform.forward , ForceMode.VelocityChange);
 } else {
  anim.SetFloat("Speed", 0f);
  rb.velocity *= 0.5f;
 }

 if(currentSpeed != 0) {
  anim.SetFloat("Speed", rb.velocity.magnitude);
 }
}

private void interact() {
 RaycastHit hit;

 if(attackTimer > maxAttackSpeed) {
  if(Physics.Raycast(transform.position, Mathf.Sign(currentSpeed) * Vector3.right, out hit, hitDistance)) {
   if (hit.transform.CompareTag("Tree")) {
    woodCount++;
   }
  }

  attackTimer = 0;
 } else {
  attackTimer += Time.deltaTime;
 }
}
}

 

For the Camera,


using UnityEngine;

public class CameraFollowScript : MonoBehaviour {

private Transform player;
[SerializeField]
private float panSpeed;
[SerializeField]
private float height;
[SerializeField]
private float distance;

private RaycastHit hit;
private Ray rayFromCamera;

void Start () {
player = GameObject.FindGameObjectWithTag("Player").transform;
}

void Update () {
rayFromCamera = new Ray(transform.position, transform.forward);

if(Physics.Raycast(rayFromCamera, out hit, 3f)) {
if (!hit.transform.CompareTag("Player")) {
var obstacle = hit.transform.gameObject;
if (obstacle.GetComponent<SpriteRenderer>() != null) {
obstacle.AddComponent<ChangeAlpha>();
}
}
}

var newPosition = new Vector3(player.position.x, player.position.y + height, player.position.z - distance);
transform.position = Vector3.Lerp(transform.position, newPosition, panSpeed * Time.deltaTime);
}
}

For changing the alpha of the object between the camera and the player,


using UnityEngine;

public class ChangeAlpha : MonoBehaviour {

private SpriteRenderer currentSprite;

void Start() {
currentSprite = GetComponent<SpriteRenderer>();

var currentColor = currentSprite.color;
currentColor.a = 0.8f;

currentSprite.color = currentColor;
}

void Update() {
var currentColor = currentSprite.color;
currentColor.a = 1f;

currentSprite.color = currentColor;
Destroy(this);
}
}

There is a flaw in my logic here. You might have noticed that when you play the game, it the ChangeAlpha code works. But, it is not efficient – this is a wrong implementation, if I will be honest.

Why? Because, the script is CONTINUOUSLY adding and removing the script on the object that is between the camera and the player which consumes a lot of resources. This is also the reason why you can’t see the component in the inspector.

Short explanation: the ChangeAlpha script is being added to the object in the CameraFollowScript then it is being removed in the Update function (which runs every frame) in the ChangeAlpha script.

Having triggers behind the obstacles may be a better option. Triggers that detects if the player (tagged as “Player) is behind the object, then changing the alpha of the obstacle, if so.

There you have it, I hope you enjoyed the tutorial. There were errors here and there and that is the beauty of learning – we make mistakes and we learn from them.

If you have comments, suggestions, recommendations, and questions, comment them down below and let’s have a healthy discussion.

Thank you and see you in the next one!

I Made a Game: Leave My Base! (Part 2)

July 15-16, 2017 – Yeah….I didn’t sleep.

I woke up around 7AM to have my early coffee and read a book I had for a while now, The Finishers by Ezra Ferraz. It’s a book about Filipino entrepreneurs and founders. After preparing my mind for the day, I went on to my station and continued my work on the game.

I started where I left of the day before, the aiming and shooting system for the weapons (the ballista and the cannon). I spent about 3 or 4 hours improving this system because this will what the player will interact with in most of the gameplay.

I also realized that this is what makes making first-person games difficult – you need to make everything look and feel right, because the character BECOMES the player. If something is off, the whole immersion will be broken.

After that, I went back to Blender and design the units. As mentioned in the previous part of this post-mortem, I was planning on making the graphics like Superhot, and I’m also inspired by Final Fantasy 7’s Fort Condor Mission. With those in mind I designed the units along with the enemies.

Units_WP
This was the original scale of the bosses which I had trouble spawning in the game. As a solution, I scaled them down a bit.

After modeling the units and the enemies, I imported them to Unity and started writing the spawning scripts.

I didn’t really have any trouble here, thanks to Unity’s navigation system. I just needed to properly write the behavior of the enemies, make sure that they have the right reactions when needed. As for the player’s units, I just need them to spawn at the right location (where the player clicked), and instantiate with a NavMeshAgent component while properly placing themselves on the NavMesh in the scene. As for the unit’s behavior: when they spawn, they will roam around until they see an enemy in range, if that happens, engage the enemy.

I also didn’t have enough time to animate the units and the enemies, so I settled with make them ‘wiggle’ a little bit when attacking. I also added some particle effects when both the units and the enemies die to simulate blood, and also when the cannon balls hit the ground or a target, to simulate explosion.

For the finishing touches, I added Unity’s water standard asset where the enemies spawn to give the feeling that they are coming from “the void”.

For the tutorial and the quit button, I didn’t have any time to make a main menu to put the tutorial in, so I incorporated them in the game world just like in the Dead Space series.

Then, I worked on the audio. I composed a solemn tune with my guitar for the background music and then I used BFXR (I love this app) for the sound effects.

After that, I added some image (post processing) effects on the camera which yields these results:

I playtested the game a couple of times more then I packed everything up around 11 AM of July 16.

Then I submitted the game around 12 noon.

Which is wrong. My greatest mistake for this jam. I forgot that I started the jam almost around 3PM of July 14; that means, I’ll be hitting my 48-hour mark at 3PM of July 16; which means, I still have about 3 hours more to improve the game when I submitted it. Crap.

Conclusion and realization:

Take note when you start the jam and when you’ll hit your n-hour mark. Plan when you will be sleeping and plan what to eat ahead of time (I thrived on chips, packed rice and beef, and peanuts…lots of peanuts). Like always, the next one will be better.

 

Thank you for reading, here’s the first part of the post-mortem, and you can check the game out here (click on the image, it will open a new tab):

ForWebsiteGamePage

I Made a Game: Leave My Base! (Part 1)

Yey! Another game jam. This time, it’s the first ever game jam by Mark BrownGame Maker’s Toolkit Jam. It was a 48-hour game jam where your game must be made from scratch. That is, everything – art assets, hundreds (if not thousands) of lines of code, and sounds – must be made in or under 48 hours. The theme will be based on one of Mark’s videos which are mainly about innovations in video games and game design.

As for the start and end of the jam, Mark was lenient. He allowed the developers to start at 6PM, Friday, in their own respective timezones which means that you don’t need to stay up late in order to start at the same time with the rest of the world. That also means that your 48 hours will only start when it’s already 6PM in your timezone.

ForPostMorted
GMTK-Jam’s banner in the itch.io gamejam page

July 14, 2017

I woke up early to get the theme early and start right away but, Mark seemed to encountered some problem, he was sick the day before, which I think caused the delay. The jam page on itch.io has a countdown which told us (me and the other participants) that the theme will be announced around 1PM. This made me excited and all. But due to the delay, the theme was announced around 2:30PM which, I think, is just fine.

The theme was: Downwell’s Dual Purpose Design.

 

At first, I found it hard to think of something to do with the theme because I’ve never played Downwell before. I’ve been watching Stefanie Joosten’s playthrough of Final Fantasy 7 and I’ve been a huge fan of Monster Hunter since early high school. And, yes, that’s Stefanie Joosten or better known as Quiet from Metal Gear Solid V: The Phantom Pain. When Stef was playing the Fort Condor Mission in Final Fantasy 7, I thought, “this mini-game has always caught my attention ever since I was a kid, watching my brothers play and I can add that mechanic to my other favorite, Monster Hunter”. Then, I thought of how would that combination of mechanics fit into the theme – use only one button to do everything in the game.

I went with that idea and jumped on to Pinterest to look for inspiration and to further visualize my idea. After gathering enough images for my Pinterest board, I picked up my pencil and my sketchpad to try to “make the game on paper” (I have to take an image because my sketchpad doesn’t fit my scanner).

IMG_20170719_182659
Here’s the first draft of the game with check marks on the things that I implemented in the game with 2 which didn’t make the game due to time constraints

IMG_20170719_182715
Here’s my first draft of the battlefield which is very close to the final product in the game.

You can see that there are a lot of scribbles there and numbers; the scribbles are just me writing down what I’m thinking, it helps especially when I’m in the zone, it helps when you can see what you’re thinking. As for the numbers, majority there are just spawn coordinates, height and radius of the colliders, and some ratio and proportions of some stuff.

Writing down things really does help. For me, it cleared my head somehow, which allowed me to process other things – freeing up mental space, if you will.

Level Design. Usually, I start with a prototype of the core gameplay to see which works and which doesn’t but, this time I started with designing the level. I started with some basic assets like the floor and some blocks just to have a general ‘feel’ and size of the in-game environment. My target for the graphics was the same with Superhot. Simple. Lowpoly. Easy and quick to make. After finishing the floor for the game with the appropriate size, I went on to design the ammo containers which will play a major role in the game. I also designed the weapons to be used in the game – a pair of both ballista and cannon.

I also started with how the battlefield will look like (see sketch above). I made 2 paths to make the game quite difficult, and also a bridge between the paths to make the enemies travel farther and to make the player sort of predict where the enemies will go based on where they spawned.

This is how the game looked like. After designing the scene, I went on to programming the ballista. Well started to program, since I encountered some problems with collisions with the bullet and the ground. I really really want to make the bullets stick to whatever it hits, but I keep on seeing a problem in the future with the navmesh. I solved this by adding a separate trigger just before the ground, specifically, for the bullets (ballista ammo and cannonball).

With this, I went on to bed to have the only sleep I got for this jam, a 6-hour sleep.

Here’s the next one where I tackle how I made the enemies go from their spawn point to the gate of the base and attack the player’s units if they come in range. I also discussed some finishing touches for the game.

 

I Made a Game : Fyrelette (Part 2)

July 1, 2017

I woke up early to start with the first thing on my list – a working, playable prototype in, at most, 8 hours. It took me about 13 hours.

The main problem I had was the optimization of the game, especially during the prototyping stage, my laptop “blue screen”ed three times; because I was trying to randomly generate a tile map with a separate particle system for each tile.

Now to give you an idea on how messed up my system was; this was just during the prototyping phase. I didn’t have any sophisticated assets yet, I have a cube for the character and the enemy and a 1×1 (Unity unit) plane fore each tile. Still, my laptop couldn’t handle it.

I couldn’t think of any solution back then, so I just minimized the particles emitted by the particle system, removed the shadows of the particles, and removed the emission property of the particles. I’m left with a simple tile emitting a red square for the fire tiles and a dark purple square for the dark tiles. I settled with this and moved on.

After the writing the code for the tile map generator, I write the code for the player; it was just a simple character movement controller using Unity’s rigidbody instead of the character controller, because why not. Just kidding, because I need to simulate realistic physics collision and gravity. Also, I have two camera modes as of this stage, a 3rd person over-the-shoulder camera and a top-down view camera, because I was not sure yet what to do.

I didn’t really allotted a lot of time in the player controls because I know that I will have trouble with something else – artificial intelligence.

AISS

Honestly, I’m not really good with artificial intelligence. I like reading about AI, but there is something about writing it that just throws me off. You can see that the picture above is the only thing I wrote when I was planning how the AI of the enemies will work; the rest I just implemented as I go through writing the AI. Also, the check marks on the images are just made by me when I finished a certain part of the plan and yes, I still haven’t done any player and enemy data (health, experience, damage, etc.) when I reached this point in development.

The first thing I did with the AI was to figure out how the enemy will stay within the bounds of the tile map that was generated when the game started. I fixed this by randomly generating a Vector3 position using the bound of the tile map generator, which I called xTile and yTile. Meaning I just generate a random position from 0 to the maximum tile in the map, both for x- and y- axes. It was a simple implementation and it worked, it also solved the problem I had with how will the enemy go around the map in order to turn the tiles into dark tiles because I was aiming a Splatoon-like gameplay.

The next thing was to make the enemy chase the player. I implemented this in two ways: the enemy will chase the player if the player is in a certain range from the enemy, and the enemy will chase the player if the player was away from the enemy in a certain amount of time. The first one was implemented by Raycasting from the enemy to the player and if the distance of that ray is less than or equal to a certain number, the enemy will start chasing the player. The second one was implemented by writing a timer for each enemy, then, if the timer reaches zero, the enemy will chase the player, then it will reset after a certain amount of time chasing the player.

Applying the functionalities above pretty much built up the artificial intelligence I need for the enemy, but, I also added a functionality on the enemies – I made them jump. This again is random, I was planning to remove this before final build but, as I tested the game, I noticed that the jumping made the enemies look cute, so I kept the jumping motion of the enemies.

After the artificial intelligence I moved to planning how the pointing system will work and how bonuses will work, basically I planned how the win-lose system will work.

winLoseSS

pointSystemSS

After planning these, I began to write the data class.

dataSS

Now, a lot of these changed as I continue to iterate. That’s the beauty of developing a game, the plans are just there to give you something to start with, but most often if not always, you will end up with something far, in one way or another, from the plan.

This day was pretty much focused on just prototyping how things will work, at the end of the day, I ended up with something like this:

build01build02

July 2, 2017

This day I was planning on finishing the data class, implement it, add a save/load functionality, and start with the graphics for the game.

Making a data class was not a problem for me, it’s just a singleton that will persist through the scenes and it’s only consists of variables and properties. The problem I encountered during this stage was THE FREAKING SAVE/LOAD FUNCTIONALITY ISN’T WORKING. I reviewed the past lessons I read about the topic and still couldn’t get it to work. The save functionality was solved pretty quickly, but I could not get the loading functionality work. Then I realized (this may sound funny), about 2 hours in, that I wasn’t saving the loaded information properly to the variables of to the instance of the singleton. That was a noob mistake and I laughed and facepalm’ed myself.

After messing around with the data for the win-lose system, I jumped to Blender and Photoshop to make the assets for the game.

UISS

I started with the blocking where the UI elements will sit on the screen. At this time I still don’t have an art for the main character but, from my Pinterest board, I have a ‘general’ feel in mind, so I jumped to Blender and started modelling the main character and the enemies; and ended up with these:

This days was focused more on aesthetic design and at the end of the day I ended up with this:

July 3, 2017

This day was full of balancing, modifying some of the UI elements, adding post-processing effects for the ‘high’ quality option, and not staying in front of my laptop for pretty much the whole day.

I submitted the game 10 minutes and 13 seconds before the submission deadline,

deadline

Conclusion and realizations:

This jam was fun. Quite challenging but I got through it with proper time management. That is, breaking down the game into small pieces as I can then prioritizing which task will come first. Like most games and developers out there, the next one will be better.

I’ll join the next one for sure! 🙂

Thank you for reading, you can play the game here:

https://itch.io/embed/155801

I Made a Game : Fyrelette (Part 1)

72 Hours. Total of 6 hours of sleep. 3 days of designing, programming, chocolates, and coffee. Hear my story of when I joined TairaGames‘s Dev Squad Jam from June 30, 2017 to July 3, 2017.

TairaGames banner in the itch.io gamejam page

June 30, 2017

The game jam started around 8:00 PM (GMT+8). I didn’t start right away with programming or asset design because I wasn’t at home when the jam started. I was about 2-3 hours late. Instead, I started with game design on my way home and for the next couple of hours after I arrived home.

The rules for the jam are simple: “your game need to conform with the given theme and your game should use two items which will be announced at the start of the jam”. The theme was “Darkness” and the items were “fire” and “map”.

The first thing that came to my mind when I first read this was a survival game or a walking simulator; because of two things. They are both relatively easy to make, I could just make a first person game, design a map or area to walk around (a house, maybe), then write a compelling story and compose a emotionally-striking music; and survival and walking simulator games doesn’t really require a complicated gameplay mechanics. Don’t get me wrong, I love these genres, but, I feel like challenging myself a little more.

RuunerSS.PNG

Another idea came to me, an endless runner. Now, I have an endless runner in my portfolio and I believe that I can make one that might be better than my last. Endless runners are common, people love it; there’s a big replay value for this genre; the mechanics are quite easy; the only problem that I saw was I need to make the artwork and soundtrack of the game, to very compelling in order to compensate for the repetitive gameplay. Or, add another mechanic that will compliment the general endless runner mechanic.

I played around with these ideas for a while then I stumbled into the idea of  the “darkness taking over light” cliche…and Splatoon.

SplatoonSS

As first I wanted to modify the “occupy as much of the map as you can” mechanic of Splatoon by making it a tile-based-turn-based game with 3-dimensional isometric cell-shaded art style. That didn’t sound bad, especially if I add the dice mechanics of the mobile that I was hooked on, Dice Hunter: Quest of the Dicemancer. Each dice has an action which the player can choose during his turn. In each turn, the player ‘tosses’ the dices then the actions (move, defend, attack, cast magic, use an item, dance, etc.) on the ‘board’ are the only actions that the player can perform during his turn. Then, each tile on the map that the player steps on will be ‘his’. The same goes for the enemy, whether AI or human.

Again, I played around with this idea for a while in my head. But, I couldn’t make out the algorithm for the 3D dices. I thought of making the dices rigid (rigidBody in Unity), then just add a force when the player ‘tosses’ the dices, but, I wanted a more code-based approach, and I failed. I can just print the actions in a button or something 2D on the screen but, that will not be as immersive as an ‘actual’ 3D spinning on the screen.

CombinedSS.PNG

My last idea was my last hope. I stayed with the “occupy as much of the map as you can” mechanic of Splatoon and I added a different approach. At the time of writing this blog, the game Nex Machina is gaining popularity. It is an “intense arcade style twin-stick shooter” by Housemarque. I like the top-down or isometric camera angle in games because you can hide some areas in your map, if you restrict the player from rotating the camera; and I grew up playing different shooter games.

I started with sketching how the game would work using Paint. I drew various camera angles (above), some key core components of the game, mechanics to incorporate in the game, some win-lose criteria, and drew random artworks that I might use. I also browsed Pinterest to look for more inspiration in the general look and feel of the game, character designs, and environment/map design. Here’s the Pinterest board I made for this jam.

I was happy with my progress so far; I pretty much designed about a third of the game on paper and in my mind when I woke up for the next day. I plotted the things that I will do regarding the jam for the next couple of days and went to bed.

Thank you for reading, click here for the next one where I tackled writing the AI, the core game mechanics, and making the art assets for the game.

Hospital Management System

This Hospital Management System was a final requirement for our Object Oriented Class (Java).

I used Hibernate in order to connect Java with H2 (my preferred database) and I used JavaFX and Scenebuilder for the user interface.

It features various account or user types with specific privileges:

User Privileges:

-Admin:Can access all tabs

-Doctor:Can’t access User

-Nurse:Can’t access User and Doctor

-Housekeeping:Can’t access Patient, Doctor, Staff, and User

Here are the screenshots of the application.

This is the login screen of the program.

13350306_1126035434085474_3257653503589023992_o


1. Patients Tab

– where the user can add patients, edit and view patient information, and discharge patients

 


2. Doctor Tab

– where the user can add doctors, edit and view doctors information, and delete doctors

13320630_1126035727418778_567313839652654151_o


3. Staff Tab

– where the user can add Staff, edit and view Staff information, and delete Staff

13323627_1126035857418765_2525646109504329227_o


4. Rooms Tab

– where the user can add Rooms, edit and view Rooms information, and delete Rooms

13346360_1126035987418752_6421043073698120331_o


5. Users Tab

– this tab is only accessible by the admin, and here, the admin can add users of various types, view their information, and delete users.

13329393_1126036147418736_233038262210719090_o