Hive is coming to Steam! Pre-order now for 30% off!

We are downright giddy to announce… Hive is coming to Steam! It’ll be the same great game as on Xbox, but will have a few extra bonuses:

  • Game will track over 40 stats on Steam and you can earn 30+ Steam Achievements.
  • There will be 2 new levels of AI. Since even low-end PCs are typically a lot more powerful than Xbox 360s (because those are now quite old) this gives an opportunity to have the AI make much, much better moves in the same amount of thinking-time.
  • Seamlessly switch between using your mouse/keyboard or playing with a gamepad.

The first release will be on PC, but we hope to release it on both Mac and Linux soon afterward. Buying the game means you’ll get a Steam key once the game is released. This will allow you to play on any/all of the platforms once each platform is available (eg: if you buy now, you can play on PC as soon as that’s released and you do not have to re-buy it to play on Mac when the Mac version comes out).

To give a better deal to our loyal fans, we’re offering a 30% discount on pre-orders! Get it below using the Humble Widget (powered by the “Humble Bundle” team):

If you can’t see the widget above, you can click this link to pre-order Hive. Have an old computer? If you’re worried about compatibility, please check the minimum requirements on the Steam Store page (scroll down a bit or search for ‘System Requirements’).

UPDATE: You can now buy this game on Steam ‘Early Access’ which will let you play the incomplete beta immediately, and you will automatically be upgraded to the full version once it is released. Please click ‘add to card’ on the Hive page on Steam.

Like being kept in the loop? Join the mailing list to keep up with our announcements:

Join our mailing list to receive announcements
E-mail address:
 

Konami Code in XNA – for Windows, Xbox, and Windows Phone (WP7)

The Konami Code is a fun part of gaming culture and a very common method for adding Easter Eggs to games. After more than a year of work on Hive, I started thinking how absurd it was that we don’t have any Easter Eggs yet. When I went to look for a module for the Konami Code in XNA (because: how could there NOT be one?!), I found that the only solution currently out there seemed to be Charles Cox’s Konami Code for WP7.

At the time of this writing, BlueLine doesn’t make any WP7 games though: just Xbox 360 games that we hope to release to PC soon. To avoid completely reinventing the wheel, and to make sure my solution would be backward compatible to anyone already using Charles Cox’s module for WP7, I decided to just piggyback on that code. I’ll send my code back to him too, so hopefully he can add it to the version on his site. I’ll also structure this post to be very similar to his post so it can be merged more easily.

The solution is a single class file that you can drop into any XNA project, and by adding a small snippet of code to your update routine, you can have Konami Code functionality in minutes.

C# – KonamiCode.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
#if WINDOWS_PHONE
using Microsoft.Xna.Framework.Input.Touch;
#endif
using Microsoft.Xna.Framework.Media;

namespace KonamiCodeXna
{

    // A delegate type that represents the code has either been entered right or wrong
    public delegate void CodeEnteredEventHandler(object sender, KonamiCodeEventArgs e);

    public class KonamiCodeEventArgs : EventArgs
    {
        /// <summary>
        /// The player index that entered the code.
        /// WARNING: This can be null (eg: on WP7, or when the code was entered using the keyboard).
        /// </summary>
        public PlayerIndex? PlayerIndex { get; private set; }

        public KonamiCodeEventArgs(PlayerIndex? playerIndex)
            :base()
        {
            this.PlayerIndex = playerIndex;
        }
    }

    /// <summary>
    /// Class for easily using the KonamiCode in XNA apps (Windows, Windows Phone, and Xbox).
    /// 
    /// Originally written for Windows Phone 7 by Charles N. Cox.
    /// Expanded to work on Xbox and Windows by Sean Colombo.
    /// </summary>
    public class KonamiCode
    {
        public event CodeEnteredEventHandler CodeEnteredRight;
        public event CodeEnteredEventHandler CodeEnteredWrong;

        // Track the progress by each PlayerIndex. If playerIndex is irrelevant, just key off of "null" instead.
        private Dictionary<PlayerIndex, int> numCorrectByPlayerIndex;
        private int numCorrectKeyboard;

        // To be able to tell when buttons are pressed/released, these vars will keep track of state from previous tick.
        private Dictionary<PlayerIndex, GamePadState> previousGamePadStateByPlayerIndex;
        private KeyboardState previousKeyState;

        public KonamiCode()
        {
            numCorrectKeyboard = 0;
            numCorrectByPlayerIndex = new Dictionary<PlayerIndex, int>();
            previousGamePadStateByPlayerIndex = new Dictionary<PlayerIndex, GamePadState>();
        }

#if WINDOWS_PHONE
        enum DirType
        {
            DirTypeUp,
            DirTypeDown,
            DirTypeLeft,
            DirTypeRight
        };

        private DirType[] correctSequence = new DirType[8] {
            DirType.DirTypeUp,
            DirType.DirTypeUp,
            DirType.DirTypeDown,
            DirType.DirTypeDown,
            DirType.DirTypeLeft,
            DirType.DirTypeRight,
            DirType.DirTypeLeft,
            DirType.DirTypeRight };

        public void checkGesture(GestureSample gs)
        {
            bool rightCode = true;
 
            switch(correctSequence[numCorrect])
            {
                case DirType.DirTypeUp:
                    if (gs.Delta.Y > 0 || (Math.Abs(gs.Delta.Y) < Math.Abs(gs.Delta.X)))
                        rightCode = false;
                    break;
                case DirType.DirTypeDown:
                    if (gs.Delta.Y < 0 || (Math.Abs(gs.Delta.Y) < Math.Abs(gs.Delta.X)))
                         rightCode = false;
                    break;
                case DirType.DirTypeRight:
                    if (gs.Delta.X < 0 || (Math.Abs(gs.Delta.Y) > Math.Abs(gs.Delta.X)))
                        rightCode = false;
                    break;
                case DirType.DirTypeLeft:
                    if (gs.Delta.X > 0 || (Math.Abs(gs.Delta.Y) > Math.Abs(gs.Delta.X)))
                        rightCode = false;
                    break;
            }

            this.RecordSuccessByPlayerIndex(rightCode, null);
        }
#else
        private Keys[] correctKeySequence = new Keys[]{ // for the keyboard
            Keys.Up,
            Keys.Up,
            Keys.Down,
            Keys.Down,
            Keys.Left,
            Keys.Right,
            Keys.Left,
            Keys.Right,
            Keys.B,
            Keys.A
        };

        private Buttons[] correctButtonSequence = new Buttons[]{ // for gamepads
            Buttons.DPadUp,
            Buttons.DPadUp,
            Buttons.DPadDown,
            Buttons.DPadDown,
            Buttons.DPadLeft,
            Buttons.DPadRight,
            Buttons.DPadLeft,
            Buttons.DPadRight,
            Buttons.B,
            Buttons.A,
        };
        private List<Buttons> buttonsToCheck; // which buttons to check for being up/down each tick. For performance reasons, we'll only check the buttons that are part of the sequence.

        /// <summary>
        /// Should be called once each update loop when listening for the code.
        /// </summary>
        public void checkKeyboard()
        {
            bool rightCode = false;
            KeyboardState keyboardState = Keyboard.GetState();

            // Only evaluate the state if SOMETHING was pressed (we only care about the sequence, not that they're IMMEDIATELY after each other).
            if (WasAnyKeyPressed(keyboardState))
            {
                if (WasKeyPressed(correctKeySequence[numCorrectKeyboard], keyboardState))
                {
                    rightCode = true;
                }

                this.RecordSuccessByPlayerIndex(rightCode, null);
            }

            previousKeyState = keyboardState;
        }

        /// <summary>
        /// Should be called once each update loop when listening for the code, for each playerINdex
        /// that is being listened to (will track their progress separately so that their keypresses
        /// don't interfere with each other).
        /// </summary>
        /// <param name="playerIndex"></param>
        public void checkPlayerIndex(PlayerIndex playerIndex)
        {
            bool rightCode = false;

            int numCorrectSoFar = 0; // the number-correct-so-far corresponds to the index in the sequence that should be expected
            if (numCorrectByPlayerIndex.ContainsKey(playerIndex))
            {
                numCorrectSoFar = numCorrectByPlayerIndex[playerIndex];
            }

            // This is called once per tick, then re-used by the other functions below.
            GamePadState currentGamePadState = GamePad.GetState(playerIndex);

            // Only evaluate the state if SOMETHING was pressed (we only care about the sequence, not that they're IMMEDIATELY after each other).
            if (IsAnyButtonPressed(playerIndex, currentGamePadState))
            {
                if (WasButtonPressed(correctButtonSequence[numCorrectSoFar], playerIndex, currentGamePadState))
                {
                    rightCode = true;
                }

                this.RecordSuccessByPlayerIndex(rightCode, playerIndex);
            }

            previousGamePadStateByPlayerIndex[playerIndex] = currentGamePadState;
        }

        /// <summary>
        /// Returns true if any key is currently pressed down, false otherwise.
        /// 
        /// If a user presses a key and holds it down, this method will return
        /// true every time it's called while that key is held down.
        /// </summary>
        /// <returns></returns>
        //public bool IsAnyKeyDown(KeyboardState keyboardState)
        //{
        //    Keys[] keys = keyboardState.GetPressedKeys();

        //    // Some systems return an empty array when nothing is pressed, some return one item containing Keys.None
        //    bool nothingPressed = ((keys.Length == 0) || ((keys.Length == 1) && (keys[0] == Keys.None)));
        //    return (!nothingPressed);
        //}

        /// <summary>
        /// Returns true if any key was JUST pressed, false otherwise.
        /// 
        /// This means that if a key is pressed and held down, the first
        /// tick will return true and subsequent ticks will return false even while
        /// the key is still being held down.
        /// </summary>
        /// <returns></returns>
        public bool WasAnyKeyPressed(KeyboardState keyboardState)
        {
            Keys[] keys = keyboardState.GetPressedKeys();

            bool somethingNewIsPressed = false;

            // Some systems return an empty array when nothing is pressed, some return one item containing Keys.None
            bool nothingPressed = ((keys.Length == 0) || ((keys.Length == 1) && (keys[0] == Keys.None)));
            if (!nothingPressed)
            {
                IEnumerable<Keys> newlyPressed = keys.Except(previousKeyState.GetPressedKeys()); // ignore keys that were already down on the previous tick.
                somethingNewIsPressed = (newlyPressed.Count() > 0);
            }

            return somethingNewIsPressed;
        }

        private bool WasKeyPressed(Keys keyToCheck, KeyboardState keyboardState)
        {
            return (previousKeyState.IsKeyUp(keyToCheck) && keyboardState.IsKeyDown(keyToCheck));
        }

        /// <summary>
        /// Returns true if any of the buttons RELEVANT TO THE KONAMI CODE were pressed. For performance, does not
        /// check all buttons each tick, just checks the buttons that appear in the correctButtonSequence.
        /// </summary>
        /// <param name="playerIndex"></param>
        /// <param name="currentGamePadState"></param>
        /// <returns></returns>
        private bool IsAnyButtonPressed(PlayerIndex playerIndex, GamePadState currentGamePadState)
        {
            bool somethingPressed = false;

            if (buttonsToCheck == null)
            {
                // Not all users will have my (Sean's) Set<> class, so abuse a Dictionary instead.
                Dictionary<Buttons, bool> buttonSet = new Dictionary<Buttons, bool>();
                foreach (Buttons button in correctButtonSequence)
                {
                    buttonSet[button] = false; // the bool is trash basically. this is just a cheap way to implement a set.
                }
                buttonsToCheck = buttonSet.Keys.ToList();
            }

            foreach (Buttons button in buttonsToCheck)
            {
                somethingPressed = (somethingPressed || WasButtonPressed(button, playerIndex, currentGamePadState));

                if (somethingPressed)
                {
                    break;
                }
            }

            return somethingPressed;
        }

        private bool WasButtonPressed(Buttons button, PlayerIndex playerIndex, GamePadState currentGamePadState)
        {
            bool wasPressed;
            if(previousGamePadStateByPlayerIndex.ContainsKey(playerIndex)){
                wasPressed = (previousGamePadStateByPlayerIndex[playerIndex].IsButtonUp(button) && currentGamePadState.IsButtonDown(button));
            } else {
                wasPressed = currentGamePadState.IsButtonDown(button);
            }
            return wasPressed;
        }
#endif

        /// <summary>
        /// Records a successful/unsuccessful keypress by PlayerIndex. In cases where the
        /// PlayerIndex is irrelevant (often, on WP7 there is only one player), then null
        /// can be used.
        /// 
        /// NOTE: This method is typically called from other helpers such as checkGesture
        /// and checkGamePadHelper instead of being called directly.
        /// </summary>
        /// <param name="rightCode"></param>
        /// <param name="playerIndex"></param>
        public void RecordSuccessByPlayerIndex(bool rightCode, PlayerIndex? playerIndex)
        {
            if (rightCode)
            {
                // PlayerIndex is null for keyboard and non-null for game pads.
                if (playerIndex == null)
                {
                    numCorrectKeyboard++;
                    if(numCorrectKeyboard >= correctKeySequence.Length)
                    {
                        //reset the code, fire the event
                        numCorrectKeyboard = 0;
                        KonamiCodeEventArgs args = new KonamiCodeEventArgs(playerIndex);
                        CodeEnteredRight.Invoke(this, args);
                    }
                }
                else
                {
                    if (numCorrectByPlayerIndex.ContainsKey((PlayerIndex)playerIndex))
                    {
                        numCorrectByPlayerIndex[(PlayerIndex)playerIndex]++;
                    }
                    else
                    {
                        numCorrectByPlayerIndex[(PlayerIndex)playerIndex] = 1;
                    }

                    if (numCorrectByPlayerIndex[(PlayerIndex)playerIndex] >= correctButtonSequence.Length)
                    {
                        //reset the code, fire the event
                        numCorrectByPlayerIndex[(PlayerIndex)playerIndex] = 0;
                        KonamiCodeEventArgs args = new KonamiCodeEventArgs(playerIndex);
                        CodeEnteredRight.Invoke(this, args);
                    }
                }
            }
            else
            {
                //wrong type, reset the count, send event
                if (playerIndex == null)
                {
                    numCorrectKeyboard = 0;
                }
                else
                {
                    numCorrectByPlayerIndex[(PlayerIndex)playerIndex] = 0;
                }
                KonamiCodeEventArgs args = new KonamiCodeEventArgs(playerIndex);
                CodeEnteredWrong.Invoke(this, args);
            }
        }

    }
}

To Use the Class

It’s really just three things:

  1. Instantiate a KonamiCode object.
  2. Subscribe to the CodeEnteredRight event (and, if you want, the CodeEnteredWrong event)
  3. Update it once, each game-tick (ie: in Update()).

Getting it Into a Default Project

To mirror the example given in Charles’ original post, I’ll show how to use this module in an example project to have the same outcome that his original code did, but have it also work on Windows and Xbox 360 (in addition to WP7).

Game1

//**Start Code For This Sample - REPLACE YOUR GAME1 CONSTRUCTOR WITH THIS
KonamiCode konami = new KonamiCode();
Color clearColor = Color.CornflowerBlue;
 
public Game1()
{
    graphics = new GraphicsDeviceManager(this);
    Content.RootDirectory = "Content";
 
    // Frame rate is 30 fps by default for Windows Phone.
    TargetElapsedTime = TimeSpan.FromTicks(333333);
 
    konami.CodeEnteredRight += new CodeEnteredEventHandler(konami_CodeEnteredRight);
    konami.CodeEnteredWrong += new CodeEnteredEventHandler(konami_CodeEnteredWrong);
 
    TouchPanel.EnabledGestures = GestureType.Flick;
 
}
 
void konami_CodeEnteredWrong(object sender, EventArgs e)
{
    clearColor = Color.Tomato;
}
 
void konami_CodeEnteredRight(object sender, EventArgs e)
{
    clearColor = Color.MediumSeaGreen;
}
//**End Code For This Sample

Update

//**Start Code For This Sample - REPLACE YOUR UPDATE LOOP WITH THIS
protected override void Update(GameTime gameTime)
{
    // Allows the game to exit
    if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
        this.Exit();
 
    #region Konami code updating
#if WINDOWS_PHONE
	while (TouchPanel.IsGestureAvailable)
	{
		GestureSample gs = TouchPanel.ReadGesture();
		konamiCode.checkGesture(gs);
	}
#else // WINDOWS || XBOX
	// Need to check the code for each game pad that's in-use.
	foreach (PlayerIndex playerIndex in new PlayerIndex[] { PlayerIndex.One, PlayerIndex.Two, PlayerIndex.Three, PlayerIndex.Four })
	{
		if (GamePad.GetState(playerIndex).IsConnected)
		{
			konamiCode.checkPlayerIndex(playerIndex);
		}
	}

	// Then check the code for the keyboard (if there is one, there will be just one so it's checked separately, not per-player).
	konamiCode.checkKeyboard();
#endif
	#endregion

    base.Update(gameTime);
}
//**End Code For This Sample

Draw

//**Start Code For This Sample - REPLACE YOUR DRAW METHOD WITH THIS
protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(clearColor);
 
    // TODO: Add your drawing code here
 
    base.Draw(gameTime);
}
//**End Code For This Sample

If you run into any issues, please let us know.

Games using this Konami code class

If you put this into a game, let us know when it’s out! We’ll add it to this list of XNA games that have Konami Code built in, using this class.

Hive for Xbox starting Alpha Testing!

Something's not right about the placement of that cursor... good thing we're doing an Alpha test!


Development has been cruising right along on Hive. While we’re still a few months away from a final version, we’ve gotten to the point that the game is playable as local multiplayer “pass-n-play” (where you share the same controller).

Obviously that’s very limited functionality, but it’s a very important milestone. Right now, players can start to hammer on the game to make sure the rules are exactly as expected and that the controls feel right.

We know there are a lot of die-hard Hive fans out there, and we’d love to have your feedback while we continue to develop the game so that we can make sure to do justice to the boardgame.

That’s why we’re starting a private Alpha Test and asking anyone interested to apply!


Hive Alpha Test

Here is some more info:

  • You need an Xbox-controller with a cord and a PC with .NET installed.*
  • You’ll get a download-link and will be notified when new versions of the alpha are available to download (probably every couple of weeks).
  • You will be invited to a private Alpha Test forum, where you can leave as much feedback as you want and discuss things with us as well as the other testers.
  • The PC Alpha-test version of the game will expire in a few months since we don’t have rights to distribute the game on PC (we got special permission for this Alpha Test).
  • We’ll need your email address. We will only email you about things relating to the Alpha test.**
  • Your name (or alias, if you prefer) will appear in the credits of the game.

Apply for the Private Alpha

If you’d like to be part of the Alpha, please do one (or more) of the following:
UPDATE: PLEASE NOTE THAT THE ALPHA IS OVER. THE GAME IS NOW AVAILABLE ON XBOX 360 AND ON STEAM!

  • Tweet that you’d like to be in the alpha (here is a pre-assembled tweet!), and follow @BlueLineGames so that we can direct-message you more info.
  • “Like” the BlueLine Game Studios facebook page then post on our wall that you want to be in the Alpha Test (we’ll fb-message you more info).
  • We prefer the other two methods but if you don’t have twitter or facebook, just send an email to “sean” at this site (bluelinegamestudios.com).

Thanks in advance for helping us make sure that Hive for Xbox is the most amazing adaptation imaginable of the game we all love!
– Sean


* Download .NET for free here. Xbox doesn’t have a good way to let non-developers test games that are currently in development, but we can just build the game for PC and run the test there. We’d like testers to plug the Xbox controller into their USB port though, so that they can get a feel for whether the controls work right. Technically, you don’t need a wired controller if you happen to have a Wireless Gaming Reciever for Windows.
** If you want to be notified for all of our new game announcements and releases, please sign up for our mailing list.

New game: Proximity!

BlueLine’s first game release is Proximity for the Pokki platform!Proximity HTML5 game.

We’re still hard at work on our larger project, Hive for Xbox 360, but we took about a week and a half aside to make Proximity. The game was an entry for the Pokki 1UP contest which is currently going on.

Proximity is a territory-based abstract strategy game – like Chess… or Hive ;). You place colored tiles with a number of armies on them and try to conquer the surrounding territories. Also: the tiles are hexagons (we may be obsessed).

The game currently supports single-player vs. AI (the AI is pretty decent) and local multiplayer.

Pokki is a platform which wraps HTML5 apps and makes them downloadable and automatcially-upgrading & has an app-store. The contest is to make a game for the platform using HTML5 and other web-standards (flash is forbidden). There are 3 judged awards and a people’s choice award which goes to the app with the most active players by the end of the competition.

Please go download and play Proxmity! 🙂

So far, most of the feedback is along these lines:

  • It’s maybe a bit too addictive
  • Are those numbers really random?
  • Oh, you can click the squirrel! 😀

Please let us know what you think of the game in the comments!

Proximity with Military skin

Proximity with Pokki skin

Proximity with Portal skin