Path: blob/main/projects/missiles/src/barrier.js
1835 views
MG.BarrierType = {1RANDOM: 'random',23BARRIER_1: 1,4BARRIER_2: 2,5BARRIER_3: 3,6BARRIER_4: 4,7BARRIER_5: 5,8BARRIER_6: 6,910BLANK: 'blank',11START: 'start',12FINISH: 'finish'13};14MG.NUM_RANDOM_BARRIERS = 6;1516/* TODO find nicer way of initalising MG.BARRIER_PATH_IDS */17MG.BARRIER_PATH_IDS = {}18MG.BARRIER_PATH_IDS[MG.BarrierType.RANDOM] = '';19MG.BARRIER_PATH_IDS[MG.BarrierType.BARRIER_1] = 'barrier-path-1';20MG.BARRIER_PATH_IDS[MG.BarrierType.BARRIER_2] = 'barrier-path-2';21MG.BARRIER_PATH_IDS[MG.BarrierType.BARRIER_3] = 'barrier-path-3';22MG.BARRIER_PATH_IDS[MG.BarrierType.BARRIER_4] = 'barrier-path-4';23MG.BARRIER_PATH_IDS[MG.BarrierType.BARRIER_5] = 'barrier-path-5';24MG.BARRIER_PATH_IDS[MG.BarrierType.BARRIER_6] = 'barrier-path-6';25MG.BARRIER_PATH_IDS[MG.BarrierType.BLANK] = 'barrier-path-blank';26MG.BARRIER_PATH_IDS[MG.BarrierType.START] = 'barrier-path-blank';27MG.BARRIER_PATH_IDS[MG.BarrierType.FINISH] = 'barrier-path-finish';2829MG.Barrier = function (type) {30if (type === undefined) {type = MG.BarrierType.RANDOM;}3132var mIsInitialised = false;3334var mTheta = 0.0;35var mDTheta = 300.0*(0.5 - Math.random());3637var mIsRandom = (type === MG.BarrierType.RANDOM);38var mType = (type === MG.BarrierType.RANDOM) ? Math.ceil(MG.NUM_RANDOM_BARRIERS*Math.random()) : type;3940var mRootNode;41var mFrontPath;42var mBackPath;4344this.init = function () {4546mRootNode = document.createElementNS(NAMESPACE_SVG, 'g');4748/* The path representing the face nearest the camera */49mFrontPath = document.getElementById(MG.BARRIER_PATH_IDS[mType]).cloneNode(true);50mFrontPath.setAttribute('class', 'barrier-path-front');5152/* The path partially obscured by the front path, added to give the illusion of thickness. */53mBackPath = document.getElementById(MG.BARRIER_PATH_IDS[mType]).cloneNode(true);54mBackPath.setAttribute('class', 'barrier-path-back');5556mRootNode.setAttribute('class', 'barrier');57mRootNode.appendChild(mBackPath);58mRootNode.appendChild(mFrontPath);5960mIsInitialised = true;61};6263this.destroy = function () {64mRootNode.parentNode.removeChild(mRootNode);65};6667/**68* Checks whether the point specified by x and y will collide with the barrier.69* Works by counting the number of intersections between the path outlining the70* barrier and a line between some point outside of the barrier, and the point71* that is being tested.72* Returns true if the point intersects the transformed barrier, false otherwise.73*/74this.collides = function (x, y) {75/* transform the provided coordinates to the coordinate system of the barrier */76var x_ = x * Math.cos(mTheta*Math.PI/180) + y * Math.sin(mTheta*Math.PI/180);77var y_ = -x * Math.sin(mTheta*Math.PI/180) + y * Math.cos(mTheta*Math.PI/180);7879/* the line to be used for finding the intersections should already exist80but needs to be made to the point to the point that is to be tested */81var lineNode = document.getElementById('collision-line');82lineNode.setAttribute('x2', x_);83lineNode.setAttribute('y2', y_);8485/* As the barriers path may not have been created yet, the original path is used */86var pathNode = document.getElementById(MG.BARRIER_PATH_IDS[mType]);878889/* `Line` and `Path` are both part of Kevin Lindsey's svg geometry library. */90/* `Path` has been hacked to properly support elliptical arc segments. */91var line = new Line(lineNode);92var path = new Path(pathNode);9394var intersections = new Intersection.intersectShapes(path, line);9596return intersections.points.length % 2 === 1;97};9899this.update = function (dt) {100mTheta += mDTheta * dt;101};102103/**104* Updates the barriers representation in the DOM to reflect changes made at105* the last update.106* `x` and `y` define the position of the viewpoint.107* `offset` is the distance of the barrier from the viewpoint.108*/109this.updateDOM = function (x, y, offset) {110var frontScale = MG.PROJECTION_PLANE_DISTANCE /111(Math.tan(Math.PI * MG.FIELD_OF_VIEW/360.0)*(offset));112113var backScale = MG.PROJECTION_PLANE_DISTANCE /114(Math.tan(Math.PI * MG.FIELD_OF_VIEW/360.0)*(offset + 10));115116mFrontPath.setAttribute('transform',117'scale(' + frontScale + ') translate(' + x + ',' + y + ') rotate(' + mTheta + ')');118mBackPath.setAttribute('transform',119'scale(' + backScale + ') translate(' + x + ',' + y + ') rotate(' + mTheta + ')');120121offset = Math.max(MG.LINE_OF_SIGHT - MG.BARRIER_SPACING ,Math.min(MG.LINE_OF_SIGHT,offset));122var fog = 100 -100*(MG.LINE_OF_SIGHT - offset)/MG.BARRIER_SPACING;123124mFrontPath.setAttribute('fill', 'rgb('+(100+fog)+'%,'125+(100+fog)+'%,'126+(100+fog)+'%)');127mBackPath.setAttribute('fill', 'rgb(' +(60+fog)+'%,'128+(60+fog)+'%,'129+(60+fog)+'%)');130mFrontPath.setAttribute('stroke', 'rgb(' +(0+fog)+'%,'131+(0+fog)+'%,'132+(0+fog)+'%)');133mBackPath.setAttribute('stroke', 'rgb(' +(0+fog)+'%,'134+(0+fog)+'%,'135+(0+fog)+'%)');136};137138this.getType = function () {139return mType;140};141142this.isRandom = function () {143return mIsRandom;144};145146this.isInitialised = function () {147return mIsInitialised;148};149150this.getRootNode = function () {151return mRootNode;152};153154};155156157