TweetRPGRandom project idea that I've prototyped now. An RPG that you play via twitter. The game plays on a server somewhere and you get status updates about the party via twitter. Each status update comes with options which you can select by replying to the tweetRPG twitter account. It's not running live at the moment, so don't bother joining just yet but here's a run of me going through a rather poorly written single level adventure: @cac Party: Ormon (Archer/1 [10/10]) Wot (Warrior/1 [10/10]) Baz (Mage/1 [10/10]) @cac Into The Lair: The Goblin King has stolen the Orb of Kain, enter his lair and retrieve it @cac The party enter a dark cave, the only known entrance to the lair @cac The party run into a band of 3 goblins. FIGHT or RUN? @cac You run! Some of the party are hurt in the escape! Ormon [10/10] Wot [10/10] Baz [10/10] @cac The party come across 3 goblins. FIGHT or RUN? @cac The goblins are defeated! Ormon [10/10] Wot [10/10] Baz [10/10] @cac The party run into a band of 4 goblins. FIGHT or RUN? @cac The goblins are vanquished! Ormon [10/10] Wot [10/10] Baz [10/10] @cac The darkness lifts to reveal a room containing a small chest. IGNORE or OPEN? @cac The chest is trapped, the party are hit by darts.Ormon [8/10] Wot [8/10] Baz [7/10] @cac The party come across 3 goblins. FIGHT or RUN? @cac The goblins are defeated! Ormon [8/10] Wot [8/10] Baz [7/10] @cac The party come across 3 goblins. FIGHT or RUN? @cac The goblins are defeated! Ormon [8/10] Wot [8/10] Baz [7/10] @cac The party run into a band of 4 goblins. FIGHT or RUN? @cac You run! Some of the party are hurt in the escape! Ormon [8/10] Wot [8/10] Baz [7/10] @cac The party run into a band of 4 goblins. FIGHT or RUN? @cac You run! Some of the party are hurt in the escape! Ormon [8/10] Wot [8/10] Baz [7/10] @cac The party run into a band of 4 goblins. FIGHT or RUN? @cac You run! Some of the party are hurt in the escape! Ormon [8/10] Wot [8/10] Baz [7/10] @cac The party run into a band of 4 goblins. FIGHT or RUN? @cac You run! Some of the party are hurt in the escape! Ormon [8/10] Wot [8/10] Baz [7/10] @cac The party come across 3 goblins. FIGHT or RUN? @cac The goblins are defeated! Ormon [8/10] Wot [8/10] Baz [7/10] @cac The party enter the throne room and recover the Orb. Quest Complete! @cac There are no more quests available. So, the party was generated and go through the adventure asking you for input as and when they need it. The code (which I'll release in a bit) was a pretty simple affair thanks to the wonderful Twitter4j. Hopefully soon you'll be able to follow tweetRPG ad join the adventure. Ok, it's not that exciting but it's pretty open ended and was a bit of fun to write. You can check out a the little website I put together as a help page and sort of short explanation of the idea. I don't spose it's the first idea for a twitter game or the last, but silly it definitely is.
<quest name="Into The Lair"
description="The Goblin King has stolen the Orb of Kain, enter his lair and retrieve it"
complete="The party enter the throne room and recover the Orb. Quest Complete!">
<level id="0"
entryText="The party enter a dark cave, the only known entrance to the lair"
turns="10">
<combat text="The party run into a band of % goblins."
win="The goblins are vanquished!"
foe="goblin" level="1" min="3" max="4" weight="10"/>
<combat text="The party come across % goblins."
win="The goblins are defeated!"
foe="goblin" level="1" min="2" max="3" weight="10"/>
<room text="The darkness lifts to reveal a room containing a small chest."
weight="3">
<option name="ignore">
<message txt="The party moves on through the dungeon"/>
</option>
<option name="open">
<roll d="6">
<range low="1" high="3">
<damage low="1" high="3"/>
<message txt="The chest is trapped, the party are hit by darts."
hp="true"/>
</range>
<range low="4" high="6">
<gold low="50" high="300"/>
</range>
</roll>
</option>
</room>
</level>
</quest>
The best bit is that the quest description has brought out of a series of issues for Yore's development (see the XML above). Cross project pollination for productivity! By kevin at 2009-04-15 21:50 | 1 comment
Why I left JGO (and others)?If you don't know what JGO or JavaGaming.Org is then turn off now So, it's been a couple of weeks since I retired from some of the forums that have been a big part of my life for the best part of 10 years. It was a snap decision, in that it only took a moment to press the button, but it's been coming for a while. First let me say, just because I don't post, doesn't mean I don't read. For instance RSS is still churning out JGO to me day after day. I still think there's a lot of good to be had from the communities. In normal fashion for me, reverse first, why didn't I leave JGO? 1. Because I don't believe in Java gaming any more - no, as you can probably already see I'm just as much a Javaholic as I ever was. Slick continues, Phys2D continues, the games keep coming and the projects that arn't public still go on. 2. Because it's too much like hard work - it wasn't hard work at all, I enjoyed asking and answering questions, moderating and most of all posting my new games and getting feedback (most of what game development is about for me). 3. Because the 4K results didn't go my way - seriously? As I keep saying over and over, 4K is about the game not about the results. If only people would accept that we wouldn't have the ridiculous debarkle every year. 4. Because I hate everyone at JGO - There are a few people my personality clashes with, as in real life, ok, maybe more than a few. However, in general I think we all have the same goal and so they can't really be that bad can they? So, why? At the time I thought I was doing it because I was getting stressed so much by the types of conversations that had begun to be the bread and butter of the place. Now, while the stress was definitely there, I sort of think of it as a silent protest (not so silent any more I guess) about the state of the place. The community used to be a community - we used to work together. Comment on each other's games, help each other out with code. Work together to make it possible to post Java and Games Development in the same thread on places like indiegamer, tigsource and gamedev.net without people falling over laughing - and we got a long way. It was a community, we worked together to solve our common problems because it's more productive that way. Unfortunately that community has been dissolving over the past few years. More and more posts are about pushing remits or worse still pet technologies. More and more posts are arguments about which way of doing something is the right, proper and the only way of doing it. There's less and less helping each other out. More than anything else, there is less objectivity. As a community it's failing because we stopped acting like a community. Recent events and posts are what finally got me to click that button, but looking back over years of posts as I have now it's been coming for while. I tried starting a community project, everyone jumped on, great sign of recovery I thought. However, no one wanted to settle on anything, it quickly divulged into 3 projects, each of which had a set of independent directions - why? Who knows? I'd guess it's because the no one wanted to put their own time on the line for anything but their own direction - no one wanted to work for the community. The 4K contest was my last bastion of hope. Normally this is where the community pulls together and really starts helping each other out. This year's was a bit quiet on that front, but at least we got some really good games. However, as normal a "discussion" breaks out about whats right and fair in judging instead of focussing on the fact that as a community we produced 63(?) full games (and for another year, managed very well) - all of which were fun, all of which might at some point in the future get someone else to think about Java and Games again. So, this post is probably pretty unfair on people. There are still people doing the right thing (tm). Being objective. Giving their time freely. Not pushing their own remit/game/library at every given opportunity - and as I said, I still think the community of people has a lot going for it. Still the best Java developers in the world visit the forum, with the best pragmatic programmer attitudes and some of the wierdest knowledge about Java, the VM and the SDK anywhere on the planet. As to whether I'll be going back, probably at some point. Maybe I already have? If I do it'll be to lurk and hope that the place is going to spring back into what it used to be. It stressed me out a lot to see something that was so great, fall. I just don't see how it's going to claw it's way back. Tong AppletThanks to the magic that is KappaOne and BossAttack, here's the embedded version of Tong - the scripts from BossAttack are just too cute now! TongSpent this evening finally remaking the game I downloaded on my DSi. It's a really simple concept, but a lot of fun. Not sure if I've really captured it all yet but I may spend a bit more time soon. It was intended to be a celebration of releasing the Slick 0.3 Release but it was a little late due various life related stuff. You can play via web start and an applet version will be along soon. Screwed UpSo, I left the forums I visit. This was an attempt to free up some space in my head. That hasn't really worked. Limiting my online existence hasn't had the impact I'd hoped. I still spend 90% of my time angry at one thing or another. I'm spending a lot of time in arguments that are pointless. I'm losing the will to succeed. I want to fight with people, I'm not sure why. The fall out has been that I'm starting pointless debates, and getting offensive for no reason. This came to a high point this morning when I replied to a benign disagreeing post with an offensive rant - more annoyingly to one of the few people I actually do get on with in the world (really sorry about that). I'm not sure what I'm supposed to do any more. Every suggestion, every solution, every comment seems like an attack. Medication doesn't help, I'm not a fan of it at the best of times. People IRL keep saying I've got a lot on my plate at the moment - it's understandable I'm getting worked up, but really - is it? I don't think so. Maybe I just need a holiday, but who's got the time or the money at the moment? I guess I just need to free up more space. By kevin at 2009-04-10 11:35 | Life
Level Generation for Yore DungeonsYore (the current project, Tales of Yore) is coming along slowly but pretty nicely. I've mostly been focusing so far on how I'm going to be able to generate large and organic feeling dungeons (i.e. don't feel generated) while inserting rich narrative that forms the quests. I've made some leaps in that department over the last few days. A quest is defined as a set of narrative events tied into author designed sections of dungeon which are inserted into randomly generated dungeon levels. So you might have a quest definition that looks like this:
<quest>
<narrative>
<-- As yet undefined events -->
</narrative>
<level index="0" width="40" height="30" roomCount="20">
<section ref="section1.txt"/>
<section ref="section2.txt"/>
<monsters type="ghost" minLevel="3" maxLevel="4"
minCount="25" maxCount="30"/>
</level>
</quest>
So this quest has a single dungeon level which is going to be generated with a tile map size of 40 by 30 and have 20 rooms generated (plus any corridors needs to join them all up). There's going to be two predefined sections inserted into the generated dungeon which will tie into the narrative events. So maybe you'll add a starting room where you meet an old man that explains the quests, and a finale room where you meet the big boss dude and have to vanquish him to obtain the target of the quest. The last bit there describes what monsters are generally going to appear on this level and how powerful they'll be. In this case I'm going to spawn a bunch of ghosts (between 25 and 30) across the level at experience level 3 or 4. So, these sections, how do they look? A bit like this: 111S111 1111111 1111111 011D110 022D220 222T222 222X222 A simple text file to describe the shape of a room (or rooms). The numbers represent the room(s) defined. These are relative IDs used in the final map. So if we're generating room ID 10 when this section is inserted, ID 10 will be used for the room marked out as 1 and ID 11 for the room marked out as 2. The indicators there are pretty basic. 'D' marks a door - so you can predefine the links between the designed rooms. The 'S' marks the stairs into the level and the 'T' marks a trap door leading down to the next level. The interesting one is the 'X' which marks the location where this section can be joined to the rest of the dungeon. There can be as many of these as needed. In this case I've defined that this section can only be linked at the single specified location, however in section 2 I provide all the edges of one of the rooms a linking points leading to interesting dungeon configurations around the section: 0011100 0111110 0111110 011D110 022D220 0X222X0 0XXXXX0 As before the rest of the dungeon is generated around these sections. This leaves me able to add just the bits I want to provide a nice rich quest without having to define the boiler plate filler in between. Great stuff. Finally, here's how it looks in game now I have a few monsters being generated and the party exploring the dungeon: ![]() I'm really started to get the heroquest rogue mix I was hoping for now. By kevin at 2009-03-15 00:46 | Code | 2 comments
Revisiting Google AndroidIf there are any long term readers of this blog out there, then you may remember that nearly a year and a half ago I posted this, 10 Bits of Feedback for Google's Android SDK. It was the first time I'd come across Android, version 0.3.0 at the time, and while it looked very promising there were some pretty severe blockers stopping the average developer being productive on the platform. In the last few days, for various reasons that I won't go into, I've had time and opportunity to revisit Android and see how far it's come. The new version I got my mits on is 1.1_r1. It's past the 1.0 version, it's got to be good by now right? So, first question, what shall I code for it as a test. With the recent Java 4K Contest fresh in my mind I thought it'd be an nice experiment to port one my entries over onto the platform. I was really happy with Putty Shuffle so there was my goal. Turn my little 4K game into an Android application. ![]() The good news! The tool set is much more mature and stable now. Once I'd updated my local Eclipse installation to 3.4 Ganymede and picked up the new versions of the Android plugin's and SDK I was up and running with samples in a few minutes. I can remember a little bit about my experiments from a year ago but not enough, so I basically worked from the samples up again. The plug-in now makes sense, it's not slow and doesn't get in the way. There are editors for all that old evil XML and emulator integration is much tighter, with views to control, monitor and view logs. All very nice. My Java4K game is an applet and uses a lot of Graphics2D calls. Unfortunately Graphics2D, Applet and all that jazz doesn't exist on Android (no AWT). However, Android does have a reasonably nice drawing API inside it's Canvas class. A couple of wrapper classes later I'm using the Graphics2D API from my game and proxying the calls onto the equivalent Canvas calls. Good stuff! Rendering is working. Next input, well this is just simple as pie. Event handlers just like in AWT, MotionEvent rather than MouseEvent. Not rocket science. Mapped those over. Few bugs and refactoring issues later, I'm up and running. I complete the first level and have a beer. The bad news! Performance appeared to be terrible. I mean really really awful. The emulator is there juddering away, not even consistently slow frame rate - ranging from 1 to 15. Painful to see. So I spend a few hours debugging, trying out different options, looking for the bottle neck. It goes on, a few hours more. Eventually I get reasonable performance out of the emulator by sacrificing the fluidity of the motion. Ick! The annoying news! So, at this stage I have a working APK (an android package), I sign it and it's ready to go. I find someone with a real phone and get them to test it. Apparently, it's running fine. The emulator turns out to be much slower than the actual devices (like by a factor of 5 on my machine). I re-tune the application, repackage, redeliver and the app that runs terribly on the emulator is now running beautifully on the real hardware. An interesting point was that the touch screen resolution (finger tip) wasn't really good enough to select 20x20 pixel blocks in the game. So I added a little bit of relaxation - if you can't find a block where the player touched, try the areas around it. This seemed to make the whole thing way easier to play. It worked really well in this game because you're rarely selecting things that are close together (unless they're joined) Here's what it looks like on the emulator at least (click for the bigger ones): So, whats changed in the past year or so.
And what's basically the same and still a pain in the rear:
So, Google, please sort out the Emulator. Give me tools I can be productive with and I'll happily build you some fun games - I know a lot of developers would too! PS. If anyone wants to try the APK out on their phone, just drop me a mail. Dungeon GenerationDungeon generation sounds easy. You just create a few rooms and link them together with corridors right? Well, yes, you can do that. It's exactly what I did for Hack4k. The problem is the dungeons don't look very good and they're extremely predictable. There's no way you could believe they were hand designed. So, you start searching around for dungeon generation and guess what comes up a lot. Rogue and/or NetHack. Fair enough they, and their derivations (Angband being most notable to me) have built wonderful dungeon generators. However, there's two issues with these for me. First, the code has been evolved by many people over many years, it's really really hard to read the generation code. Second, they all seem to work on block walls, i.e. a wall uses up a tile in the tile map. I really don't want that, partly because it uses up so much space but also because I come from a HeroQuest background where walls are just edges. As a little addition, a lot of the existing generation algorithms rely on rectangular rooms - something else I think leads to less organic dungeons. Ok, so having justified (probably for no reason) my reasons for re-inventing the wheel, let's go on to what I've tried. For my purposes the data model is a tile map. Each different room (or corridor) has a unique ID. Each tile is either zero (nothing there) or it contains the ID of a room. Where two adjacent tiles have different values it's interpreted as a wall between the two tiles. There's also a marker to indicate if the tile contains a door. If both sides of a wall have a door marker then a door goes through the wall. Onto the dungeon generation! The important bits of the dungeon generation for me are:
The algorithm to generate the dungeon (I keep saying dungeon, but I suppose it's any 2D map really) is pretty easy to understand and implement. My code is a little messy (since it's tied into my game at the moment) so I'm not going to post it, but here's how it works: 1) Decide how many rooms to generate. I do this with mapWidth*mapHeight*2. However, it depends on the type of dungeon you want. With less rooms you'll get more corridors to link it up. I like nice densely packed dungeons so my metric is quite high. 2) Attempt to randomly place the rooms in the dungeon. Pick a random spot in the dungeon and see if it's clear for the room you want to place. If you just use rectangular rooms this is just a block check. If you want to use floor plans (like me) then you just need to scan the tiles that match the plan. I have L shape rooms in the example above, if we just checked a rectangle around the L we'd end up with no tight fitting rooms. If the area is clear then fill it with the room ID, if not then pick another location and try again. You keep doing this for each of the total number of rooms required. 3) Link any adjacent rooms that don't already have connections. Scan through all the rooms you've just placed. If a room doesn't have a door pick a random edge location that's next to another room and add a door to link the two. This selection of random edge location is very important. Remember in arbitrary room shapes the edge locations that can support doors aren't just the edges of the rectangle that contains the room. Even more, in a carefully predefined room there may be only certain locations the designer wants there to be doors. In my version of this algorithm I have the shape of the room and the selection of random edge points pulled out into a FloorPlan class which just returns a list of points which can support doors. 4) Identify Islands An island in this case is a group of rooms that are connected to each other. Once all the adjacent rooms have been linked you may end up with 1 or more of these groups. The dungeon needs to have a single island, i.e. all rooms are connected to each other in some way. To identify the islands you simply traverse the tree of rooms that we know we've connected together. Pick the first room, assign it an island ID. Assign the same ID to any rooms that it's connected to, and that they're connected to, and so on... until all the connected rooms have the same island ID. Increment the ID and start looking for a room that doesn't have an island ID yet. Once you find one, repeat the process and mark out the next island. So, once you've been through all the rooms they'll all be identified as part of one island or another. Here's how my debug view shows this (different colors, different islands):
In this step, if we end up with a single island, dungeon generation is complete! 5) Resolve islands Resolving islands means to link up the islands with additional doors and/or rooms. There are two steps to this. First, when we were looking for adjacent rooms above we only cared if the rooms had no links at all. This means in some cases we may not have joined up rooms where we could. This is a good thing. It means the dungeon doesn't link every room possible, requiring exploration on the part of the player. At this stage however if we may be able to find adjacent rooms which have different island IDs. If we do, we should link them with a random door. This will resolve a pair of islands into a single island. At that point we jump back to step 4, re-determine the islands and then try again if we still have more than one island. Second, if we can't find any adjacent rooms to join then we can start adding corridors to link things up. Above I mentioned it was important to be able to pick a random point on the edge of room where a door could fit. This was so we could link rooms. Now, we want to be able to find a random point on and edge where a door could fit even though there isn't a room on the other side (yet). This is easy of course if we just ask for a random door location linking to room ID zero (our empty space marker). For each room in existence we try to find such an edge point. If we can find one, we jump out to the space the door would connect to, pick a random direction (north, south, each or west) and start moving along. At each step consider whether the current space is next to a room with a different island ID to the original room. Also consider whether the space in the room we're next to can be used as a doorway. Keep going to we either find such a location, or we hit something else (the same island, or the edge of the map). If we hit the "something else" then give up and try the next room. However, if we find a location that can link to another island then we trace back along the path we've followed filling in a room with a new ID. This ID will represent our new corridor room that will link the two islands. Once the room is complete simply link it to both the room at the start and the room that we've found in the second island, as with any other room link up previously. If we've managed to build a corridor between two islands then jump back up to step 4 to redetermine the islands. If we run out of rooms and haven't made any links, just start of this step again and try some more random combinations. It's best to stick a guard condition here, since things are random it's possible we'll never manage to link all the islands up. Now if we keep going in this process until either the number of islands reaches one or by some unlucky random occurrence we reach the maximum number of iterations suitable for the particular game then stop. Dungeon generation is complete! That's it. Hopefully this rather long winded but detailed blog post will help someone who ends up with the same dungeon generation needs as me in the future - though they'll most probably grow their own since it's fun. The algorithm above is performant, it scales up and down with dungeon size well and does give me pretty organic looking dungeon design. More than that it supports tuning with different densities of rooms and arbitrary room shapes. Better still for my game's purposes, it allows me to plonk pre-defined rooms (or room clusters) right into the generated maps. Diablo-esque rogue-a-like here I come! Here's a shot on the dungeon in game, it's very early so no monsters or features just yet:
Into the ExpanseHere comes the next one... back to Slick, back to Java, mmmm, stars:
By kevin at 2009-02-04 22:19 | Code | add new comment
Putty ShuffleI've just put the last levels into my final (?) 4k entry for this year's competition. Putty Shuffle is a 16 level block sliding puzzle game which incoporates the putty merge/split mechanic from my previous creation, Putty Puzzle. I reakon it's a better more approachable version, though the visuals arn't as cute due to the 4k limit. It's applet based on the Putty Shuffle website and looks a bit like this:
So, that brings it to three entries for the year. Not bad for someone who wasn't going to enter at all this year. Check out the other two below (they both need resonably decent machines to run I'm afraid): ![]() ![]() Think thats it for this year though... maybe. |
DisclaimerNote that the views on this page are not intended to offend. If they do, you might be taking the content too seriously.
Twitter Updates
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() 2D OpenGL Based Game Library ![]() 2D Game Physics Engine in Java Game Developers How about a list of the developers doing interesting things in java gaming. Game Dev Resources Looking for Game Development Resources? Check out the List! |