This is a sensational source of information for any C# roguelike dev
http://www.evilscience.co.uk/?cat=5
This is a sensational source of information for any C# roguelike dev
http://www.evilscience.co.uk/?cat=5
This is a totally brilliant article on building a roguelike PCG dungeon in C# – just excellent:
http://csharpcodewhisperer.blogspot.com.au/2013/07/Rouge-like-dungeon-generation.html
As this blog is about web development, rouguelikes and mobile dev – here’s a great podcast focussing on mobile rogue likes. Ok so there’s no real development specific content, but its a great overview of cool mobile rogue likes.
http://www.roguelikeradio.com/2013/09/episode-79-mobile-roguelikes.html
The Game
So you may have noticed I entered the 7drl (7 day roguelike comp) this year – a comp to write a game in 7 days. It’s actually not a lot of time to write a game and given work and home commitments – its really really not very long. Anyway I wrote a crazy game called Rogue Coder using JS, HTML5 and MVC4. The end product is here www.domssite.com/roguecoder
The Review
So uberhunter is reviewing all games in the 7drl on youtube and he just reviewed roguecoder. It’s a fair stressful experience watching your game (warts and all) get a review from such a guy.
here it is http://www.youtube.com/watch?v=eEaPH34DxxE
Lessons Learned
The value of a review like this is priceless. Its a great way to look at your game through the eyes of an independent and experienced player. It’s hard to watch at times because I keep thinking “I really wish I had fixed that bug”. It’s also hard to watch a review like this because you are not there to guide and advise, and you are not there to explain the things that you have in your head but never quite got the time to either fix or document . I think I have taken some a few important lessons:
1. Ensure core game play works (the bugs with the compiler actually stop the game from being playable).
2. Watch the way someone else plays the game and look at their actions and strategies to determine ways to make the game more playable, robust and enjoyable.
Whats next
V2 of course stay stay tuned here in the next few weeks. Of course a big thank you to uberhunter for the review
I come from the age when text adventures were serious fun, ZORK and Hitchhikers guide to the galaxy were two of my favourite text adventures. OK so maybe the golden age of the text adventure is still stuck in the 1980’s but I still remember those glory days. So the game I am building is certainly not up there in the same territory as ZORK but I hope you can see the sort of cool things you can do with Js/Jquery and HTML 5.
The game is pretty simple use the N,S,E and W to move around the dungeon and a few other useful commands. Search for the Dragon and if you have the right weapon and equipment you may be able to kill it. If you use a mobile browser you should see some buttons that make life a little easier than using a little virtual keyboard.
Here is the game : http://domssite.com/search/
Who is this for
Anyone interested in learning Javascript, jQuery and HTML 5.
How to use the tutorial
Its not an ordinary tutorial so you need to accept that first. Its based on reading and understanding code and code comments. I have used heaps of comments throughout the code to explain whats going on. There’s a lot of Arrays, so you’ll see lots of code using arrays and its not a bad starting place for working with js structures. The whole tutorial is 1 single file – whilst a single large file is not the best way to build large web apps – its not a bad approach showing everything in one file.
<!--Text Adventure : Search for the Dragon --> <!--***************************************** Text Adventure - A JS/JQuery/HTML5 Tutorial by comments The game : Standard Text Aventure where you can move from room to room, collecting items and killing monsters Goal is to get to the final room of the dungeon and kill the dragon Start in room 1 Monsters dont move Monsters can be killed by certain weapons Should work in both mobile and non-mobile browsers History : 0.1 Initial version before Hilary's comments/advice ***************************************** --> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Search</title> <script src="Scripts/jquery-1.7.1.min.js"></script> <link href="Content/Site.css" rel="stylesheet" /> </head> <body> <div class="content"> <style> </style> <div id="screenContainer"> <div id="display"> <div id="input"> <form> <!--Screen Title--> <h1>Search... </h1> <!--Screen Sub-Title--> <h3>For a Dragon...Text Adventure Game by @DungeonBard </h3> <div id="GameOverDiv"> </div> <div id="GameDiv"> <!--The following div is hidden or shown depending on if its a non-mobile browser--> <div id="Keyboard"> <label>Command:</label> <input type="text" name="userInput" class="buttonMod" id="userInput" /> </div> <!--The following div is hidden or shown depending on if its a mobile browser--> <div id="controllers"> <!--We use a table for the simple alignment of the buttons--> <table> <tr> <td></td> <td> <input type='button' class='button' value='N' title="North" style="left: 200px" /></td> <td></td> </tr> <tr> <td> <input type='button' class='button' value='W' title="West" /></td> <td></td> <td> <input type='button' class='button' value='E' title="East" /></td> </tr> <tr> <td></td> <td> <input type='button' class='button' value='S' title="South" /></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> </tr> <tr> <td> <input type='button' class='button' value='P' title="Pickup" /></td> <td> <input type='button' class='button' value='A' title="About" /></td> <td> <input type='button' class='button' value='?' title="Help" /></td> </tr> </table> </div> </div> <div id="output"></div> </form> </div> </div> </div> </body> </html>
<script type="text/javascript">
//Our main js code called by Jquery on doc ready
$(document).ready(function () {
//game variables
var message, //screen message to display
hits = 10, //hit points for the player
lightLevel = 100, //current light level
currentRoom = 0, //initial room
exitRoom = 31, //final room of the dungeon
IsGameOver = false; //Maintain the state of the game
IsOgreAlive = true, //Stores the state of the Ogre - Alive/Dead
IsDragonAlive = true; //this is the gameover state
//All the commands we use in the game
var gameWords = new Array("HELP", "Find/earch", "N-orth", "S-outh", "W-est", "E-east','A-About");
//All the rooms in the game
var rooms = new Array("Dungeon Entrance", "Corridor of uncertainty", 'Ancient old cavern', "Great Cavern", "Underground River", "Stream", 'Dungeon Stream', "Dungeon Pool",
"Large Cavern", "Rough Tunnell", "Long Tunnell", "Dark Room", "Dark Room", "Cold Room", "Old Tunnel", "Cold Room",
"Old Cavern", "Short Corridor", "Short Corridor", "Grey Room", "Green Room", "Old Prison Cell", "Underground River",
"Large Cavern", "Rough Tunnell", "Long Tunnell", "Dark Room", "Dark Room", "Cold Room", "Old Tunnel", "Dragons Room");
//Each exit relates to the index ie. Exits[0] SE which means rooms[0] the long path has two exits on the South and East. If we look
//down to the //Movement Code section you can see how we work out which rooms are connected to which
var exits = new Array("E", "SWE", "WE", "SWE", "WE", "WE", "SWE", "WS",
"NSE", "SE", "WE", "NW", "SE", "W", "SNE", "NSW",
"NS", "NS", "SE", "WE", "NWE", "SWE", "WS", "N",
"N", "NWE", "NWE", "WE", "WE", "NW", "NE", "W");
//All out game objects
var GameObjects = new Array('', "Painting", "Knife", "Wand of Firebolts", "Goblet", "Wand of Wind", "Coins", "Helmet", "Candle", "Torch", "Iron Shield", "Armour", "Oil", "AXE", "ROPE", "BOAT", "AEROSOL", "CANDLE", "KEY");
//Inventory array Contains all the things you can carry
var inventory = new Array();
inventory[0] = 2; //lets start our player off with a knife
//location of game objects - these objects relate to a array index - so Object[1] the Painting is located
//in rooms[2] the small garden - 999 indicates out of play
var objectLocations = [999, 1, 999, 3, 4, 5, 6, 7, 8, 10, 11, 15, 14, 12, 18, 19, 16, 17, 9]
//This function detects if the browser if a mobile - you'll see when we call this we apply the
function isMobile() {
return navigator.userAgent.match(/Android/i) || navigator.userAgent.match(/BlackBerry/i) || navigator.userAgent.match(/iPhone|iPad|iPod/i)
|| navigator.userAgent.match(/Opera Mini/i) || navigator.userAgent.match(/IEMobile/i);
}
//The next line checks for a mobile browser and if it find st it will hide the buttons or hide the text box
if (isMobile()) {
//hide the text box - we dont need that for a mobile browser as its hard to use mobile keyboard for lots of commands
$("#Keyboard").hide();
} else {
//hide the buttons as we don't want that for the normal web experience
$('#controllers').hide();
//jquery command to force the textbox to take focus
$("#userInput").focus();
}
//javascript function to pickup the object in this room
var pickup = function (roomIndex) {
var itemIndex;
if (objectLocations[roomIndex] > 0 && objectLocations[roomIndex] < 100) {
itemIndex = objectLocations[roomIndex];
inventory[inventory.length] = itemIndex;
objectLocations[roomIndex] = 999;
alert(objectLocations[roomIndex]);
}
}
//This function loops through the object location array and returns
function getObjectForRoom(currentRoom) {
var roomIndex = -1;
for (var i = 0; i < objectLocations.length ; i++) {
if (objectLocations[i] == currentRoom)
roomIndex = i;
}
return roomIndex
}
//This is a method/function that shows the game screen. If we look in deatil at this function we can see that
//it uses another function DisplayText to show each line of the screen.
function DisplayGameScreen() {
//clear the output div
$display.empty();
//Display the screen output text - note this does not include the buttons
DisplayText("You are now in the :");
DisplayText(rooms[currentRoom]);
DisplayText("Exits: " + ShowAdjacentRooms(exits[currentRoom]) + "<br />");
DisplayText('DB:' + currentRoom + 'Light:' + lightLevel + "Hits:" + hits);
if (getObjectForRoom(currentRoom) != -1) {
var index = getObjectForRoom(currentRoom);
DisplayText("You can see " + GameObjects[index]);
}
//If there is something in our inventory then display it
if (inventory.length > 0) {
DisplayText("You are carrying: ");
for (var i = 0; i < inventory.length ; i++) {
DisplayText("-" + GameObjects[inventory[i]]);
}
}
if (message != null)
DisplayText(message.toUpperCase());
//Game over code
if (IsDragonAlive) {
$('#GameOverDiv').hide();
$('#GameDiv').show();
}
else {
$('#GameOverDiv').show();
$('#GameDiv').hide();
}
message = "What?";
}
//Replaces the indexOf js function as i have found it doesn't always work for me!!!!!!!!
function checkIndex(issFullArray, issToCheck) {
for (i = 0; i < issFullArray.length; i++) {
if (issFullArray[i] == issToCheck) {
return true;
}
}
return false;
}
//Uses the text for a room to build a string that shows which rooms are next to the current room
function ShowAdjacentRooms(e) {
var newExits = "";
if (e != null) {
for (i = 0; i < e.length; i++) {
if (i === e.length - 1) {
newExits += e.substring(i, i + 1);
} else if (i === e.length - 2) {
newExits += e.substring(i, i + 1) + " & ";
} else {
newExits += e.substring(i, i + 1) + ", ";
}
}
}
return newExits;
}
//Simple js function to display a line of text
function DisplayText(text) {
$display.html($display.html().toString() + text + "<br>");
}
//Each round we call this function to do all the main game processing
function ProcessGameRound(command) {
//Remove any spaces from the command text
trimCommand = $.trim(command);
//Process command takes the players action
ProcessCommand(command);
//NOw that we have taken the players logic we need to activate the main game room logic
if (currentRoom == 10 && OgreAlive) {
//if you are fighting the ogre and you have the spells
if (checkIndex(inventory, 3)) {
message += "\<br\>YOU attack the ogre with magic spells and kill him!";
OgreAlive = false;
}
else {
message += "\<br\>Ogre attacks you!";
hits--;
}
}
//If you are in the final room and the dragon is still alive
if (currentRoom == 31 && IsDragonAlive) {
//if you are fighting the dragon and you have the oil, burning torch
if (checkIndex(inventory, 5) && checkIndex(inventory, 9) && checkIndex(inventory, 12)) {
message += "\<br\>You attack the dragon with oil, burning torch and the wand of Wind - It creates and kill him!";
IsDragonAlive = false; //End Game
}
else {
message += "\<br\>The dragon attacks you with firebreath and kills you!";
hits = 0;
}
}
if (currentRoom == 25) {
//if you are fighting the gas room burning torch
if (checkIndex(inventory, 10)) {
message += "\<br\>The gas in the room is ignited by the torch - You become a human BBQ and die!";
hits = 0;
}
}
DisplayGameScreen();
}
function ProcessCommand(command) {
var direction = command;
message = "OK";
switch (command) {
//Movement Code
case "N":
if (exits[currentRoom].indexOf(direction) > -1)
currentRoom -= 8;
else
message = "Can't move there";
break;
case "S":
if (exits[currentRoom].indexOf(direction) > -1)
currentRoom += 8;
else
message = "Can't move there";
break;
case "E":
if (exits[currentRoom].indexOf(direction) > -1)
currentRoom++;
else
message = "Can't move there";
break;
case "W":
if (exits[currentRoom].indexOf(direction) > -1)
currentRoom--;
else
message = "Can't move there";
break;
//End of Movement Code
case "P":
pickup(currentRoom);
break
case "A":
if (exits[currentRoom].indexOf(direction) > -1)
message = "About ... Game built for #1GAM, LD48 (failed) and my friend Hilary";
break
case "?":
message = "The following commands are valid: N S E W P A ?";
break
}
}
//JQuery selector that handles the form submit -
$('#input form').submit(function (evt) {
ProcessGameRound($('#userInput').val().toUpperCase());
$('#userInput').val('');
evt.preventDefault();
});
//sets the output div to the display variable
$display = $('#output');
// This is jQuery selector that picks up an event from the button - in this case we look at the value of the button ie. its text and use that
//to call the same function as we would call from the equivalent keyboard command
$(".button").click(function (e) {
switch (this.value) {
case "N":
ProcessGameRound('N');
break;
case "S":
ProcessGameRound('S');
break;
case "E":
ProcessGameRound('E');
break;
case "W":
ProcessGameRound('W');
break;
case "F":
ProcessGameRound('F');
break;
case "P":
pickup(currentRoom);
break;
case "A":
ProcessGameRound('A');
break;
}
});
DisplayGameScreen();
});
</script>
Are the bugs
Yep – Totally , lots that the point – we’ll start cleaning them up in the next version
Next
I’ll add in a series of improvements in version 2 of this game.
Source Control link
I started doing some reviews for this years 7drl but ran out of time and ended up realising that someone is doing a much better job than me on this front so I gave up – but the fruits of this guys work is just brilliant. The cool thing about the review is this includes a walkthrough of the game – Ok so he hasn’t reviewed RogueCoder yet but thats all cool – I’ll let you know (good or bad)!!!
http://www.youtube.com/user/TheUberHunter/videos
just look at any recent ones titled 7drl 2013
Ok this is a fairly crazy game – I built in 7 days (actually would end up to be about 20 -30 hours) with a lack of sleep – if you have a chance to have a play – let me know your thoughts – big thanks to Scott Hanselman for letting me use him as a main character. I’ll publish the code soon
It’s written in asp.net mvc4, html5, Javascript
Just doing some reviews this is the first game i have come across by slash and its seriously cool – great old school rogue-like with very cool IRC feature where I got to chat with the dev – SLASH. Its an excellent game with classic rogue-like features and cool shading effects!!! Also for HTML/JS people this is a great example of what you can do (also includes Websockets – SLASH told me).
Not sure how many I’ll get to but this was a great start.
Cool game http://slashware.net/rodney/
I have just finished (well sunday) my 7 Day Roguelike game. Its an annual comp that requires you to build a game in 7 days. I’ll send some more details out soon and if you would like to play with it test it great. It was built in HTML5, JS, C#,ASP.NET MVC4. I’ll also add the git source control. Big thanks to Scott Hanselman for agreeing to be a character in it.