Last active
August 2, 2016 03:12
-
-
Save anotheredward/5895c31d007bda14b45fc5e3be694dcf to your computer and use it in GitHub Desktop.
CHCH.js Roguelike
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<pre id="maze"></pre> | |
<script> | |
//Why a roguelike? | |
//A RL is a sweetspot between effort vs. new features | |
//You get something awesome every 5 LoC or even just by tweaking a single variable, and this makes it fun to program | |
//What's exciting about JS is that you can make something you can see in a browser, fast, and then share it with everyone | |
//JS being a simple to understand, practical, and easy to share language has helped it develop an awesome community | |
//Things to tweak | |
//Try adding a ghost trail to the player by not replacing their last position with a . | |
//Try making an AI that moves randomly, that moves towards the player, that runs away from the player (like tag) | |
// pacman AI have some great examples of these behaviours: http://gameinternals.com/post/2072558330/understanding-pac-man-ghost-behavior | |
//Try writing code to generate a map, ideas here: http://ondras.github.io/rot.js/manual/#map | |
//Try tweaking the visibility code, you can make the whole maze invisible, make only certain items always visible, | |
// give the player a direction and let them only see that way | |
// or even try and implement a better algorithm: http://journal.stuffwithstuff.com/2015/09/07/what-the-hero-sees/ | |
//Try adding more items, doors that you can stand on but not see through, different treasure, keys, stairs to different levels, go crazy! | |
const maze = [ | |
'##########', | |
'#@.......#', | |
'#........#', | |
'#..###...#', | |
'#....##..#', | |
'#..T...R.|', | |
'##########', | |
] | |
let map = maze.map(line => line.split('')) | |
let player = {x: 1, y: 1, char: '@'} | |
let robot = {x: 7, y: 5, char: 'R'} | |
const keyCodeToDirection = { | |
37: {x: -1, y: 0}, | |
38: {x: 0, y: -1}, | |
39: {x: 1, y: 0}, | |
40: {x: 0, y: 1} | |
} | |
function addPoint(point1, point2) { | |
return { x: point1.x + point2.x, y: point1.y + point2.y } | |
} | |
function render(map) { | |
document.getElementById('maze').innerHTML = | |
filterMap(map, player).map(characters => characters.join('')).join('\n') | |
} | |
function filterMap (map, player) { | |
return map.map((line, y) => | |
line.map((character, x) => | |
canSee(player, x, y) ? character : ' ' | |
) | |
) | |
} | |
function canSee (player, x, y) { | |
return rectAroundPlayer(player, 5) | |
.some(point => point.x === x && point.y === y) | |
} | |
document.onkeydown = function(e) { | |
const direction = keyCodeToDirection[e.keyCode] | |
if (direction) { | |
e.preventDefault() | |
player = move(player, direction) | |
robot = move(robot, direction) | |
render(map) | |
} | |
} | |
function move(entity, direction) { | |
const newPosition = addPoint(entity, direction) | |
const newCharacter = map[newPosition.y][newPosition.x] | |
if (newCharacter === '.') { | |
return teleportEntity(entity, newPosition) | |
} else if (newCharacter === 'T') { | |
if (entity.char === 'R') | |
alert("Oh No! The robot wins!") | |
else | |
alert("Congrats! You win!") | |
} | |
return entity | |
} | |
function teleportEntity(entity, {x,y}) { | |
map[entity.y][entity.x] = '.' | |
map[y][x] = entity.char | |
return {x, y, char: entity.char} | |
} | |
render(map) | |
// Util Functions | |
function rectAroundPlayer (point, diameter) { | |
const radius = Math.floor(diameter / 2) | |
return getRect({x: point.x -radius, y: point.y -radius}, {x: point.x +radius, y: point.y +radius}) | |
} | |
function getRect(topLeft, bottomRight) { | |
const line = range(topLeft.x, bottomRight.x + 1) | |
const column = range(topLeft.y, bottomRight.y + 1) | |
const box = line.map(x => column.map(y => ({x,y}))) | |
return flatten(box) | |
} | |
// General utils | |
function flatten (arr) { | |
return [].concat.apply([], arr) | |
} | |
function range(a, b, step) { | |
if (arguments.length === 1) { | |
b = a; | |
a = 0; | |
} | |
step = step || 1; | |
var x, r = []; | |
for (x = a; (b - x) * step > 0; x += step) { | |
r.push(x); | |
} | |
return r; | |
} | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment