Make yer own!

Make yer own!

So you've decided you want to write a game…

  • Home

My Bad Habit

Posted in Uncategorized by J Artis
Mar 11 2012
TrackBack Address.

I have a confession to make: Hurgle Studios has several more games “written” that aren’t released yet. Well, the GAME part is written. Maybe not finished, maybe could use some polish, but pretty solid and ready to go. The parts that are missing are the ones that seem superficial – menus, music, instructions, credits… But those parts are for some reason always the hardest for me to force myself to write.

This week, I set a challenge before myself: Could I take five of these prototypes and mash them out into completed games?

The answer is a resounding “Wellllllll…”

(more…)

Share
No Comments yet »

Number names in Scrabble scoring

Posted in Uncategorized by J Artis
Oct 08 2011
TrackBack Address.

While playing a game of Scrabble recently, and thinking about some word games I have been working on, something wandered across my mind: Given the spelled-out names of each number, as single words, what would the point value be with no bonuses? Were any numbers worth their name in points? For a cheap laugh, I present to you the point values for the numbers 1-20 and their point values. (Spoiler alert: Twelve)



ONE 3
TWO 6
THREE 8
FOUR 7
FIVE 10
SIX 10
SEVEN 8
EIGHT 9
NINE 4
TEN 3
ELEVEN 9
TWELVE 12
THIRTEEN 11
FOURTEEN 11
FIFTEEN 13
SIXTEEN 14
SEVENTEEN 12
EIGHTEEN 12
NINETEEN 8
TWENTY 12

Interesting, no?

Share
No Comments yet »

Analysis of Sinister Sudoku

Posted in Uncategorized by J Artis
Sep 18 2011
TrackBack Address.

Sinister Sudoku started off as a thought experiment, based on a very small amount of research I had done before. I’ve worked on a handful of sudoku-inspired games, and I knew that any puzzle could be transformed in a number of ways to make a different puzzle. I had not seen any proof (although my research was a little limited in scope) but I had a strong suspicion that the same transformations could be applied to a partial solution, or set of clues, to get a different but still solvable set of clues. That single point of curiousity turned into what I consider to be one of my better puzzle games to date.

(more…)

Share
No Comments yet »

Finding words for HexWords

Posted in Uncategorized by J Artis
Mar 26 2011
TrackBack Address.

In this post, I’m going to walk through my thought process as I write the word finder for building a HexWord puzzle (as described in my earlier post). This is kind of an experimental post – Instead of finding some paper nearby and sketching out an outline there and coding from it, I’ll do it here for everyone to see. What a bad idea this might turn out to be! In any case, I hope it is of some help.

We’ll start with a few assumptions:

  • There is a dictionary of words that you have access to, already sorted such that it only contains six letter words.
  • You can get a list, in some sequential order (clockwise or counter), of letters around a central hex.
  • The code has to “just work” right now, not necessarily be the best or most efficient solution. We can fix that later.
  • We will have to check both directions to see if a word fits either way

So let’s say we have a string that represents our current in-place letters, and blanks will be represented by * – For example, “XED***” – what is the next step?

1.) Pick a starting point in the dictionary (array of words) – you may want to do this at random to avoid clustering near one end of the alphabet – and get that word. You want to build a 12-character string which is that word twice, so you can scan through it (to cover words cycling at different starting points), and see if your string matches it iteratively.

We need to write a function, then, that compares two six-letter strings, our target string T and our dictionary string D, returns TRUE if it matches, FALSE if it doesn’t. We call that function inside an iterator from 0 to 5, to check all starting positions. THIS function should return an integer that is either an index into that string (so we know where to start the word) or something obviously invalid (say, -1) if the word has no matches.

What do we do about reverse cases? Set a flag in our check indicating that the word is reversed, perhaps, reverse T, and call the iterator again, that’s my reflex.

When we do find a word that matches, we set it into the grid. Be aware that we might need to backtrack if we can’t find a match for T this time around, so instead of locking the word into the grid, we might want to store a list of the words in order as we find them, along with the starting and current index into the wordlist for each word we find. This is so we can step back more than one word until we find some combination that fits the grid properly.

public function wordMatches(target: String, testWord: String): Boolean
{
   for (var charIndex = 0; charIndex < 6; charIndex++)
   {
      if (target.charAt(charIndex) != "*" &&
         target.charAt(charIndex) != testWord.charAt(charIndex) )
      {
         return false;
      }
   }
   return true;
}

Okay, that will tell us if two words match perfectly. Next let’s write our iterator so we know where to start them.

public function getWordMatchIndex(target: String, baseTestWord:String): int
{
   var doubleTest: String = baseTestWord + baseTestWord;
 
   for (var startPoint: int = 0; startPoint < 6; startPoint++)
   {
      var shiftedTestWord: String = doubleTest.substr(startPoint, 6);
 
      if (wordMatches(target, shiftedTestWord)) return startPoint;
   }
 
   // For the reverse case, we will simply return a negative index
   // That gives us a start point AND a direction
 
   doubleTest = doubleTest.split("").reverse().join(""); // One line reverse
 
   for (startPoint = 0; startPoint < 6; startPoint++)
   {
      shiftedTestWord = doubleTest.substr(startPoint, 6);
 
      if (wordMatches(target, shiftedTestWord))
      {
         // Handle a special case since there is no negative zero
         if (startPoint == 0) return -6;
         return -startPoint;
      }
   }
 
   // And some nonsensical value if there is no match
   return 999;
}

Now to verify that it does what we expect it to do. The joys of unit testing!

// Unit testing time!
public function testWordMatching(): void
{
   var testTarget: String = "**xe**";
   var sampleDict: Array = ["tuxedo", "xenons", "dexter", "exacts", "nogood", "mixups"];
 
   for (var i:int = 0; i < sampleDict.length; i++)
   {
      trace ("Match index for " + testTarget + " against " + sampleDict[i] + ": "
            + getWordMatchIndex(testTarget, sampleDict[i]) );
   }
}

This code gives us the following when we run it:

Match index for **xe** against tuxedo: 0
Match index for **xe** against xenons: 4
Match index for **xe** against dexter: -1
Match index for **xe** against exacts: -2
Match index for **xe** against nogood: 999
Match index for **xe** against mixups: 999

How do we use these results? Starting from the “start point” of the target chain of hexes (I’m assuming the hex ABOVE the “root” hex will always be index zero):

  • For any positive integer, ring element n will be matched word letter ((n + match index) % 6)
  • For any negative integer, reverse the matched word. Ring element n will still be matched word letter ((n + match index) % 6)
  • For 999, cry, regroup, and try again.

Looks like we’re off to a good start. All of this was coded live in tandem with the blog post, and I managed to make it work (granted, I did have to go back and change the occasional typo in both places). From here, my immediate plan is to try a naive “It oughtta work” population of the board by picking one root hex, filling it in with a random word, and iterating over the rest of them going through my whole dictionary each time, and seeing if I get a full board. If there’s no match, I will move on to the next one and leave blanks where they end up: Let’s see what results I get!
SUCCESS! SORTA!

Next step is going to be adding the backtracking and making sure ALL of the words are valid. But for now… it does something akin to what we need, so we’ll hang it up until next time. Until then, save early, save often.

Share
No Comments yet »

Considering control schemes

Posted in Uncategorized by J Artis
Mar 09 2011
TrackBack Address.

For a change of pace from my other recent projects, and for a laugh, I decided I would start on a hexword (hexagonal crossword) puzzle game in AS3. I quite enjoy doing them in pen-and-paper puzzle collections, but there are a lot of elements that don’t directly translate from working pen-and-paper to working with a keyboard and mouse. Whenever you move a game or puzzle or the like from one format to another, there is going to be a change to the control scheme – and deciding on how that works will be of vital importance to your game.

Starting specifically with this example, let’s look at how it is played:

The field is made of hexagons in a specific pattern. Some are filled and numbered, some are blank. Words are filled in around the numbered hexes, but it is the player’s task to determine what the words are, whether they travel clockwise or counter-clockwise, and where the word starts. This is affected by the other words sharing letters with the current word.

In a pen-and-paper game, you can fill in any hexagon you want with any letter you want by moving your hand to it and writing a letter. The player will have certain knowledge, though, that the computer does not by default: Which word they are trying to fill in, and which direction they will be moving next. Additionally, using the mouse and keyboard in concert is more complex than simply moving a pen.

Some concessions are taken for granted: The easiest way to get a letter into the computer is by using the keyboard. The mouse can clearly indicate which hex you wish to fill with a letter. It may get tedious, however, to make a player click each hex one at a time and then fill in the letter. Doing some “research” (read: playing crosswords online) I have discovered a number of common mechanics for saving effort on the player’s behalf.

In a traditional square crossword puzzle, one common technique for deciding which word you want to fill in and whether it is horizontal or vertical is to click on the filled, numbered square. One click places your cursor at the first character of the horizontal word, a second switches to the first character of the vertical word. The game now knows which word you are filling in, which direction you are travelling, and which character to begin with. Now you can switch fairly safely to pure keyboard input – each letter typed fills in the square, then the cursor advances to the next character (or the next empty square) in the word. A parallel to this in hexword is that clicking on a center square will place your cursor at the top, perhaps, and there will be an indicator whether your cursor will travel clockwise or counterclockwise.

In a traditional crossword, which is orthogonal, the arrow keys can move you to the next character-accepting square in that direction, and set the current travel direction to vertical or horizontal based on the direction you moved. With hexagons, though, there are six directions you can move – although many can be ruled out. Luckily for us*, the layout of a hexword puzzle only allows one left or right movement option for each tile. In other hex-based games, having some extra piece of knowledge (like the center tile here) can help you decide which is the proper way to move.

With auto-advancing covering the knowledge of what you want to fill in next, and selecting root tiles to indicate the word you’re filling in, you cover a lot of the inconvenience of a split control scheme. The arrow keys moving tiles and switching roots can even grant an almost exclusive keyboard control. It may not QUITE be the pen and paper mechanic, but it’s easy enough to use quickly and without any serious confusion. With that, I’m off to add keyboard controls, and make sure the input works the way I anticipate. I think the next time we meet, we will talk about actually generating the puzzle. Until then, save early, save often.

* To be honest, until writing this blog post and looking closely at the screenshot, I was so used to hex left-and-right problems that I didn’t even realize that we already had that piece of knowledge. This shows how important it is to see what you already know before you start solving problems.

 

Share
No Comments yet »

What is a “Bad-ass” platformer?

Posted in Uncategorized by J Artis
Feb 08 2011
TrackBack Address.

A friend sent me an instant message today that said, simply, “make a bad ass platformer”. No context, no further discussion (to be fair, I was out when it came in), no hints as to what he meant. It comes at an interesting time, as I’ve recently been playing with the Flixel library quite a bit, and one of the first “getting-to-know-you” tutorials I stepped through was a rudimentary platformer – which Flixel is natively suited very well toward. With a lot of the dirty work taken care of already, it does leave one time to think: What DOES make a “bad-ass” platformer?

- Platforms -

I know this is going to come out sounding incredibly dumb, but one of the considerations that should always be on your mind during the level design part is how the player moves. Know how high you can jump, and how fast you move, and any other changes to your speed in whatever direction. Set some obstacles in the player’s way – but nothing completely insurmountable (unless it serves as an interlock to make sure some other action is completed first). Remember that no matter how good you are at your own game, someone else is going to push those bounds a little further. If you are sure you cannot make a jump, make it one tile further just in case. Of course, if your levels are procedurally generated that changes things a bit, but the premise remains – platformers are exercises in moving a character, first and foremost.

- Powerups -

A popular (if occasionally derisive) term for a specific flavor of platformer is “Metroidvania”, paying homage to the two biggest franchises in powerup-driven adventure platformers. Less overall emphasis is placed on the physics and movement, and more on the change of abilities granted by collecting certain items. This leads to a lot more of the “interlock” situations I mentioned above, where an area of the game is off limits until you get the right items – often, because it allows you to move differently, or change the layout of the level (think jetpacks or wall-destroying lasers). This has several side benefits – give bonuses for least items acquired, or for getting all of the items in the game – but requires much extra thought in the level design.

- Progression -

The player needs to be able to see, at all times (in some way), an indicator that they are moving through the game. A map, or a counter of items collected, or a stage number (even if there’s not a priori knowledge of how many levels there are) can all serve this purpose, as can many other subtle signs – changes in the background or environment, ramping difficulty, or tighter restrictions on play for example. These things provide motivation to continue playing or exploring the game world above and beyond trying to reach some arbitrary end point, and also can keep the game from getting too repetitive if engineered correctly.

- Pictures -

Yeah, art is important. It is not the most important aspect of a game, granted, but it can make or break it. Doesn’t mean it has to be amazing 3d renders – just appropriate to the game, and engaging but not distracting. The best art in a video game is that which doesn’t stand out from the rest of the game, but that which feels natural and right. It is when it is not viewed by the player as a separate entity from the gameplay that it has truly served its purpose.

- Phun -

Okay, that was waaay too much of a stretch, but it has to be FUN. Make people play it and tell you if it is FUN or not. If not, fix it. Or hang it up and try again.

Anyway, there are more elements that are important in any game, but these stand out as some key aspects of specifically “badass platformers”. And now that I’ve taken some time to think over what it would take, I should start dropping them into a game and seeing if anything phun comes of it. Until next time, save early, save often.

Share
No Comments yet »

SpriteFont AS3 class

Posted in Uncategorized by J Artis
Feb 03 2011
TrackBack Address.

I mentioned that I was thinking about posting this, so I will. It’s… “rough”. But it works in a pinch, when you need to put some text on a bitmap.

// Notes about SpriteFont:
// - The bitmap should be a 16x16 grid of characters, starting at ascii 32
// - It's assumed the character width is 3/4 the width of a block unless you specify WIDE to be true
// - The character height is assumed to be the full height of the block, so lineheight is 1.25 * char height
 
package
{
   import flash.display.Bitmap;
   import flash.display.BitmapData;
   import flash.text.*;
   import flash.events.*;
   import flash.geom.*;
 
   public class SpriteFont
   {
      private var mFontData: BitmapData;
 
      public var mLetterWidth: Number;
      public var mLetterHeight: Number;
 
      private var mBlockWidth: Number;
      private var mBlockHeight: Number;
 
      public var mLineHeight: Number;
 
      public static const LEFT: Number = 0;
      public static const CENTER: Number = 1;
      public static const RIGHT: Number = 2;
 
      public function SpriteFont(bmp:BitmapData, WIDE:Boolean = false)
      {
         mFontData = bmp;
 
         mBlockHeight = mFontData.height / 16;
         mBlockWidth = mFontData.width / 16;
 
         mLetterHeight = mBlockHeight;
         mLetterWidth = Math.floor(mBlockWidth * 0.75);
         if (WIDE)
            mLetterWidth = mBlockWidth;
 
         mLineHeight = Math.floor(mLetterHeight * 1.25);
      }
      /*****************************************************************************************
      * drawString(dest, str, dX, dY, alignment)                                               *
      *                                                                                        *
      * Draws string (str) to the bitmapData of dest, with dX and dY as the registration point *
      * based on the alignment (one of the constants above)                                    *
      *****************************************************************************************/
 
      public function drawString(dest:Bitmap, str:String, dstX:Number, dstY:Number, alignment:Number): void
      {
         var srcX:int, srcY:int, curX:int, curY:int;
         srcX = 0; srcY = 0;
         curX = 0; curY = 0;
 
         var ddx:int;
         var ddy:int;
 
         var strings:Array = str.split("\n");
 
         for (var line:int = 0; line < strings.length; line++)
         {
            var lineWidth:int = strings[line].length * mLetterWidth;
            ddy = dstY;
            switch(alignment)
            {
               case LEFT:
                  ddx = dstX;
                  break;
               case CENTER:
                  ddx = dstX - (Math.floor(lineWidth / 2));
                  break;
               case RIGHT:
                  ddx = dstX - lineWidth;
                  break;
               default: // Fall back to left-justified
                  ddx = dstX;
                  break;
            }
 
            for (var i:int = 0; i < strings[line].length; i++)
            {
               var cCode:int = strings[line].charCodeAt(i);
 
               // Bounds check for sanity
               if (cCode < 32 || cCode > 255)
               {
                  // How should this be handled? Right now, make it a space.
                  // This is pretty non i18n-friendly...
                  cCode = 32;
               }
 
               cCode -= 32;
               srcX = mBlockWidth * (cCode % 16);
               srcY = mBlockHeight * (Math.floor(cCode / 16));
               dest.bitmapData.copyPixels(mFontData, new Rectangle(srcX, srcY, mBlockWidth, mBlockHeight), new Point(ddx+curX, ddy+curY), null, null, true);
               curX += mLetterWidth;
            }
            curY += mLineHeight;
            curX = 0;
         }
      }
   }
}

You can download the file along with a sample font here: SpriteFontAS3

Share
2 Comments »

Flash Minus Flash

Posted in Uncategorized by J Artis
Jan 27 2011
TrackBack Address.

One of the projects I am working on targets Flash Player 10 – which unfortunately you cannot natively target (as best I can tell) with Flash CS3, so I downloaded the trial of CS5. I love it to pieces, but I’m approximately a hojillion dollars short of buying it, so I have decided to take a shot at building it with Flex. AS3 as a language has grown on me quite a bit, so much so that I am thinking of adding it to the languages for the tutorials – which I promise will resume soon. But while I would not say I have grown DEPENDENT on the Flash IDE, I have grown… attached.

Library

The library in Flash makes it easy to go through, change, update, and organize the resources in a project, which can be done with a minimal amount of effort in actual script as well. The upside is it makes it very easy especially for quick prototyping to get all of your resources in one place in a big hurry – the downside is if you ever migrate a project out of Flash, there is a large amount of un-breaking to be done, and it can be difficult to keep your place when moving over to Flex. One thing I have learned is that making a static Resource class can help with a slightly less painful transition, and you no longer have to worry about updating the library every time you change a bitmap.

Sound

Audio has to be in the right format. Audio *HAS TO BE* in the right format. And no, Flex will not let you use a .wav and compress it for you. I fought with this for a little while since the MP3 compressor I was using had some issues. One additional concern that I have not had the pleasure of running into yet, but am aware of intently, is that seamless looping with MP3 files (based on soundComplete events) can be tricky, owing to the nature of MP3 files themselves. When I let the Flash IDE handle it, problems of that nature were minimal – but I have not finished testing Flex builds extensively to determine if it made any significant difference.

Text

I am still struggling with embedding and importing custom fonts in a script-only environment. I could just be missing some fairly obvious step, but it feels… unnatural. From what I understand a lot of that may be due to the nature of .TTF files and the different styles they can contain, but it is difficult enough to do successfully in script even with the aid of the Flash library making connections for you, and nigh impossible (by my standards) to do purely in script. I am giving serious consideration to returning to an earlier strategy of bitmap fonts and my own spriteFont class – which I will probably post here before too terribly long.

TL;DR

I enjoy working primarily in script, and have broken a lot of my IDE dependency, but losing the “library” did put a big kink in my project. If you start in either the IDE or pure AS3, you will be fine, if you have to transition in the middle of a project… I am sorry. Keeping everything organized and named properly helps immensely though.

As this little experiment comes together I’ll keep you posted. Until then, save early, save often.

Share
No Comments yet »

A new point of view

Posted in Uncategorized by J Artis
Jan 13 2011
TrackBack Address.

A lot of people claim they want to create a new game “unlike anything else out there”, and proceed to describe it in terms of everything else out there. (It’s like Halo but in the old west!) If you have an amazing new concept for a game, that is all well and good, but to be honest, odds are it’s been done – or something like it has been done. What is a developer to do in these circumstances?

The answer is simple – pick something you know and love, and look at it a new way.

I spend a lot of time wandering around the internet and looking at new techniques and effects – partly just to keep up my programming chops, but partly for inspiration. One of my projects that is forthcoming is a puzzle game that is similar to one I’m a big fan of (hint: it rhymes with “Lumines“) but I was sure I didn’t just want to create an outright clone. I fiddled around with a few ideas of how to change the gameplay mechanic, and some of them are still incorporated. Presentation, however, can speak volumes about a project.

The original game is played on a grid similar to this one, and uses a matching mechanic with a delay mechanism to prevent the board from clearing immediately. The game is heavily driven by the music, although it is not inherently rhythm based. As I idly surfed around I thought to myself: Music is traditionally delivered in round formats. The LP, the compact disc, even (perhaps a stretch) the reels inside a tape, or the platters on a hard drive. What if the game were round?

What I did here is map the grid game onto a circle. This affords us a few minor gameplay changes (for instance, the game no longer has a distinct “left” and “right” edge), and also provides a few new interesting considerations. You no longer move left and right – you move clockwise and counterclockwise. Pieces no longer drop “down”, they drop “in” (they could just as easily have dropped “out”, this was primarily an aesthetic choice). Seeing a fairly familiar game in a new light provided an opportunity to adapt it into something new.

Try this yourself: Picture a game with simple rules, one you are familiar with. Instead of trying to come up with some drastic gameplay twist, come up with a simple presentation twist – how can you give the player a visualization of the game in some new manner? Then analyse what else it will change in the gameplay, and how you can adapt to that; whether it is new controls, rule changes, or just adapting the style of your art assets. What would Tetris look like if it were played on the outside of a cylinder? Breakout inside of a sphere instead of upon a square?

Looking at familiar things in a new way can lead you to something new and different.

Oh, and if you’re interested in finding out more about this game, details will be showing up here as it nears completion. I look forward to sharing it with all of you. Until next time, save early, save often.

Share
No Comments yet »

AS3 Keyboard names from key codes

Posted in Uncategorized by J Artis
Jan 10 2011
TrackBack Address.

Silly little Actionscript function that isn’t perfect, but fills a need I had – and I haven’t really found another one that does quite the same thing. If it is obviously missing anything, it is fairly easy to edit and add.

public function getKeyName(KeyToName: Number) : String
{
	var KeyString: String = "";
	switch(KeyToName)
	{
		case 8: KeyString = "Backspace"; break;
		case 13: KeyString = "Enter"; break;
		case 16: KeyString = "Shift"; break;
		case 17: KeyString = "Ctrl"; break;
		case 18: KeyString = "Alt"; break;
		case 19: KeyString = "Pause"; break;
		case 20: KeyString = "Caps Lock"; break;
		case 27: KeyString = "Esc"; break;
		case 32: KeyString = "Space"; break;
		case 33: KeyString = "PgUp"; break;
		case 34: KeyString = "PgDn"; break;
		case 35: KeyString = "End"; break;
		case 36: KeyString = "Home"; break;
		case 37: KeyString = "Left"; break;
		case 38: KeyString = "Up"; break;
		case 39: KeyString = "Right"; break;
		case 40: KeyString = "Down"; break;
		case 45: KeyString = "Insert"; break;
		case 46: KeyString = "Delete"; break;
		case 112: KeyString = "F1"; break;
		case 113: KeyString = "F2"; break;
		case 114: KeyString = "F3"; break;
		case 115: KeyString = "F4"; break;
		case 116: KeyString = "F5"; break;
		case 117: KeyString = "F6"; break;
		case 118: KeyString = "F7"; break;
		case 119: KeyString = "F8"; break;
		case 120: KeyString = "F9"; break;
		case 121: KeyString = "F10"; break;
		case 122: KeyString = "F11"; break;
		case 123: KeyString = "F12"; break;
		case 145: KeyString = "Scroll Lock"; break;
		default: KeyString = String.fromCharCode(KeyToName); break;
	}
	return KeyString;
}
Share
No Comments yet »
Next page »

Recent Posts

  • My Bad Habit
  • Number names in Scrabble scoring
  • Analysis of Sinister Sudoku
  • Finding words for HexWords
  • Considering control schemes
Powered by WordPress | “Blend” from Spectacu.la WP Themes Club