Dungeon Dual is back online! This was my 2014 7-Day Roguelike and probably my most popular successful 7DRL to date.
Unfortunately I lost the domain and a lot of the web pages for some of my old games earlier this year due to myself being a dummy. I was able to bring RoboCaptain and Heavy Axe back online relatively easily.
Since it has co-op multiplayer, Dungeon Dual was a little trickier. It's also entirely written in CoffeeScript, which I have not touched since switching to TypeScript a few years ago. There's also a WebSockets server that handles the back-and-forth between the two players.
In any event, after a long afternoon of hacking, the original 7DRL version is back online in all of it's... glory?
It definitely plays a bit rough, but I must say I was rather surprised at how fun it was. It was cool to see a lot of that old gameplay working again. (like banish! which is still insanely overpowered)
Showing posts with label roguelikes. Show all posts
Showing posts with label roguelikes. Show all posts
Version 0.55 - Tutorials and More
Saturday, August 10, 2019
I've put the latest version (0.55) of Warning Call here.
The bulk of my time has been spent building a tutorial level. It's not done yet, but it's accessible from the start menu. More to come here - I've never written a tutorial before so it's an interesting challenge. All of the feedback I've gotten from the kind devs on r/roguelikedev has been helpful in seeing the game in a different light.
Major changes from the last version include:
The bulk of my time has been spent building a tutorial level. It's not done yet, but it's accessible from the start menu. More to come here - I've never written a tutorial before so it's an interesting challenge. All of the feedback I've gotten from the kind devs on r/roguelikedev has been helpful in seeing the game in a different light.
Major changes from the last version include:
- Removed Targetbots (t) from the first level
- Fixed bug where Empowering and Ammo-generating nanites would not allow power usages if you had zero charges.
- Enforcing same hotkey press for powers & confirming target. This makes it easy to double-tap a hotkey when targeting quickly. This also allows you to return the Axe using the same key that you threw it with. (pro-tip: you can have more than 1 Axe power installed at once!)
- Made sure Warp Beacons cannot be trapped behind impassable terrain
- Gridbots (x) no longer get stuck in the wall when they explode out of a Xenobot (X)
- Put the Power menu as the first line of the footer
- Added the SEED # to the header (mostly for help in bug reporting, but eventually for game-sharing)
- Spread out the guaranteed powers on the first level - the starting room was way too cluttered
- Fixed mysterious game-crashing bug with 'empty' nanites spawning on the ground in deeper levels
Feel free to post comments, bugs, and feedback below, or on the reddit link above. Or e-mail me: todd AT (this domain).
Latest Version of Warning Call (aka Hardpointe) online
Friday, July 26, 2019
The latest version (0.5) of Warning Call is here. (I changed the name from Hardpointe, but the game is the same). If you have commentary leave it on reddit here.
A full list of changes since the last playable version is below. Thanks, and enjoy!
From 0.5:
- On-screen radial menu replaces 'ambiguous input' menu:
- Makes it simple to double-tap space to wait when standing on wreckage
- Can no longer escape out of radial menu
- Interface updates:
- Warp Beacons and Airlocks are highlighted when not in view
- Significantly expanded HELP content
- Better item and power descriptions all around
- Cycle between enemies while targeting with 'e'
- Inventory is sorted more usefully
- Power install menu has better shortcuts (allows player to quickly tap SPACE + # to install a power into a given slot)
- Grenande targeting shows area of effect
- 3 new nanotech types (found as items and on the grid):
- Recharging nanotech (temporarily makes all power uses 'free')
- Reloading nanotech (temporarily makes all weapon uses 'free')
- Strengthening nanotech (temporarily adds the HULK effect and +1 melee damage)
- New enemies:
- Gridbot (1-hp enemies that always appear in pairs)
- Xenobot (explodes into gridbots when destroyed)
- Megadrone (constructs mini-drones out of nearby scrap)
- Protectobot (casts shields onto nearby allies)
- Interdictor (able to see cloaked targets and use a displacement field to cancel PHASEWALK and CLOAK effects)
- Ability to 'sacrifice' Warp Crystals to double SCORE
- Enemies take damage when falling through chasms
- Different icon for weapon powers vs. ability-based powers
- Better distribution of grenades, powers, and nanotech items
- More wreckage distributed across levels
- HACK effect is now temporary, and scales with power level
- PHASEWALK is now more liberal when calculating if a ranged attack goes through you and hits a nearby enemy
- Power level is now tied to how long (or far) powers last
- Lowered the base duration of most power effects (but they now scale with level)
- Warp beacon menu improved and text made more helpful
- new HULK power that temporarily adds +1 to melee attacks
New Site - Old Games Back Up
Sunday, June 23, 2019
I finally uploaded my redesign of heroicfisticuffs.com and have started restoring some of my older games. First up are roguelikes from the 2012 and 2015 7-Day roguelike challenges, all browser-based and utilizing the amazing rot.js library.
RoboCaptain
Next up will be Dungeon Dual. This one is a bit trickier since I need to get the co-op engine running again as well as a django server that powered the leaderboard and login process.
Let me know if you run into any trouble playing either game.
RoboCaptain
RoboCaptain specializes in ranged combat and power-management similar the old X-Wing games. Looking back at it now it is pretty rough, but also very complete and still fun, which is saying something.Heavy Axe
Heavy Axe is a small-scale classic roguelike featuring extremely tactical combat. Journey through the temple to slay the gods themselves, using a massively heavy axe. Moving with the Axe drains stamina, and stamina determines damage, so moves must be planned carefully to avoid running into an unkillable foe.
Next up will be Dungeon Dual. This one is a bit trickier since I need to get the co-op engine running again as well as a django server that powered the leaderboard and login process.
Let me know if you run into any trouble playing either game.
I can't just kill you, can I?
Sunday, June 9, 2019
One of my overriding design principles of Hardpointe is to keep the number small. Originally the rule was "nothing over 3."
- The player has a maximum of 3 hit points. The player can cheat a bit here and add 3 shield points temporarily using the shield power.
- All regular enemies have a maximum of 3 hit points. For some enemies, this is a combination of health and shields, the later of which are usually temporary and also vulnerable to EMP grenades.
- All attacks do 1 damage. There are no enemies that do over 1 damage. The player can add +1 to their damage by using a wall-smash, surprise attack, or the `hulk` effect.
I really enjoy the tactical decisions that these design choices enforce on the player. But they also force some tough decisions on me, the developer.
When the player only is only ever 3 hits away from death, there is no room for taking easy (or "cheap") hits at the player. Part of this is making information about battlefield as clear as possible. Another part is toning down the usual brutal mechanics that power my favorite roguelikes.
For example, in Hardpointe there are tiny nanites that effect the player when you step on them. You will see them, and you can use the HUD to find out what they do. But, there is always the chance of a player stepping on them accidentally. So, for that reason, there are no cases of 'instant' damage in the game.
| Corrosive nanites (orange dots) |
Right now, the closest we get are 'Corrosive' nanites, which make the player (or any enemy) weak enough to kill in one hit - temporarily. This is a great advantage to the player if they can make use of them, but also not instant death if they are forced to step on a square, or they trigger the effect inadvertently while not paying attention.
There are other nanites that will make the player temporarily invulnerable, or temporarily do +1 damage. Again, great advantages for the player, but getting terribly close to an instant-death situation if an enemy steps on them and the player does not notice.
![]() |
| Enemy changes color as a warning* |
In this case we turn the monster a different color when they are either invulnerable (as the player is in this gif above after stepping on the neon green nanites on the left) or `Hulked Up`, after stepping on strengthening nanites (dark green on the right). There's also a HULK power that the player can use but I think it is a bit overpowered.
(* don't worry, I made the color change more dramatic once I saw this in GIF form)
(* don't worry, I made the color change more dramatic once I saw this in GIF form)
A long-dormant chunk of code in Hardpointe deals with radiation and fire as features. Since in most games fire does damage, I've not yet come up with a good way to add it that does not seem unfair. Radiation is a bit different - it will not kill you instantly, but will start a timer on the player. If you don't get out of the irradiated zone before the timer ends, you will take 1 damage. This seems like a good trade-off. There's also a HAZMAT suit power coded up that I can make use of some day and add specialized rooms or levels where the player will need to sacrifice a power to make it through unscathed.
In summary - I can't promise not to kill you. But I can promise that you will see it coming.
Give me the 30 second version
Tuesday, April 9, 2019
"So, what's it about?"
I'm probably mis-quoting Darren Grey here, but it's close enough. I was in London for a visit last year and while I was there I decided to look Darren up. I've been a big fan of his for quite a while. We've run in the same circles online, from the old rec.games.roguelikes.development (RGRD) to rogue temple and all of the incarnations of the 7-Day Roguelike Challenge to the current rogue-reddit "scene" at (r/roguelikedev and r/roguelikes). He also writes some great games - he's done a lot for the community.
So of course I was excited to meet him in person. And of course we start chatting about development, what are you currently working on, etc. Turns out being a new dad is not so condusive to programming, but I had been continuing to develop my failed 2017 7DRL Hardpointe. That's when I get the question: "So, what's it about?"
Oops. I didn't have a smooth or particularly convincing answer. Something about tactical combat, maybe?
A few months later, here was my first definition:
Here's my 2nd try:
Maybe somewhere in between?
How's that? (They keep getting longer... oops.)
I'm probably mis-quoting Darren Grey here, but it's close enough. I was in London for a visit last year and while I was there I decided to look Darren up. I've been a big fan of his for quite a while. We've run in the same circles online, from the old rec.games.roguelikes.development (RGRD) to rogue temple and all of the incarnations of the 7-Day Roguelike Challenge to the current rogue-reddit "scene" at (r/roguelikedev and r/roguelikes). He also writes some great games - he's done a lot for the community.
So of course I was excited to meet him in person. And of course we start chatting about development, what are you currently working on, etc. Turns out being a new dad is not so condusive to programming, but I had been continuing to develop my failed 2017 7DRL Hardpointe. That's when I get the question: "So, what's it about?"
Oops. I didn't have a smooth or particularly convincing answer. Something about tactical combat, maybe?
A few months later, here was my first definition:
Hardpointe is a "medium" sized roguelike with a focus on tactical combat and movement. Managing a limited set of powers, upgrades, and items will be critical to your success.
Here's my 2nd try:
Hardpointe (name subject to change) is a browser-based roguelike with a focus on tactical movement and finite resource management. Players have 3 power slots that can be upgraded or swapped out as luck and necessity see fit. Combat is deterministic and the numbers are small - almost all attacks do 1 damage and almost nothing in the game goes over 3 hp. (With 1 or 2 exceptions). There are no real 'vanilla' enemies. Fighting 1-on-1 is usually easy, but difficulty can scale quickly with multiple foes.
Maybe somewhere in between?
Hardpointe is a browser-based "medium-sized" roguelike with a focus on tactical combat and finite resource management. A lone soldier must infiltrate and destroy an asteroid fortress filled with robotic hordes bent on Earth's destruction. You will harness unique powers, abilities, and an assortment of weapons that you find along the way. Each enemy has unique abilities and behaviors that will require different strategies. Combat is deterministic and health is extremely limited; positioning and thoughtful movement will be your keys to victory.
How's that? (They keep getting longer... oops.)
Hardpointe still alive
Saturday, March 9, 2019
Despite my lack of posts and entire blog going offline for a bit, I continue to develop Hardpointe in my "free time". Progress did stall for the last half of 2018, but seeing all of the posts around 7DRLs earlier in Feb really pushed me to get back into making progress.
A lot of work has been behind the scenes since the last version. I did a lot of work to add a 'radial' menu. In an effort to reduce on-screen distraction and the number of button presses, when there is an ambiguous action, the radial menu pops up, and the available options always show up in the same spot. (e.g. 'Heave' is always the up key) It makes for much smoother gameplay.
Enemy AI was also changed to make them less omniscient and more cautious about doors. There was an annoying habit for enemies to "wait" behind doors and punch you right as you walked in. This wasn't really by design. Now enemies take a turn to go from non-alert to alert statuses. So if you walk into a room and they DO happen to be behind the door, they will act surprised for a beat. That gives you an opportunity to attack, back away, or do something else.
I didn't do any power switching in this video but that menu has been streamlined as well. You can now just hit space + <slot to replace> and not have to page through multiple screens or even read anything if you don't need to.
Here's me dying on the 1st level because I messed up a dash somewhere and got hit. In a 3-hp game you really need to pay attention to every single hit. Apparently I'm a bit rusty.
A lot of work has been behind the scenes since the last version. I did a lot of work to add a 'radial' menu. In an effort to reduce on-screen distraction and the number of button presses, when there is an ambiguous action, the radial menu pops up, and the available options always show up in the same spot. (e.g. 'Heave' is always the up key) It makes for much smoother gameplay.
Enemy AI was also changed to make them less omniscient and more cautious about doors. There was an annoying habit for enemies to "wait" behind doors and punch you right as you walked in. This wasn't really by design. Now enemies take a turn to go from non-alert to alert statuses. So if you walk into a room and they DO happen to be behind the door, they will act surprised for a beat. That gives you an opportunity to attack, back away, or do something else.
I didn't do any power switching in this video but that menu has been streamlined as well. You can now just hit space + <slot to replace> and not have to page through multiple screens or even read anything if you don't need to.
Here's me dying on the 1st level because I messed up a dash somewhere and got hit. In a 3-hp game you really need to pay attention to every single hit. Apparently I'm a bit rusty.
How to Play Dungeon Dual
Sunday, March 16, 2014
My successful 2014 7-Day Roguelike entry is Dungeon Dual!
You can read some of the unexciting progress here on 7drl.org.
So, now that I've had a few hours to recover, here is
After you start a game, you can send the URL to your friend. It will also show up on the main page until someone joins.
Each game is totally asynchronous, which means you don't have to wait up for the other player. This is one thing I hate about other attempts at "multiplayer" roguelikes. In Dungeon Dual, the classic turn-based roguelike mechanic is unbroken.
However, if you have an ally certain tactics are available:
Fireball
Apprentice ability. Engulfs a 3x3 grid of enemies (and potentially you) in a ball of fire. Damage scales with maximum stamina. Can be used with allies.
Entanglement
Apprentice ability. Stuns a 3x3 grid of enemies for a short period of time. Can be used with allies.
Forcebolt
Apprentice ability. Casts a powerful bolt of force at a single target, with damage scaling with maximum stamina.
Banish
Apprentice ability. Sends a single enemy across the realms for your ally to deal with. It might be a good idea to warn him or her in advance!
Charge
Squire ability. Enables you to dash across the screen and attack an enemy in a single turn, as long as they are at least 1 square away. This is great for hunting down pesky archers and spell-throwers.
Warcry
Squire ability. Unleashes a terrible roar that scares all enemies in sight, causing them to flee for a short period. Great for clearing a room or cornering a troublesome enemy. Can also be used with allies.
Defend
Squire ability. Temporarily boosts your (or your ally's) defense, protecting you against damage. Can also be used with allies.
Vigor
Also known as flasks of stamina, these will refill your stamina and also boost your maximum by 1. You will almost always find a flask of vigor or health on each level.
Health
These flasks are critical to survival in the dungeons. They will refill your health and also boost your maximum by 1. You will almost always find a flask of vigor or health on each level.
Fire
Drinking from this flask will cause you to burst into flames. Generally speaking this is a bad thing.
Weakness
The contents of this flask will drain you of your stamina. Try not to taste it during combat.
Might
Doubles your melee damage for a few turns. Time the use of these wisely.
Invisibility
Temporarily makes you invisible to all enemies. Great for getting out of a sticky situation.
Armor
At this point in the game, armor doesn't do much other than subtract potential damage from monster attacks.
Weapons
You will find an increasingly deadly array of weapons in the dungeon. Some have special effects such as piercing (attacks an enemy behind your target), smashing (attacks all surrounding enemies), and stunning (stuns enemies 1/3rd of the time).
Hats
They don't do anything I just wanted to have a game with hats!!
PS If you've read this far, e-mail me or make a comment and I will add your own personal hat to the game. ;)
Thanks for playing. Always happy to hear feedback, good and bad. And congratulations to all other 2014 7DRL participants.
You can read some of the unexciting progress here on 7drl.org.
So, now that I've had a few hours to recover, here is
How to Play Dungeon Dual
Co-Op
You can play with a friend! This is accomplished through the wonderful magic of WebSockets. You don't need to play with a friend, but you may want to.After you start a game, you can send the URL to your friend. It will also show up on the main page until someone joins.
Each game is totally asynchronous, which means you don't have to wait up for the other player. This is one thing I hate about other attempts at "multiplayer" roguelikes. In Dungeon Dual, the classic turn-based roguelike mechanic is unbroken.
However, if you have an ally certain tactics are available:
- You will regain stamina faster
- You can trade items
- You can chat and share knowledge of items/levels (e.g. "hey don't drink this one, it's poison")
- Certain abilities can be used cross-realms:
- The Apprentice can shoot fireballs and cast entanglement onto the other screen, affecting your ally's enemies (hopefully you don't set your friend on fire in the process)
- The Apprentice can banish monsters to the other screen
- The Squire can use Warcry and Defend on the other screen to aid his ally
These features will only be possible when you and your ally are "in sync". This is determined by a fuzzy algorithm that takes into account both spacial distance (how far away are you on the grid of the same dungeon level) and time, which is determined by turn count. The game will try to help you out and give hints when you are out of sync such as "Hurry" or "Wait" or "Change levels".
From a technical perspective, the WebSockets server needs to be running for co-op to work. It runs on my webhost, but seems to die every now and then. If you notice it is offline, try to reach me via e-mail, over IRC on #rgrd, or via twitter. Server status is displayed on the main dungeondual.com page
Basic Mechanics
There are two stats in the game: Health and Stamina.
Stamina
Stamina is used to cast spells and abilities. It recharges over time, but not if you are in combat or are poisoned. Flasks of Vigor will instantly refresh your stamina and increase your maximum by 1. Stamina also scales damage of certain spells like fireball and forcebolt.
Stamina is also used up when you take damage in combat. Be sure not to take on too many enemies at once or you will not be able to recover!
Health
Lose all of your health and you are dead. Once your stamina is gone, any damage will go directly to your health. Health does not recover naturally, but can be restored using Flasks of Health. Flasks of Health will also increase your maximum health by 1.
Abilities
Both classes have unique abilities. You can quickly toggle them using the 1-5 number keys. You can also access them from the 'z' menu. Abilities are activated by pointing and clicking with the mouse. Clicking on your ally's screen will use the ability on their screen instead.Fireball
Apprentice ability. Engulfs a 3x3 grid of enemies (and potentially you) in a ball of fire. Damage scales with maximum stamina. Can be used with allies.
Entanglement
Apprentice ability. Stuns a 3x3 grid of enemies for a short period of time. Can be used with allies.
Forcebolt
Apprentice ability. Casts a powerful bolt of force at a single target, with damage scaling with maximum stamina.
Banish
Apprentice ability. Sends a single enemy across the realms for your ally to deal with. It might be a good idea to warn him or her in advance!
Charge
Squire ability. Enables you to dash across the screen and attack an enemy in a single turn, as long as they are at least 1 square away. This is great for hunting down pesky archers and spell-throwers.
Warcry
Squire ability. Unleashes a terrible roar that scares all enemies in sight, causing them to flee for a short period. Great for clearing a room or cornering a troublesome enemy. Can also be used with allies.
Defend
Squire ability. Temporarily boosts your (or your ally's) defense, protecting you against damage. Can also be used with allies.
Flasks
You will find a few (six? seven? I forget) types of potions (or "ye flask" as I call them) scattered across the dungeons. Some are bad, most are good. In standard roguelike fashion, you will not know what they are until you try them for the first time.Vigor
Also known as flasks of stamina, these will refill your stamina and also boost your maximum by 1. You will almost always find a flask of vigor or health on each level.
Health
These flasks are critical to survival in the dungeons. They will refill your health and also boost your maximum by 1. You will almost always find a flask of vigor or health on each level.
Fire
Drinking from this flask will cause you to burst into flames. Generally speaking this is a bad thing.
Weakness
The contents of this flask will drain you of your stamina. Try not to taste it during combat.
Might
Doubles your melee damage for a few turns. Time the use of these wisely.
Invisibility
Temporarily makes you invisible to all enemies. Great for getting out of a sticky situation.
Other Equipment
You will find armor and weapons in the dungeon as well.Armor
At this point in the game, armor doesn't do much other than subtract potential damage from monster attacks.
Weapons
You will find an increasingly deadly array of weapons in the dungeon. Some have special effects such as piercing (attacks an enemy behind your target), smashing (attacks all surrounding enemies), and stunning (stuns enemies 1/3rd of the time).
Hats
They don't do anything I just wanted to have a game with hats!!
PS If you've read this far, e-mail me or make a comment and I will add your own personal hat to the game. ;)
Thanks for playing. Always happy to hear feedback, good and bad. And congratulations to all other 2014 7DRL participants.
Roguelike Animations using Javascript and ROT.js
Wednesday, February 26, 2014
I am using javascript (CoffeeScript, actually) and the excellent ROT.js library to build the next version of RoboCaptain. ROT.js is great; it makes easy stuff really easy and hard stuff much more straightforward. It allows you to break away from messing around finely tuning your Field Of View algorithm or your AStar pathfinding routines and spend time building actual game content.
I am something of a roguelike traditionalist (you can find me calling out non-roguelikes in a hopefully non-obnoxious manner on reddit) but while I do love my ASCII, I also think looking nice is important. Once I started building ranged weapons into my game I realized: I need animation.
In most programming languages, animation is straightforward. Start an animation, wait, continue where you left off. In javascript, this is less straight forward, because javascript is a single-threaded non-blocking language. The appropriate way to do delays in javascript is to use setTimeout. However, if your code looks like this:
Then your game will not work like you think it will. As your drawAnimation function starts firing off setTimeout events and drawing (for example) the path of the shot across the screen with 20ms delays, the javascript machine continues chugging along. This means while your player is watching their bullets fly across the screen, javascript has already moved on and is now calling your damage() and potentially kill() functions. Even worse, depending on how you write your code, it will keep going and eventually start moving other monsters, potentially even the one that just got shot.
Despite the cries of anguish from javascript purists, my first idea was to implement a delay() function, forcing javascript to wait until my animation drawing was done before continuing. Javascript purists hate this because you will be blocking the entire browser (or tab?) while this is happening. I figured when programming a game, this was OK, because it's not like anything else is happening on the page other than the game.
Unfortunately if you use this method ROT.js will not ever get a chance to run it's display handling code, and your canvas will not update until after your terrible delays are over.
Using setTimeout is a pain in the ass. It makes coding very messy because you have to use callbacks, something like this:
Using this method I was still running into asynchronous event issues, and gods help you if you want to nest your animations (like a shooting rocket causing an explosion).
After a lot of messing about, I came up with a relatively elegant solution. It might be obvious to some, but no amount of googling on my part led me to anything similar.
You have to treat your animations as game actors. They need to have turns just like the player and monsters. They use the same drawing routines, screen updating routines, etc.
Now my game loop looks something like this (in CoffeeScript, but you should get the idea):
endPlayerTurn: () ->
@nextTurn()
nextTurn: () ->
if @hasAnimations()
first_animation = @animations[0]
@animationTurn(first_animation)
return
next_actor = @scheduler.next()
if next_actor.group == "player"
@finishEndPlayerTurn()
return
if next_actor.objtype == "monster"
monster = next_actor
@intel.doMonsterTurn(monster)
@finishEndPlayerTurn()
@nextTurn()
return
I am something of a roguelike traditionalist (you can find me calling out non-roguelikes in a hopefully non-obnoxious manner on reddit) but while I do love my ASCII, I also think looking nice is important. Once I started building ranged weapons into my game I realized: I need animation.
In most programming languages, animation is straightforward. Start an animation, wait, continue where you left off. In javascript, this is less straight forward, because javascript is a single-threaded non-blocking language. The appropriate way to do delays in javascript is to use setTimeout. However, if your code looks like this:
player.shoot(monster, weapon)
game.drawAnimation(player, weapon)
game.damage(monster)
if monster.is_dead() then
game.kill(monster)
Then your game will not work like you think it will. As your drawAnimation function starts firing off setTimeout events and drawing (for example) the path of the shot across the screen with 20ms delays, the javascript machine continues chugging along. This means while your player is watching their bullets fly across the screen, javascript has already moved on and is now calling your damage() and potentially kill() functions. Even worse, depending on how you write your code, it will keep going and eventually start moving other monsters, potentially even the one that just got shot.
Despite the cries of anguish from javascript purists, my first idea was to implement a delay() function, forcing javascript to wait until my animation drawing was done before continuing. Javascript purists hate this because you will be blocking the entire browser (or tab?) while this is happening. I figured when programming a game, this was OK, because it's not like anything else is happening on the page other than the game.
Unfortunately if you use this method ROT.js will not ever get a chance to run it's display handling code, and your canvas will not update until after your terrible delays are over.
Using setTimeout is a pain in the ass. It makes coding very messy because you have to use callbacks, something like this:
player.shoot(monster, weapon)}
game.drawAnimation(player, weapon, function () {
game.damage(monster)
if monster.is_dead() then
game.kill(monster)
Using this method I was still running into asynchronous event issues, and gods help you if you want to nest your animations (like a shooting rocket causing an explosion).
After a lot of messing about, I came up with a relatively elegant solution. It might be obvious to some, but no amount of googling on my part led me to anything similar.
You have to treat your animations as game actors. They need to have turns just like the player and monsters. They use the same drawing routines, screen updating routines, etc.
Now my game loop looks something like this (in CoffeeScript, but you should get the idea):
endPlayerTurn: () ->
@nextTurn()
nextTurn: () ->
if @hasAnimations()
first_animation = @animations[0]
@animationTurn(first_animation)
return
next_actor = @scheduler.next()
if next_actor.group == "player"
@finishEndPlayerTurn()
return
if next_actor.objtype == "monster"
monster = next_actor
@intel.doMonsterTurn(monster)
@finishEndPlayerTurn()
@nextTurn()
return
animationTurn: (animation) ->
animation.runTurn(@, @ui, @my_level)
if not animation.active
@removeAnimation(animation)
@finishEndPlayerTurn()
setTimeout(=>
@nextTurn()
50)
return
So, now my code is much more readable. Players and monsters take turns as per usual, using the ROT.js scheduler. Animations are independent actors that always take their turns first, if any are still alive. Within each animation there is a runTurn() method that calls the relevant game code: draw a rocket, draw a flash of light, move an expanding circle outwards, etc. The setTimeout is there but feels much less intrusive to me this way.
The code exits out to the main ROT.js loop elegantly, and does not hold up any operation or freeze the browser. The last step is to just make sure the player can't move or start a new turn until the animation is over (this last part is somewhat optional, in my experience roguelikes are not that fast-paced anyways).
The tricky thing is thinking of animations as game actors. The player may launch a rocket or a laser, but it will be the actual laser actor that calls the attack() or damage() functions. It is a little tricky to get used to, but I find it much more simple and easy to code than worrying about callbacks.
Your mileage may vary, but I wanted to put this out there so the next developer trying to solve this problem can save a few days of refactoring hell.
RoboCaptain: That's levitation, Holmes
Monday, December 2, 2013
Jetpacks! Chasms to fly over! Also melee weapons with special attack patterns! Also flying enemies! Also ammo-based guns!
Melee weapons are a bit different from systems. They take up a coveted slot, but you can carry them around when they aren't in use. When activated, the current weapons all have special attack patterns (ala brogue). The blade will pierce multiple enemies, the flail will damage all surrounding enemies, and the hammer will temporarily stun your target.
Coming soon: radiation, fire, exploding barrels, and upgrades. And recharging. And rockets. And...
PS - I will need beta (alpha?) testers at some point this month. Shoot me a comment or e-mail (twpage AT gmail) if you are curious and want to help.
Melee weapons are a bit different from systems. They take up a coveted slot, but you can carry them around when they aren't in use. When activated, the current weapons all have special attack patterns (ala brogue). The blade will pierce multiple enemies, the flail will damage all surrounding enemies, and the hammer will temporarily stun your target.
Coming soon: radiation, fire, exploding barrels, and upgrades. And recharging. And rockets. And...
PS - I will need beta (alpha?) testers at some point this month. Shoot me a comment or e-mail (twpage AT gmail) if you are curious and want to help.
RoboCaptain 2.0
Tuesday, November 19, 2013
Just wondering if anyone still actually has this blog in a dusty corner of their RSS reader?
I dusted off my old 2011 7DRL RoboCaptain a few months ago and have made steady progress. The new engine utilizes the wonderful rot.js and is fully re-coded in CoffeeScript.
It looks kind of like this:
For the first time today I actually spent time "playing" the game for more than testing purposes. There are already some interesting tactics arising from having to utilize different systems. There is a lot of work to be done on balancing this mechanic. I think the original 7DRL struck a chord with lots of people, but having to constantly switch between systems in order to recharge them seemed very fiddly to me by the end.
The current mechanic modifies the original one. You don't have to worry (as much) about recharging your systems, but instead you need to pick which one is currently ACTIVE.
Some systems function whether or not they are active, but being activated makes them better. Active lasers will have 2x change of critical hits. Active shields will recharge over time. Active melee weapons will perform special attacks like shoving enemies back or piercing through multiple enemies (thanks Brogue).
Other systems only function while active. The cloak is an obvious one. The promised jetpack also makes an appearance (jet-punch is a must-have feature). When activated, the Armor system makes your melee attacks do double damage and allows you to smash through walls -- very satisfying.
I'm still working out how to balance the two different kinds of systems with things like melee weapons, limited ammunition weapons, and rockets. I think melee weapons will become systems. Since you are limited to 5 or 6 systems, this will become a strategic choice. I may also add ammo-based weapons that are designed to be disposable, but have special features when compared to the default laser. In theory you could even drop your lasers and do (for example) a melee/cloak-only build. Or even leave your shields behind and stack your robo-suit with 4 weapons systems.
Currently I decided that you can't "carry" systems around to install later, so the strategic choices around which 5 (or 6) to keep installed is an important one.
Anyways, if you are still listening, drop me a line. I will need beta testers soon enough.
Cheers.
HF
I dusted off my old 2011 7DRL RoboCaptain a few months ago and have made steady progress. The new engine utilizes the wonderful rot.js and is fully re-coded in CoffeeScript.
It looks kind of like this:
For the first time today I actually spent time "playing" the game for more than testing purposes. There are already some interesting tactics arising from having to utilize different systems. There is a lot of work to be done on balancing this mechanic. I think the original 7DRL struck a chord with lots of people, but having to constantly switch between systems in order to recharge them seemed very fiddly to me by the end.
The current mechanic modifies the original one. You don't have to worry (as much) about recharging your systems, but instead you need to pick which one is currently ACTIVE.
Some systems function whether or not they are active, but being activated makes them better. Active lasers will have 2x change of critical hits. Active shields will recharge over time. Active melee weapons will perform special attacks like shoving enemies back or piercing through multiple enemies (thanks Brogue).
Other systems only function while active. The cloak is an obvious one. The promised jetpack also makes an appearance (jet-punch is a must-have feature). When activated, the Armor system makes your melee attacks do double damage and allows you to smash through walls -- very satisfying.
I'm still working out how to balance the two different kinds of systems with things like melee weapons, limited ammunition weapons, and rockets. I think melee weapons will become systems. Since you are limited to 5 or 6 systems, this will become a strategic choice. I may also add ammo-based weapons that are designed to be disposable, but have special features when compared to the default laser. In theory you could even drop your lasers and do (for example) a melee/cloak-only build. Or even leave your shields behind and stack your robo-suit with 4 weapons systems.
Currently I decided that you can't "carry" systems around to install later, so the strategic choices around which 5 (or 6) to keep installed is an important one.
Anyways, if you are still listening, drop me a line. I will need beta testers soon enough.
Cheers.
HF
Finally!! I Beat Brogue
Tuesday, August 7, 2012
![]() |
| YEEEEAAAAH!! |
After 2 months of
After a particularly grueling pair of almost-wins, my actual victory game turned out to be (mostly) a breeze. I spent the first 12 levels with no weapon but the starting dagger, and no pet.
![]() |
| This was pretty embarassing... |
- A sword
- A captive ogre
- A +3 Ring of Awareness
- A cage zoo
I (ab)used my wand of beckoning that I had been carrying around to free a dar priestess and a troll. Now I was set. The ogre didn't last long, but the dar priestess survived, and learned flight. I had been waiting for a good moment to use my wand of plenty that I had been carrying around all game, and then I had 2 flying dar priestesses. The troll later turned invisible which is surprisingly NOT useful when you have other pets that cannot see it... with little no regret I polymorphed the troll into a toad and left him to wander the dungeon.
About level 18 or 19 I found a golem. Between the golem and the two priestesses I basically had the perfect tank-healer-dps combination. After I (we?) plowed through two tentacled Horrors in a row, I knew I had a lock on victory... assuming I didn't do anything stupid!'
For the rest of the game it was just a matter of aggressively destroying any discord-casting enemies (Lich, dar battlemage, pixie) and letting my pets do the rest. Eventually I found a war pike and was able to deal some decent damage of my own. Tentacled Horrors, Dragons, and Golems all fell quite easily. Revenants and Liches are much easier to kill when one of your allies can cast negate. The staff of turret destruction tunneling, which I had attained on level 1 or 2, was incredibly helpful in getting through the rest of the levels quickly and safely.
![]() |
| The rest of the game went something like this |
A couple of other things I learned along the way:
- Plate armor really is worth it. I never knew!
- Some pets are not worth rescuing (dar battlemage, salamander)
- Centaurs are easily foiled by doors
- A staff of tunneling is surprisingly useful
- You don't have to pick up every key!
- Sometimes it is OK to just take the stairs without exploring every last room...
My thanks to Pender for creating such an amazing game. Now I can relax and return to my regularly scheduled development work!
Adventures in UI Design
Saturday, May 26, 2012
Traditional roguelike games are restricted in what they can display graphically. Restrictions are part of what make roguelikes great (this is definitely true for the original rogue), but graphics no longer have to be one of them. While troubleshooting the firing logic for robocaptain I found myself stuck in a "traditional" mode of thinking.
In the original 7DRL version of the game, firing took two steps: 'f' to confirm target, and 'f' again to fire. Alternatively, once 'f' was pressed the first time, the player could hit 'g' to cycle between targets. This is mostly fine, but can be improved. While I mostly play with the mouse, I want the keyboard controls to be just as good.
The thing that 'unstuck' me was realizing I wasn't limited to conventional roguelike graphical restrictions. The restriction being '1 tile, 1 character'. Why not just add another indicator over top of the existing character?
I came up with a simple 'targeting' overlay that constantly tracks the closest (or last hit) enemy. This targeting overlay can be cycled at any time by hitting 'g'. Hitting 'f' will automatically shoot at the currently targeted enemy.
This kind of 'passive tracking' saves the player an extra keystroke, since most of the time you are shooting the only/closest enemy. The rest of the time you can use 'g' to cycle between targets just as before. The game will remember the last enemy you shot at and always keep them as the default target.
In the original 7DRL version of the game, firing took two steps: 'f' to confirm target, and 'f' again to fire. Alternatively, once 'f' was pressed the first time, the player could hit 'g' to cycle between targets. This is mostly fine, but can be improved. While I mostly play with the mouse, I want the keyboard controls to be just as good.
The thing that 'unstuck' me was realizing I wasn't limited to conventional roguelike graphical restrictions. The restriction being '1 tile, 1 character'. Why not just add another indicator over top of the existing character?
I came up with a simple 'targeting' overlay that constantly tracks the closest (or last hit) enemy. This targeting overlay can be cycled at any time by hitting 'g'. Hitting 'f' will automatically shoot at the currently targeted enemy.
This kind of 'passive tracking' saves the player an extra keystroke, since most of the time you are shooting the only/closest enemy. The rest of the time you can use 'g' to cycle between targets just as before. The game will remember the last enemy you shot at and always keep them as the default target.
Don't look down...
Work on robocaptain continues. My goal is to transform it from 7DRL into a "lunch break" roguelike. Which is a phrase I just made up after listening to the first 20 minutes or so of roguelike radio (who I noticed has a slick logo now!).
Somewhere between coffee break and a full roguelike. Shooting for 30 or 40 minutes of playtime to finish the game. Maybe less.
In the meantime here is some proof of progress! Anyone reading this interested in alpha/beta testing, drop me a line.
Still working on some less-aggressive color schemes, but for now it is easier for me to design things this way.
Somewhere between coffee break and a full roguelike. Shooting for 30 or 40 minutes of playtime to finish the game. Maybe less.
In the meantime here is some proof of progress! Anyone reading this interested in alpha/beta testing, drop me a line.
Still working on some less-aggressive color schemes, but for now it is easier for me to design things this way.
Subscribe to:
Posts (Atom)










