02/12/2023
This commit is contained in:
		
							
								
								
									
										401
									
								
								need-for-speed/js/nfs.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										401
									
								
								need-for-speed/js/nfs.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,401 @@
 | 
			
		||||
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();
 | 
			
		||||
		Reference in New Issue
	
	Block a user