Building levels

The chunk creator is at a place that it’s usable, and though there are a lot of nice-to-have features that I will probably add in the coming days, it works to build and view levels.

Here’s one such level:

Chunk in creator

I will also be returning to Hex briefly, since in order to submit it to #1GAM it needs an icon, and it currently doesn’t have one.

 

Wrapping things up

I’m rapidly approaching the end of the line for Hex. I added a menu screen, and I’m in the process of adding some rudimentary particles.

After the particles go in, all that’s left for February is to add some instructions, and to add some animations for actions. Then I’ll move on. Maybe I’ll come back to Hex in the future, but for now, I’m ready for a new challenge.

As always, the latest build of Hex can be found here.

 

Things I’ve done (and left undone)

I’ve decided against having the units’ health bars fade in and out. It’s not a technical limitation so much as a look and feel one. It felt clunky and weird, so I removed it and decided to keep it out of MVP+ (if not the game). I did rework the win UX, though not by much.

I have 4 issues left open that I want to address before the end of February, and then I’ll be moving on to my next game: Gravity Runner.

 

A little spring in their step

The units now float! I tried to bake in some randomness to their speed so they wouldn’t all be synced up, but I didn’t have any luck with that (I’ve been adjusting the step size on Vector3.MoveTowards()). As always the latest has been posted over here.

Edit: just kidding, I figured out how to make them bounce at (very slightly) different speeds! Latest has been posted to GitHub and uploaded to the site.

 

No more teleportation

Units no longer magically appear on the cell they move to. Now they’ll move smoothly (if a bit slowly) to their destination.

Unity has kind of interesting way to do asynchronous waiting that I think is worth talking about. Unity has a method called StartCoroutine() which allows you to pass in a method as a parameter (provided that it meets certain protocols) and it will run on another thread. I don’t think that it blocks the current thread, which would lead to some race conditions, but if your logical representation of the board/map is not entirely dependent on things like whether or not a piece is in motion, then you should be okay.

 

Move logging

Game logging is now live! While this doesn’t mean much for the front end yet, it will allow me to implement undo functionality, as well as be useful for notating the game (should it ever get to a point where that’s an interesting feature to have). You can check out the changes that went into this feature here.

 

A free(ish) camera

I’ve just uploaded my latest version of Hex, delivering on my promise to free the camera. Sort of. I decided since there isn’t a whole lot to see in the game world, it didn’t make sense to have a totally free camera. Instead, I opted for a camera that runs on a track, and can zoom in and out. It also always stares at the middle of the board. It can’t zoom in and out forever, since there’s not a lot to see, but it can spin forever, which can be fun. The CameraController script (shown below), relies on input from the arrow keys to control the camera. Feel free to use it for non-commercial purposes, but let me know if you do, because I’d love to hear about it!

As a disclaimer, for whatever reason, the camera is very choppy on the web player, but it isn’t on my machine. I’ve opened issue #29 to track this.

 

//-----------------------------------------------------------------------
// <copyright file="CameraController.cs" company="Pete Biencourt">
//     Copyright (c) Pete Biencourt. All rights reserved.
// </copyright>
// <author>Pete Biencourt</author>
//-----------------------------------------------------------------------

namespace HexGame
{
    using UnityEngine;

    /// <summary>
    /// Camera controller
    /// </summary>
    public class CameraController : MonoBehaviour
    {
        /// <summary>
        /// Track radius
        /// </summary>
        public float TrackRadius = 7.5f;

        /// <summary>
        /// Rotation step size
        /// </summary>
        public float RotationStepSize = 0.05f;

        /// <summary>
        /// Zoom step size
        /// </summary>
        public float ZoomStepSize = 0.1f;

        /// <summary>
        /// Minimum camera height
        /// </summary>
        public float MinYValue = 2f;

        /// <summary>
        /// Maximum camera height
        /// </summary>
        public float MaxYValue = 10f;

        /// <summary>
        /// Tracks the value of the radian parameter for the camera's track
        /// </summary>
        private float parameterValue;

        /// <summary>
        /// Starts the camera
        /// </summary>
        void Start()
        {
            this.parameterValue = 0f;
            this.UpdateParameterAndGetNewPosition(0f);
        }

        /// <summary>
        /// Updates the camera
        /// </summary>
        public void Update()
        {
            if (Input.GetKey(KeyCode.RightArrow))
            {
                this.UpdateParameterAndGetNewPosition(this.RotationStepSize);
            }

            if (Input.GetKey(KeyCode.LeftArrow))
            {
                this.UpdateParameterAndGetNewPosition((-1) * this.RotationStepSize);
            }

            if (Input.GetKey(KeyCode.UpArrow) && !Input.GetKey(KeyCode.DownArrow))
            {
                this.Zoom((-1) * this.ZoomStepSize);
            }

            if (!Input.GetKey(KeyCode.UpArrow) && Input.GetKey(KeyCode.DownArrow))
            {
                this.Zoom(this.ZoomStepSize);
            }

            Camera.main.transform.LookAt(new Vector3(0f, 0f, 0f));
        }

        /// <summary>
        /// Handles keeping the camera on its track
        /// </summary>
        /// <param name="parameterDelta">How much to move it by</param>
        private void UpdateParameterAndGetNewPosition(float parameterDelta)
        {
            this.parameterValue += parameterDelta;
            Vector3 pos = Camera.main.transform.position;
            pos.z = (-1) * this.TrackRadius * Mathf.Cos(this.parameterValue);
            pos.x = (-1) * this.TrackRadius * Mathf.Sin(this.parameterValue);
            Camera.main.transform.position = pos;
        }

        /// <summary>
        /// Zooms the camera in or out
        /// </summary>
        /// <param name="zoomDelta">How much to zoom</param>
        private void Zoom(float zoomDelta)
        {
            Vector3 pos = Camera.main.transform.position;
            pos.y += zoomDelta;
            if (pos.y < this.MinYValue)
            {
                pos.y = this.MinYValue;
            }
            if (pos.y > this.MaxYValue)
            {
                pos.y = this.MaxYValue;
            }
            Camera.main.transform.position = pos;
        }
    }
}