// Tom's Halls game
// Tom W Hall 2007 - 2008
// tomshalls@gmail.com
// Global variables
var gViewport;
var gPlayer;
var gLoopInterval;
var gLoopIntervalMs = 15;
// Force / direction constants
var forceNeutral = 0;
var forceLeft = 1;
var forceRight = 2;
var forceUp = 3;
var forceDown = 4;
addEvent(window, 'load', initialSetUp);
doPreLoadImages('images/grey-flower-tile.png', 'images/divider.png', 'images/loading.png');
preLoadImages();
// Initializes game
function initialSetUp()
{
gConfig = new Config();
gViewport = new Viewport('viewport');
gPlayer = new Player(gViewport);
gViewport.addPlayer(gPlayer);
updateScreen();
updateLives();
updateManuscriptPages();
addEvent(window.document, 'keypress', keyPress);
addEvent(window.document, 'keydown', keyPress);
addEvent(window.document, 'keyup', keyUp);
addEvent(document.getElementById('game-info-text'), 'click', gameInfoTextClick);
}
// Updates screen's Javascript reference etc
function updateScreen()
{
clearInterval(gLoopInterval);
gViewport.clear();
var head = document.getElementsByTagName('head')[0];
var script = document.getElementById('screen-script');
if (script)
{
head.removeChild(script);
}
script = document.createElement('script');
script.id = 'screen-script';
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', 'js/screens/screen_' + gPlayer.screenX + '_' + gPlayer.screenY + '.js');
head.appendChild(script);
gPlayer.screenEntryLeft = gPlayer.left;
gPlayer.screenEntryTop = gPlayer.top;
gPlayer.updateDomElement();
gViewport.domElement.focus();
}
// Main game loop
function loop()
{
if (gPlayer.lostLife)
{
updateLives();
gPlayer.lostLife = false;
}
else if (gPlayer.lostLifeCountdown > 0)
{
gPlayer.deathFade();
}
else
{
gViewport.updateSprites();
gPlayer.applyPhysics();
if (gPlayer.gotManuscriptPage)
{
updateManuscriptPages();
gPlayer.gotManuscriptPage = false;
}
}
}
// Adds event listener to object
function addEvent(obj, evt, func)
{
if (obj.addEventListener)
{
obj.addEventListener(evt, func, false);
return true;
}
else if (obj.attachEvent)
{
return obj.attachEvent("on" + evt, func);
}
else
{
obj[evt] = func;
}
}
// Handles key down
function keyPress(e)
{
var keyDownID = window.event ? event.keyCode : (e.keyCode != 0 ? e.keyCode : e.which);
switch(keyDownID)
{
case 37:
gPlayer.tryMoveLeft();
break;
case 39:
gPlayer.tryMoveRight();
break;
case 38:
gPlayer.tryMoveUp();
break;
case 40:
gPlayer.tryMoveDown();
break;
case 32:
gPlayer.tryJump();
break;
case 112:
if (gPlayer.speedY < 0)
{
gPlayer.invincible = true;
}
break;
}
}
// Handles key up
function keyUp(e)
{
var keyDownID = window.event ? event.keyCode : (e.keyCode != 0 ? e.keyCode : e.which);
switch(keyDownID)
{
case 37:
gPlayer.endTryMoveLeft();
break;
case 39:
gPlayer.endTryMoveRight();
break;
case 38:
gPlayer.endTryMoveUp();
break;
case 40:
gPlayer.endTryMoveDown();
break;
}
}
// Toggles display of the game info panel
function gameInfoTextClick()
{
var gameInfo = document.getElementById('game-info');
if (gameInfo.style.display == 'block')
{
gameInfo.style.display = 'none';
gLoopInterval = setInterval('loop()', gLoopIntervalMs);
}
else
{
gameInfo.style.display = 'block';
clearInterval(gLoopInterval);
}
}
// Updates the current screen name
function updateScreenName(screenName)
{
updateInnerText('screen-name-text', screenName);
}
// Updates the Manuscript Pages box
function updateManuscriptPages()
{
updateInnerText('manuscript-pages', gPlayer.manuscriptPages);
}
// Updates the player lives box
function updateLives()
{
if (gPlayer.lives < 1)
{
gPlayer.screenX = 100;
gPlayer.screenY = 200;
gPlayer.left = 352;
gPlayer.top = 264;
gPlayer.domClass = 'player-left';
updateScreen();
}
var lives = document.getElementById('lives');
while (lives.hasChildNodes())
{
lives.removeChild(lives.firstChild);
}
var numLives = gPlayer.lives;
if (numLives > 0)
{
var i = numLives;
do
{
var life = document.createElement('div');
life.className = 'player-left';
life.style.width = '32px';
life.style.height = '64px';
lives.appendChild(life);
}
while (--i);
}
}
// Updates the inner text of the supplied DOM element with the supplied text
function updateInnerText(elementId, text)
{
var el = document.getElementById(elementId);
while (el.hasChildNodes())
{
el.removeChild(el.firstChild);
}
var textNode = document.createTextNode(text);
el.appendChild(textNode);
}
function preLoadImages()
{
doPreLoadImages(
'images/ascii-asterisc.gif',
'images/ascii-hash.gif',
'images/ascii-plus.gif',
'images/black-bg.gif',
'images/fire.gif',
'images/bookshelf.jpg',
'images/border.jpg',
'images/cdshelf.jpg',
'images/earth.jpg',
'images/earth-bg.jpg',
'images/email.jpg',
'images/forest.jpg',
'images/game-info.jpg',
'images/grass.jpg',
'images/hell.jpg',
'images/lives.jpg',
'images/logo.jpg',
'images/manuscript-pages.jpg',
'images/parchment.jpg',
'images/plot.jpg',
'images/saloon.jpg',
'images/sand.jpg',
'images/sky.jpg',
'images/technical-background.jpg',
'images/tom.jpg',
'images/wood.jpg',
'images/wood-pale.jpg',
'images/bathtub-left.png',
'images/bathtub-right.png',
'images/bed.png',
'images/bricks.png',
'images/bricks-bg.png',
'images/bricks-bg-dark.png',
'images/ceiling.png',
'images/crazy-robert-left.png',
'images/crazy-robert-right.png',
'images/desk.png',
'images/devil-left.png',
'images/devil-right.png',
'images/gravy-jug-left.png',
'images/gravy-jug-right.png',
'images/gunslinger-left.png',
'images/gunslinger-right.png',
'images/hifi-rack.png',
'images/ladder.png',
'images/log.png',
'images/manuscript.png',
'images/ozymandias.png',
'images/plant-pot.png',
'images/skull-left.png',
'images/skull-right.png',
'images/player-left.png',
'images/player-right.png',
'images/player-updown.png',
'images/plot.png',
'images/speaker-left.png',
'images/speaker-right.png',
'images/spider.png',
'images/spider-silk.png',
'images/statue.png',
'images/stodgeson-left.png',
'images/stodgeson-right.png',
'images/stove.png',
'images/sunflower.png',
'images/sunflower-stalk.png',
'images/table-leg.png',
'images/tile-blue.png',
'images/tile-copper.png',
'images/tile-green.png',
'images/tile-grey.png',
'images/tile-red.png',
'images/toilet-left.png',
'images/toilet-right.png',
'images/tomato.png',
'images/wallpaper.png'
);
}
function doPreLoadImages()
{
var images = new Array();
var i = 0;
do
{
var image = new Image();
image.src = doPreLoadImages.arguments[i];
images.push(image);
i++;
}
while (i < arguments.length)
}
function Config()
{
this.startScreenX = 101;
this.startScreenY = 101;
this.left = 50;
this.top = 448;
this.domClass = 'player-right';
this.invincible = false;
}
// SCREEN CREATION METHODS ----------
function addElement(id, domClass, left, top, width, height)
{
gViewport.addElement(new Element(id, domClass, left, top, width, height, gViewport));
}
function addSteps(topX, topY, width, height, stepHeight, domClass, isSolid)
{
var stepWidth = Math.round(width / (height / stepHeight));
var x = (width >= 0) ? topX : topX - Math.abs(stepWidth);
var y = topY;
do
{
if (isSolid)
{
if (width >= 0)
{
gViewport.addElement(new Element(null, domClass, topX, y, (x - topX) + stepWidth, stepHeight, gViewport));
}
else
{
gViewport.addElement(new Element(null, domClass, x, y, topX - x, stepHeight, gViewport));
}
}
else
{
gViewport.addElement(new Element(null, domClass, x, y, Math.abs(stepWidth), stepHeight, gViewport));
}
x += stepWidth;
y += stepHeight;
}
while (y < topY + height);
}
function addHorizontalMonster(id, left, top, width, height, leftLimit, rightLimit, force, movementIncrement, leftDomClass, rightDomClass)
{
gViewport.addElement(new HorizontalMonster(id, left, top, width, height, leftLimit, rightLimit, force, movementIncrement, leftDomClass, rightDomClass, gViewport));
}
function addVerticalMonster(id, left, top, width, height, topLimit, bottomLimit, force, movementIncrement, upDomClass, downDomClass)
{
gViewport.addElement(new VerticalMonster(id, left, top, width, height, topLimit, bottomLimit, force, movementIncrement, upDomClass, downDomClass, gViewport));
}
function addSpider(id, left, top, topLimit, bottomLimit, force, movementIncrement)
{
gViewport.addSpider(new Spider(id, left, top, topLimit, bottomLimit, force, movementIncrement, gViewport));
}
function addSunflower(id, left, top, topLimit, bottomLimit, force, movementIncrement)
{
gViewport.addSunflower(new Sunflower(id, left, top, topLimit, bottomLimit, force, movementIncrement, gViewport));
}
function addElevator(id, domClass, left, top, width, height, topLimit, bottomLimit, force, movementIncrement)
{
gViewport.addElement(new Elevator(id, domClass, left, top, width, height, topLimit, bottomLimit, force, movementIncrement, gViewport));
}
function addZoomevator(id, domClass, left, top, width, height, leftLimit, rightLimit, force, movementIncrement)
{
gViewport.addElement(new Zoomevator(id, domClass, left, top, width, height, leftLimit, rightLimit, force, movementIncrement, gViewport));
}
function addManuscriptPage(id, left, top)
{
var manuscriptPg = null;
if (gViewport.manuscriptPages.length > 0)
{
var i = gViewport.manuscriptPages.length -1;
do
{
var mp = gViewport.manuscriptPages[i];
if (mp.id == id)
{
manuscriptPg = mp;
break;
}
}
while (i--);
}
if (manuscriptPg == null)
{
manuscriptPg = new ManuscriptPage(id, left, top, gViewport);
gViewport.addManuscriptPage(manuscriptPg);
}
if (manuscriptPg.collected == false)
{
gViewport.addElement(manuscriptPg);
manuscriptPg.addDomElement();
}
}
// ---------- SCREEN CREATION METHODS