Showing posts with label JavaScript. Show all posts
Showing posts with label JavaScript. Show all posts

Saturday, November 16, 2013

Level Loaded and Navigable


It's been a while since I've posted any visuals, and I'm happy to show the level that I had been making maps for actually running in my game engine. The path to this point had some interesting steps:

Hexographer parsing

Hexographer writes all of its data out in a pretty easy to interpret text file format. I opened it up in emacs, and saw the size of the level, terrain declarations, terrain instances - all pretty straightforward.

I started writing a Python script to take things apart, and was immediately surprised to find garbage in the strings that I wasn't expecting. Turns out, the text isn't ASCII, it's UTF-16. Whoops. So, I poked around on the internet and figured out how to use Python's "chardet" library, which got things squared away there.

I started writing a tool to take my interpreted structure of the level and dumping that to custom JavaScript, which I'd write to a file, but I quickly got annoyed by the fact that lists in JavaScript can't have a terminating comma: "[1,2,3]" is valid, but "[1,2,3,]" is not. I imagine I could have got around, but I decided, instead to use Python's json library to create the JavaScript for me.

I still think the idea is a good one, but if I had made a custom exporter, code that currently looks like this: 

  "terrain": {
    "Corner 1": {
      "blocks_mvt": true,
      "blocks_vis": true,
      "filename": "c1_0_x.png"
    },

would probably look more like this:

  "terrain": {
    "Corner 1": {
      blocks_mvt: true,
      blocks_vis: true,
      filename: "c1_0_x.png"
    },

Not a big change, but then the calling code would refer to terr.filename, instead of terr['filename'].

Coordinate Conversion

I actually expected this to be trickier than it was - switching coordinate systems can be tricky, and hex grids are weirder than most. Hexographer uses an "offset horizontal layout" in Amit's terminology, and I'm using "cube coordinates". It turns out, the conversion wasn't so bad, and inside a tool, I don't mind the math. I did it in my head, and it worked on the first try.

Transparent Tile Background

I copied my Island of the Rat King code over to my new working directory,, and brought things up, tinkered here and there to change the procedural level generation of last month to an asynchronous asset loading pattern (even with compiled in level data, the tile art is loaded at runtime). All I was seeing was green grid lines on a black background  - which was promising, but not quite right. I tinkered around, and discovered that my tiles were mostly transparent, with opaque black lines for the features, and green lines for the edges of hexes. I went back to my drawing script, and tagged most of my hexes to draw a white background, reexported the tiles, and things are showing up pretty much as I expected

Things not quite working right

Visibility

I'm not sure if I'm entirely satisfied with my visibility. For solid hexes, it's doing great, but for partial hexes, maybe it needs to be reconsidered. Or maybe I adjust some of the data. For example, walls that appear to be straight occupy jagged hexagonal regions. The entire hexagon gets tagged as blocking visibility or not, and that means that the corners, even if the pen strokes suggest otherwise, might block visibility. In a lot of cases, I could flip half-walls and corners to not block visibility, but that might have other issues.

Pathfinding

This isn't anything new - I just haven't ever got around to implementing a simple A* tool, instead, using a breadth-first search. With cubic hexagonal coordinates, I've got a good distance heuristic, which was what kept me from implementing A* back in The Cave of the Rat King.  So, if you're patient, you'll be able to click around corners. But it shouldn't take that long.

Schedule

Here it is, halfway through November, and my goal was to have a party-based tactical RPG done by the end of the month. I've got one level loading, with no enemies, with one character. I may find myself scaling back a lot. I could turn it into "explore this spooky house", which really only makes it a small improvement on The Maze of the Rat King. I think I might do a single-character turn-based tactical RPG, with really simple enemy AI, and really simple inventory (possibly none).


Wednesday, October 2, 2013

September Game "Maze of the Rat King" bug fixed, time to start on October game

So, if you've been waiting to play the September game until I'm done with it, I now give you permission to hit http://bigdicegames.com/RatMaze/maze.html as I'm not going to be updating it further.

That sounds bad, let me rephrase: "Yay, the maze game is now full up with awesome, and it's ready to go!" Which sounds a little over the top. Somewhere in the middle, though, I'll say, yes, there's stuff that didn't get done (like any of these fixed time limit games), there's stuff I'm pleased with, and I'm happy to have working pieces to carry forward to the next game.

The last bit that I just fixed was a weird loading behavior - when I would load the game the first time, or one of my friends would load the game any time, certain assets wouldn't load, and the game would just show a black screen.

Turns out, what was happening was that I had a bug where I was launching the Jaws.js game framework twice. Jaws, like most Javascript engines, gets a lot of its work done through callbacks, so what was happening was that I'd set up a list of assets, the framework would issue asynchronous calls to load those assets, and would go away. Each time an asset would be loaded, it'd tally up the loaded asset (or failed load, if that happened, which it didn't in this case).

I was loading 23 assets, I was seeing 23 callbacks, but I was only seeing 20 loaded assets. It took me a while to recognize that 3 of those assets were being loaded twice, and it took me a while to recognize that I was launching the framework (and hence the loader) twice. Once I saw that, it made sense - the tile art was much smaller than the splash screen, and loading a 100x115 PNG twice is much faster than loading a 800x450 PNG, so some of the tiles would get loaded twice, the loader would say, aha, I've loaded 23 things, that's all I need, let's start the game. And then my splash screen code would leap into action and it'd all end in tears, as the first thing that I do is try to draw my biggest piece of art. Bam.

I'm not going to badmouth Jaws.js - it's so far been a pretty good tool, and I've been able to walk through the code pretty well. There are things that I'd change, and a few places where I've stitched in debugging code and a few places where I've stitched in new functionality. I really need to get back to the original author and share my experiences - even if he's not interested in my patches, I expect he'd appreciate knowing that it's getting use.

I do think that as I continue to make games with my toolbox of code, I'll lean less and less on Jaws.js and might eventually get rid of it altogether. I think right now, I'm using the asset loading and the keyboard/mouse/touch handling, which I could probably rewrite without much effort if I needed to.

I don't need to for the moment, so I won't.

Next up: Our hero has escaped from The Maze of the Rat King, and pursues him overland through adventures in the wilderness.

Saturday, September 7, 2013

Key, Gate, Exit


Well, I've got something working. I don't like the behavior, and I don't like the implementation. But it's "working". Including sometimes when it isn't exactly working the way I want, even then it's pretty much working.

My process here is to first pick a random spot on the map, I call that the seed. Then I find a spot as far as I can (pathfinding-wise) from the seed. That's the exit from the maze. Then I find a spot as far as I can from the exit, that's the start. I'm not entirely sure that that's the right feel for a maze - but it does give the player the maximum distance to travel in the best case.

After that, I find the path from the start to the finish, and drop the gate 70% of the way along it. This divides the maze into two sub-mazes. I want to pick a spot in the player's sub-maze, far away from the start position and far away from the gate. Instead, I just pick a spot halfway from the start to the gate. This puts all the interesting bits of the maze on a single path, and if you're extremely lucky, you won't have to backtrack at all.

I'm finding that I want to build some nicer tools for handling tile positions - right now, I'm iterating over lists more than I want, and it's gross.

Also, sometimes, the player ends up at a location that's not the furthest from the exit, so something's not right.

If/when I rewrite the tile position code, maybe that bug will get sorted out.

I'm calling this stuff good for now, with the intent to come back and rewrite it to make it pretty.

TODO:
clicks make player move
player animates from location to location
player picks up key
player can't pass through gate without key
landing on exit is a victory

That's not much, really, and I have over 3 weeks to do it. That means I'm likely to actually get around to the cleanup, I hope.


Tuesday, July 9, 2013

Bugfixes, Model Rendering Work



One thing I've got a lot of value from is breaking of weekend-scoped pieces of development, so that you can show off your progress to your coworkers on Monday morning. Some games have more weekend-sized pieces than others, but I think the ones that can be broken up that way are easier to maintain progress on as you move along.

With "One Game a Month" there aren't a lot of weekends per game, so that idea has to be modified some - either smaller chunks, or smaller games.

I told some coworkers about Zone of Battle: Tank Patrol yesterday, and almost all of them had problems loading it. Weird. Now, I had only tested on Linux/Chrome, which isn't representative of all OS/browser combinations out there, but even some Linux/Chrome coworkers couldn't load it. They were able to give me some valuable debug output.

So, recently done:

  • Tank movement - I got this in yesterday morning. There's arrow key steering for simple control, or tank steering, if that's your thing.
  • Some obvious browser bugs fixed - no guarantees about your browser, but I'm guessing more people will be able to play it now.
  • Projectiles launching from the muzzle - this was a small change, but it makes a big difference in the feel of the projectiles.
  • Static objects in the world - I made a cone and two sizes of cubes. They don't block tanks or projectiles, they're just visual, but they make the tanks feel like they're in a space, rather than just floating around onscreen.
And the top of the TODO list:
  • collisions - between tanks and objects, between tanks and tanks
  • enemy tanks shooting at you - this will be the last important piece of gameplay. It will probably change the feel of the game substantially, requiring tuning speeds and scales, but that's a great place to be.
  • HUD - radar, score, damage display

Sunday, July 7, 2013

Patrolling Tanks


The first thing to note is that you can see the current state here: http://bigdicegames.com/BZone/bzone.html

Stuff I've got done since the last update:

  • build, deploy script tinkering - I had thought that my build script didn't work with WebGL stuff. Maybe I fixed some problem I was having. Maybe there never was a problem. It seems to work, so, cool.
  • new tank class - makes things like position and heading be easier to deal with.
  • updated the model - not that you can tell. The old model was facing down the Y axis, which made the heading 90 degrees off from what made sense to me. So, the new rule is that models face along the positive X axis, with up in the positive Z direction. Y is, of course, left, because we're using a right handed coordinate system.
  • updated the model conversion script - again, not visible. The new script is Closure-friendly, using "goog.provide" and having a namespace. Also, it avoids breaking IE8, who freaks out if you put a comma at the end of your list: [1, 2, 3,]
  • rudimentary tank AI - riffing off last month's guard patrol route code, I've given the tanks some simple patrol routes. The tanks turn to face their next patrol waypoint, then move at full speed until they reach it. They can sometimes overshoot, but I've only seen that a few times. The waypoints right now are just points on a big circle, nothing smart.
Next up:
  • player control - the player ought to be able to move around.
  • projectiles - pew, pew!
  • skycube - I've been thinking about using a texture, but maybe flat shaded polygons would be OK. I'll probably need to set up a special view matrix for the skycube.
  • obstacles - stuff for the player to hide behind, stuff for the tanks to avoid
  • pathfinding - once I've got static obstacles, I'll need simple pathfinding
  • collision - tanks should not be able to drive through each other, nor should they drive through obstacles. Projectiles should not shoot through tanks or obstacles.
  • mission system - as I'm getting the simple mechanics knocked off, I've been thinking about what the bigger gameplay design is going to be. I think the player will be assigned some number (4) of patrol waypoints, to which they'll have to navigate (pretty easy, and there'll be an autopilot). Along the way, they'll encounter some enemy tanks, which they'll have to shoot. At the end of the patrol route, the player can return to base. The end. Not a new game design, not super compelling, but a little better than "there are tanks, shoot them". If I were feeling really ambitious, I might have an escort mission or bigger enemy tanks (think "capital ships"). Or enemy bases. Bases might not be too hard, except making something that feels like a living base might be more work than I have time for.
  • buddy AI - I've thought about adding a friendly tank that will help you in your patrols. Maybe you can give him orders, like "shoot my target", "hold your fire", "engage at will", "form up next to me". This doesn't seem too hard, we'll see.
  • HUD - I'll need a radar display. Maybe a damage readout.
  • damage model - moving a little bit away from the simplest arcade "one hit, one kill" model, to a model where different sides of the vehicle have different levels of defense, which can be degraded.
  • animation smoothness - for some reason, the movement of the tanks is visibly jerky; every so often, I'll see a hitch in the update. I'm not entirely sure what's going on there, maybe I'm measuring incremental time progress incorrectly. I'd like to fix this, but it's in the "important but not urgent" bucket for now.


Sunday, June 30, 2013

Another one in the can


Well, there's the sneaking game. Or, rather:

http://www.bigdicegames.com/SafetyLast/safetylast.html

there's the sneaking game. It's got 5 levels, which you can play through with one guard per level, which is pretty easy, or three guards per level, which can be pretty challenging. I'm not actually sure if you can beat the game - three guards is pretty unforgiving, especially on the big, open levels, or the tight levels.

Things I got in since my previous post (12-ish hours ago):

  • Crazy Ivan. Every now and then (between 4 and 14 seconds, or thereabouts), a patrolling guard will stop and turn to a random direction, which might be more than 180 degrees from his current facing. Assuming he doesn't see you, he'll return to his original direction and proceed with his patrol. Just like tailing a Russian sub, you don't want to get too close to a guard, especially if you can't duck for cover quickly.
  • Patrol Route Recovery. I'm not sure it feels right, yet, but when a guard decides he needs to return to a patrol route, he finds the closest waypoint that he can see, then traces forward to find the last visible waypoint after that. It feels OK, but I'd rather have dynamic patrol routes, which would make this less important.
  • Title Screen / Instructions / Credits. I ported the game into my old codebase that I've been bringing forward (code reuse!) since January. This required a certain amount of cleanup and general "paying down of technical debt". It's still a nightmare, but it's a little better than before
  • More levels. Well, it had been better - introducing more levels is a huge hack that involved duplicating code because I couldn't be bothered to do it more cleanly. That's the nature of pushing on a hard deadline.
  • Visual cleanup. The grey dots that had been illustrating the patrol waypoints are now hidden. Now, the game reminds me a little bit of Berzerk, or Armor Attack. I had thought that I'd make some 8-bit retro pixel art sprites, but not this time around.
It's satisfying that this one's "complete". There's a lot that I'd like to do, but the fundamental framework is there for me to come back to later. Or, maybe, I throw out the framework and draw from the lessons learned. I should really write down lessons learned, if I'm going to do that, because I doubt I'll remember.

I'm kind of thinking of taking bits of this forward into my next game, which if I get time and energy to get WebGL up and running, will be some sort of 3D game. Or, if I don't get that working to my satisfaction, I could hack together a raycaster and have a 3Dish sort of game, which would still be OK. I'm not sure I like the idea of trying to get perspective-correct texture mapping working in JavaScript.

Whew.

This marks halfway through the One Game A Month challenge, and I'm pleased to have made it this far. I've turned in some pretty sloppy games, but always something game-ish, and a variety of different games. I have a couple of bigger games that I want to work on after this is all done, and one of the things I was hoping to get out of 1GAM was a toolbox of code that I could reuse. I intend to be more deliberate about identifying useful technologies and working them into the next 6 games.



Saturday, June 29, 2013

Sneaking: well, it's technically a game now...

There are a lot of important points in the life of a game. One point is when you stop working on it. One point is when you ship it. These may not be the same, especially if you're working on an online game.

One important point is when the team actually has fun playing the game, and stays at work playing the game instead of going home. Not all games get to that point. Most don't, I'd wager.

One point that I know I always was searching for on previous projects is the point when the game is "fun". It's hard to know what that means, and pieces of the game might be fun early on, but making the whole game fun is tricky.

Well before any of these points is a point where the player was some in-game recognized notion of success and failure. In some games, these may be vague - for arcade games, failure is the "GAME OVER" screen that tells you to put another quarter in. For console games, you may not have as clear a failure mode - just get knocked down and start over. Maybe you go back to the beginning of the level. Console games often have a clear ending point - defeat the final boss, the credits roll, and you walk out to the kitchen because who reads the credits?

Even though I know that my little sneaking game isn't going to have a lot going for it by the end of the month (still got 27 hours), but it's got success and failure finally.

What you see here is a maze (green boxes) and a guard (green dot) as well as the player character (pinkish dot) and an exit square (pink box). Get your guy down to the lower right hand corner of the screen, and you win. But the guard might see you, as he does in this picture (blue line). When the guard sees you, he runs faster than you do, so you don't want to let him see you too often.

There are several things I want to get in to the game before I call it quits:
  • Proper "game over" logic, and probably a title screen. I know how to do this stuff, it's easy, it's just getting around to doing it, which may mean refactoring the code I've written. (It's a mess.)
  • Multiple levels. I was thinking of doing 10 levels. I might get 3 written. They're not hard to make, really, so 3 should totally be doable. Maybe even 10, if I get everything else squared away. Heh, squared. Like boxes. Ehhh, maybe I've spent too much time at the computer already.
  • Multiple guards. Again, a little bit of refactoring will be necessary - right now the guard is a mess of global variables. (Bad!) Having multiple guards to contend with will make the game harder.
  • Limited visibility arcs for the guards. Right now, the guard has 360 degrees of visibility, so you can't really sneak up behind him. If I narrow this down to, say, 120 degrees, it'll make the game easier, so this should go in along with having multiple guards.
  • Turning speed for the guards. The guard currently has no notion of "forward", he just gets pulled toward his destination. That destination can jump across the level, and does - for instance, when the guard sees you; he immediately heads in your direction. I'll need to give the guard a heading in order to have visibility arcs, and shortly after that, I'll add in a turning rate.
  • Lookie-loos. Right now, the guard's patrol route is a little boring - he just plods along in a straight line toward his next waypoint. I have this idea of inserting points where the guard stops and turns around and looks behind himself, which would be a good thing for a guard to do, but would make following a guard a really dangerous thing to do. I can insert this as explicit turns in the patrol path, or I could give the guard a random fuse that he'll occasionally stop and check his six. Maybe I ought to call that the "Crazy Ivan".
  • Cleanup? Those grey dots you see in the screenshot - those are waypoints for the guard. Handy for me as a developer, maybe useful for the player... maybe too useful. Maybe confusing. I think I ought to take them out. You know, when I'm done with everything else.
  • Smarter / Lazier guards. That sounds weird. Right now, if a guard loses the player, he'll head to the last place that he saw the player, which means he's got a limited ability to chase around corners. One corner, really. As soon as he loses the player, he goes back to patrolling, starting with the "next" waypoint that he can see. This may be way back across the level - which seems weird in some circumstances, like if the guard breaks off chase with the player, then returns to a waypoint to the south, but the next waypoint is north of the break-off point; the guard executes a weird 180 degree turn, retracing his steps. Probably makes sense to check what the "last" waypoint in view is, and then maybe consider the closest waypoint, or something that looks smarter.
There are a few things I won't be getting to, I'm sure:
  • Pretty graphics. Sorry, not happening in time. Maybe the player and the guards will become stick figures. Don't get excited.
  • Sound, Music, Score. Feel free to hum and make your own sounds. And award yourself points.
  • Dynamic Levels. Yeesh. Procedurally generated levels would be nice. 
  • Dynamic Patrol Routes. This would kind of need to happen with dynamic levels.
  • Pickups / Powerups / Rich Environment. One thing that I thought of doing early on was to give the player two things to do on the level before getting to the exit. Like picking up a rope and opening a window. There will be no ropes and no windows. I also thought that maybe you could pick up gold, or somehow get points for traversing the whole of the level. I don't see that happening, either. A long time ago, I had an idea for a similar game, and in that game, there would be things like squeaky floorboards, which would bring the guards running. Not in this game, though. Maybe later. If I were to return, maybe I'd create some powerups to help the player out. Super sneaky limited use shoes. Or smoke bombs. I'm not sure.
  • Level Countdown Timer. Actually, maybe I can get that in. That'd really ramp up the difficulty. But it also kind of pushes against the sneaky feeling of the game. Maybe I award bonus points for the timer, and let it go to zero without killing the player, just don't award any points past a certain time. That could be OK.
  • Guards coordinating their patrol routes. Imagine a randomly generated map, with randomly generated patrol waypoints. It'd be good if the guards covered these in a somewhat intelligent (appearing) fashion. Several years ago, I fiddled with a similar system where the guards would seek out waypoints that hadn't been visited recently. There was nothing keeping the guards from clumping up and patrolling in a gang, which wasn't what I had in mind.

Saturday, May 18, 2013

Small domino game

It's been a few months of small games, and May turns out to be another one. We've launched our project at work, which hopefully means I'll be more able to do some work on games in my free time. Of course, it's getting to be summer, and I've got travel plans, but hey.



I'm going back to an idea I've toyed with before, but never got fully implemented - which seems like a good enough source. It's a domino puzzle game, which is perhaps all I should, or need to, say about it at this point.

Things I did today:

  • created a new domino project
  • created a domino spritesheet
  • cut the domino sprites up, using the Jaws.js SpriteSheet class
  • drew a few dominoes from the cut up sprite sheet
Things I need to do:
  • allow the user to drag dominoes around
  • create "slots" on the board
  • snap the dominoes into the "slots"
  • verify constraints
Not so much to do, but I only have a few days. So, it'll still be a push.

Monday, March 18, 2013

Dots 'n' Boxes - playable, sometimes beatable

Over the weekend, I did a little bit of work on the small Dots-n-Boxes (DnB) game that I've been working on for March.

Dots and Boxes is Hard(ish)

Years and years ago, I took a game theory class taught, in part, by Elwyn Berlekamp. The man's an important figure in combinatorial game theory, but I was frustrated, because that didn't seem to cover the parts of game theory that I was interested in. We had one lecture on finding optimal mixed strategies, given a payoff matrix - which I still think is more generally applicable.

Berlekamp wrote the book on DnB, and surprise, surprise, it's a good example of using combinatorial game theory to find optimal play. Well, its one of the few examples of a game that is appropriate for CGT. When was the last time you played a good game of Nim? Yeah.

Later on, I saw John Conway speak at the Game Developers Conference, and the point of his keynote was that game developers should put more mathematical grounding in their games. I think he wanted more games that could have provably optimal play. If you want a contest to prove your mathematical insight, you're welcome to build such a thing, but that's (mostly) not the kind of games I'm interested in.

As part of that keynote, Conway brought a person from the audience (let's assume this guy wasn't a plant) and challenged the audience member to play a game of DnB. Conway pointed out that a 3x3 dot game of DnB has approximately the complexity of tic-tac-toe, and no adult would have any difficulty playing to a draw after they've played tic-tac-toe a few times. Conway proceeded to trounce the audience member game after game after game.

I expect there are a few tricks to 3x3 DnB, which Conway must have picked up, but it's weird to me that they're hard for a casual player to grasp.

I think one of the things that distinguishes DnB from tic-tac-toe is that DnB is a combinatorial game, where tic-tac-toe is not. If you're not familiar with CGT, that may require a little more explanation. In CGT, an important property of games is that they break up into independent smaller games. Nim is a good example of this kind of game - in Nim, players alternately take stones from a set of piles of stones, and the last player to move wins. With some analysis, you can determine that you can play optimally by XORing the sizes of the stone piles together and always leaving your opponent a game configuration that XORs to 0. (I leave the analysis to the reader. Or Google it. Or take it on faith. Or don't - it's been a while, but that sounds correct.)

So, Nim is actually one game, made up of several smaller games, each on a single pile of stones. Each time you make a move in the game of multi-pile Nim, you're actually selecting one pile of stones, and making a move in a game of single-pile Nim. The analysis of multi-pile Nim ends up being the study of how these independent games of single-pile Nim work together.

Back to DnB, though. At the beginning of the game, maybe you play randomly, and you try to avoid drawing a third wall on any box, or else your opponent gets a free box. Good so far. At some point, all these "free" lines have been taken, and all that remains are a number of chains. So, maybe you pick the smallest chain, and add a line to a chain, and your opponent takes that chain and gives you the next chain, alternating, and if you're lucky, you get enough of the long chains to win.

Wait, lucky? Did I mean that? Well, I shouldn't have - there's no luck in this game. Well, if you're actually playing randomly, there could be.

Anyway, you can see that these long chains have the feel of the single-pile games of Nim, and you can hear Conway and Berlekamp in the shadows, laughing at you. Should have paid attention in game theory class.

It's been a while since I read Berlekamp's book on DnB, but I recall him making some claim that an observant DnB player can beat a good computer playing DnB using normal lookahead. I think that he had a research student write a mediocre computer player, and Berlekamp was able to beat it at some reasonable lookahead depth. Maybe he was being unfair, or maybe he was making a point that you can abstract board state in DnB down to a much simpler representation (the set of lengths of chains in late-game play), which is much more susceptible to efficient analysis.

Weekend Progress

This weekend, I started by making just about the simplest computer player that I could - one that listed all the legal moves, and picked one at random. I like giving my AI opponents names, so I named this one "Randy".

This opponent isn't much to play against - one can readily beat him if you're paying any sort of attention. Well, and not trying to lose. I spent a little bit of time trying to lose to Randy, and found a few bugs where the AI kept trying to find good moves, even when the game was over.

After getting Randy to play as well as he was going to, I set Randy playing against another Randy, and it was interesting to me that it was typical that games typically were won by a large margin. This may have been due to there being a few very long chains, and once you started playing in a long chain, you usually cleaned the board.

After Randy, I proceeded to use the same framework of choosing moves, and added in a fixed-depth Minimax opponent.

One thing that I find frustrating is the gulf between the academic presentation of AI (particularly minimax game tree analysis) and the practical AI that's used for computer opponents in actual games. This sort of gets to my dismissal of John Conway's plea for more mathematically-based computer opponents. The problem is that the assumptions and the goals are completely different - academics typically assume that they have a single thread of execution and can consume that, maybe for a maximum length of time, and if they can come up with an optimal answer, that's great, or, if not, at least a best guess. In practical opponent design, it's more important to provide a good challenge to the human, and you typically only get a few milliseconds at a time before you have to give the CPU back to let the game render or play music or whatever. Some of this can sometimes be handled by threads, but it seems to me that being able to make incremental progress towards a good solution is important, as it'll give you more room to negotiate as the other parts of the game consume more or less resources.

So, I hacked together a simple minimax opponent, and I'm being all sorts of gross, as I'm making heavy copies of a heavy board state object, and I'm not caching them, so if I'm evaluating one board state in one branch of the game tree, and then I re-evaluate that board state in another branch, I don't reuse the knowledge I came up with, I redo all of the work. So, branching factor kills me.

Even with all of that, I play a little bit of 3x3 dot DnB, and the 2 and 3 depth minimax player is playing acceptably - not perfectly, but decently. Depth 3 on 3x3 can play me to a draw and beat me now and then, and I can beat it, but I think that means I'm a terrible player.

I tried playing 3x4 dot DnB, and it was at the edge of my patience. I also cranked it up to 4x4, and that was well outside what I wanted to wait for.

This morning, I added in a simpler representation - I took each piece of important information out of the board state and combined all of the data into a single number that uniquely represented the board. In the code, I call it a 'hash', which is not exactly correct - it's a binary packed representation. I can turn a board into a 'hash', and construct a board from a 'hash'. From this, I can start caching results, which will help prune out redundant evaluation.

Another thing I could do is look into implementing alpha-beta pruning, which ought to eliminate a bunch of other unnecessary evaluation, but I think won't be as useful.

Another thing that would help a great deal is to identify equivalent boards. The easiest set of equivalences is to recognize that rotating a board 90 degrees doesn't make an interesting difference when figuring out the best move. If you can rotate the board into a canonical best state, and evaluate that, then you can reverse the rotation and get the best move for 4 rotations (on a square board) plus 4 more with reflection. That's an 8x speedup, which is pretty good for shallow trees.

Another bit of equivalences that'd be useful to capture would be to boil the board down to chain lengths. A chain of length three behaves the same way, no matter where it is on the board. And then a chain of three and a chain of five combine the same, even though there are a lot of ways that those two chains might be positioned on the board.

Monday, March 11, 2013

Marching forward

I told myself that my March game was going to be deliberately small, as the Space Courier game was a lot bigger than I had planned, and (real) work needs to be able to expand to fill the time that it will, so best to keep the after hours coding project scoped small.

So, I decided to again punt on designing anything new, and this time went to an old standby, the dots-and-boxes game.

This weekend, I started off by copying code over from the Space Courier directory (woohoo, code reuse!), and culling out the stuff that was obviously unrelated to dots and boxes.

I added in a little bit of drawing code, and a little bit of "if the player clicks at position x,y on the screen, what line segment do they mean?" code.

And then I got distracted by other stuff in my life.

Thursday, February 28, 2013

It's Time to Bring This Ship In To the Shore IN SPACE

OK, As of last night, around 11:30, I pushed what I considered the completed version of Interplanetary Space Courier. Two games in two months, I didn't go completely crazy, and I haven't lost my day job (yet).

What Have I Learned So Far?

 Oh, probably a great number of things, mostly little bits of techniques that I've used in previous games that I've adapted to new stuff. As I go, I'm building up a toolbox or library that I can go back to and loot from, which will make things easier on future projects.

So, the easy answer is that there's lots of little things I've learned how to do in JavaScript, like playing sounds, or drawing backgrounds.

I've also learned that JawsJS is a fine framework for my JavaScript games, but as I go forward, I'm leaning on it less and less - so I may end up abandoning it entirely and just use my own code. It's not bad, it's just not helping me as much as some other frameworks have done in the past. (I'm thinking primarily about PyGame, but PlayN and DirectX might be worth considering.) One thing that contributes to this feeling is that HTML5 with JavaScript is a pretty feature-rich platform to begin with, so I need less support to get my work done.

One great area of stuff I haven't learned is good Closure practices. I took on this challenge of One Game a Month in part to force me to write more JavaScript, and I chose JawsJS because it was friendly to the Google Closure toolkit, which is something I want to become fluent in.

I've learned that posting to this blog helps me maintain momentum - just journaling about stuff makes it feel different - talking about features I completed, or pieces I'm working on puts it in a different perspective than just seeing it on a TODO list.

On a meta-level, I've reminded myself that a game jam format (and One Game a Month is sort of like 12 month-long game jams stacked end to end) is a good way to provide a deadline, and a deadline provides focus, but it doesn't guarantee that you'll accomplish the things that aren't your top priority. I've seen so many people jump into a game jam, maybe a LudumDare 48 hour challenge, and say "Ok, I'm going to learn Python, and PyGame, and...". You know, more power to you, but finishing a game is hard, and learning a language isn't easy, and doing both is maybe biting off a lot.

So, about my challenge to myself to learn JavaScript and Closure and HTML5, and make 12 games...

Well, OK, so it's a little crazy, sure. But I'm not trying to learn the language in a weekend - I've already learned bits of it, enough to get by, most of the time. Closure, like I've said, I need to remind myself to incorporate that more into my workflow. Closure is a good tool in that you can integrate it into your existing project a little bit at a time. I just have started at the dependency management support and minification, and haven't incorporated a lot of other good Closure practices.

What's Next?

I want to do something that's tablet-friendly, and doesn't take a lot of time, to give me time to breathe a bit. It'll also give me time in case work goes crazy, like I fear it might.

My current thought is to make a Dots and Boxes game with a pretty straightforward alpha-beta pruned adaptive-depth game tree evaluator. I expect to cache evaluations, which should keep the tree evaluation under control. The one interesting bit is that a player may get to go again after their move, which is a small wrinkle in the implementation. Not hard, but important to get right.

I'm also thinking of making a Choose Your Own Adventure-inspired game book. I knew that going into this that I didn't want to just do computer games (and certainly not just browser games). So, a branching-path game book would be kind of fun. It'd require me to write English, instead of JavaScript. Hm, I could do both if I wanted to make a fancy app. Or, maybe not. I've looked a tiny bit into the EPub format, and have downloaded some Python code that makes EPub files, so there's some opportunity there.


Wednesday, February 27, 2013

Now, with more visible data. Also, bugs. IN SPAAACE.

Whew.

Coming up on the end of February, and things are mostly done.

Things What Are Working

Persistence

I transferred the persistence code from cookies to localStorage, which works just fine, and simplifies some of the code, because I just jam a bunch of data into an Object, which I use JSON.stringify() on, and I'm done. Similarly, JSON.parse() and I'm back up and running on the other side. No nasty parsing numbers in my own code.

Running out of Fuel

It's now possible to exhaust your fuel supply, which triggers a lose condition. There's no win condition, and I'm unsure if I'll get around to implementing achievements, which would have been sort of like win conditions.

More Data on Trading Menu 

On the buy/sell menus, I now display how many of an item the planet wants or wants to sell, as well as how many of the item you have. This makes navigating the planet menus a little less obnoxious.

Ship Inventory Dialog

You can press 'I' while inflight to see what you're carrying, as well as the price you paid, so that you can decide if you want to sell.

Things What Just Ain't Right

Persistence

At the title screen, there's a hacked-in option that allows you to discard the stored status. Something broke, and that no longer does anything.

Ship Inventory Dialog

If you leave the game with cargo in your holds, when you come back, the per-unit cost doesn't show up correctly in the inventory dialog.

Sounds

I've noticed that the cash register sound has been truncated recently - perhaps due to a refactoring that I did recently. I think I need to collect the sounds into a single place so that sounds don't go out of scope.

Positioning Large Ships on Landing

Some of the bigger ships look silly when they're positioned overlapping planets. It'd be easy to add in an offset to push them further out.

So, How Does It End?

I definitely feel like I've got a satisfying quantity of code written. I'm not entirely sure that it's balanced the way I'd like, and it feels a little sparse; this is a good part of a game, but it feels like you need some more conflict to make it worth the treadmill. Still, as a tech demo, it works. As an exercise in building a smallish (but larger than I had planned) chunk of code, I let a bunch of sloppy stuff in. I can't say that the sloppiness actually hurt me, but it makes me less eager to reuse that code, so it seems like it will hurt me down the road, or at least, benefit me less than I wanted.

More post-mortem-y-ness, I imagine, in a couple of days.

Tuesday, February 26, 2013

Buying, Selling Ships... IN SPACE.

The month's almost over, I'll be able to retire the "IN SPACE" suffix soon.

At 9am today, I pushed out a version that had buying and selling of 8 different ships. I was quick to call that "feature complete", which is perhaps a bit hasty. There's still plenty that I really want to get done by the end of February.

  • Rewrite persistence system to use localStorage instead of cookies, and then use the new persistence system to store trade history, ship position, sector coordinates, what ship the player has purchased, and anything else I'm forgetting.
  • Player loses when they run out of fuel. Permadeath is harsh, but it makes venturing out into the void a real risk. Not so much of a risk when you have a fast ship, but still.
  • Have a player inventory screen to see what's in the hold and what price you paid (to remind you not to sell for too little).
  • Warning klaxon when low on fuel.
  • Experiment with inertial movement - this would really change all the ships' accelerations and top speeds to make them feel right. It will also require a slow "life support" cost to maintain the tension of getting from sector to sector.
  • Achievement for getting a lot of money
  • Achievement for exploring a lot of systems
  • Achievement for limping in to a system with less than 1% fuel
  • Achievement for reaching distant sectors
We'll see if inertia gets in. And achievements. At one point, I was thinking about having asteroid mining as a thing you could do. That's not getting in.

Even though I'm looking at a lot of features that'd be neat to see in the game, I can still look at what is in the half-full glass, and be fairly satisfied. I've wanted to make a game something like this since playing TradeWars on the old BBS systems I dialed into back in 1988. Yikes.

Monday, February 25, 2013

BigWorld, Economy, New Ship Art -- mostly IN SPACE

I took most of the weekend, and got a few big pieces working:

Sector to Sector

I had refactored the planet code to be contained in a Sector object, and procedurally generated based on the coordinates of the sector, which then made it possible to fly off the edge of Sector(0, 0) to Sector(0, 1) and see new planets, but then fly back to Sector(0, 0), and all your old ports of call are still there. Pretty easy to get working, no real surprises there. I toyed with the idea of having 4 sectors in memory at once to permit drawing planets at the corners, but that was more work than I wanted to do at the time, so I just used a single sector, which I figured would cause problems if there were planets right up at the edge of a sector - planets could blink in and out as the player crosses the boundary.

Well, I expect that's happening, but I haven't seen it, yet, and space is large, so I'm going to conjecture it's not a big problem, and I'll work on other stuff.

I'm pleased that flying from sector to sector is currently a tense activity; you don't know if you've got enough fuel to reach there (at least with current levels of fuel expenditure). If I tweak the physics, I'll want to make sure I keep this level of danger.

Buying and Selling

Oh, I've had buying and selling in before, but now, when you buy and sell, you deplete the quantity of goods for sale, or deplete the amount of goods wanted. This causes prices to rise and fall. (I have a hard time keeping straight which prices I'm talking about, so the code has functions like "computePricesForPlayerSelling", which is cumbersome, but unambiguous.)

One side-effect of this is that you can take a profitable route and make it unprofitable, even before you account for fuel. So, pay attention, buying and selling technology starts out being quick cash in your pocket, but there's nothing keeping you from going broke buying high and selling low.

Ship Art

The first ship sprite I had in the game was a pretty simple geometric shape, reminiscent of old vector space games. I had a copy of "Bill Budge's Space Album" back in the day, and one of the games on that was a pair of spaceships flying around a planet. Not exactly SpaceWar, but along the same lines.

I've been planning to add an ability to buy new ships (to have something to do with all that cash, for one thing), and that means additional sprites. I had doodled some 30 different recognizable ships in a notebook, but that was a lot. I decided to narrow down things to three variables; speed, range, and cargo capacity. Each ship would either have a high or low value of each of these three variables. That makes 8 ships, which is a reasonable place to start.

I set out to draw sprites in GIMP, which isn't a terrible tool for the job. I don't know if some of my frustrations could be addressed by adopting better habits, or installing special plugins, but I'm able to get my work done. I'm shooting for a 16-bit color palette, which gives me structure for picking colors. I want yellow, and there's only a few of them, so I don't paralyzed with too many choices.

I started out making all my ships fit into a 32x32 pixel square, and then I realized that some of my ships would have to be a lot bigger, so that meant going back and redrawing some of my ships. Along the way, I used some photographic references, which led me away from the stylized, clean, look I was using elsewhere, so I went back and redrew some of my ships.

I now have 7 of the 8 ship sprites at a minimally shippable level of quality. I could go back and tweak them with all the time I have left, but I have to walk away from the art so I can get other stuff done.

Only a few days left. Buying new ships is an important piece of gameplay that still needs to be written, and then it's revisiting and improving stuff that's basically working now. This project's grown a lot from where I started it, but I'm pleased with where it's going.

Friday, February 22, 2013

Randomness Leaves Town, Randomness Comes to Town, IN SPACE

As I've mentioned earlier, I've got several chunks of code that I want to work on over the next week. Almost all of them have a few properties:

  • Supporting another piece of the code - if I change this bit, that other piece is going to need to change. Part of this is sloppy coding, which I admit to, and know I can do better. But most of it is just tight coupling of what the systems do - if I change the way that ships move, that changes the way that planets need to be laid out. And those connections are usually two-way links; the "birthday cake" diagrams I drew in class about abstraction layers aren't helping me here. Or, you know, maybe they would, if I thought through the problem better. But there's no time for thinking!
  • Perched on a refactoring cliff - the work that I need to do involves taking working code and putting it into a state of not-working before getting it to work again. I should really set up a local Git repository to take some of the risk out of changes like this (also, to lessen my exposure to catastrophic machine failure). I usually like to have lots of incremental work that can go in without destabilizing the game. These changes aren't that.
  • Not well-suited to screenshots - working on economic systems is important, but how do you take a picture of them? I could have a dashboard, demonstrating that the systems are working, but that's not what the user would see. Maybe I should do it, anyway, to prove that it's working to myself. I'm sure to have printf-debugging log file output, perhaps that's sufficient.
  • Self-directed - this isn't a big deal, but some of the stuff on my TODO list has come about from external feedback. Some are requests for features that I've wanted to do anyway, some are other people's ideas of how they'd like to play the game. I need to remind myself that these are all good, and I need to consider them all, and decide what gets in and what doesn't. February 28th is coming up fast, so not everything I want will get in, and not everything that friends suggested will, either. But I'm happy when I get to tell a buddy that his feature is in and working. Most of the big stuff I'm working on is on my personal must-have list, so there's nobody to brag to but myself.
So, that's the knot that I'm going to try to unravel over the next weekend.

I'm happy to say that I put in a little bit of time into the BigWorld procedural universe generation refactoring task, and it's going well. I've moved the planets (aside: I'd like to call these things "systems", as that feels more astrophysically plausible, but it's also more awkward, and the code says "planets") into a new class called Sector. I also have a SectorMgr which provides Sectors to the rest of the game. Is it a factory? A cache? I think that's getting underneath the abstraction - it serves up Sectors based on sector coordinates, and the illusion to the player is that the universe is huge and unchanging (at least, on the level of what planet systems are where). Carve away a little bit at it, and the Sectors are coming in and out of memory, but they'll be there when you need them.

So, right now, the SectorMgr is serving up a single Sector, and that Sector is procedurally (ish) generated from a seeded random number generator. Which is just about indistinguishable from the way the game had been working up until now.

The bit that is noticeable is that I keep reusing the same seed ([0,0]), so restarting the game no longer gives you a new layout of systems. You get a random layout, but it's always the same random layout each time.

One of the next things to do is to allow the player to fly off the edge of a sector and give them a new sector to fly onto. This isn't hard, just a little bit of changing some of the references high up.

Once this gets working, players may notice that they've seen all 1570+ of the hardcoded planet names I've accumulated. This will bring me to another procedural exercise: generating system names. A pretty simple Markov chain generator should get me most of the way. I have some ideas of ways to make it better, including working from both ends; names have interesting suffixes that I want my name generator to produce. We'll see if I'm still that ambitious as I write the code.

Once all that's up and running, the next huge system is the dynamic economic model.

Thursday, February 21, 2013

Haven't I seen you before? IN SPACE?

Ah, if it isn't me old friend [username]. Hail, and well met.

Home is where you wear your hat.

I spent a few hours last night/this morning working on getting persistence working in the Space Courier game. I'd seen about 12 lines of code in several places for reading and writing cookies, and I figured I'd be able to put it in and be able to have fuel and money persist from session to session.

The first problem I ran into was that Chrome doesn't like the idea of cookies if the page you're viewing is using the file:// protocol instead of http://. Well, it doesn't mind you trying to read or write them, it just silently fails. I'm OK with Chrome making fairly aggressive security policy, that's what I want it to do. (How are those popunders working?)

Somehow, I had the insight that running off of the local machine's filesystem might have caused problems (I knew that cookies have to have connected domains, and maybe the leap of inspiration wasn't so far), so I was able to push a version out to my webserver, which worked, but it wasn't as fast as I'd like for rapid iteration on features. Maybe this is an exceptional case where I can get some wobbly structure in place that works sufficiently for webserver-based players, and I don't need to worry about it for filesystem-based play. (I want to say 'online' and 'offline', but that gets confusing; if you use the "navigator.onLine" property, that seems to be true, even for filesystem-based pages, which doesn't make a lot of sense to me.)

I think the next step here is to use the localStorage API (see WebStorage, DOMStorage, and sessionStorage), which gives me what I'll need to keep working. It'd be kind of nice to have a uniform API that works well across all browsers, under both http and filesystem use, but I really shouldn't be trying to solve problems I don't have right now.

Ok, so cookies are problematic, but I have some workarounds. Good.

Saturday morning serialization.

Another problem I bumped into, which was probably a little bit of my own confusion, had to do with implicit and/or explicit conversion of strings to numbers or vice versa. As I shift over to using localStorage, I know that the documented behavior is that the keys are strings and the data is strings. If I want to store numbers, I can turn them into strings (probably implicitly, which is OK), but then to read them back, I'll want to turn them back into numbers. JavaScript isn't picky about integers versus "real" numbers (floating point isn't really a data type, it's a representation choice).

What I am doing right now is reading a string out of the cookie for the money value, then converting it to an int, using
moneyVal = moneyString.parseInt();

And, similarly, for fuel:
fuelVal = fuelString.parseFloat();

Again, this is adequate to my requirements (for now), but I might want to have a more flexible data description object, saying that fuel is a float, and money is an int, and you know how to serialize and deserialize ints, so when I start talking about how much ore the player is carrying around, we don't have to go through all that again.

There's only seven days left in the month, so I'm reminding myself at every step that I need to do what makes my job easier in the short term, and defer working on stuff that might make my job easier sometime that's not right now. Or, at least, this week.

Interdependent Day

There are still several meaty pieces of code that I want to write this weekend, and it seems like three of them are all fairly tied together.
  1. "BigWorld" procedural generation of planet placement. This is probably the one that I need to start on, but it's also the one that has the most work to be done, risks breaking the most code, and will have the least visible result. The idea is that I'll generate data for a small number of planets on a small "sector", and as the player moves off of that sector to another sector, I generate new data. If the player returns to the first sector, I regenerate the data in the same way, and everything looks the same to the player. This will be cool to me, once I get it working. But it breaks a bunch of other stuff, like knowing about all planets the player might visit, or have visited. That data just isn't around anymore, so I have to be satisfied with notes like "planet 6 in sector (0,3)", and when the player gets back to sector (0, 3), then I can actually look at planet 6.
  2. Dynamic planet economies. I could do this now, but if I did the BigWorld feature afterwards, I'd have to redo the economy feature. So this probably goes second. As players go around the world, it'll feel more "alive" if their trades have an effect; if I bought a lot of ore yesterday on Ares, and sold it today on Ganymede, the next time I went to Ares, the selling price of ore might be a little higher (moving on the supply/demand graph), and the next time I went to Ganymede, the buying price might be a little lower. This will have interesting effects (I hope), pushing the player to explore more space to keep getting good profits.
  3. Upgrading ships. This doesn't seem super connected to the other features, but it's got some dependencies back and forth with the BigWorld implementation. I've thought about a bunch of different ways to upgrade your ships, and what I think I might do for now is just have a catalog of different ship types. But maybe you can't buy all ships at all planets. So that's a BigWorld connection there - how do I make sure that ships are available? Flipping it around, if I don't have a lot of ships to explore space with today, how will I properly balance the sector size and system density? That's a soft back dependency - I'll just wing it for now, and then adjust the constants to tune things later.
And then, there's polish to work on, including making planets prettier, making the menu UX clearer (why can't I buy any more Organics? Oh, I've got a full hold of Ore), and switching to using a more physically realistic inertial movement implementation (more balancing and tuning tied up in that).

A buddy has been bugging me for varying planet sizes, which I could totally do, maybe I'll toss a 0.8 - 1.2 randomization in when I do the procedural sector population. But again, it's a polish thing, and not something I want to do before I get the big three, above, complete. And, I'd want it to feel right with the upgraded ships, which might have different sizes, themselves.

Tuesday, February 19, 2013

Space Courier: Now with buying and selling IN SPACE

It occurred to me over the weekend that I'm not really making a courier game so much as a cargo hauling and exploration game. Still, I'm sticking with "Space Courier". I want my own font. Somebody should get on that.

I intended to put a lot of work into the game over the long President's Day weekend, and I did spend several hours on Monday, so I should be satisfied with that. Part of time management is being honest about what time you really have available to your project.

I added in a dialog box with a menu tree of different activities (buying and selling goods, buying fuel). In projects past, I've done this sort of thing as a stack of more or less uniform items, so that exiting out of a part of the tree is just popping a thing off the stack. This time, though, I did some gross hardcoding; there's three levels of the menu tree - a toplevel menu where you pick buy / sell / fuel / leave, a second level where you pick what good you want to buy or sell (ore / organics / technology), and a third where you confirm the actual price being offered. I'm not really pleased with the design, but it's working for now, and as I'm rushing to get stuff into the game, I'm sacrificing code quality.

Which makes me reflect - is that really what I want to be doing? One of my goals is to make a game a month, and I seem to be on track to keep up with that. But another goal is to incorporate good JavaScript / Closure design habits, and I think that's being thrown under the bus. Perhaps my next month's game will allow me to rebalance, doing a less technically challenging game, but giving me time to refactor some of the code I've been carrying forward.

One half-joke I've made several times is that a game engine is whatever you carry forward into your second game. I've been dragging around a little bit of code from one project to the next, and have some ideas of ways that I want stuff to work, but it's not packaged nicely. Really, that's OK, because my goal isn't to have a fancy engine at the end of 2013, it's to have good practices and (at least) 12 games playable.

Next up:
  • saving game state to a cookie in the browser
  • dynamic pricing, so that planets supply or demand can be depleted by player actions
  • "big world" system placement, using procedural naming and sector-based system distribution. This will be a huge change, as I won't be able to think about the player visiting all of the planets, or having known systems to refer to.
There are several user requests that have come in already that are on my list:
  • make it easier to understand what the player has in his ship, which will make it more clear why a system might not want to buy or sell anything.
  • frictionless / inertial / Asteroids spaceflight model
  • vary the sizes of planets
They're all good ideas. Some are more good than others. If and when I get to them, I'll get to them.


Monday, February 11, 2013

Space Courier: Now with more Anaxides

I just made that name up.

The space courier "game" now populates the galaxy with a sampling of 100 planets, drawn from a list of... I forget now, something around 1570 potential systems. There's one big file that associates a name with a planet color - I had been thinking that I might want to have a lot more specific information about a planet, but I think just saying that Tattooine is a yellow planet, and Barsoom is red is sufficient. Given that, I should probably just make a big list of yellow planets, red planets, and so on.

I borrowed some names from familiar fiction, which feels like light trespass, but I'm not investing a lot of gameplay in the fact that planet #90 is named, let's say, Gelidus. If somebody wanted to send me a cease-and-desist, I'd be OK with renaming it. Gallidous, maybe.

But, to thin out the use of potentially legally uncomfortable use of trademarked names, I looked for other proper nouns - I recalled hearing about a difficult to pronounce name applied to a planetary body outside Pluto's orbit. That sketchy description didn't immediately yield to my Google search attempts, but with persistence, I found that the name I was looking for was "Quaoar". Oh, and starting there, "Sedna" is also a perfectly good name. Hm, so is "Palomar", though it doesn't sound so entirely other-worldly. But cultures name stuff after scientists, so, sure.

And, from there, it was a short leap to looking at the names of Greek gods on Wikipedia, and I had a list of over 1500 planet names before I clicked on the link to see also "List of minor Greek deities".

Every now and then, I'd insert a name that came from my own imagination, often a variation on a name I was taking from Greek myth. "Chicocrates", for example, came to mind when I was entering "Hippocrates". And, from there, "Harpocrates" and "Grouchocrates". Humor is hard.

So, if you play the game today, you can fly in a galaxy of 100 planets, pulled from my list of 1500 names. It seems like I ought to be able to be smarter and populate sectors of space from my list of planets in such a way that the player can fly from sector to sector, and only have a few sectors in memory (one most of the time, but up to four near a corner) at a time. Maybe, if I get procedural name generation working, the player could fly for very long distances (limited by the precision of an IEEE floating point number) without running out of universe. That'd be something.

Brainstorming Feature Level 1 (1500+ planets):
Shuffle the list of planets, based on a random number seed. Partition the planets into sublists of 100 each, which will be used to populate "sectors". Within a sector, position the 100 planets based on a seeded value. Place the sector tiles together in an easily-reconstructed fashion (a square grid would be easy, or maybe a hex grid, if I was feeling fancy). With care, it would be possible to create a single sector without building any of its neighbors, thus keeping memory use low.

Brainstorming Feature Level 2 ( many, many, more planets):
As above, but use procedural name generation (also here) so that the planet names aren't limited to my imagination (or my ability to crawl Wikipedia). Populate a sector with planets seeded by the coordinates of the sector and a single universe constant.

In any case, my notes for keeping track of trades and economic data seem like they're sufficient to provide "local history", to give the player's actions an impact on the world (if you do a tight trading loop between adjacent systems, you'll quickly expend the goods available for trading).

Having a vast universe to explore is interesting, but before long, I'll need to actually allow the player to buy and sell stuff. That's next.

Friday, February 8, 2013

Space Courier: Now We're Movin'

I should really get into the habit of writing these when I have easy access to the screenshots.

Small improvements to the game today:
http://bigdicegames.com/SpaceCourier/courier.html

  • Planets - I put simple sprites (32px circles) in last night, including what may appear to a casual observer to be a small moon.
  • Ship "animation" - when you hold the up arrow key, I increase a throttle variable. At certain points as that variable goes from 0 to 1, I switch from no rocket thrust to small thrust to full thrust. Likewise if you take your finger off the key.
  • Ship movement - the ship was turning, and now it's moving. Well, the galaxy is moving. That is, I'm tracking "world" positions for the planets and the ship, and then I'm subtracting the ship position from the planet position to get the location of the various planets from where the ship is, and then I'm adding in some window coordinates to make everything centered in the viewport. Pretty straightforward stuff, and it'd be slightly less confusing if I had a better term for "world" coordinates when I also have "planet position", which may be in any coordinate frame.

To Do:
  • Text rendering - gotta do this sooner or later, and almost all of the important gameplay features remaining require this. I kind of want to have labels on planets, but that might be distracting. Or maybe awesome. We'll see.
  • Sounds - the optional OneGameAMonth theme is "sound". And I downloaded a few samples from freesound.org. In space, no one can hear you argue that rocket sound effects are out of place.
  • Docking with planets
  • Ship inventory
  • Ship upgrades
  • "Deck of Worlds" - right now, the planets have no identity - they have positions and sprites, but that's all. I'm thinking that I'll author a collection of defined planets (Aaalderoid is a peaceful, blue planet that produces 100 food, 10 fuel, and 10 ore a year). Initializing the galaxy map would consist of drawing cards from the deck, and then placing them somewhere in my navigation graph. This may lead to more custom planet art.
  • Navigation graph - right now, the planets just cluster around the origin, more or less. I want to stretch them out so that no two planets are closer than roughly one screen height, and some are much further away. You know, for better exploring.

Thursday, February 7, 2013

One Game a Month, part 2 - Electric Boogaloo

One day, I'm really going to have to watch Breakin' and Breakin' 2.

Having squeezed "Switch 2013" into a vaguely playable condition in January, now it's time to start the process over again for February. February's about 10% shorter than January, I'm starting late, and there are fewer holiday weekends... so it seems like it's a perfect time to increase the scope.

See also "Second System Syndrome".

Still, I've chosen a direction for the next game: Interplanetary Courier Missions. There are a bunch of places to go with this, and I certainly played enough TradeWars 2000 and Star Trek at a formative age that the obvious stuff is begging to be implemented.

I'd like to try to avoid pouring every possible space game activity into the game - maybe this game has no combat at all (what?!), which would seriously limit the scope, and keep me from diving into full-on 4X territory (Explore, Expand, Exploit, Exterminate). Maybe the first three, but that has problematic abbreviation problems.

So far, I have a ship that renders onscreen, and turns left and right when you press the arrow keys.

http://bigdicegames.com/SpaceCourier/courier.html

Nothing exciting yet, I'll admit.

Some other features that I'll want to add:
  • text rendering
  • fuel consumption
  • saving state from session to session in cookies
  • docking with planets / space stations
  • randomized galaxy map
  • randomized economic profiles
  • ship upgrades
That's plenty, really. Not much of a game, but you know, good for February.