(function() {
var map = [
[ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ],
[ 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ],
[ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ],
[ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ]
];
var adds = { a1: [0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,1], a2: [0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,1],
a3: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], a4: [0,0,0,0,0,0,0,0,0,2,2,2,0,0,2,2,1] };
var runTime = 0;
var times = [];
function Platformer() {
var gameSpecs = {
gWidth:10280, gHeight:272,cameraWidth:640, cameraHeight:272,
cameraFollowOffsetX:-9320, cameraFollowOffsetY:0, tileW:16, tileH:16,
spriteSheetImage: null, containerDivId:"container", rootDivId:"root",
controllerDivId:"controller", gameScale:2, useScreenOrganizer:true,startWidth:50, startHeight:25,
controllerHeight:144, initialLives:3, initPlayerPosition:new tabageos.MoverPoint(32,32),
gameLoop:this.loop,initializationSpecifics:this.setup, disableBackgroundAlpha:0,
addedResizeMethod:null, sceneResetSpecifics:null,fullResetSpecifics:null, additionalSceneResetSpecifics:null,
positionResetSpecifics:this._resetPosition, cameraType:1, backgroundColor:"#c8c8c8"
};
tabageos.GameSkeleton.call(this, gameSpecs);
this.establishKeyEventsForReset();
}
Platformer.constructor = Platformer;
//JavaScript basic inheritance, the tabageos library also includes an implementation of Object.assign if Object.assign is not already defined in the browser.
Platformer.prototype = Object.create(tabageos.GameSkeleton.prototype);
Platformer.prototype.setup = function(sax,say) {
this.lives = 3000000;
this.title.floor.context.fillStyle = "#ffffff";
this.title.floor.context.fillRect(0,0,1280,272);
//we add our own html to the title screen.
var tdiv = document.createElement("div");
tdiv.innerHTML = "<h1 style='color:#6495ed'>Endless Runner</h1><br />"+
"Click start or press shift to start<br />"+
"Press right or D to run. W or up to jump. <br /> To use a gamepad, after starting, press one of its directional buttons then follow the on screen prompts.";
tdiv.setAttribute("style", "position:absolute;width:640px;top:0px;left:0px;text-align:center;color:#6495ed");
this.title.div.appendChild(tdiv);
var mp = tabageos.BlitMath.cloneMultiArray(map);//we clone map, because we'll use map to reset.
//for now the player will just be a simple MapMover, by the end we will use TravelingSceneryThrower for it.
this.player = new tabageos.MapMover(48,48,16,16,mp,0,1);
this.player._jumps = 1;//gravity is now applied to the character, by default it does not move with gravity, ._jumps is 0 by default for MapMovers.
this.player._jumpSpeed = 4;//default _jumpSpeed is 4
this.player._gravityLevel = .305;//.285 is the default _gravityLevel.
this.player._autoAnimate = 1;
this.player._walkSpeed = 4;
this.player._directCanvasObject = this.charLayer;
//these are properties inherited from GameSkeleton.
//this.resizeRootForNoTouch = 1; //when no touch, resize just the root instead of the whole container, root should be inside container, and controller should be under root also inside container.
//resizeRootForNoTouch is for when your game is not fullscreen/page.
this.dontResizeVertical = 1;
this.addedResizeMethod = this.pageSpecificResizing;//allows to add additional functionality during resizing beyond just fitting the game/controller layers to the page.
this.charLayer.context.fillStyle = "#6495ed";
//now the user can plug in a game pad, and press one of the directional buttons to start using it.
this.enableGamePad = 1;
//colorValues tells
this.camera.colorValues = {1:"#c8c8c8",2:"#0c0c0c", 3:"#ffff00"};
//with setupForRenderFromMap what is going to happen is that the display layer will be drawn directly from the map instead of from an offscreen canvas.
//and when the map is about to run out, the mapUpdateMethod will be called.
//and so the map array keeps growing in size, but there is no giant CanvasObject created.
//however when using a predrawn offscreen canvas there is only 1 render call to render that offscreen canvas to the camera.
//in this case the camera will render each tile from the map directly, so there is a render call for each tile.
//smaller predrawn level layers perform better.
//but this example shows how to set things up to draw from the array directly, and how to keep repopulating the array.
this.camera.setupForRenderFromMap(mp,null,16,16,2,648,272);
this.camera.mapUpdateMethod = this.updateMap;
//adding html to the gameOverContainer.
var goDiv = document.createElement("div");
goDiv.setAttribute("style", "position:absolute;font-family: 'soupoj', sans-serif;width:640px;color:black;text-align:center");
goDiv.innerHTML = "<h2>Game Over</h2><br /><br /><br /><span style='cursor:pointer' onclick='tabageos.GameSkeleton.game.hudExit()'>Press Start</span>";
this.gameOverContainer.div.appendChild(goDiv);
};
Platformer.prototype._resetPosition = function() {
//this method happens when the level is reset.
//reset the player position.
this.player.setX(48);
this.player.setY(16);
this.horizontalCameraMove = 0;
//and camera position.
this.camera.v.x = 0;
this.camera.v.y = 0;
//and reset map.
var mp = tabageos.BlitMath.cloneMultiArray(map);
this.camera._map = mp;
this.player._map = mp;
this.player._mapRows = mp.length;
this.player._mapColumns = mp[0].length;
//do camera operations once
this.callCamera();
};
Platformer.prototype.updateMap = function() {
//this method is being called from the camera not from 'this'.
var mp = tabageos.GameSkeleton.game.camera._map;//which actually is this._map inside this function.
tabageos.BlitMath.addSpecificValuesToMultiArray(mp, adds.a1);//add a1, the floor, 3 times.
tabageos.BlitMath.addSpecificValuesToMultiArray(mp, adds.a1);
tabageos.BlitMath.addSpecificValuesToMultiArray(mp, adds.a1);
var ran = Math.floor(Math.random()*4) + 1;//pick a random number 1,2,3,4.
tabageos.BlitMath.addSpecificValuesToMultiArray(mp, adds["a"+ran]);//add that random array set.
if(ran == 3) { //if the added random set is the blank, drop set, add 6 more.
tabageos.BlitMath.addSpecificValuesToMultiArray(mp, adds["a"+ran]);
tabageos.BlitMath.addSpecificValuesToMultiArray(mp, adds["a"+ran]);
tabageos.BlitMath.addSpecificValuesToMultiArray(mp, adds["a"+ran]);
tabageos.BlitMath.addSpecificValuesToMultiArray(mp, adds["a"+ran]);
tabageos.BlitMath.addSpecificValuesToMultiArray(mp, adds["a"+ran]);
tabageos.BlitMath.addSpecificValuesToMultiArray(mp, adds["a"+ran]);
}
tabageos.GameSkeleton.game.player._map = mp;//but we use the GameSkeleton.game reference to reference the player.
tabageos.GameSkeleton.game.player._mapRows = mp.length;
tabageos.GameSkeleton.game.player._mapColumns = mp[0].length;
};
Platformer.prototype.showRunTime = function(ts) {
//this method hijacks the loop.
//so we use _helperPoint to ensure this block happens just once.
if(this._helperPoint.x == -444) {
this._helperPoint.x = 0;
var now = (new Date().getTime() - runTime) / 1000;
times.push(now);
var best = now+1-1;var i = 0;
for(i;i<times.length;i++) {
if(times[i] > best) {
best = times[i]+1-1;
}
}
//show text for 7 seconds.
this.showText("Current Run Time: " + Math.floor(now) + " seconds 
 Best Run Time: " + Math.floor(best) + " seconds",7000,17,640,270,-3,-3,'soupoj',0,'background-color:#6495ed00');
}
//textFinished actually happens a bit before the 7 seconds are up.
//and if the user presses space also it would restart the level.
if(this.textFinished() || this.controller.buttons.a) {
this.hideText();
this.endLevelComplete(0);
}
};
Platformer.prototype.loop = function() {
//move and collide with the map
this.player.move(this.horizontalCameraMove ? this.controller.buttons.left : 0, this.horizontalCameraMove ? 1 : 0,this.controller.buttons.up || this.controller.buttons.a,this.controller.buttons.down);
//if horizontalCameraMove is not yet set, and the user presses right, set horizontalCameraMove.
//horizontalCameraMove causes the camera to contiuosly move horizontally no longer following the player.
if(this.controller.buttons.right && !this.horizontalCameraMove) {
this.controller.buttons.right = 0;
runTime = new Date().getTime();//the run has begun, keep the start time.
this.horizontalCameraMove = 2.6;
}
if(this.player.x + 16 < this.camera.v.x || this.player.y > 272 - 32 || this.player.x > this.camera.width - 32) {
this._helperPoint.x = -444;
this.levelComplete(this.showRunTime);
}
//that's it, move is handling movement and collision.
//and the player animates itself also during move because we have set that up during the setup call.
//GameSkeleton is smoothing a requestAnimationFrame call and calling this method in the middle of those calculations.
};
new Platformer();
})();
back to top