You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

402 lines
10 KiB

10 months ago
var NFS_HEIGHT = 500;
var CAR_BOTTOM = 10;
var CAR_HEIGHT = 80 + CAR_BOTTOM;
var CAR_WIDTH = 40;
var OBSTACLE_WIDTH = 100;
var OBSTACLE_HEIGHT = 33.328;
var OBSTACLE_APPEARANCE_GAP = 1000; //1 second
var OBSTACLE_APPEARANCE_DX = 100;
var PX_DX = 3;
var PX_DX_DX = 0.05;
var GAME_TIME = 1;
var GAME_TIME_DX = 11;
var INITIAL_BULLETS_BOTTOM = CAR_HEIGHT;
function Util() {}
Util.getRandomInt = function(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
};
function Obstacle(lanes, laneNo) {
var _this = this;
this._init = function() {
this.element = document.createElement('img');
this.laneNo = laneNo;
this.lanes = lanes;
this.element.className = 'obstacle';
this.element.setAttribute('src', 'images/obstacle.png');
this.lanes[laneNo].appendChild(this.element);
this.dynamicMarginTop = 1;
};
this._init();
}
function ObstacleManager(lanes, car) {
var _this = this;
this._init = function() {
this.lanes = lanes;
this.car = car;
this.obstacles = [];
};
this.generateObstacles = function() {
_this.obstacleGeneratorId = setInterval(_this._generateObstacle, OBSTACLE_APPEARANCE_GAP);
};
this._generateObstacle = function() {
if (_this.obstacles.length < 3) {
var laneNo;
laneNo = Util.getRandomInt(0, _this.lanes.length - 1);
var obstacle = new Obstacle(_this.lanes, laneNo);
_this.obstacles.push(obstacle);
return obstacle;
}
};
this.refreshObstacles = function() {
var updatedObstacles = [];
for (var i = 0; i < _this.obstacles.length; i++) {
_this.obstacles[i].element.style.top = _this.obstacles[i].dynamicMarginTop + 'px';
if (!(parseInt(_this.obstacles[i].element.style.top) > NFS_HEIGHT - CAR_BOTTOM)) {
_this.obstacles[i].dynamicMarginTop += PX_DX;
updatedObstacles.push(_this.obstacles[i]);
} else {
_this.obstacles[i].element.parentElement.removeChild(_this.obstacles[i].element);
for (var j = 0; j < _this.obstacles.length; j++) {
if (_this.obstacles[j].element.parentElement === _this.obstacles[i].element.parentElement) {
_this.obstacles[j].element.style.top = _this.obstacles[j].dynamicMarginTop + OBSTACLE_HEIGHT + 'px';
}
}
}
}
_this.obstacles = updatedObstacles;
};
this.removeObstacle = function(obstacle){
var index = this.obstacles.indexOf(obstacle);
if(index !== -1){
console.log(this.obstacles[index].parentElement);
this.obstacles[index].element.parentElement.removeChild(this.obstacles[index].element);
this.obstacles.splice(index, 1);
}
};
this.getOldestObstacleInLane = function(bulletLane){
var obstacle;
for(var i = 0; i < _this.obstacles.length; i++){
if(_this.obstacles[i].laneNo == bulletLane){
if(obstacle === undefined || _this.obstacles[i].dynamicMarginTop > obstacle.dynamicMarginTop){
obstacle = _this.obstacles[i];
}
}
}
return obstacle;
};
this.stop = function() {
if (this.obstacleGeneratorId) {
clearInterval(this.obstacleGeneratorId);
this.obstacleGeneratorId = false;
}
};
this._init();
}
function CollisionHandler(car, obstacleManager) {
var _this = this;
this._init = function() {
this.car = car;
this.obstacleManager = obstacleManager;
};
this.checkCollisions = function() {
for (var i = 0; i < _this.obstacleManager.obstacles.length; i++)
return _this._checkCollision(_this.obstacleManager.obstacles[i]);
};
this._checkCollision = function(obstacleO) {
if ((obstacleO.dynamicMarginTop + OBSTACLE_HEIGHT > NFS_HEIGHT - CAR_HEIGHT) && (obstacleO.laneNo == _this.car.currentLane)) {
return true;
}
};
this.checkShot = function(){
var bulletLane;
for(var i = 0; i < _this.obstacleManager.lanes.length; i++){
if(_this.obstacleManager.lanes[i].getElementsByClassName('bullets').length > 0) {
bulletLane = i;
break;
}
}
var oldestObstacleInCurrentLane = obstacleManager.getOldestObstacleInLane(bulletLane);
if(oldestObstacleInCurrentLane !== undefined && _this.car.gun.bullets !== undefined) {
if (_this.car.gun.dynamicBulletBottom + oldestObstacleInCurrentLane.dynamicMarginTop + CAR_HEIGHT + OBSTACLE_HEIGHT > NFS_HEIGHT) {
_this.car.gun.stop();
_this.car.enableGun();
_this.obstacleManager.removeObstacle(oldestObstacleInCurrentLane);
}
}
if(_this.car.gun.dynamicBulletBottom + CAR_HEIGHT > NFS_HEIGHT){
_this.car.gun.stop();
_this.car.enableGun();
}
};
this._init();
}
function Car(currentLane, lanes) {
var _this = this;
this._init = function() {
this.currentLane = currentLane;
this.lanes = lanes;
this.element = document.createElement('img');
this.element.className = 'car';
this.element.setAttribute('src', 'images/car.png');
this.lanes[this.currentLane].appendChild(this.element);
this.gun = new Gun(this.lanes);
};
this._changeLane = function(laneNumber) {
if (_this.currentLane != laneNumber) {
_this.lanes[laneNumber].appendChild(_this.element);
}
if (_this.currentLane > laneNumber) {
_this.currentLane--;
} else if (_this.currentLane < laneNumber) {
_this.currentLane++;
}
};
this._keyNavigation = function(e) {
switch (e.which) {
case 37: // left
_this._changeLane((_this.currentLane - 1) < 0 ? 0 : (_this.currentLane - 1));
break;
case 39: // right
_this._changeLane((_this.currentLane + 1) > _this.lanes.length - 1 ? _this.lanes.length - 1 : (_this.currentLane + 1));
break;
default:
return; // exit this handler for other keys
}
};
this._fireGunEvent = function(e){
switch (e.which){
case 32:
_this._disableGun();
_this.gun.fireBullets(_this.currentLane);
break;
}
};
this.enableGun = function(){
document.addEventListener('keyup', this._fireGunEvent, false);
};
this._disableGun = function(){
document.removeEventListener('keyup', this._fireGunEvent, false);
};
this._initEvents = function() {
document.addEventListener('keydown', this._keyNavigation, false);
this.enableGun();
};
this._removeEvents = function() {
document.removeEventListener('keydown', this._keyNavigation, false);
this._disableGun();
};
this.stop = function() {
_this._removeEvents();
};
this._init();
}
function Gun(lanes){
var _this = this;
this._init = function(){
this.lanes = lanes;
};
this.fireBullets = function(currentLane){
var bullets = document.createElement('img');
bullets.setAttribute('src', 'images/bullets.png');
bullets.className = 'bullets';
_this.lanes[currentLane].appendChild(bullets);
_this.bullets = bullets;
_this.dynamicBulletBottom = INITIAL_BULLETS_BOTTOM;
_this.bulletId = requestAnimationFrame(_this.animateFireBullets);
};
this.animateFireBullets = function () {
_this.dynamicBulletBottom += PX_DX;
_this.bullets.style.bottom = _this.dynamicBulletBottom + 'px';
_this.bulletId = requestAnimationFrame(_this.animateFireBullets);
};
_this.stop = function () {
if(_this.bulletId){
cancelAnimationFrame(_this.bulletId);
_this.bulletId = false;
_this.bullets.parentElement.removeChild(_this.bullets);
_this.bullets = undefined;
}
};
this._init();
}
function NFS() {
var _this = this;
this._init = function() {
this.lanes = document.getElementsByClassName('lane');
this.container = document.getElementById('container');
this.obstacles = [];
this.car = new Car(Util.getRandomInt(0, this.lanes.length - 1), this.lanes);
this.obstacleManager = new ObstacleManager(this.lanes, this.car);
this.collisionHander = new CollisionHandler(this.car, this.obstacleManager);
this.dynamicBackgroundPositionY = 1;
document.getElementById('toggle').addEventListener('click', function() {
if (this.innerHTML == 'Start') {
_this.obstacleManager.generateObstacles();
_this.play();
_this.car._initEvents();
_this._startTime();
this.innerHTML = 'Pause';
} else if (this.innerHTML == 'Pause') {
_this.stop();
this.innerHTML = 'Start';
}
});
};
this._startTime = function(){
this.timeId = setInterval(function(){GAME_TIME++;}, 1000);
};
this._stopTime = function(){
if(this.timeId){
clearInterval(this.timeId);
this.timeId = false;
}
};
this.play = function() {
_this.dynamicBackgroundPositionY += PX_DX;
_this.container.style.backgroundPositionY = _this.dynamicBackgroundPositionY + 'px';
_this.obstacleManager.refreshObstacles();
if(GAME_TIME % GAME_TIME_DX == 0) {
PX_DX += PX_DX_DX;
OBSTACLE_APPEARANCE_GAP -= OBSTACLE_APPEARANCE_DX;
}
_this.playId = window.requestAnimationFrame(_this.play);
if (_this.collisionHander.checkCollisions()) {
_this.gameOver();
}
_this.collisionHander.checkShot();
};
this.gameOver = function(){
var gameOver = document.createElement('div');
gameOver.className = 'game-over';
gameOver.innerHTML = 'GAME OVER';
_this.container.appendChild(gameOver);
_this.stop();
};
this.stop = function() {
this.obstacleManager.stop();
window.cancelAnimationFrame(_this.playId);
_this.car.stop();
_this._stopTime();
};
this._init();
}
var nfs = new NFS();